mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 13:29:11 +00:00 
			
		
		
		
	Merge branch 'unstable' into contrib
This commit is contained in:
		
						commit
						d2a2dbb4b6
					
				
					 230 changed files with 9263 additions and 13830 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitattributes
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					src/api/dotnet/Properties/AssemblyInfo.cs text eol=crlf
 | 
				
			||||||
| 
						 | 
					@ -906,6 +906,72 @@ void enum_sort_example() {
 | 
				
			||||||
    std::cout << "2: " << result_goal.as_expr() << std::endl;
 | 
					    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() {
 | 
					int main() {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        demorgan(); std::cout << "\n";
 | 
					        demorgan(); std::cout << "\n";
 | 
				
			||||||
| 
						 | 
					@ -937,10 +1003,13 @@ int main() {
 | 
				
			||||||
        tactic_example9(); std::cout << "\n";
 | 
					        tactic_example9(); std::cout << "\n";
 | 
				
			||||||
        tactic_qe(); std::cout << "\n";
 | 
					        tactic_qe(); std::cout << "\n";
 | 
				
			||||||
        tst_visit(); std::cout << "\n";
 | 
					        tst_visit(); std::cout << "\n";
 | 
				
			||||||
	incremental_example1(); std::cout << "\n";
 | 
					        incremental_example1(); std::cout << "\n";
 | 
				
			||||||
	incremental_example2(); std::cout << "\n";
 | 
					        incremental_example2(); std::cout << "\n";
 | 
				
			||||||
	incremental_example3(); std::cout << "\n";
 | 
					        incremental_example3(); std::cout << "\n";
 | 
				
			||||||
        enum_sort_example(); 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";
 | 
					        std::cout << "done\n";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    catch (exception & ex) {
 | 
					    catch (exception & ex) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,7 @@ def init_project_def():
 | 
				
			||||||
    add_lib('smt_tactic', ['smt'], 'smt/tactic')
 | 
					    add_lib('smt_tactic', ['smt'], 'smt/tactic')
 | 
				
			||||||
    add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls')
 | 
					    add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls')
 | 
				
			||||||
    # TODO: split muz_qe into muz, qe. Perhaps, we should also consider breaking muz into muz and pdr.
 | 
					    # TODO: split muz_qe into muz, qe. Perhaps, we should also consider breaking muz into muz and pdr.
 | 
				
			||||||
    add_lib('muz_qe', ['smt', 'sat', 'smt2parser'])
 | 
					    add_lib('muz_qe', ['smt', 'sat', 'smt2parser', 'aig_tactic'])
 | 
				
			||||||
    add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'muz_qe'], 'tactic/smtlogics')
 | 
					    add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'muz_qe'], 'tactic/smtlogics')
 | 
				
			||||||
    add_lib('ufbv_tactic', ['normal_forms', 'core_tactics', 'macros', 'smt_tactic', 'rewriter'], 'tactic/ufbv')
 | 
					    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', 'muz_qe', 'sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ extern "C" {
 | 
				
			||||||
        Z3_TRY;
 | 
					        Z3_TRY;
 | 
				
			||||||
        LOG_Z3_mk_int_symbol(c, i);
 | 
					        LOG_Z3_mk_int_symbol(c, i);
 | 
				
			||||||
        RESET_ERROR_CODE();
 | 
					        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);
 | 
					            SET_ERROR_CODE(Z3_IOB);
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1070,6 +1070,10 @@ extern "C" {
 | 
				
			||||||
            case OP_BV2INT:    return Z3_OP_BV2INT;
 | 
					            case OP_BV2INT:    return Z3_OP_BV2INT;
 | 
				
			||||||
            case OP_CARRY:     return Z3_OP_CARRY;
 | 
					            case OP_CARRY:     return Z3_OP_CARRY;
 | 
				
			||||||
            case OP_XOR3:      return Z3_OP_XOR3;
 | 
					            case OP_XOR3:      return Z3_OP_XOR3;
 | 
				
			||||||
 | 
					            case OP_BSMUL_NO_OVFL: 
 | 
				
			||||||
 | 
					            case OP_BUMUL_NO_OVFL:
 | 
				
			||||||
 | 
					            case OP_BSMUL_NO_UDFL:
 | 
				
			||||||
 | 
					                return Z3_OP_UNINTERPRETED;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                UNREACHABLE();
 | 
					                UNREACHABLE();
 | 
				
			||||||
                return Z3_OP_UNINTERPRETED;
 | 
					                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);
 | 
					            unsigned sz = Z3_get_bv_sort_size(c, s);
 | 
				
			||||||
            rational max_bound = power(rational(2), sz);
 | 
					            rational max_bound = power(rational(2), sz);
 | 
				
			||||||
            Z3_ast bound = Z3_mk_numeral(c, max_bound.to_string().c_str(), int_s);
 | 
					            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
 | 
					            // if n <_sigend 0 then r - s^sz else r
 | 
				
			||||||
            Z3_ast args[2] = { r, bound };
 | 
					            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);
 | 
					            RETURN_Z3(res);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
| 
						 | 
					@ -156,7 +166,14 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
				
			||||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
					            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
				
			||||||
            return 0;
 | 
					            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);
 | 
					        Z3_CATCH_RETURN(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,17 +194,40 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
				
			||||||
        RESET_ERROR_CODE();
 | 
					        RESET_ERROR_CODE();
 | 
				
			||||||
        if (is_signed) {
 | 
					        if (is_signed) {
 | 
				
			||||||
            Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
 | 
					            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 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);
 | 
					            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 {
 | 
					        else {
 | 
				
			||||||
            unsigned sz = Z3_get_bv_sort_size(c, Z3_get_sort(c, t1));
 | 
					            unsigned sz = Z3_get_bv_sort_size(c, Z3_get_sort(c, t1));
 | 
				
			||||||
            t1 = Z3_mk_zero_ext(c, 1, t1);
 | 
					            t1 = Z3_mk_zero_ext(c, 1, t1);
 | 
				
			||||||
 | 
					            Z3_inc_ref(c, t1);
 | 
				
			||||||
            t2 = Z3_mk_zero_ext(c, 1, t2);
 | 
					            t2 = Z3_mk_zero_ext(c, 1, t2);
 | 
				
			||||||
 | 
					            Z3_inc_ref(c, t2);
 | 
				
			||||||
            Z3_ast r = Z3_mk_bvadd(c, t1, 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);
 | 
					        Z3_CATCH_RETURN(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -197,10 +237,26 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
				
			||||||
        Z3_TRY;
 | 
					        Z3_TRY;
 | 
				
			||||||
        RESET_ERROR_CODE();
 | 
					        RESET_ERROR_CODE();
 | 
				
			||||||
        Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
 | 
					        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 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);
 | 
					        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);
 | 
					        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_ast Z3_API Z3_mk_bvsub_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
 | 
				
			||||||
        Z3_TRY;
 | 
					        Z3_TRY;
 | 
				
			||||||
        RESET_ERROR_CODE();
 | 
					        RESET_ERROR_CODE();
 | 
				
			||||||
        Z3_sort s = Z3_get_sort(c, t2);
 | 
					 | 
				
			||||||
        Z3_ast minus_t2 = Z3_mk_bvneg(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);
 | 
					        Z3_ast min = Z3_mk_bvsmin(c, s);
 | 
				
			||||||
        return Z3_mk_ite(c, Z3_mk_eq(c, t2, min), 
 | 
					        Z3_inc_ref(c, min);
 | 
				
			||||||
                         Z3_mk_bvslt(c, t1, Z3_mk_int(c, 0, s)),
 | 
					        Z3_ast x = Z3_mk_eq(c, t2, min);
 | 
				
			||||||
                         Z3_mk_bvadd_no_overflow(c, t1, minus_t2, true));
 | 
					        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);
 | 
					        Z3_CATCH_RETURN(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -222,10 +294,19 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
				
			||||||
        RESET_ERROR_CODE();
 | 
					        RESET_ERROR_CODE();
 | 
				
			||||||
        if (is_signed) {
 | 
					        if (is_signed) {
 | 
				
			||||||
            Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
 | 
					            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);
 | 
					            Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
 | 
				
			||||||
            if (Z3_get_error_code(c) != Z3_OK) return 0;
 | 
					            Z3_inc_ref(c, minus_t2);
 | 
				
			||||||
            return Z3_mk_implies(c, Z3_mk_bvslt(c, zero, t2), Z3_mk_bvadd_no_underflow(c, t1, 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 {
 | 
					        else {
 | 
				
			||||||
            return Z3_mk_bvule(c, t2, t1);
 | 
					            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;
 | 
					        Z3_TRY;
 | 
				
			||||||
        RESET_ERROR_CODE();
 | 
					        RESET_ERROR_CODE();
 | 
				
			||||||
        Z3_sort s = Z3_get_sort(c, t1);
 | 
					        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);
 | 
					        Z3_ast min = Z3_mk_bvmsb(c, s);
 | 
				
			||||||
        if (Z3_get_error_code(c) != Z3_OK) return 0;
 | 
					        Z3_inc_ref(c, min);
 | 
				
			||||||
        Z3_ast args[2] = { Z3_mk_eq(c, t1, min),
 | 
					        Z3_ast x = Z3_mk_eq(c, t1, min);
 | 
				
			||||||
                           Z3_mk_eq(c, t2, Z3_mk_int(c, -1, s)) };
 | 
					        Z3_inc_ref(c, x);
 | 
				
			||||||
        return Z3_mk_not(c, Z3_mk_and(c, 2, args));
 | 
					        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);
 | 
					        Z3_CATCH_RETURN(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,6 @@ Revision History:
 | 
				
			||||||
#define Z3_CATCH_RETURN_NO_HANDLE(VAL) } catch (z3_exception &) { return VAL; }
 | 
					#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 CHECK_REF_COUNT(a) (reinterpret_cast<ast const*>(a)->get_ref_count() > 0)
 | 
				
			||||||
#define VALIDATE(a) SASSERT(!a || CHECK_REF_COUNT(a))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace api {
 | 
					namespace api {
 | 
				
			||||||
    // Generic wrapper for ref-count objects exposed by the 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 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 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 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 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_app 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_ast a) { return reinterpret_cast<app*>(a); }
 | 
				
			||||||
inline Z3_app of_app(app* a) { return reinterpret_cast<Z3_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 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 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 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 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 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); }
 | 
					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 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_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 app* to_pattern(Z3_pattern p) { return reinterpret_cast<app*>(p); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline Z3_lbool of_lbool(lbool b) { return static_cast<Z3_lbool>(b); }
 | 
					inline Z3_lbool of_lbool(lbool b) { return static_cast<Z3_lbool>(b); }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -249,6 +249,8 @@ namespace z3 {
 | 
				
			||||||
        array & operator=(array const & s);
 | 
					        array & operator=(array const & s);
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        array(unsigned sz):m_size(sz) { m_array = new T[sz]; }
 | 
					        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; }
 | 
					        ~array() { delete[] m_array; }
 | 
				
			||||||
        unsigned size() const { return m_size; }
 | 
					        unsigned size() const { return m_size; }
 | 
				
			||||||
        T & operator[](int i) { assert(0 <= i); assert(static_cast<unsigned>(i) < m_size); return m_array[i]; }
 | 
					        T & operator[](int i) { assert(0 <= i); assert(static_cast<unsigned>(i) < m_size); return m_array[i]; }
 | 
				
			||||||
| 
						 | 
					@ -872,7 +874,18 @@ namespace z3 {
 | 
				
			||||||
           \brief Return a simplified version of this expression. The parameter \c p is a set of parameters for the Z3 simplifier.
 | 
					           \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); }
 | 
					        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.
 | 
					       \brief Wraps a Z3_ast as an expr object. It also checks for errors.
 | 
				
			||||||
| 
						 | 
					@ -928,49 +941,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(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); }
 | 
					    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<typename T> class cast_ast;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<> class cast_ast<ast> {
 | 
					    template<> class cast_ast<ast> {
 | 
				
			||||||
| 
						 | 
					@ -1032,6 +1002,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; }
 | 
					        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 {
 | 
					    class func_entry : public object {
 | 
				
			||||||
        Z3_func_entry m_entry;
 | 
					        Z3_func_entry m_entry;
 | 
				
			||||||
        void init(Z3_func_entry e) {
 | 
					        void init(Z3_func_entry e) {
 | 
				
			||||||
| 
						 | 
					@ -1680,6 +1711,30 @@ namespace z3 {
 | 
				
			||||||
        d.check_error();
 | 
					        d.check_error();
 | 
				
			||||||
        return expr(d.ctx(), r);
 | 
					        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>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Constructor.
 | 
					        /// Constructor.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </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)
 | 
					        public Context(Dictionary<string, string> settings)
 | 
				
			||||||
            : base()
 | 
					            : base()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -399,4 +399,4 @@
 | 
				
			||||||
  <Target Name="AfterBuild">
 | 
					  <Target Name="AfterBuild">
 | 
				
			||||||
  </Target>
 | 
					  </Target>
 | 
				
			||||||
  -->
 | 
					  -->
 | 
				
			||||||
</Project>
 | 
					</Project>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,21 @@ public class Context extends IDisposable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructor.
 | 
					     * 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
 | 
					    public Context(Map<String, String> settings) throws Z3Exception
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,23 @@
 | 
				
			||||||
This directory contains scripts to build the test application using
 | 
					This directory contains scripts to build the test application using
 | 
				
			||||||
OCaml. You also need CamlIDL to be able to generate the OCaml API.
 | 
					OCaml. You also need CamlIDL to be able to generate the OCaml API.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- To download OCaml:
 | 
					- To download OCaml:
 | 
				
			||||||
  http://caml.inria.fr/ocaml/      
 | 
					  http://caml.inria.fr/ocaml/      
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- To download CamlIDL:
 | 
					- To download CamlIDL:
 | 
				
			||||||
  http://forge.ocamlcore.org/projects/camlidl/
 | 
					  http://forge.ocamlcore.org/projects/camlidl/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- One must build the OCaml library before compiling the example.
 | 
					- One must build the OCaml library before compiling the example.
 | 
				
			||||||
  Go to directory ../ocaml
 | 
					  Go to directory ../ocaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Use 'build-test.cmd' to build the test application using the OCaml compiler.
 | 
					- Use 'build-test.cmd' to build the test application using the OCaml compiler.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Remark: The OCaml and C compiler tool chains must be configured in your environment.
 | 
					Remark: The OCaml and C compiler tool chains must be configured in your environment.
 | 
				
			||||||
Running from the Visual Studio Command Prompt configures the Microsoft C compiler.
 | 
					Running from the Visual Studio Command Prompt configures the Microsoft C compiler.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- The script 'exec.cmd' adds the bin directory to the path. So,
 | 
					- The script 'exec.cmd' adds the bin directory to the path. So,
 | 
				
			||||||
  test_mlapi.exe can find z3.dll.
 | 
					  test_mlapi.exe can find z3.dll.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,23 @@
 | 
				
			||||||
The OCaml API for Z3 was tested using OCaml 3.12.1.
 | 
					The OCaml API for Z3 was tested using OCaml 3.12.1.
 | 
				
			||||||
You also need CamlIDL to be able to generate the OCaml API.
 | 
					You also need CamlIDL to be able to generate the OCaml API.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- To download OCaml:
 | 
					- To download OCaml:
 | 
				
			||||||
  http://caml.inria.fr/ocaml/      
 | 
					  http://caml.inria.fr/ocaml/      
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- To download CamlIDL:
 | 
					- To download CamlIDL:
 | 
				
			||||||
  http://forge.ocamlcore.org/projects/camlidl/
 | 
					  http://forge.ocamlcore.org/projects/camlidl/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- To build the OCaml API for Z3:
 | 
					- To build the OCaml API for Z3:
 | 
				
			||||||
  .\build-lib.cmd
 | 
					  .\build-lib.cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Remark: The OCaml and C compiler tool chains must be configured in your environment.
 | 
					Remark: The OCaml and C compiler tool chains must be configured in your environment.
 | 
				
			||||||
Running from the Visual Studio Command Prompt configures the Microsoft C compiler.
 | 
					Running from the Visual Studio Command Prompt configures the Microsoft C compiler.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Remark: Building the OCaml API copies some pathnames into files,
 | 
					Remark: Building the OCaml API copies some pathnames into files,
 | 
				
			||||||
so the OCaml API must be recompiled if the Z3 library files are moved.
 | 
					so the OCaml API must be recompiled if the Z3 library files are moved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
See ..\examples\ocaml\build-test.cmd for an example of how to compile and link with Z3.
 | 
					See ..\examples\ocaml\build-test.cmd for an example of how to compile and link with Z3.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Acknowledgements:
 | 
					Acknowledgements:
 | 
				
			||||||
The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. 
 | 
					The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. 
 | 
				
			||||||
Many thanks to them!
 | 
					Many thanks to them!
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,3 @@
 | 
				
			||||||
@echo off
 | 
					@echo off
 | 
				
			||||||
 | 
					
 | 
				
			||||||
call .\compile_mlapi.cmd ..\include ..\bin ..\bin
 | 
					call .\compile_mlapi.cmd ..\include ..\bin ..\bin
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,19 @@
 | 
				
			||||||
@echo off
 | 
					@echo off
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if not exist ..\..\ocaml\z3.cmxa (
 | 
					if not exist ..\..\ocaml\z3.cmxa (
 | 
				
			||||||
        echo "YOU MUST BUILD OCAML API! Go to directory ..\ocaml"
 | 
					        echo "YOU MUST BUILD OCAML API! Go to directory ..\ocaml"
 | 
				
			||||||
        goto :EOF
 | 
					        goto :EOF
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
REM ocaml (>= 3.11) calls the linker through flexlink
 | 
					REM ocaml (>= 3.11) calls the linker through flexlink
 | 
				
			||||||
ocamlc -version >> ocaml_version
 | 
					ocamlc -version >> ocaml_version
 | 
				
			||||||
set /p OCAML_VERSION= <ocaml_version
 | 
					set /p OCAML_VERSION= <ocaml_version
 | 
				
			||||||
if %OCAML_VERSION% GEQ 3.11 (
 | 
					if %OCAML_VERSION% GEQ 3.11 (
 | 
				
			||||||
    set XCFLAGS=
 | 
					    set XCFLAGS=
 | 
				
			||||||
) else (
 | 
					) else (
 | 
				
			||||||
    set XCFLAGS=/nologo /MT /DWIN32
 | 
					    set XCFLAGS=/nologo /MT /DWIN32
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ocamlc -w A -ccopt "%XCFLAGS%" -o test_mlapi_byte.exe -I ..\..\ocaml z3.cma test_mlapi.ml
 | 
					ocamlc -w A -ccopt "%XCFLAGS%" -o test_mlapi_byte.exe -I ..\..\ocaml z3.cma test_mlapi.ml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ocamlopt -w A -ccopt "%XCFLAGS%" -o test_mlapi.exe -I ..\..\ocaml z3.cmxa test_mlapi.ml
 | 
					ocamlopt -w A -ccopt "%XCFLAGS%" -o test_mlapi.exe -I ..\..\ocaml z3.cmxa test_mlapi.ml
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
@echo off
 | 
					@echo off
 | 
				
			||||||
SETLOCAL
 | 
					SETLOCAL
 | 
				
			||||||
set PATH=..\..\bin;%PATH%
 | 
					set PATH=..\..\bin;%PATH%
 | 
				
			||||||
test_mlapi.exe
 | 
					test_mlapi.exe
 | 
				
			||||||
ENDLOCAL
 | 
					ENDLOCAL
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -585,6 +585,9 @@ class FuncDeclRef(AstRef):
 | 
				
			||||||
    def as_ast(self):
 | 
					    def as_ast(self):
 | 
				
			||||||
        return Z3_func_decl_to_ast(self.ctx_ref(), self.ast)
 | 
					        return Z3_func_decl_to_ast(self.ctx_ref(), self.ast)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def as_func_decl(self):
 | 
				
			||||||
 | 
						return self.ast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def name(self):
 | 
					    def name(self):
 | 
				
			||||||
        """Return the name of the function declaration `self`.
 | 
					        """Return the name of the function declaration `self`.
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -268,6 +268,8 @@ public:
 | 
				
			||||||
    bool is_int_real(expr const * n) const { return is_int_real(get_sort(n)); }
 | 
					    bool is_int_real(expr const * n) const { return is_int_real(get_sort(n)); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MATCH_UNARY(is_uminus);
 | 
					    MATCH_UNARY(is_uminus);
 | 
				
			||||||
 | 
					    MATCH_UNARY(is_to_real);
 | 
				
			||||||
 | 
					    MATCH_UNARY(is_to_int);
 | 
				
			||||||
    MATCH_BINARY(is_sub);
 | 
					    MATCH_BINARY(is_sub);
 | 
				
			||||||
    MATCH_BINARY(is_add);
 | 
					    MATCH_BINARY(is_add);
 | 
				
			||||||
    MATCH_BINARY(is_mul);
 | 
					    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) {
 | 
					char const * get_ast_kind_name(ast_kind k) {
 | 
				
			||||||
    return g_ast_kind_names[k];
 | 
					    return g_ast_kind_names[k];
 | 
				
			||||||
| 
						 | 
					@ -2755,7 +2755,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
 | 
				
			||||||
        app const * cls   = to_app(f1);
 | 
					        app const * cls   = to_app(f1);
 | 
				
			||||||
        unsigned num_args = cls->get_num_args();
 | 
					        unsigned num_args = cls->get_num_args();
 | 
				
			||||||
#ifdef Z3DEBUG
 | 
					#ifdef Z3DEBUG
 | 
				
			||||||
        vector<bool> found;
 | 
					        svector<bool> found;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        for (unsigned i = 0; i < num_args; i++) {
 | 
					        for (unsigned i = 0; i < num_args; i++) {
 | 
				
			||||||
            expr * lit = cls->get_arg(i);
 | 
					            expr * lit = cls->get_arg(i);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1193,7 +1193,6 @@ enum pattern_op_kind {
 | 
				
			||||||
   heurisitic quantifier instantiation.
 | 
					   heurisitic quantifier instantiation.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
class pattern_decl_plugin : public decl_plugin {
 | 
					class pattern_decl_plugin : public decl_plugin {
 | 
				
			||||||
    sort * m_list;
 | 
					 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    virtual decl_plugin * mk_fresh() { return alloc(pattern_decl_plugin); }
 | 
					    virtual decl_plugin * mk_fresh() { return alloc(pattern_decl_plugin); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -260,6 +260,7 @@ class smt_printer {
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            m_out << sym << "[";
 | 
					            m_out << sym << "[";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (unsigned i = 0; i < num_params; ++i) {
 | 
					        for (unsigned i = 0; i < num_params; ++i) {
 | 
				
			||||||
            parameter const& p = params[i];
 | 
					            parameter const& p = params[i];
 | 
				
			||||||
            if (p.is_ast()) {
 | 
					            if (p.is_ast()) {
 | 
				
			||||||
| 
						 | 
					@ -642,9 +643,7 @@ class smt_printer {
 | 
				
			||||||
            m_out << m_var_names[m_num_var_names - idx - 1];
 | 
					            m_out << m_var_names[m_num_var_names - idx - 1];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            if (!m_is_smt2) {
 | 
					            m_out << "?" << idx;
 | 
				
			||||||
                m_out << "?" << idx;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -326,6 +326,7 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        unsigned index0;
 | 
					        unsigned index0;
 | 
				
			||||||
        sort* last_sort = 0;
 | 
					        sort* last_sort = 0;
 | 
				
			||||||
 | 
					        SASSERT(num_params > 0);
 | 
				
			||||||
        for (unsigned i = 0; i < num_params; ++i) {
 | 
					        for (unsigned i = 0; i < num_params; ++i) {
 | 
				
			||||||
            parameter const& p = params[i];
 | 
					            parameter const& p = params[i];
 | 
				
			||||||
            if (!p.is_int()) {
 | 
					            if (!p.is_int()) {
 | 
				
			||||||
| 
						 | 
					@ -636,9 +637,13 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app* dl_decl_util::mk_numeral(uint64 value, sort* s) {
 | 
					    app* dl_decl_util::mk_numeral(uint64 value, sort* s) {
 | 
				
			||||||
        if (is_finite_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) };
 | 
					            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));
 | 
					            return m.mk_const(m.mk_func_decl(m_fid, OP_DL_CONSTANT, 2, params, 0, (sort*const*)0));
 | 
				
			||||||
        }
 | 
					        }        
 | 
				
			||||||
        if (m_arith.is_int(s) || m_arith.is_real(s)) {
 | 
					        if (m_arith.is_int(s) || m_arith.is_real(s)) {
 | 
				
			||||||
            return m_arith.mk_numeral(rational(value, rational::ui64()), s);
 | 
					            return m_arith.mk_numeral(rational(value, rational::ui64()), s);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -656,9 +661,9 @@ namespace datalog {
 | 
				
			||||||
        return 0;
 | 
					        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)) {
 | 
					        if (is_numeral(e)) {
 | 
				
			||||||
            app* c = to_app(e);
 | 
					            const app* c = to_app(e);
 | 
				
			||||||
            SASSERT(c->get_decl()->get_num_parameters() == 2);
 | 
					            SASSERT(c->get_decl()->get_num_parameters() == 2);
 | 
				
			||||||
            parameter const& p = c->get_decl()->get_parameter(0);
 | 
					            parameter const& p = c->get_decl()->get_parameter(0);
 | 
				
			||||||
            SASSERT(p.is_rational());
 | 
					            SASSERT(p.is_rational());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -169,11 +169,11 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app* mk_le(expr* a, expr* b);
 | 
					        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 
 | 
					        // Utilities for extracting constants 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,52 +20,50 @@ Notes:
 | 
				
			||||||
#include "expr_abstract.h"
 | 
					#include "expr_abstract.h"
 | 
				
			||||||
#include "map.h"
 | 
					#include "map.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref&  result) {
 | 
					void expr_abstractor::operator()(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;
 | 
					 | 
				
			||||||
    expr * curr = 0, *b = 0;
 | 
					    expr * curr = 0, *b = 0;
 | 
				
			||||||
    SASSERT(n->get_ref_count() > 0);
 | 
					    SASSERT(n->get_ref_count() > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    stack.push_back(n);
 | 
					    m_stack.push_back(n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (unsigned i = 0; i < num_bound; ++i) {
 | 
					    for (unsigned i = 0; i < num_bound; ++i) {
 | 
				
			||||||
        b = bound[i];
 | 
					        b = bound[i];
 | 
				
			||||||
        expr* v = m.mk_var(base + num_bound - i - 1, m.get_sort(b));
 | 
					        expr* v = m.mk_var(base + num_bound - i - 1, m.get_sort(b));
 | 
				
			||||||
        pinned.push_back(v);
 | 
					        m_pinned.push_back(v);
 | 
				
			||||||
        map.insert(b, v);
 | 
					        m_map.insert(b, v);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while(!stack.empty()) {
 | 
					    while(!m_stack.empty()) {
 | 
				
			||||||
        curr = stack.back();
 | 
					        curr = m_stack.back();
 | 
				
			||||||
        if (map.contains(curr)) {
 | 
					        if (m_map.contains(curr)) {
 | 
				
			||||||
            stack.pop_back();
 | 
					            m_stack.pop_back();
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        switch(curr->get_kind()) {
 | 
					        switch(curr->get_kind()) {
 | 
				
			||||||
        case AST_VAR: {
 | 
					        case AST_VAR: {
 | 
				
			||||||
            map.insert(curr, curr);
 | 
					            m_map.insert(curr, curr);
 | 
				
			||||||
            stack.pop_back();
 | 
					            m_stack.pop_back();
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case AST_APP: {
 | 
					        case AST_APP: {
 | 
				
			||||||
            app* a = to_app(curr);
 | 
					            app* a = to_app(curr);
 | 
				
			||||||
            bool all_visited = true;
 | 
					            bool all_visited = true;
 | 
				
			||||||
            ptr_vector<expr> args;
 | 
					            m_args.reset();
 | 
				
			||||||
            for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
					            for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
				
			||||||
                if (!map.find(a->get_arg(i), b)) {
 | 
					                if (!m_map.find(a->get_arg(i), b)) {
 | 
				
			||||||
                    stack.push_back(a->get_arg(i));
 | 
					                    m_stack.push_back(a->get_arg(i));
 | 
				
			||||||
                    all_visited = false;
 | 
					                    all_visited = false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    args.push_back(b);
 | 
					                    m_args.push_back(b);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (all_visited) {
 | 
					            if (all_visited) {
 | 
				
			||||||
                b = m.mk_app(a->get_decl(), args.size(), args.c_ptr());
 | 
					                b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr());
 | 
				
			||||||
                pinned.push_back(b);
 | 
					                m_pinned.push_back(b);
 | 
				
			||||||
                map.insert(curr, b);
 | 
					                m_map.insert(curr, b);
 | 
				
			||||||
                stack.pop_back();
 | 
					                m_stack.pop_back();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            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);
 | 
					            expr_abstract(m, new_base, num_bound, bound, q->get_expr(), result1);
 | 
				
			||||||
            b = m.update_quantifier(q, patterns.size(), patterns.c_ptr(), result1.get());
 | 
					            b = m.update_quantifier(q, patterns.size(), patterns.c_ptr(), result1.get());
 | 
				
			||||||
            pinned.push_back(b);            
 | 
					            m_pinned.push_back(b);            
 | 
				
			||||||
            map.insert(curr, b);
 | 
					            m_map.insert(curr, b);
 | 
				
			||||||
            stack.pop_back();            
 | 
					            m_stack.pop_back();            
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            UNREACHABLE();
 | 
					            UNREACHABLE();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!map.find(n, b)) {
 | 
					    VERIFY (m_map.find(n, b));
 | 
				
			||||||
        UNREACHABLE();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    result = 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"
 | 
					#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);
 | 
					void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref&  result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,6 +200,7 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        m_manager->raise_exception("sort of floating point constant was not specified");
 | 
					        m_manager->raise_exception("sort of floating point constant was not specified");
 | 
				
			||||||
 | 
					        UNREACHABLE();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SASSERT(is_sort_of(s, m_family_id, FLOAT_SORT));
 | 
					    SASSERT(is_sort_of(s, m_family_id, FLOAT_SORT));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,6 @@ void func_decl_dependencies::collect_ng_func_decls(expr * n, func_decl_set * s)
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
class func_decl_dependencies::top_sort {
 | 
					class func_decl_dependencies::top_sort {
 | 
				
			||||||
    enum color { OPEN, IN_PROGRESS, CLOSED };
 | 
					    enum color { OPEN, IN_PROGRESS, CLOSED };
 | 
				
			||||||
    ast_manager &       m_manager;    
 | 
					 | 
				
			||||||
    dependency_graph &  m_deps;
 | 
					    dependency_graph &  m_deps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef obj_map<func_decl, color> color_map;
 | 
					    typedef obj_map<func_decl, color> color_map;
 | 
				
			||||||
| 
						 | 
					@ -177,7 +176,7 @@ class func_decl_dependencies::top_sort {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					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) {
 | 
					    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);
 | 
					    m_deps.insert(f, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    top_sort cycle_detector(m_manager, m_deps);
 | 
					    top_sort cycle_detector(m_deps);
 | 
				
			||||||
    if (cycle_detector(f)) {
 | 
					    if (cycle_detector(f)) {
 | 
				
			||||||
        m_deps.erase(f);
 | 
					        m_deps.erase(f);
 | 
				
			||||||
        dealloc(s);
 | 
					        dealloc(s);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,10 +22,9 @@ Revision History:
 | 
				
			||||||
#include"uint_set.h"
 | 
					#include"uint_set.h"
 | 
				
			||||||
#include"var_subst.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_manager(m),
 | 
				
			||||||
  m_macro_manager(mm),
 | 
					  m_macro_manager(mm),
 | 
				
			||||||
  m_bsimp(p), 
 | 
					 | 
				
			||||||
  m_simplifier(s),
 | 
					  m_simplifier(s),
 | 
				
			||||||
  m_new_vars(m),
 | 
					  m_new_vars(m),
 | 
				
			||||||
  m_new_eqs(m),
 | 
					  m_new_eqs(m),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,6 @@ class quasi_macros {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ast_manager &             m_manager;
 | 
					    ast_manager &             m_manager;
 | 
				
			||||||
    macro_manager &           m_macro_manager;
 | 
					    macro_manager &           m_macro_manager;
 | 
				
			||||||
    basic_simplifier_plugin & m_bsimp;   
 | 
					 | 
				
			||||||
    simplifier &              m_simplifier;
 | 
					    simplifier &              m_simplifier;
 | 
				
			||||||
    occurrences_map           m_occurrences;
 | 
					    occurrences_map           m_occurrences;
 | 
				
			||||||
    ptr_vector<expr>          m_todo;    
 | 
					    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);
 | 
					    void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					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();
 | 
					    ~quasi_macros();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,13 +119,13 @@
 | 
				
			||||||
                 :pattern (?select (?select (?asElems e) a) i))))
 | 
					                 :pattern (?select (?select (?asElems e) a) i))))
 | 
				
			||||||
(assert (forall ((x Int) (f Int) (a0 Int))
 | 
					(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))
 | 
					                     (not (= (?isAllocated x a0) 1))
 | 
				
			||||||
                     (= (?isAllocated (?select f x) a0) 1))
 | 
					                     (= (?isAllocated (?select f x) a0) 1))
 | 
				
			||||||
                 :pattern (?isAllocated (?select f x) a0))))
 | 
					                 :pattern (?isAllocated (?select f x) a0))))
 | 
				
			||||||
(assert (forall ((a Int) (e Int) (i Int) (a0 Int))
 | 
					(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))
 | 
					                     (not (= (?isAllocated a a0) 1))
 | 
				
			||||||
                     (= (?isAllocated (?select (?select e a) i) a0) 1))
 | 
					                     (= (?isAllocated (?select (?select e a) i) a0) 1))
 | 
				
			||||||
                 :pattern (?isAllocated (?select (?select e a) i) a0))))
 | 
					                 :pattern (?isAllocated (?select (?select e a) i) a0))))
 | 
				
			||||||
| 
						 | 
					@ -281,13 +281,13 @@
 | 
				
			||||||
                  :pattern (IntsAllocated h (?StructGet_ s f)))))
 | 
					                  :pattern (IntsAllocated h (?StructGet_ s f)))))
 | 
				
			||||||
(assert  (forall ((x Int) (f Int) (a0 Int))
 | 
					(assert  (forall ((x Int) (f Int) (a0 Int))
 | 
				
			||||||
                 (!
 | 
					                 (!
 | 
				
			||||||
                  (or (<= (+ a0 (* -1 (?fClosedTime f))) 0)
 | 
					                  (or (<= (+ a0 (* (- 1) (?fClosedTime f))) 0)
 | 
				
			||||||
                      (not (?isAllocated_ x a0))
 | 
					                      (not (?isAllocated_ x a0))
 | 
				
			||||||
                      (?isAllocated_ (?select f x) a0))
 | 
					                      (?isAllocated_ (?select f x) a0))
 | 
				
			||||||
                  :pattern (?isAllocated_ (?select f x) a0))))
 | 
					                  :pattern (?isAllocated_ (?select f x) a0))))
 | 
				
			||||||
(assert  (forall ((a Int) (e Int) (i Int) (a0 Int))
 | 
					(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))
 | 
					                      (not (?isAllocated_ a a0))
 | 
				
			||||||
                      (?isAllocated_ (?select (?select e a) i) a0))
 | 
					                      (?isAllocated_ (?select (?select e a) i) a0))
 | 
				
			||||||
                  :pattern (?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;
 | 
					    vector<T, CallDestructors>                m_results2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool is_cached(expr * n) const { T c; return m_cache.find(n, c); }
 | 
					    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 cache_result(expr * n, T c) { m_cache.insert(n, c); }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void visit(expr * n, bool & visited);
 | 
					    void visit(expr * n, bool & visited);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@ void array_rewriter::updt_params(params_ref const & _p) {
 | 
				
			||||||
    array_rewriter_params p(_p);
 | 
					    array_rewriter_params p(_p);
 | 
				
			||||||
    m_sort_store = p.sort_store();
 | 
					    m_sort_store = p.sort_store();
 | 
				
			||||||
    m_expand_select_store = p.expand_select_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) {
 | 
					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;
 | 
					    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;
 | 
					    array_util    m_util;
 | 
				
			||||||
    bool          m_sort_store;
 | 
					    bool          m_sort_store;
 | 
				
			||||||
    bool          m_expand_select_store;
 | 
					    bool          m_expand_select_store;
 | 
				
			||||||
 | 
					    bool          m_expand_store_eq;
 | 
				
			||||||
    template<bool CHECK_DISEQ>
 | 
					    template<bool CHECK_DISEQ>
 | 
				
			||||||
    lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
 | 
					    lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
 | 
				
			||||||
public:    
 | 
					public:    
 | 
				
			||||||
    array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
 | 
					    array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
 | 
				
			||||||
        m_util(m) {
 | 
					        m_util(m) {
 | 
				
			||||||
        updt_params(p);
 | 
					        updt_params(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ast_manager & m() const { return m_util.get_manager(); }
 | 
					    ast_manager & m() const { return m_util.get_manager(); }
 | 
				
			||||||
    family_id get_fid() const { return m_util.get_family_id(); }
 | 
					    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_complement(expr * arg, expr_ref & result);
 | 
				
			||||||
    br_status mk_set_difference(expr * arg1, expr * arg2, 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_set_subset(expr * arg1, expr * arg2, expr_ref & result);
 | 
				
			||||||
 | 
					    br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,4 +2,5 @@ def_module_params(module_name='rewriter',
 | 
				
			||||||
                  class_name='array_rewriter_params',
 | 
					                  class_name='array_rewriter_params',
 | 
				
			||||||
                  export=True,
 | 
					                  export=True,
 | 
				
			||||||
                  params=(("expand_select_store", BOOL, False, "replace a (select (store ...) ...) term by an if-then-else term"),
 | 
					                  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")))
 | 
					                          ("sort_store", BOOL, False, "sort nested stores when the indices are known to be different")))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,7 +93,9 @@ void var_counter::count_vars(ast_manager & m, const app * pred, int coef) {
 | 
				
			||||||
    unsigned n = pred->get_num_args();
 | 
					    unsigned n = pred->get_num_args();
 | 
				
			||||||
    for (unsigned i = 0; i < n; i++) {
 | 
					    for (unsigned i = 0; i < n; i++) {
 | 
				
			||||||
        m_sorts.reset();
 | 
					        m_sorts.reset();
 | 
				
			||||||
        ::get_free_vars(pred->get_arg(i), m_sorts);
 | 
					        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) {
 | 
					        for (unsigned j = 0; j < m_sorts.size(); ++j) {
 | 
				
			||||||
            if (m_sorts[j]) {
 | 
					            if (m_sorts[j]) {
 | 
				
			||||||
                update(j, coef);
 | 
					                update(j, coef);
 | 
				
			||||||
| 
						 | 
					@ -108,24 +110,27 @@ unsigned var_counter::get_max_var(bool& has_var) {
 | 
				
			||||||
    unsigned max_var = 0;
 | 
					    unsigned max_var = 0;
 | 
				
			||||||
    while (!m_todo.empty()) {
 | 
					    while (!m_todo.empty()) {
 | 
				
			||||||
        expr* e = m_todo.back();
 | 
					        expr* e = m_todo.back();
 | 
				
			||||||
        unsigned scope = m_scopes.back();
 | 
					 | 
				
			||||||
        m_todo.pop_back();
 | 
					        m_todo.pop_back();
 | 
				
			||||||
        m_scopes.pop_back();
 | 
					 | 
				
			||||||
        if (m_visited.is_marked(e)) {
 | 
					        if (m_visited.is_marked(e)) {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        m_visited.mark(e, true);
 | 
					        m_visited.mark(e, true);
 | 
				
			||||||
        switch(e->get_kind()) {
 | 
					        switch(e->get_kind()) {
 | 
				
			||||||
        case AST_QUANTIFIER: {
 | 
					        case AST_QUANTIFIER: {
 | 
				
			||||||
 | 
					            var_counter aux_counter;
 | 
				
			||||||
            quantifier* q = to_quantifier(e);
 | 
					            quantifier* q = to_quantifier(e);
 | 
				
			||||||
            m_todo.push_back(q->get_expr());
 | 
					            bool has_var1 = false;
 | 
				
			||||||
            m_scopes.push_back(scope + q->get_num_decls());
 | 
					            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 = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            break;                 
 | 
					            break;                 
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case AST_VAR: {
 | 
					        case AST_VAR: {
 | 
				
			||||||
            if (to_var(e)->get_idx() >= scope + max_var) {
 | 
					            if (to_var(e)->get_idx() >= max_var) {
 | 
				
			||||||
                has_var = true;
 | 
					                has_var = true;
 | 
				
			||||||
                max_var = to_var(e)->get_idx() - scope;
 | 
					                max_var = to_var(e)->get_idx();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -133,7 +138,6 @@ unsigned var_counter::get_max_var(bool& has_var) {
 | 
				
			||||||
            app* a = to_app(e);
 | 
					            app* a = to_app(e);
 | 
				
			||||||
            for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
					            for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
				
			||||||
                m_todo.push_back(a->get_arg(i));
 | 
					                m_todo.push_back(a->get_arg(i));
 | 
				
			||||||
                m_scopes.push_back(scope);                    
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -150,14 +154,12 @@ unsigned var_counter::get_max_var(bool& has_var) {
 | 
				
			||||||
unsigned var_counter::get_max_var(expr* e) {
 | 
					unsigned var_counter::get_max_var(expr* e) {
 | 
				
			||||||
    bool has_var = false;
 | 
					    bool has_var = false;
 | 
				
			||||||
    m_todo.push_back(e);
 | 
					    m_todo.push_back(e);
 | 
				
			||||||
    m_scopes.push_back(0);
 | 
					 | 
				
			||||||
    return get_max_var(has_var);
 | 
					    return get_max_var(has_var);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned var_counter::get_next_var(expr* e) {
 | 
					unsigned var_counter::get_next_var(expr* e) {
 | 
				
			||||||
    bool has_var = false;
 | 
					    bool has_var = false;
 | 
				
			||||||
    m_todo.push_back(e);
 | 
					    m_todo.push_back(e);
 | 
				
			||||||
    m_scopes.push_back(0);
 | 
					 | 
				
			||||||
    unsigned mv = get_max_var(has_var);
 | 
					    unsigned mv = get_max_var(has_var);
 | 
				
			||||||
    if (has_var) mv++;
 | 
					    if (has_var) mv++;
 | 
				
			||||||
    return mv;
 | 
					    return mv;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,7 @@ public:
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {}
 | 
					    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 begin() const { return m_data.begin(); }
 | 
				
			||||||
    iterator end() const { return m_data.end(); }    
 | 
					    iterator end() const { return m_data.end(); }    
 | 
				
			||||||
    void update(unsigned el, int delta);
 | 
					    void update(unsigned el, int delta);
 | 
				
			||||||
| 
						 | 
					@ -71,6 +72,7 @@ protected:
 | 
				
			||||||
    ptr_vector<sort> m_sorts;
 | 
					    ptr_vector<sort> m_sorts;
 | 
				
			||||||
    expr_fast_mark1  m_visited;
 | 
					    expr_fast_mark1  m_visited;
 | 
				
			||||||
    ptr_vector<expr> m_todo;
 | 
					    ptr_vector<expr> m_todo;
 | 
				
			||||||
 | 
					    ast_mark         m_mark;
 | 
				
			||||||
    unsigned_vector  m_scopes;
 | 
					    unsigned_vector  m_scopes;
 | 
				
			||||||
    unsigned get_max_var(bool & has_var);    
 | 
					    unsigned get_max_var(bool & has_var);    
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,13 +242,13 @@ br_status float_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
 | 
				
			||||||
        return BR_DONE;
 | 
					        return BR_DONE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // expand as using ite's
 | 
					    // 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,
 | 
					                        arg2,
 | 
				
			||||||
                        m().mk_ite(mk_eq_nan(arg2), 
 | 
					                        m().mk_ite(mk_eq_nan(arg2), 
 | 
				
			||||||
                                   arg1,
 | 
					                                   arg1,
 | 
				
			||||||
                                   m().mk_ite(m_util.mk_lt(arg1, arg2),
 | 
					                                   m().mk_ite(m_util.mk_lt(arg1, arg2),
 | 
				
			||||||
                                              arg1,
 | 
					                                           arg1,
 | 
				
			||||||
                                              arg2)));
 | 
					                                           arg2)));
 | 
				
			||||||
    return BR_REWRITE_FULL;
 | 
					    return BR_REWRITE_FULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -262,7 +262,7 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
 | 
				
			||||||
        return BR_DONE;
 | 
					        return BR_DONE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // expand as using ite's
 | 
					    // 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,
 | 
					                        arg2,
 | 
				
			||||||
                        m().mk_ite(mk_eq_nan(arg2), 
 | 
					                        m().mk_ite(mk_eq_nan(arg2), 
 | 
				
			||||||
                                   arg1,
 | 
					                                   arg1,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,6 +62,8 @@ struct mk_simplified_app::imp {
 | 
				
			||||||
                    st = m_dt_rw.mk_eq_core(args[0], args[1], result);
 | 
					                    st = m_dt_rw.mk_eq_core(args[0], args[1], result);
 | 
				
			||||||
                else if (s_fid == m_f_rw.get_fid())
 | 
					                else if (s_fid == m_f_rw.get_fid())
 | 
				
			||||||
                    st = m_f_rw.mk_eq_core(args[0], args[1], result);
 | 
					                    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)
 | 
					                if (st != BR_FAILED)
 | 
				
			||||||
                    return st;
 | 
					                    return st;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -169,7 +169,9 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
 | 
				
			||||||
                    st = m_dt_rw.mk_eq_core(args[0], args[1], result);
 | 
					                    st = m_dt_rw.mk_eq_core(args[0], args[1], result);
 | 
				
			||||||
                else if (s_fid == m_f_rw.get_fid())
 | 
					                else if (s_fid == m_f_rw.get_fid())
 | 
				
			||||||
                    st = m_f_rw.mk_eq_core(args[0], args[1], result);
 | 
					                    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)
 | 
					                if (st != BR_FAILED)
 | 
				
			||||||
                    return st;
 | 
					                    return st;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,6 @@ Notes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--*/
 | 
					--*/
 | 
				
			||||||
#include"var_subst.h"
 | 
					#include"var_subst.h"
 | 
				
			||||||
#include"used_vars.h"
 | 
					 | 
				
			||||||
#include"ast_ll_pp.h"
 | 
					#include"ast_ll_pp.h"
 | 
				
			||||||
#include"ast_pp.h"
 | 
					#include"ast_pp.h"
 | 
				
			||||||
#include"ast_smt2_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";);
 | 
					          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));
 | 
					    SASSERT(is_well_sorted(m, q));
 | 
				
			||||||
    if (is_ground(q->get_expr())) {
 | 
					    if (is_ground(q->get_expr())) {
 | 
				
			||||||
        // ignore patterns if the body is a ground formula.
 | 
					        // 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;
 | 
					        result = q;
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    used_vars used;
 | 
					    m_used.reset();
 | 
				
			||||||
    used.process(q->get_expr());
 | 
					    m_used.process(q->get_expr());
 | 
				
			||||||
    unsigned num_patterns = q->get_num_patterns();
 | 
					    unsigned num_patterns = q->get_num_patterns();
 | 
				
			||||||
    for (unsigned i = 0; i < num_patterns; i++)
 | 
					    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();
 | 
					    unsigned num_no_patterns = q->get_num_no_patterns();
 | 
				
			||||||
    for (unsigned i = 0; i < num_no_patterns; i++)
 | 
					    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();
 | 
					    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();
 | 
					        q->set_no_unused_vars();
 | 
				
			||||||
        result = q;
 | 
					        result = q;
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
| 
						 | 
					@ -70,7 +69,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
				
			||||||
    ptr_buffer<sort>  used_decl_sorts; 
 | 
					    ptr_buffer<sort>  used_decl_sorts; 
 | 
				
			||||||
    buffer<symbol>    used_decl_names;
 | 
					    buffer<symbol>    used_decl_names;
 | 
				
			||||||
    for (unsigned i = 0; i < num_decls; ++i) {
 | 
					    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_sorts.push_back(q->get_decl_sort(i));
 | 
				
			||||||
            used_decl_names.push_back(q->get_decl_name(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;
 | 
					    unsigned         num_removed = 0;
 | 
				
			||||||
    expr_ref_buffer  var_mapping(m);
 | 
					    expr_ref_buffer  var_mapping(m);
 | 
				
			||||||
    int              next_idx = 0;
 | 
					    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) {
 | 
					    for (unsigned i = 0; i < num_decls; ++i) {
 | 
				
			||||||
        sort * s = used.contains(i);
 | 
					        sort * s = m_used.contains(i);
 | 
				
			||||||
        if (s) {
 | 
					        if (s) {
 | 
				
			||||||
            var_mapping.push_back(m.mk_var(next_idx, s));
 | 
					            var_mapping.push_back(m.mk_var(next_idx, s));
 | 
				
			||||||
            next_idx++;
 | 
					            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.
 | 
					    // (VAR 0) is in the first position of var_mapping.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (unsigned i = num_decls; i < sz; i++) {
 | 
					    for (unsigned i = num_decls; i < sz; i++) {
 | 
				
			||||||
        sort * s = used.contains(i);
 | 
					        sort * s = m_used.contains(i);
 | 
				
			||||||
        if (s)
 | 
					        if (s)
 | 
				
			||||||
            var_mapping.push_back(m.mk_var(i - num_removed, s));
 | 
					            var_mapping.push_back(m.mk_var(i - num_removed, s));
 | 
				
			||||||
        else
 | 
					        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());
 | 
					    std::reverse(var_mapping.c_ptr(), var_mapping.c_ptr() + var_mapping.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expr_ref  new_expr(m);
 | 
					    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) {
 | 
					    if (num_removed == num_decls) {
 | 
				
			||||||
        result = new_expr;
 | 
					        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);
 | 
					    expr_ref_buffer new_no_patterns(m);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for (unsigned i = 0; i < num_patterns; i++) {
 | 
					    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);
 | 
					        new_patterns.push_back(tmp);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    for (unsigned i = 0; i < num_no_patterns; i++) {
 | 
					    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);
 | 
					        new_no_patterns.push_back(tmp);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -145,7 +143,12 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
				
			||||||
                             num_no_patterns,
 | 
					                             num_no_patterns,
 | 
				
			||||||
                             new_no_patterns.c_ptr());
 | 
					                             new_no_patterns.c_ptr());
 | 
				
			||||||
    to_quantifier(result)->set_no_unused_vars();
 | 
					    to_quantifier(result)->set_no_unused_vars();
 | 
				
			||||||
    SASSERT(is_well_sorted(m, 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) {
 | 
					void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result) {
 | 
				
			||||||
| 
						 | 
					@ -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";);
 | 
					          tout << "\n----->\n" << mk_ismt2_pp(result, m) << "\n";);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sorts) {
 | 
					static void get_free_vars_offset(ast_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
 | 
				
			||||||
    ast_mark mark;
 | 
					 | 
				
			||||||
    ptr_vector<expr> todo;
 | 
					 | 
				
			||||||
    todo.push_back(e);
 | 
					    todo.push_back(e);
 | 
				
			||||||
    while (!todo.empty()) {
 | 
					    while (!todo.empty()) {
 | 
				
			||||||
        e = todo.back();
 | 
					        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()) {
 | 
					        switch(e->get_kind()) {
 | 
				
			||||||
        case AST_QUANTIFIER: {
 | 
					        case AST_QUANTIFIER: {
 | 
				
			||||||
            quantifier* q = to_quantifier(e);
 | 
					            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;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case AST_VAR: {
 | 
					        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) {
 | 
					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_
 | 
					#define _VAR_SUBST_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include"rewriter.h"
 | 
					#include"rewriter.h"
 | 
				
			||||||
 | 
					#include"used_vars.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
   \brief Alias for var_shifter class.
 | 
					   \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.
 | 
					   \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);
 | 
					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(expr* e, ptr_vector<sort>& sorts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -636,7 +636,31 @@ bool bv_simplifier_plugin::try_mk_extract(unsigned high, unsigned low, expr * ar
 | 
				
			||||||
        if (!all_found) {
 | 
					        if (!all_found) {
 | 
				
			||||||
            return false;
 | 
					            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;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (m_manager.is_ite(a)) {
 | 
					    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 * arg1    = *it1;
 | 
				
			||||||
        expr * arg2    = *it2;
 | 
					        expr * arg2    = *it2;
 | 
				
			||||||
        TRACE("expr_bv_util", tout << "low1: " << low1 << " low2: " << low2 << "\n";
 | 
					        TRACE("expr_bv_util", tout << "low1: " << low1 << " low2: " << low2 << "\n";
 | 
				
			||||||
              ast_ll_pp(tout, m_manager, arg1); 
 | 
					              tout << mk_pp(arg1, m_manager) << "\n";
 | 
				
			||||||
              ast_ll_pp(tout, m_manager, arg2););
 | 
					              tout << mk_pp(arg2, m_manager) << "\n";);
 | 
				
			||||||
        unsigned sz1  = get_bv_size(arg1);
 | 
					        unsigned sz1  = get_bv_size(arg1);
 | 
				
			||||||
        unsigned sz2  = get_bv_size(arg2);
 | 
					        unsigned sz2  = get_bv_size(arg2);
 | 
				
			||||||
        SASSERT(low1 < sz1 && low2 < sz2);
 | 
					        SASSERT(low1 < sz1 && low2 < sz2);
 | 
				
			||||||
        unsigned rsz1 = sz1 - low1;
 | 
					        unsigned rsz1 = sz1 - low1;
 | 
				
			||||||
        unsigned rsz2 = sz2 - low2;
 | 
					        unsigned rsz2 = sz2 - low2;
 | 
				
			||||||
        TRACE("expr_bv_util", tout << "rsz1: " << rsz1 << " rsz2: " << rsz2 << "\n";
 | 
					        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) {
 | 
					        if (rsz1 == rsz2) {
 | 
				
			||||||
            mk_extract(sz1 - 1, low1, arg1, lhs);
 | 
					            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);
 | 
					        m_bsimp.mk_and(tmps.size(), tmps.c_ptr(), result);
 | 
				
			||||||
        TRACE("mk_eq_bb", 
 | 
					        TRACE("mk_eq_bb", 
 | 
				
			||||||
              ast_ll_pp(tout, m_manager, arg1);
 | 
					              tout << mk_pp(arg1, m_manager) << "\n";
 | 
				
			||||||
              ast_ll_pp(tout, m_manager, arg2);
 | 
					              tout << mk_pp(arg2, m_manager) << "\n";
 | 
				
			||||||
              ast_ll_pp(tout, m_manager, result););
 | 
					              tout << mk_pp(result, m_manager) << "\n";);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,6 +285,7 @@ bool poly_simplifier_plugin::merge_monomials(bool inv, expr * n1, expr * n2, exp
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            result = m_manager.mk_app(m_fid, m_MUL, mk_numeral(k1), b);
 | 
					            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;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,10 +18,6 @@ Revision History:
 | 
				
			||||||
--*/
 | 
					--*/
 | 
				
			||||||
#include"matcher.h"
 | 
					#include"matcher.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
matcher::matcher(ast_manager & m):
 | 
					 | 
				
			||||||
    m_manager(m) {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool matcher::operator()(expr * e1, expr * e2, substitution & s) {
 | 
					bool matcher::operator()(expr * e1, expr * e2, substitution & s) {
 | 
				
			||||||
    reset();
 | 
					    reset();
 | 
				
			||||||
    m_subst = &s;
 | 
					    m_subst = &s;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,6 @@ class matcher {
 | 
				
			||||||
    typedef pair_hash<obj_ptr_hash<expr>, obj_ptr_hash<expr> > expr_pair_hash;
 | 
					    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;
 | 
					    typedef hashtable<expr_pair, expr_pair_hash, default_eq<expr_pair> > cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ast_manager &         m_manager;
 | 
					 | 
				
			||||||
    substitution *        m_subst;
 | 
					    substitution *        m_subst;
 | 
				
			||||||
    // cache                 m_cache;
 | 
					    // cache                 m_cache;
 | 
				
			||||||
    svector<expr_pair>    m_todo;
 | 
					    svector<expr_pair>    m_todo;
 | 
				
			||||||
| 
						 | 
					@ -38,7 +37,7 @@ class matcher {
 | 
				
			||||||
    void reset();
 | 
					    void reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    matcher(ast_manager & m);
 | 
					    matcher() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
       \brief Return true if e2 is an instance of e1.
 | 
					       \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 * arg     = to_app(e)->get_arg(i);
 | 
				
			||||||
                    expr * new_arg;
 | 
					                    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);
 | 
					                    new_args.push_back(new_arg);
 | 
				
			||||||
                    if (arg != new_arg)
 | 
					                    if (arg != new_arg)
 | 
				
			||||||
                        has_new_args = true;
 | 
					                        has_new_args = true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,2 +1,2 @@
 | 
				
			||||||
Command context provides the infrastructure for executing commands in front-ends such as SMT-LIB 2.0.
 | 
					Command context provides the infrastructure for executing commands in front-ends such as SMT-LIB 2.0.
 | 
				
			||||||
It is also provides the solver abstraction to plugin solvers in this kind of front-end.
 | 
					It is also provides the solver abstraction to plugin solvers in this kind of front-end.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,2 +1,2 @@
 | 
				
			||||||
Basic Euclidean solver for linear integer equations.
 | 
					Basic Euclidean solver for linear integer equations.
 | 
				
			||||||
This solver generates "explanations". 
 | 
					This solver generates "explanations". 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,2 +1,2 @@
 | 
				
			||||||
Template for interval arithmetic. The template can be instantiated using different numeral (integers/mpz, rationals/mpq, floating-point/mpf, etc) packages.
 | 
					Template for interval arithmetic. The template can be instantiated using different numeral (integers/mpz, rationals/mpq, floating-point/mpf, etc) packages.
 | 
				
			||||||
The class im_default_config defines a default configuration for the template that uses rationals. It also shows what is the expected signature used by the template.
 | 
					The class im_default_config defines a default configuration for the template that uses rationals. It also shows what is the expected signature used by the template.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,3 @@
 | 
				
			||||||
Polynomial manipulation package.
 | 
					Polynomial manipulation package.
 | 
				
			||||||
It contains support for univariate (upolynomial.*) and multivariate polynomials (polynomial.*).
 | 
					It contains support for univariate (upolynomial.*) and multivariate polynomials (polynomial.*).
 | 
				
			||||||
Multivariate polynomial factorization does not work yet (polynomial_factorization.*), and it is disabled.
 | 
					Multivariate polynomial factorization does not work yet (polynomial_factorization.*), and it is disabled.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -660,8 +660,7 @@ namespace realclosure {
 | 
				
			||||||
                return; // interval was already saved.
 | 
					                return; // interval was already saved.
 | 
				
			||||||
            to_restore.push_back(v);
 | 
					            to_restore.push_back(v);
 | 
				
			||||||
            inc_ref(v);
 | 
					            inc_ref(v);
 | 
				
			||||||
	    void * mem = allocator().allocate(sizeof(mpbqi));
 | 
					            v->m_old_interval = new (allocator()) mpbqi();
 | 
				
			||||||
            v->m_old_interval = new (mem) mpbqi();
 | 
					 | 
				
			||||||
            set_interval(*(v->m_old_interval), v->m_interval);
 | 
					            set_interval(*(v->m_old_interval), v->m_interval);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        void save_interval(value * v) {
 | 
					        void save_interval(value * v) {
 | 
				
			||||||
| 
						 | 
					@ -1237,8 +1236,7 @@ namespace realclosure {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sign_condition * mk_sign_condition(unsigned qidx, int sign, sign_condition * prev_sc) {
 | 
					        sign_condition * mk_sign_condition(unsigned qidx, int sign, sign_condition * prev_sc) {
 | 
				
			||||||
	    void * mem = allocator().allocate(sizeof(sign_condition));
 | 
					            return new (allocator()) sign_condition(qidx, sign, prev_sc);
 | 
				
			||||||
            return new (mem) sign_condition(qidx, sign, prev_sc);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
| 
						 | 
					@ -1246,7 +1244,7 @@ namespace realclosure {
 | 
				
			||||||
           This method does not set the interval. It remains (-oo, oo)
 | 
					           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 * 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);
 | 
					            inc_ref(ext);
 | 
				
			||||||
            set_p(r->num(), num_sz, num);
 | 
					            set_p(r->num(), num_sz, num);
 | 
				
			||||||
            if (ext->is_algebraic()) {
 | 
					            if (ext->is_algebraic()) {
 | 
				
			||||||
| 
						 | 
					@ -1283,7 +1281,7 @@ namespace realclosure {
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
        void mk_infinitesimal(symbol const & n, symbol const & pp_n, numeral & r) {
 | 
					        void mk_infinitesimal(symbol const & n, symbol const & pp_n, numeral & r) {
 | 
				
			||||||
            unsigned idx = next_infinitesimal_idx();
 | 
					            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);
 | 
					            m_extensions[extension::INFINITESIMAL].push_back(eps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            set_lower(eps->interval(), mpbq(0));
 | 
					            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) {
 | 
					        void mk_transcendental(symbol const & n, symbol const & pp_n, mk_interval & proc, numeral & r) {
 | 
				
			||||||
            unsigned idx = next_transcendental_idx();
 | 
					            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);
 | 
					            m_extensions[extension::TRANSCENDENTAL].push_back(t);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            while (contains_zero(t->interval())) {
 | 
					            while (contains_zero(t->interval())) {
 | 
				
			||||||
| 
						 | 
					@ -1798,8 +1796,7 @@ namespace realclosure {
 | 
				
			||||||
           M and scs will be empty after this operation.
 | 
					           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) {
 | 
					        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 (allocator()) sign_det();
 | 
				
			||||||
            sign_det * r = new (mem) sign_det();
 | 
					 | 
				
			||||||
            r->M_s.swap(M_s);
 | 
					            r->M_s.swap(M_s);
 | 
				
			||||||
            set_array_p(r->m_prs, prs);
 | 
					            set_array_p(r->m_prs, prs);
 | 
				
			||||||
            r->m_taqrs.set(allocator(), taqrs.size(), taqrs.c_ptr());
 | 
					            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) {
 | 
					        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();
 | 
					            unsigned idx = next_algebraic_idx();
 | 
				
			||||||
	    void * mem = allocator().allocate(sizeof(algebraic));
 | 
					            algebraic * r = new (allocator()) algebraic(idx);
 | 
				
			||||||
            algebraic * r = new (mem) algebraic(idx);
 | 
					 | 
				
			||||||
            m_extensions[extension::ALGEBRAIC].push_back(r);
 | 
					            m_extensions[extension::ALGEBRAIC].push_back(r);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            set_p(r->m_p, p_sz, p);
 | 
					            set_p(r->m_p, p_sz, p);
 | 
				
			||||||
| 
						 | 
					@ -2561,8 +2557,7 @@ namespace realclosure {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rational_value * mk_rational() {
 | 
					        rational_value * mk_rational() {
 | 
				
			||||||
	    void * mem = allocator().allocate(sizeof(rational_value));
 | 
					            return new (allocator()) rational_value();
 | 
				
			||||||
            return new (mem) rational_value();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,7 +85,6 @@ namespace subpaving {
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class context_mpf_wrapper : public context_wrapper<context_mpf> {
 | 
					    class context_mpf_wrapper : public context_wrapper<context_mpf> {
 | 
				
			||||||
        f2n<mpf_manager> &            m_fm;
 | 
					 | 
				
			||||||
        unsynch_mpq_manager &         m_qm;
 | 
					        unsynch_mpq_manager &         m_qm;
 | 
				
			||||||
        scoped_mpf                    m_c;
 | 
					        scoped_mpf                    m_c;
 | 
				
			||||||
        scoped_mpf_vector             m_as;
 | 
					        scoped_mpf_vector             m_as;
 | 
				
			||||||
| 
						 | 
					@ -103,7 +102,6 @@ namespace subpaving {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        context_mpf_wrapper(f2n<mpf_manager> & fm, params_ref const & p, small_object_allocator * a):
 | 
					        context_mpf_wrapper(f2n<mpf_manager> & fm, params_ref const & p, small_object_allocator * a):
 | 
				
			||||||
            context_wrapper<context_mpf>(fm, p, a),
 | 
					            context_wrapper<context_mpf>(fm, p, a),
 | 
				
			||||||
            m_fm(fm),
 | 
					 | 
				
			||||||
            m_qm(fm.m().mpq_manager()),
 | 
					            m_qm(fm.m().mpq_manager()),
 | 
				
			||||||
            m_c(fm.m()),
 | 
					            m_c(fm.m()),
 | 
				
			||||||
            m_as(fm.m()),
 | 
					            m_as(fm.m()),
 | 
				
			||||||
| 
						 | 
					@ -145,7 +143,6 @@ namespace subpaving {
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class context_hwf_wrapper : public context_wrapper<context_hwf> {
 | 
					    class context_hwf_wrapper : public context_wrapper<context_hwf> {
 | 
				
			||||||
        f2n<hwf_manager> &            m_fm;
 | 
					 | 
				
			||||||
        unsynch_mpq_manager &         m_qm;
 | 
					        unsynch_mpq_manager &         m_qm;
 | 
				
			||||||
        hwf                           m_c;
 | 
					        hwf                           m_c;
 | 
				
			||||||
        svector<hwf>                  m_as;
 | 
					        svector<hwf>                  m_as;
 | 
				
			||||||
| 
						 | 
					@ -166,7 +163,6 @@ namespace subpaving {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        context_hwf_wrapper(f2n<hwf_manager> & fm, unsynch_mpq_manager & qm, params_ref const & p, small_object_allocator * a):
 | 
					        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),
 | 
					            context_wrapper<context_hwf>(fm, p, a),
 | 
				
			||||||
            m_fm(fm),
 | 
					 | 
				
			||||||
            m_qm(qm) {
 | 
					            m_qm(qm) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										328
									
								
								src/muz_qe/aig_exporter.cpp
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										328
									
								
								src/muz_qe/aig_exporter.cpp
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
					@ -0,0 +1,328 @@
 | 
				
			||||||
 | 
					/*++
 | 
				
			||||||
 | 
					Copyright (c) 2013 Microsoft Corporation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Module Name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aig_exporter.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Abstract:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Export AIG files from horn clauses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "aig_exporter.h"
 | 
				
			||||||
 | 
					#include "dl_context.h"
 | 
				
			||||||
 | 
					#include <set>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aig_exporter::aig_exporter(const rule_set& rules, context& ctx, const fact_vector *facts) :
 | 
				
			||||||
 | 
					        m_rules(rules), m_facts(facts), m(ctx.get_manager()), m_rm(ctx.get_rule_manager()),
 | 
				
			||||||
 | 
					        m_aigm(m), m_next_decl_id(1), m_next_aig_expr_id(2), m_num_and_gates(0),
 | 
				
			||||||
 | 
					        m_latch_vars(m), m_latch_varsp(m), m_ruleid_var_set(m), m_ruleid_varp_set(m)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::set<func_decl*> predicates;
 | 
				
			||||||
 | 
					        for (rule_set::decl2rules::iterator I = m_rules.begin_grouped_rules(),
 | 
				
			||||||
 | 
					            E = m_rules.end_grouped_rules(); I != E; ++I) {
 | 
				
			||||||
 | 
					            predicates.insert(I->m_key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (fact_vector::const_iterator I = facts->begin(), E = facts->end(); I != E; ++I) {
 | 
				
			||||||
 | 
					            predicates.insert(I->first);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // reserve pred id = 0 for initalization purposes
 | 
				
			||||||
 | 
					        unsigned num_preds = (unsigned)predicates.size() + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // poor's man round-up log2
 | 
				
			||||||
 | 
					        unsigned preds_bitsize = log2(num_preds);
 | 
				
			||||||
 | 
					        if ((1U << preds_bitsize) < num_preds)
 | 
				
			||||||
 | 
					            ++preds_bitsize;
 | 
				
			||||||
 | 
					        SASSERT((1U << preds_bitsize) >= num_preds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < preds_bitsize; ++i) {
 | 
				
			||||||
 | 
					            m_ruleid_var_set.push_back(m.mk_fresh_const("rule_id", m.mk_bool_sort()));
 | 
				
			||||||
 | 
					            m_ruleid_varp_set.push_back(m.mk_fresh_const("rule_id_p", m.mk_bool_sort()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void aig_exporter::mk_latch_vars(unsigned n) {
 | 
				
			||||||
 | 
					        for (unsigned i = m_latch_vars.size(); i <= n; ++i) {
 | 
				
			||||||
 | 
					            m_latch_vars.push_back(m.mk_fresh_const("latch_var", m.mk_bool_sort()));
 | 
				
			||||||
 | 
					            m_latch_varsp.push_back(m.mk_fresh_const("latch_varp", m.mk_bool_sort()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        SASSERT(m_latch_vars.size() > n);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expr* aig_exporter::get_latch_var(unsigned i, const expr_ref_vector& vars) {
 | 
				
			||||||
 | 
					        mk_latch_vars(i);
 | 
				
			||||||
 | 
					        return vars.get(i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void aig_exporter::assert_pred_id(func_decl *decl, const expr_ref_vector& vars, expr_ref_vector& exprs) {
 | 
				
			||||||
 | 
					        unsigned id = 0;
 | 
				
			||||||
 | 
					        if (decl && !m_decl_id_map.find(decl, id)) {
 | 
				
			||||||
 | 
					            id = m_next_decl_id++;
 | 
				
			||||||
 | 
					            SASSERT(id < (1U << vars.size()));
 | 
				
			||||||
 | 
					            m_decl_id_map.insert(decl, id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < vars.size(); ++i) {
 | 
				
			||||||
 | 
					            exprs.push_back((id & (1U << i)) ? vars[i] : m.mk_not(vars[i]));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void aig_exporter::collect_var_substs(substitution& subst, const app *h,
 | 
				
			||||||
 | 
					        const expr_ref_vector& vars, expr_ref_vector& eqs) {
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < h->get_num_args(); ++i) {
 | 
				
			||||||
 | 
					            expr *arg = h->get_arg(i);
 | 
				
			||||||
 | 
					            expr *latchvar = get_latch_var(i, vars);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (is_var(arg)) {
 | 
				
			||||||
 | 
					                var *v = to_var(arg);
 | 
				
			||||||
 | 
					                expr_offset othervar;
 | 
				
			||||||
 | 
					                if (subst.find(v, 0, othervar)) {
 | 
				
			||||||
 | 
					                    eqs.push_back(m.mk_eq(latchvar, othervar.get_expr()));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    subst.insert(v, 0, expr_offset(latchvar, 0));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                eqs.push_back(m.mk_eq(latchvar, arg));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void aig_exporter::operator()(std::ostream& out) {
 | 
				
			||||||
 | 
					        expr_ref_vector transition_function(m), output_preds(m);
 | 
				
			||||||
 | 
					        var_ref_vector input_vars(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rule_counter& vc = m_rm.get_counter();
 | 
				
			||||||
 | 
					        expr_ref_vector exprs(m);
 | 
				
			||||||
 | 
					        substitution subst(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (rule_set::decl2rules::iterator I = m_rules.begin_grouped_rules(),
 | 
				
			||||||
 | 
					            E = m_rules.end_grouped_rules(); I != E; ++I) {
 | 
				
			||||||
 | 
					            for (rule_vector::iterator II = I->get_value()->begin(),
 | 
				
			||||||
 | 
					                EE = I->get_value()->end(); II != EE; ++II) {
 | 
				
			||||||
 | 
					                rule *r = *II;
 | 
				
			||||||
 | 
					                unsigned numqs = r->get_positive_tail_size();
 | 
				
			||||||
 | 
					                if (numqs > 1) {
 | 
				
			||||||
 | 
					                    std::cerr << "non-linear clauses not supported\n";
 | 
				
			||||||
 | 
					                    exit(-1);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (numqs != r->get_uninterpreted_tail_size()) {
 | 
				
			||||||
 | 
					                    std::cerr << "negation of queries not supported\n";
 | 
				
			||||||
 | 
					                    exit(-1);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                exprs.reset();
 | 
				
			||||||
 | 
					                assert_pred_id(numqs ? r->get_tail(0)->get_decl() : 0, m_ruleid_var_set, exprs);
 | 
				
			||||||
 | 
					                assert_pred_id(r->get_head()->get_decl(), m_ruleid_varp_set, exprs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                subst.reset();
 | 
				
			||||||
 | 
					                subst.reserve(1, vc.get_max_rule_var(*r)+1);
 | 
				
			||||||
 | 
					                if (numqs)
 | 
				
			||||||
 | 
					                    collect_var_substs(subst, r->get_tail(0), m_latch_vars, exprs);
 | 
				
			||||||
 | 
					                collect_var_substs(subst, r->get_head(), m_latch_varsp, exprs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (unsigned i = numqs; i < r->get_tail_size(); ++i) {
 | 
				
			||||||
 | 
					                    expr_ref e(m);
 | 
				
			||||||
 | 
					                    subst.apply(r->get_tail(i), e);
 | 
				
			||||||
 | 
					                    exprs.push_back(e);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                transition_function.push_back(m.mk_and(exprs.size(), exprs.c_ptr()));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // collect table facts
 | 
				
			||||||
 | 
					        if (m_facts) {
 | 
				
			||||||
 | 
					            for (fact_vector::const_iterator I = m_facts->begin(), E = m_facts->end(); I != E; ++I) {
 | 
				
			||||||
 | 
					                exprs.reset();
 | 
				
			||||||
 | 
					                assert_pred_id(0, m_ruleid_var_set, exprs);
 | 
				
			||||||
 | 
					                assert_pred_id(I->first, m_ruleid_varp_set, exprs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (unsigned i = 0; i < I->second.size(); ++i) {
 | 
				
			||||||
 | 
					                    exprs.push_back(m.mk_eq(get_latch_var(i, m_latch_varsp), I->second[i]));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                transition_function.push_back(m.mk_and(exprs.size(), exprs.c_ptr()));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expr *tr = m.mk_or(transition_function.size(), transition_function.c_ptr());
 | 
				
			||||||
 | 
					        aig_ref aig = m_aigm.mk_aig(tr);
 | 
				
			||||||
 | 
					        expr_ref aig_expr(m);
 | 
				
			||||||
 | 
					        m_aigm.to_formula(aig, aig_expr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					        std::cout << mk_pp(tr, m) << "\n\n";
 | 
				
			||||||
 | 
					        std::cout << mk_pp(aig_expr, m) << "\n\n";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // make rule_id vars latches
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < m_ruleid_var_set.size(); ++i) {
 | 
				
			||||||
 | 
					            m_latch_vars.push_back(m_ruleid_var_set.get(i));
 | 
				
			||||||
 | 
					            m_latch_varsp.push_back(m_ruleid_varp_set.get(i));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // create vars for latches
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < m_latch_vars.size(); ++i) {
 | 
				
			||||||
 | 
					            mk_var(m_latch_vars.get(i));
 | 
				
			||||||
 | 
					            mk_input_var(m_latch_varsp.get(i));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        unsigned tr_id = expr_to_aig(aig_expr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // create latch next state variables: (ite tr varp var)
 | 
				
			||||||
 | 
					        unsigned_vector latch_varp_ids;
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < m_latch_vars.size(); ++i) {
 | 
				
			||||||
 | 
					            unsigned in_val = mk_and(tr_id, get_var(m_latch_varsp.get(i)));
 | 
				
			||||||
 | 
					            unsigned latch_val = mk_and(neg(tr_id), get_var(m_latch_vars.get(i)));
 | 
				
			||||||
 | 
					            latch_varp_ids.push_back(mk_or(in_val, latch_val));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        m_latch_varsp.reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // create output variable (true iff an output predicate is derivable)
 | 
				
			||||||
 | 
					        unsigned output_id = 0;
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            expr_ref_vector output(m);
 | 
				
			||||||
 | 
					            const func_decl_set& preds = m_rules.get_output_predicates();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (func_decl_set::iterator I = preds.begin(), E = preds.end(); I != E; ++I) {
 | 
				
			||||||
 | 
					                exprs.reset();
 | 
				
			||||||
 | 
					                assert_pred_id(*I, m_ruleid_var_set, exprs);
 | 
				
			||||||
 | 
					                output.push_back(m.mk_and(exprs.size(), exprs.c_ptr()));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            expr *out = m.mk_or(output.size(), output.c_ptr());
 | 
				
			||||||
 | 
					            aig = m_aigm.mk_aig(out);
 | 
				
			||||||
 | 
					            m_aigm.to_formula(aig, aig_expr);
 | 
				
			||||||
 | 
					            output_id = expr_to_aig(aig_expr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					            std::cout << "output formula\n";
 | 
				
			||||||
 | 
					            std::cout << mk_pp(out, m) << "\n\n";
 | 
				
			||||||
 | 
					            std::cout << mk_pp(aig_expr, m) << "\n\n";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 1) print header
 | 
				
			||||||
 | 
					        // aag var_index inputs latches outputs andgates
 | 
				
			||||||
 | 
					        out << "aag " << (m_next_aig_expr_id-1)/2 << ' ' << m_input_vars.size()
 | 
				
			||||||
 | 
					            << ' ' << m_latch_vars.size() << " 1 " << m_num_and_gates << '\n';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 2) print inputs
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < m_input_vars.size(); ++i) {
 | 
				
			||||||
 | 
					            out << m_input_vars[i] << '\n';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // 3) print latches
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < m_latch_vars.size(); ++i) {
 | 
				
			||||||
 | 
					            out << get_var(m_latch_vars.get(i)) << ' ' << latch_varp_ids[i] << '\n';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 4) print outputs  (just one for now)
 | 
				
			||||||
 | 
					        out << output_id << '\n';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 5) print formula
 | 
				
			||||||
 | 
					        out << m_buffer.str();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned aig_exporter::expr_to_aig(const expr *e) {
 | 
				
			||||||
 | 
					        unsigned id;
 | 
				
			||||||
 | 
					        if (m_aig_expr_id_map.find(e, id))
 | 
				
			||||||
 | 
					            return id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (is_uninterp_const(e))
 | 
				
			||||||
 | 
					            return get_var(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (e->get_kind()) {
 | 
				
			||||||
 | 
					        case AST_APP: {
 | 
				
			||||||
 | 
					            const app *a = to_app(e);
 | 
				
			||||||
 | 
					            switch (a->get_decl_kind()) {
 | 
				
			||||||
 | 
					            case OP_OR:
 | 
				
			||||||
 | 
					                SASSERT(a->get_num_args() > 0);
 | 
				
			||||||
 | 
					                id = expr_to_aig(a->get_arg(0));
 | 
				
			||||||
 | 
					                for (unsigned i = 1; i < a->get_num_args(); ++i) {
 | 
				
			||||||
 | 
					                    id = mk_or(id, expr_to_aig(a->get_arg(i)));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                m_aig_expr_id_map.insert(e, id);
 | 
				
			||||||
 | 
					                return id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            case OP_NOT:
 | 
				
			||||||
 | 
					                return neg(expr_to_aig(a->get_arg(0)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            case OP_FALSE:
 | 
				
			||||||
 | 
					                return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            case OP_TRUE:
 | 
				
			||||||
 | 
					                return 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case AST_VAR:
 | 
				
			||||||
 | 
					            return get_var(e);
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            UNREACHABLE();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        UNREACHABLE();
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned aig_exporter::neg(unsigned id) const {
 | 
				
			||||||
 | 
					        return (id % 2) ? (id-1) : (id+1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned aig_exporter::mk_and(unsigned id1, unsigned id2) {
 | 
				
			||||||
 | 
					        if (id1 > id2)
 | 
				
			||||||
 | 
					            std::swap(id1, id2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::pair<unsigned,unsigned> key(id1, id2);
 | 
				
			||||||
 | 
					        and_gates_map::const_iterator I = m_and_gates_map.find(key);
 | 
				
			||||||
 | 
					        if (I != m_and_gates_map.end())
 | 
				
			||||||
 | 
					            return I->second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        unsigned id = mk_expr_id();
 | 
				
			||||||
 | 
					        m_buffer << id << ' ' << id1 << ' ' << id2 << '\n';
 | 
				
			||||||
 | 
					        m_and_gates_map[key] = id;
 | 
				
			||||||
 | 
					        ++m_num_and_gates;
 | 
				
			||||||
 | 
					        return id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned aig_exporter::mk_or(unsigned id1, unsigned id2) {
 | 
				
			||||||
 | 
					        return neg(mk_and(neg(id1), neg(id2)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned aig_exporter::get_var(const expr *e) {
 | 
				
			||||||
 | 
					        unsigned id;
 | 
				
			||||||
 | 
					        if (m_aig_expr_id_map.find(e, id))
 | 
				
			||||||
 | 
					            return id;
 | 
				
			||||||
 | 
					        return mk_input_var(e);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned aig_exporter::mk_var(const expr *e) {
 | 
				
			||||||
 | 
					        SASSERT(!m_aig_expr_id_map.contains(e));
 | 
				
			||||||
 | 
					        unsigned id = mk_expr_id();
 | 
				
			||||||
 | 
					        m_aig_expr_id_map.insert(e, id);
 | 
				
			||||||
 | 
					        return id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    unsigned aig_exporter::mk_input_var(const expr *e) {
 | 
				
			||||||
 | 
					        SASSERT(!m_aig_expr_id_map.contains(e));
 | 
				
			||||||
 | 
					        unsigned id = mk_expr_id();
 | 
				
			||||||
 | 
					        m_input_vars.push_back(id);
 | 
				
			||||||
 | 
					        if (e)
 | 
				
			||||||
 | 
					            m_aig_expr_id_map.insert(e, id);
 | 
				
			||||||
 | 
					        return id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned aig_exporter::mk_expr_id() {
 | 
				
			||||||
 | 
					        unsigned id = m_next_aig_expr_id;
 | 
				
			||||||
 | 
					        m_next_aig_expr_id += 2;
 | 
				
			||||||
 | 
					        return id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										68
									
								
								src/muz_qe/aig_exporter.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										68
									
								
								src/muz_qe/aig_exporter.h
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
					@ -0,0 +1,68 @@
 | 
				
			||||||
 | 
					/*++
 | 
				
			||||||
 | 
					Copyright (c) 2013 Microsoft Corporation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Module Name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aig_exporter.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Abstract:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Export AIG files from horn clauses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _AIG_EXPORTER_H_
 | 
				
			||||||
 | 
					#define _AIG_EXPORTER_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "aig.h"
 | 
				
			||||||
 | 
					#include "dl_rule_set.h"
 | 
				
			||||||
 | 
					#include "rel_context.h"
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					    class aig_exporter {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        aig_exporter(const rule_set& rules, context& ctx, const fact_vector *facts = 0);
 | 
				
			||||||
 | 
					        void operator()(std::ostream& out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        typedef obj_map<func_decl, unsigned> decl_id_map;
 | 
				
			||||||
 | 
					        typedef obj_map<const expr, unsigned> aig_expr_id_map;
 | 
				
			||||||
 | 
					        typedef std::map<std::pair<unsigned,unsigned>, unsigned> and_gates_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const rule_set&    m_rules;
 | 
				
			||||||
 | 
					        const fact_vector *m_facts;
 | 
				
			||||||
 | 
					        ast_manager&       m;
 | 
				
			||||||
 | 
					        rule_manager&      m_rm;
 | 
				
			||||||
 | 
					        aig_manager        m_aigm;
 | 
				
			||||||
 | 
					        decl_id_map        m_decl_id_map;
 | 
				
			||||||
 | 
					        unsigned           m_next_decl_id;
 | 
				
			||||||
 | 
					        aig_expr_id_map    m_aig_expr_id_map;
 | 
				
			||||||
 | 
					        unsigned           m_next_aig_expr_id;
 | 
				
			||||||
 | 
					        and_gates_map      m_and_gates_map;
 | 
				
			||||||
 | 
					        unsigned           m_num_and_gates;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expr_ref_vector m_latch_vars, m_latch_varsp;
 | 
				
			||||||
 | 
					        expr_ref_vector m_ruleid_var_set, m_ruleid_varp_set;
 | 
				
			||||||
 | 
					        unsigned_vector m_input_vars;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::stringstream m_buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void mk_latch_vars(unsigned n);
 | 
				
			||||||
 | 
					        expr* get_latch_var(unsigned i, const expr_ref_vector& vars);
 | 
				
			||||||
 | 
					        void assert_pred_id(func_decl *decl, const expr_ref_vector& vars, expr_ref_vector& exprs);
 | 
				
			||||||
 | 
					        void collect_var_substs(substitution& subst, const app *h,
 | 
				
			||||||
 | 
					            const expr_ref_vector& vars, expr_ref_vector& eqs);
 | 
				
			||||||
 | 
					        unsigned expr_to_aig(const expr *e);
 | 
				
			||||||
 | 
					        unsigned neg(unsigned id) const;
 | 
				
			||||||
 | 
					        unsigned mk_and(unsigned id1, unsigned id2);
 | 
				
			||||||
 | 
					        unsigned mk_or(unsigned id1, unsigned id2);
 | 
				
			||||||
 | 
					        unsigned get_var(const expr *e);
 | 
				
			||||||
 | 
					        unsigned mk_var(const expr *e);
 | 
				
			||||||
 | 
					        unsigned mk_input_var(const expr *e = 0);
 | 
				
			||||||
 | 
					        unsigned mk_expr_id();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										235
									
								
								src/muz_qe/clp_context.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								src/muz_qe/clp_context.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,235 @@
 | 
				
			||||||
 | 
					/*++
 | 
				
			||||||
 | 
					Copyright (c) 2013 Microsoft Corporation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Module Name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    clp_context.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Abstract:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Bounded CLP (symbolic simulation using Z3) context.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Author:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Nikolaj Bjorner (nbjorner) 2013-04-26
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Revision History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "clp_context.h"
 | 
				
			||||||
 | 
					#include "dl_context.h"
 | 
				
			||||||
 | 
					#include "unifier.h"
 | 
				
			||||||
 | 
					#include "var_subst.h"
 | 
				
			||||||
 | 
					#include "substitution.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class clp::imp {
 | 
				
			||||||
 | 
					        struct stats {
 | 
				
			||||||
 | 
					            stats() { reset(); }
 | 
				
			||||||
 | 
					            void reset() { memset(this, 0, sizeof(*this)); }
 | 
				
			||||||
 | 
					            unsigned m_num_unfold;
 | 
				
			||||||
 | 
					            unsigned m_num_no_unfold;
 | 
				
			||||||
 | 
					            unsigned m_num_subsumed;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        context&               m_ctx;
 | 
				
			||||||
 | 
					        ast_manager&           m;
 | 
				
			||||||
 | 
					        rule_manager&          rm;
 | 
				
			||||||
 | 
					        smt_params             m_fparams;
 | 
				
			||||||
 | 
					        smt::kernel            m_solver;
 | 
				
			||||||
 | 
					        var_subst              m_var_subst;
 | 
				
			||||||
 | 
					        expr_ref_vector        m_ground;
 | 
				
			||||||
 | 
					        app_ref_vector         m_goals;
 | 
				
			||||||
 | 
					        volatile bool          m_cancel;
 | 
				
			||||||
 | 
					        stats                  m_stats;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        imp(context& ctx):
 | 
				
			||||||
 | 
					            m_ctx(ctx), 
 | 
				
			||||||
 | 
					            m(ctx.get_manager()),
 | 
				
			||||||
 | 
					            rm(ctx.get_rule_manager()),
 | 
				
			||||||
 | 
					            m_solver(m, m_fparams),      // TBD: can be replaced by efficient BV solver.
 | 
				
			||||||
 | 
					            m_var_subst(m, false),
 | 
				
			||||||
 | 
					            m_ground(m),
 | 
				
			||||||
 | 
					            m_goals(m),
 | 
				
			||||||
 | 
					            m_cancel(false)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // m_fparams.m_relevancy_lvl = 0;
 | 
				
			||||||
 | 
					            m_fparams.m_mbqi = false;
 | 
				
			||||||
 | 
					            m_fparams.m_soft_timeout = 1000;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ~imp() {}        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lbool query(expr* query) {
 | 
				
			||||||
 | 
					            m_ctx.ensure_opened();
 | 
				
			||||||
 | 
					            m_solver.reset();
 | 
				
			||||||
 | 
					            m_goals.reset();
 | 
				
			||||||
 | 
					            rm.mk_query(query, m_ctx.get_rules());
 | 
				
			||||||
 | 
					            m_ctx.apply_default_transformation();
 | 
				
			||||||
 | 
					            func_decl *head_decl = m_ctx.get_rules().get_output_predicate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            expr_ref head(m_ctx.get_rules().get_predicate_rules(head_decl)[0]->get_head(), m);
 | 
				
			||||||
 | 
					            ground(head);
 | 
				
			||||||
 | 
					            m_goals.push_back(to_app(head));
 | 
				
			||||||
 | 
					            return search(20, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        void cancel() {
 | 
				
			||||||
 | 
					            m_cancel = true;
 | 
				
			||||||
 | 
					            m_solver.cancel();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        void cleanup() {
 | 
				
			||||||
 | 
					            m_cancel = false;
 | 
				
			||||||
 | 
					            m_goals.reset();
 | 
				
			||||||
 | 
					            m_solver.reset_cancel();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void reset_statistics() {
 | 
				
			||||||
 | 
					            m_stats.reset();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void collect_statistics(statistics& st) const {
 | 
				
			||||||
 | 
					            //st.update("tab.num_unfold", m_stats.m_num_unfold);
 | 
				
			||||||
 | 
					            //st.update("tab.num_unfold_fail", m_stats.m_num_no_unfold);
 | 
				
			||||||
 | 
					            //st.update("tab.num_subsumed", m_stats.m_num_subsumed);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void display_certificate(std::ostream& out) const {
 | 
				
			||||||
 | 
					            expr_ref ans = get_answer();
 | 
				
			||||||
 | 
					            out << mk_pp(ans, m) << "\n";    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expr_ref get_answer() const {
 | 
				
			||||||
 | 
					            return expr_ref(m.mk_true(), m);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void reset_ground() {
 | 
				
			||||||
 | 
					            m_ground.reset();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        void ground(expr_ref& e) {
 | 
				
			||||||
 | 
					            ptr_vector<sort> sorts;
 | 
				
			||||||
 | 
					            get_free_vars(e, sorts);
 | 
				
			||||||
 | 
					            if (m_ground.size() < sorts.size()) {
 | 
				
			||||||
 | 
					                m_ground.resize(sorts.size());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            for (unsigned i = 0; i < sorts.size(); ++i) {
 | 
				
			||||||
 | 
					                if (sorts[i] && !m_ground[i].get()) {
 | 
				
			||||||
 | 
					                    m_ground[i] = m.mk_fresh_const("c",sorts[i]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            m_var_subst(e, m_ground.size(), m_ground.c_ptr(), e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static bool rule_sort_fn(const rule *r1, const rule *r2) {
 | 
				
			||||||
 | 
					            return r1->get_uninterpreted_tail_size() < r2->get_uninterpreted_tail_size();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lbool search(unsigned depth, unsigned index) {
 | 
				
			||||||
 | 
					            if (index == m_goals.size()) {
 | 
				
			||||||
 | 
					                return l_true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (depth == 0) {
 | 
				
			||||||
 | 
					                return l_undef;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            IF_VERBOSE(1, verbose_stream() << "search " << depth << " " << index << "\n";);
 | 
				
			||||||
 | 
					            unsigned num_goals = m_goals.size();
 | 
				
			||||||
 | 
					            app* head = m_goals[index].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            rule_vector rules(m_ctx.get_rules().get_predicate_rules(head->get_decl()));
 | 
				
			||||||
 | 
					            std::stable_sort(rules.begin(), rules.end(), rule_sort_fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            lbool status = l_false;
 | 
				
			||||||
 | 
					            for (unsigned i = 0; i < rules.size(); ++i) {
 | 
				
			||||||
 | 
					                rule* r = rules[i];
 | 
				
			||||||
 | 
					                m_solver.push();
 | 
				
			||||||
 | 
					                reset_ground();
 | 
				
			||||||
 | 
					                expr_ref tmp(m);
 | 
				
			||||||
 | 
					                tmp = r->get_head();
 | 
				
			||||||
 | 
					                IF_VERBOSE(2, verbose_stream() << index << " " << mk_pp(tmp, m) << "\n";);
 | 
				
			||||||
 | 
					                ground(tmp);
 | 
				
			||||||
 | 
					                for (unsigned j = 0; j < head->get_num_args(); ++j) {
 | 
				
			||||||
 | 
					                    expr_ref eq(m);
 | 
				
			||||||
 | 
					                    eq = m.mk_eq(head->get_arg(j), to_app(tmp)->get_arg(j));
 | 
				
			||||||
 | 
					                    m_solver.assert_expr(eq);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                for (unsigned j = r->get_uninterpreted_tail_size(); j < r->get_tail_size(); ++j) {
 | 
				
			||||||
 | 
					                    tmp = r->get_tail(j);
 | 
				
			||||||
 | 
					                    ground(tmp);
 | 
				
			||||||
 | 
					                    m_solver.assert_expr(tmp);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                lbool is_sat = m_solver.check();
 | 
				
			||||||
 | 
					                switch (is_sat) {
 | 
				
			||||||
 | 
					                case l_false:
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case l_true:
 | 
				
			||||||
 | 
					                    if (depth == 1 && (index+1 > m_goals.size() || r->get_uninterpreted_tail_size() > 0)) {
 | 
				
			||||||
 | 
					                        status = l_undef;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    for (unsigned j = 0; j < r->get_uninterpreted_tail_size(); ++j) {
 | 
				
			||||||
 | 
					                        tmp = r->get_tail(j);
 | 
				
			||||||
 | 
					                        ground(tmp);
 | 
				
			||||||
 | 
					                        m_goals.push_back(to_app(tmp));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    switch(search(depth-1, index+1)) {
 | 
				
			||||||
 | 
					                    case l_undef:
 | 
				
			||||||
 | 
					                        status = l_undef;
 | 
				
			||||||
 | 
					                        // fallthrough
 | 
				
			||||||
 | 
					                    case l_false:
 | 
				
			||||||
 | 
					                        m_goals.resize(num_goals);   
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case l_true:
 | 
				
			||||||
 | 
					                        return l_true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case l_undef:
 | 
				
			||||||
 | 
					                    status = l_undef;
 | 
				
			||||||
 | 
					                    throw default_exception("undef");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                m_solver.pop(1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return status;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        proof_ref get_proof() const {
 | 
				
			||||||
 | 
					            return proof_ref(0, m);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    clp::clp(context& ctx):
 | 
				
			||||||
 | 
					        m_imp(alloc(imp, ctx)) {        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    clp::~clp() {
 | 
				
			||||||
 | 
					        dealloc(m_imp);
 | 
				
			||||||
 | 
					    }    
 | 
				
			||||||
 | 
					    lbool clp::query(expr* query) {
 | 
				
			||||||
 | 
					        return m_imp->query(query);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void clp::cancel() {
 | 
				
			||||||
 | 
					        m_imp->cancel();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void clp::cleanup() {
 | 
				
			||||||
 | 
					        m_imp->cleanup();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void clp::reset_statistics() {
 | 
				
			||||||
 | 
					        m_imp->reset_statistics();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void clp::collect_statistics(statistics& st) const {
 | 
				
			||||||
 | 
					        m_imp->collect_statistics(st);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void clp::display_certificate(std::ostream& out) const {
 | 
				
			||||||
 | 
					        m_imp->display_certificate(out);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    expr_ref clp::get_answer() {
 | 
				
			||||||
 | 
					        return m_imp->get_answer();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										45
									
								
								src/muz_qe/clp_context.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/muz_qe/clp_context.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,45 @@
 | 
				
			||||||
 | 
					/*++
 | 
				
			||||||
 | 
					Copyright (c) 2013 Microsoft Corporation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Module Name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    clp_context.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Abstract:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Bounded CLP (symbolic simulation using Z3) context.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Author:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Nikolaj Bjorner (nbjorner) 2013-04-26
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Revision History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--*/
 | 
				
			||||||
 | 
					#ifndef _CLP_CONTEXT_H_
 | 
				
			||||||
 | 
					#define _CLP_CONTEXT_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ast.h"
 | 
				
			||||||
 | 
					#include "lbool.h"
 | 
				
			||||||
 | 
					#include "statistics.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					    class context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class clp {
 | 
				
			||||||
 | 
					        class imp;
 | 
				
			||||||
 | 
					        imp* m_imp;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        clp(context& ctx);
 | 
				
			||||||
 | 
					        ~clp();
 | 
				
			||||||
 | 
					        lbool query(expr* query);
 | 
				
			||||||
 | 
					        void cancel();
 | 
				
			||||||
 | 
					        void cleanup();
 | 
				
			||||||
 | 
					        void reset_statistics();
 | 
				
			||||||
 | 
					        void collect_statistics(statistics& st) const;
 | 
				
			||||||
 | 
					        void display_certificate(std::ostream& out) const;        
 | 
				
			||||||
 | 
					        expr_ref get_answer();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,8 @@ namespace datalog {
 | 
				
			||||||
    ast_manager & get_ast_manager_from_rel_manager(const relation_manager & rm);
 | 
					    ast_manager & get_ast_manager_from_rel_manager(const relation_manager & rm);
 | 
				
			||||||
    context & get_context_from_rel_manager(const relation_manager & rm);
 | 
					    context & get_context_from_rel_manager(const relation_manager & rm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    typedef func_decl_set decl_set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if DL_LEAK_HUNTING
 | 
					#if DL_LEAK_HUNTING
 | 
				
			||||||
    void leak_guard_check(const symbol & s);
 | 
					    void leak_guard_check(const symbol & s);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -329,6 +331,10 @@ namespace datalog {
 | 
				
			||||||
            virtual mutator_fn * mk_filter_interpreted_fn(const base_object & t, app * condition)
 | 
					            virtual mutator_fn * mk_filter_interpreted_fn(const base_object & t, app * condition)
 | 
				
			||||||
            { return 0; }
 | 
					            { return 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual transformer_fn * mk_filter_interpreted_and_project_fn(const base_object & t,
 | 
				
			||||||
 | 
					                app * condition, unsigned removed_col_cnt, const unsigned * removed_cols)
 | 
				
			||||||
 | 
					            { return 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual transformer_fn * mk_select_equal_and_project_fn(const base_object & t, 
 | 
					            virtual transformer_fn * mk_select_equal_and_project_fn(const base_object & t, 
 | 
				
			||||||
                    const element & value, unsigned col) { return 0; }
 | 
					                    const element & value, unsigned col) { return 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -452,8 +458,8 @@ namespace datalog {
 | 
				
			||||||
        class convenient_join_fn : public join_fn {
 | 
					        class convenient_join_fn : public join_fn {
 | 
				
			||||||
            signature m_result_sig;
 | 
					            signature m_result_sig;
 | 
				
			||||||
        protected:
 | 
					        protected:
 | 
				
			||||||
            const unsigned_vector m_cols1;
 | 
					            unsigned_vector m_cols1;
 | 
				
			||||||
            const unsigned_vector m_cols2;
 | 
					            unsigned_vector m_cols2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            convenient_join_fn(const signature & o1_sig, const signature & o2_sig, unsigned col_cnt,
 | 
					            convenient_join_fn(const signature & o1_sig, const signature & o2_sig, unsigned col_cnt,
 | 
				
			||||||
                const unsigned * cols1, const unsigned * cols2) 
 | 
					                const unsigned * cols1, const unsigned * cols2) 
 | 
				
			||||||
| 
						 | 
					@ -468,8 +474,8 @@ namespace datalog {
 | 
				
			||||||
        class convenient_join_project_fn : public join_fn {
 | 
					        class convenient_join_project_fn : public join_fn {
 | 
				
			||||||
            signature m_result_sig;
 | 
					            signature m_result_sig;
 | 
				
			||||||
        protected:
 | 
					        protected:
 | 
				
			||||||
            const unsigned_vector m_cols1;
 | 
					            unsigned_vector m_cols1;
 | 
				
			||||||
            const unsigned_vector m_cols2;
 | 
					            unsigned_vector m_cols2;
 | 
				
			||||||
            //it is non-const because it needs to be modified in sparse_table version of the join_project operator
 | 
					            //it is non-const because it needs to be modified in sparse_table version of the join_project operator
 | 
				
			||||||
            unsigned_vector m_removed_cols;
 | 
					            unsigned_vector m_removed_cols;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -496,7 +502,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class convenient_project_fn : public convenient_transformer_fn {
 | 
					        class convenient_project_fn : public convenient_transformer_fn {
 | 
				
			||||||
        protected:
 | 
					        protected:
 | 
				
			||||||
            const unsigned_vector m_removed_cols;
 | 
					            unsigned_vector m_removed_cols;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            convenient_project_fn(const signature & orig_sig, unsigned col_cnt, const unsigned * removed_cols) 
 | 
					            convenient_project_fn(const signature & orig_sig, unsigned col_cnt, const unsigned * removed_cols) 
 | 
				
			||||||
                    : m_removed_cols(col_cnt, removed_cols) {
 | 
					                    : m_removed_cols(col_cnt, removed_cols) {
 | 
				
			||||||
| 
						 | 
					@ -654,6 +660,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef sort * relation_sort;
 | 
					    typedef sort * relation_sort;
 | 
				
			||||||
    typedef ptr_vector<sort> relation_signature_base0;
 | 
					    typedef ptr_vector<sort> relation_signature_base0;
 | 
				
			||||||
 | 
					    typedef ptr_hash<sort> relation_sort_hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef app * relation_element;
 | 
					    typedef app * relation_element;
 | 
				
			||||||
    typedef app_ref relation_element_ref;
 | 
					    typedef app_ref relation_element_ref;
 | 
				
			||||||
| 
						 | 
					@ -737,8 +744,8 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct hash {
 | 
					        struct hash {
 | 
				
			||||||
            unsigned operator()(relation_signature const& s) const { 
 | 
					            unsigned operator()(relation_signature const& s) const { 
 | 
				
			||||||
                relation_sort const* sorts = s.c_ptr();
 | 
					                return obj_vector_hash<relation_signature>(s);
 | 
				
			||||||
                return string_hash(reinterpret_cast<char const*>(sorts), sizeof(*sorts)*s.size(), 12); }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct eq {
 | 
					        struct eq {
 | 
				
			||||||
| 
						 | 
					@ -814,9 +821,11 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef uint64 table_sort;
 | 
					    typedef uint64 table_sort;
 | 
				
			||||||
    typedef svector<table_sort> table_signature_base0;
 | 
					    typedef svector<table_sort> table_signature_base0;
 | 
				
			||||||
 | 
					    typedef uint64_hash table_sort_hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef uint64 table_element;
 | 
					    typedef uint64 table_element;
 | 
				
			||||||
    typedef svector<table_element> table_fact;
 | 
					    typedef svector<table_element> table_fact;
 | 
				
			||||||
 | 
					    typedef uint64_hash table_element_hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct table_traits {
 | 
					    struct table_traits {
 | 
				
			||||||
        typedef table_plugin plugin;
 | 
					        typedef table_plugin plugin;
 | 
				
			||||||
| 
						 | 
					@ -879,8 +888,8 @@ namespace datalog {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        struct hash {
 | 
					        struct hash {
 | 
				
			||||||
            unsigned operator()(table_signature const& s) const { 
 | 
					            unsigned operator()(table_signature const& s) const { 
 | 
				
			||||||
                table_sort const* sorts = s.c_ptr();
 | 
					                return svector_hash<table_sort_hash>()(s);
 | 
				
			||||||
                return string_hash(reinterpret_cast<char const*>(sorts), sizeof(*sorts)*s.size(), 12); }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct eq {
 | 
					        struct eq {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,6 @@ namespace datalog {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        qlinear(bmc& b): b(b), m(b.m), m_bv(m), m_bit_width(1) {}
 | 
					        qlinear(bmc& b): b(b), m(b.m), m_bv(m), m_bit_width(1) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        lbool check() {
 | 
					        lbool check() {
 | 
				
			||||||
            setup();
 | 
					            setup();
 | 
				
			||||||
            m_bit_width = 4;
 | 
					            m_bit_width = 4;
 | 
				
			||||||
| 
						 | 
					@ -298,6 +297,7 @@ namespace datalog {
 | 
				
			||||||
                r->to_formula(fml);
 | 
					                r->to_formula(fml);
 | 
				
			||||||
                r2 = r;
 | 
					                r2 = r;
 | 
				
			||||||
                rm.substitute(r2, sub.size(), sub.c_ptr());
 | 
					                rm.substitute(r2, sub.size(), sub.c_ptr());
 | 
				
			||||||
 | 
					                proof_ref p(m);
 | 
				
			||||||
                if (r0) {
 | 
					                if (r0) {
 | 
				
			||||||
                    VERIFY(unifier.unify_rules(*r0.get(), 0, *r2.get()));
 | 
					                    VERIFY(unifier.unify_rules(*r0.get(), 0, *r2.get()));
 | 
				
			||||||
                    expr_ref_vector sub1 = unifier.get_rule_subst(*r0.get(), true);
 | 
					                    expr_ref_vector sub1 = unifier.get_rule_subst(*r0.get(), true);
 | 
				
			||||||
| 
						 | 
					@ -307,7 +307,10 @@ namespace datalog {
 | 
				
			||||||
                    r1->to_formula(concl);
 | 
					                    r1->to_formula(concl);
 | 
				
			||||||
                    scoped_proof _sp(m);
 | 
					                    scoped_proof _sp(m);
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    proof* p = r->get_proof();
 | 
					                    p = r->get_proof();
 | 
				
			||||||
 | 
					                    if (!p) {
 | 
				
			||||||
 | 
					                        p = m.mk_asserted(fml);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    proof* premises[2] = { pr, p };
 | 
					                    proof* premises[2] = { pr, p };
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    positions.push_back(std::make_pair(0, 1));
 | 
					                    positions.push_back(std::make_pair(0, 1));
 | 
				
			||||||
| 
						 | 
					@ -320,13 +323,17 @@ namespace datalog {
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    r2->to_formula(concl);
 | 
					                    r2->to_formula(concl);
 | 
				
			||||||
                    scoped_proof _sp(m);
 | 
					                    scoped_proof _sp(m);
 | 
				
			||||||
                    proof* p = r->get_proof();
 | 
					                    p = r->get_proof();
 | 
				
			||||||
 | 
					                    if (!p) {
 | 
				
			||||||
 | 
					                        p = m.mk_asserted(fml);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    if (sub.empty()) {
 | 
					                    if (sub.empty()) {
 | 
				
			||||||
                        pr = p;
 | 
					                        pr = p;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else {
 | 
					                    else {
 | 
				
			||||||
                        substs.push_back(sub);
 | 
					                        substs.push_back(sub);
 | 
				
			||||||
                        pr = m.mk_hyper_resolve(1, &p, concl, positions, substs);
 | 
					                        proof* ps[1] = { p };
 | 
				
			||||||
 | 
					                        pr = m.mk_hyper_resolve(1, ps, concl, positions, substs);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    r0 = r2;
 | 
					                    r0 = r2;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -1005,7 +1012,6 @@ namespace datalog {
 | 
				
			||||||
                    symbol is_name(_name.str().c_str());
 | 
					                    symbol is_name(_name.str().c_str());
 | 
				
			||||||
                    std::stringstream _name2;
 | 
					                    std::stringstream _name2;
 | 
				
			||||||
                    _name2 << "get_succ#" << i;
 | 
					                    _name2 << "get_succ#" << i;
 | 
				
			||||||
                    symbol acc_name(_name2.str().c_str());
 | 
					 | 
				
			||||||
                    ptr_vector<accessor_decl> accs;
 | 
					                    ptr_vector<accessor_decl> accs;
 | 
				
			||||||
                    type_ref tr(0);
 | 
					                    type_ref tr(0);
 | 
				
			||||||
                    accs.push_back(mk_accessor_decl(name, tr));
 | 
					                    accs.push_back(mk_accessor_decl(name, tr));
 | 
				
			||||||
| 
						 | 
					@ -1213,6 +1219,15 @@ namespace datalog {
 | 
				
			||||||
                r->to_formula(fml);
 | 
					                r->to_formula(fml);
 | 
				
			||||||
                r2 = r;
 | 
					                r2 = r;
 | 
				
			||||||
                rm.substitute(r2, sub.size(), sub.c_ptr());
 | 
					                rm.substitute(r2, sub.size(), sub.c_ptr());
 | 
				
			||||||
 | 
					                proof_ref p(m);
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    scoped_proof _sp(m);
 | 
				
			||||||
 | 
					                    p = r->get_proof();
 | 
				
			||||||
 | 
					                    if (!p) {
 | 
				
			||||||
 | 
					                        p = m.mk_asserted(fml);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (r0) {
 | 
					                if (r0) {
 | 
				
			||||||
                    VERIFY(unifier.unify_rules(*r0.get(), 0, *r2.get()));
 | 
					                    VERIFY(unifier.unify_rules(*r0.get(), 0, *r2.get()));
 | 
				
			||||||
                    expr_ref_vector sub1 = unifier.get_rule_subst(*r0.get(), true);
 | 
					                    expr_ref_vector sub1 = unifier.get_rule_subst(*r0.get(), true);
 | 
				
			||||||
| 
						 | 
					@ -1220,9 +1235,8 @@ namespace datalog {
 | 
				
			||||||
                    apply_subst(sub, sub2);
 | 
					                    apply_subst(sub, sub2);
 | 
				
			||||||
                    unifier.apply(*r0.get(), 0, *r2.get(), r1);
 | 
					                    unifier.apply(*r0.get(), 0, *r2.get(), r1);
 | 
				
			||||||
                    r1->to_formula(concl);
 | 
					                    r1->to_formula(concl);
 | 
				
			||||||
                    scoped_proof _sp(m);
 | 
					 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    proof* p = r->get_proof();
 | 
					                    scoped_proof _sp(m);
 | 
				
			||||||
                    proof* premises[2] = { pr, p };
 | 
					                    proof* premises[2] = { pr, p };
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    positions.push_back(std::make_pair(0, 1));
 | 
					                    positions.push_back(std::make_pair(0, 1));
 | 
				
			||||||
| 
						 | 
					@ -1235,13 +1249,13 @@ namespace datalog {
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    r2->to_formula(concl);
 | 
					                    r2->to_formula(concl);
 | 
				
			||||||
                    scoped_proof _sp(m);
 | 
					                    scoped_proof _sp(m);
 | 
				
			||||||
                    proof* p = r->get_proof();
 | 
					 | 
				
			||||||
                    if (sub.empty()) {
 | 
					                    if (sub.empty()) {
 | 
				
			||||||
                        pr = p;
 | 
					                        pr = p;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else {
 | 
					                    else {
 | 
				
			||||||
                        substs.push_back(sub);
 | 
					                        substs.push_back(sub);
 | 
				
			||||||
                        pr = m.mk_hyper_resolve(1, &p, concl, positions, substs);
 | 
					                        proof * ps[1] = { p };
 | 
				
			||||||
 | 
					                        pr = m.mk_hyper_resolve(1, ps, concl, positions, substs);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    r0 = r2;
 | 
					                    r0 = r2;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -1416,19 +1430,12 @@ namespace datalog {
 | 
				
			||||||
    lbool bmc::query(expr* query) {
 | 
					    lbool bmc::query(expr* query) {
 | 
				
			||||||
        m_solver.reset();
 | 
					        m_solver.reset();
 | 
				
			||||||
        m_answer = 0;
 | 
					        m_answer = 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        m_ctx.ensure_opened();
 | 
					        m_ctx.ensure_opened();
 | 
				
			||||||
        m_rules.reset();
 | 
					        m_rules.reset();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        datalog::rule_manager& rule_manager = m_ctx.get_rule_manager();
 | 
					        datalog::rule_manager& rule_manager = m_ctx.get_rule_manager();
 | 
				
			||||||
        datalog::rule_set        old_rules(m_ctx.get_rules());
 | 
					        datalog::rule_set old_rules(m_ctx.get_rules());
 | 
				
			||||||
        datalog::rule_ref_vector query_rules(rule_manager);
 | 
					        rule_manager.mk_query(query, m_ctx.get_rules());
 | 
				
			||||||
        datalog::rule_ref        query_rule(rule_manager);
 | 
					        expr_ref bg_assertion = m_ctx.get_background_assertion();        
 | 
				
			||||||
        rule_manager.mk_query(query, m_query_pred, query_rules, query_rule);
 | 
					 | 
				
			||||||
        m_ctx.add_rules(query_rules);
 | 
					 | 
				
			||||||
        expr_ref bg_assertion = m_ctx.get_background_assertion();
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        m_ctx.set_output_predicate(m_query_pred);
 | 
					 | 
				
			||||||
        m_ctx.apply_default_transformation();
 | 
					        m_ctx.apply_default_transformation();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (m_ctx.get_params().slice()) {
 | 
					        if (m_ctx.get_params().slice()) {
 | 
				
			||||||
| 
						 | 
					@ -1436,10 +1443,9 @@ namespace datalog {
 | 
				
			||||||
            datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx);
 | 
					            datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx);
 | 
				
			||||||
            transformer.register_plugin(slice);
 | 
					            transformer.register_plugin(slice);
 | 
				
			||||||
            m_ctx.transform_rules(transformer);
 | 
					            m_ctx.transform_rules(transformer);
 | 
				
			||||||
            m_query_pred = slice->get_predicate(m_query_pred.get());
 | 
					 | 
				
			||||||
            m_ctx.set_output_predicate(m_query_pred);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        m_rules.add_rules(m_ctx.get_rules());
 | 
					        m_query_pred = m_ctx.get_rules().get_output_predicate();
 | 
				
			||||||
 | 
					        m_rules.replace_rules(m_ctx.get_rules());
 | 
				
			||||||
        m_rules.close();
 | 
					        m_rules.close();
 | 
				
			||||||
        m_ctx.reopen();
 | 
					        m_ctx.reopen();
 | 
				
			||||||
        m_ctx.replace_rules(old_rules);
 | 
					        m_ctx.replace_rules(old_rules);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,6 +82,34 @@ namespace datalog {
 | 
				
			||||||
        return alloc(join_fn, *this, t1, t2, col_cnt, cols1, cols2);    
 | 
					        return alloc(join_fn, *this, t1, t2, col_cnt, cols1, cols2);    
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class check_table_plugin::join_project_fn : public table_join_fn {
 | 
				
			||||||
 | 
					        scoped_ptr<table_join_fn> m_tocheck;
 | 
				
			||||||
 | 
					        scoped_ptr<table_join_fn> m_checker;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        join_project_fn(check_table_plugin& p, const table_base & t1, const table_base & t2,
 | 
				
			||||||
 | 
					                        unsigned col_cnt, const unsigned * cols1, const unsigned * cols2,
 | 
				
			||||||
 | 
					                        unsigned removed_col_cnt, const unsigned * removed_cols) {
 | 
				
			||||||
 | 
					            m_tocheck = p.get_manager().mk_join_project_fn(tocheck(t1), tocheck(t2), col_cnt, cols1, cols2, removed_col_cnt, removed_cols);
 | 
				
			||||||
 | 
					            m_checker = p.get_manager().mk_join_project_fn(checker(t1), checker(t2), col_cnt, cols1, cols2, removed_col_cnt, removed_cols);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual table_base* operator()(const table_base & t1, const table_base & t2) {
 | 
				
			||||||
 | 
					            table_base* ttocheck = (*m_tocheck)(tocheck(t1), tocheck(t2));
 | 
				
			||||||
 | 
					            table_base* tchecker = (*m_checker)(checker(t1), checker(t2));
 | 
				
			||||||
 | 
					            check_table* result = alloc(check_table, get(t1).get_plugin(), ttocheck->get_signature(), ttocheck, tchecker);
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    table_join_fn * check_table_plugin::mk_join_project_fn(const table_base & t1, const table_base & t2,
 | 
				
			||||||
 | 
					            unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, 
 | 
				
			||||||
 | 
					            const unsigned * removed_cols) {
 | 
				
			||||||
 | 
					        if (!check_kind(t1) || !check_kind(t2)) {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return alloc(join_project_fn, *this, t1, t2, col_cnt, cols1, cols2, removed_col_cnt, removed_cols);    
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class check_table_plugin::union_fn : public table_union_fn {
 | 
					    class check_table_plugin::union_fn : public table_union_fn {
 | 
				
			||||||
        scoped_ptr<table_union_fn> m_tocheck;
 | 
					        scoped_ptr<table_union_fn> m_tocheck;
 | 
				
			||||||
        scoped_ptr<table_union_fn> m_checker;
 | 
					        scoped_ptr<table_union_fn> m_checker;
 | 
				
			||||||
| 
						 | 
					@ -120,7 +148,6 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        table_base* operator()(table_base const& src) {
 | 
					        table_base* operator()(table_base const& src) {
 | 
				
			||||||
            IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";);
 | 
					 | 
				
			||||||
            table_base* tchecker = (*m_checker)(checker(src));
 | 
					            table_base* tchecker = (*m_checker)(checker(src));
 | 
				
			||||||
            table_base* ttocheck = (*m_tocheck)(tocheck(src));
 | 
					            table_base* ttocheck = (*m_tocheck)(tocheck(src));
 | 
				
			||||||
            check_table* result = alloc(check_table, get(src).get_plugin(), tchecker->get_signature(), ttocheck, tchecker);
 | 
					            check_table* result = alloc(check_table, get(src).get_plugin(), tchecker->get_signature(), ttocheck, tchecker);
 | 
				
			||||||
| 
						 | 
					@ -135,6 +162,31 @@ namespace datalog {
 | 
				
			||||||
        return alloc(project_fn, *this, t, col_cnt, removed_cols);        
 | 
					        return alloc(project_fn, *this, t, col_cnt, removed_cols);        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class check_table_plugin::select_equal_and_project_fn : public table_transformer_fn {
 | 
				
			||||||
 | 
					        scoped_ptr<table_transformer_fn> m_checker;
 | 
				
			||||||
 | 
					        scoped_ptr<table_transformer_fn> m_tocheck;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        select_equal_and_project_fn(check_table_plugin& p, const table_base & t, const table_element & value, unsigned col) {
 | 
				
			||||||
 | 
					            m_checker = p.get_manager().mk_select_equal_and_project_fn(checker(t), value, col);
 | 
				
			||||||
 | 
					            m_tocheck = p.get_manager().mk_select_equal_and_project_fn(tocheck(t), value, col);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        table_base* operator()(table_base const& src) {
 | 
				
			||||||
 | 
					            table_base* tchecker = (*m_checker)(checker(src));
 | 
				
			||||||
 | 
					            table_base* ttocheck = (*m_tocheck)(tocheck(src));
 | 
				
			||||||
 | 
					            check_table* result = alloc(check_table, get(src).get_plugin(), tchecker->get_signature(), ttocheck, tchecker);
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    table_transformer_fn * check_table_plugin::mk_select_equal_and_project_fn(const table_base & t, 
 | 
				
			||||||
 | 
					            const table_element & value, unsigned col) {
 | 
				
			||||||
 | 
					        if (!check_kind(t)) {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return alloc(select_equal_and_project_fn, *this, t, value, col);        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class check_table_plugin::rename_fn : public table_transformer_fn {
 | 
					    class check_table_plugin::rename_fn : public table_transformer_fn {
 | 
				
			||||||
        scoped_ptr<table_transformer_fn> m_checker;
 | 
					        scoped_ptr<table_transformer_fn> m_checker;
 | 
				
			||||||
        scoped_ptr<table_transformer_fn> m_tocheck;
 | 
					        scoped_ptr<table_transformer_fn> m_tocheck;
 | 
				
			||||||
| 
						 | 
					@ -233,6 +285,33 @@ namespace datalog {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class check_table_plugin::filter_interpreted_and_project_fn : public table_transformer_fn {
 | 
				
			||||||
 | 
					        scoped_ptr<table_transformer_fn> m_checker;
 | 
				
			||||||
 | 
					        scoped_ptr<table_transformer_fn> m_tocheck;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        filter_interpreted_and_project_fn(check_table_plugin& p, const table_base & t, app * condition,
 | 
				
			||||||
 | 
					            unsigned removed_col_cnt, const unsigned * removed_cols)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_checker = p.get_manager().mk_filter_interpreted_and_project_fn(checker(t), condition, removed_col_cnt, removed_cols);
 | 
				
			||||||
 | 
					            m_tocheck = p.get_manager().mk_filter_interpreted_and_project_fn(tocheck(t), condition, removed_col_cnt, removed_cols); 
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        table_base* operator()(table_base const& src) {
 | 
				
			||||||
 | 
					            table_base* tchecker = (*m_checker)(checker(src));
 | 
				
			||||||
 | 
					            table_base* ttocheck = (*m_tocheck)(tocheck(src));
 | 
				
			||||||
 | 
					            check_table* result = alloc(check_table, get(src).get_plugin(), ttocheck->get_signature(), ttocheck, tchecker);
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    table_transformer_fn * check_table_plugin::mk_filter_interpreted_and_project_fn(const table_base & t,
 | 
				
			||||||
 | 
					        app * condition, unsigned removed_col_cnt, const unsigned * removed_cols) {
 | 
				
			||||||
 | 
					        if (check_kind(t)) {
 | 
				
			||||||
 | 
					            return alloc(filter_interpreted_and_project_fn, *this, t, condition, removed_col_cnt, removed_cols);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class check_table_plugin::filter_by_negation_fn : public table_intersection_filter_fn {
 | 
					    class check_table_plugin::filter_by_negation_fn : public table_intersection_filter_fn {
 | 
				
			||||||
        scoped_ptr<table_intersection_filter_fn> m_checker;
 | 
					        scoped_ptr<table_intersection_filter_fn> m_checker;
 | 
				
			||||||
        scoped_ptr<table_intersection_filter_fn> m_tocheck;
 | 
					        scoped_ptr<table_intersection_filter_fn> m_tocheck;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,13 +35,16 @@ namespace datalog {
 | 
				
			||||||
        unsigned m_count;
 | 
					        unsigned m_count;
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
        class join_fn;
 | 
					        class join_fn;
 | 
				
			||||||
 | 
					        class join_project_fn;
 | 
				
			||||||
        class union_fn;
 | 
					        class union_fn;
 | 
				
			||||||
        class transformer_fn;
 | 
					        class transformer_fn;
 | 
				
			||||||
        class rename_fn;
 | 
					        class rename_fn;
 | 
				
			||||||
        class project_fn;
 | 
					        class project_fn;
 | 
				
			||||||
 | 
					        class select_equal_and_project_fn;
 | 
				
			||||||
        class filter_equal_fn;
 | 
					        class filter_equal_fn;
 | 
				
			||||||
        class filter_identical_fn;
 | 
					        class filter_identical_fn;
 | 
				
			||||||
        class filter_interpreted_fn;
 | 
					        class filter_interpreted_fn;
 | 
				
			||||||
 | 
					        class filter_interpreted_and_project_fn;
 | 
				
			||||||
        class filter_by_negation_fn;
 | 
					        class filter_by_negation_fn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
| 
						 | 
					@ -54,10 +57,15 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual table_join_fn * mk_join_fn(const table_base & t1, const table_base & t2,
 | 
					        virtual table_join_fn * mk_join_fn(const table_base & t1, const table_base & t2,
 | 
				
			||||||
            unsigned col_cnt, const unsigned * cols1, const unsigned * cols2);
 | 
					            unsigned col_cnt, const unsigned * cols1, const unsigned * cols2);
 | 
				
			||||||
 | 
					        virtual table_join_fn * mk_join_project_fn(const table_base & t1, const table_base & t2,
 | 
				
			||||||
 | 
					            unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, 
 | 
				
			||||||
 | 
					            const unsigned * removed_cols);
 | 
				
			||||||
        virtual table_union_fn * mk_union_fn(const table_base & tgt, const table_base & src, 
 | 
					        virtual table_union_fn * mk_union_fn(const table_base & tgt, const table_base & src, 
 | 
				
			||||||
            const table_base * delta);
 | 
					            const table_base * delta);
 | 
				
			||||||
        virtual table_transformer_fn * mk_project_fn(const table_base & t, unsigned col_cnt, 
 | 
					        virtual table_transformer_fn * mk_project_fn(const table_base & t, unsigned col_cnt, 
 | 
				
			||||||
            const unsigned * removed_cols);
 | 
					            const unsigned * removed_cols);
 | 
				
			||||||
 | 
					        virtual table_transformer_fn * mk_select_equal_and_project_fn(const table_base & t, 
 | 
				
			||||||
 | 
					            const table_element & value, unsigned col);
 | 
				
			||||||
        virtual table_transformer_fn * mk_rename_fn(const table_base & t, unsigned permutation_cycle_len,
 | 
					        virtual table_transformer_fn * mk_rename_fn(const table_base & t, unsigned permutation_cycle_len,
 | 
				
			||||||
            const unsigned * permutation_cycle);
 | 
					            const unsigned * permutation_cycle);
 | 
				
			||||||
        virtual table_mutator_fn * mk_filter_identical_fn(const table_base & t, unsigned col_cnt, 
 | 
					        virtual table_mutator_fn * mk_filter_identical_fn(const table_base & t, unsigned col_cnt, 
 | 
				
			||||||
| 
						 | 
					@ -65,6 +73,8 @@ namespace datalog {
 | 
				
			||||||
        virtual table_mutator_fn * mk_filter_equal_fn(const table_base & t, const table_element & value, 
 | 
					        virtual table_mutator_fn * mk_filter_equal_fn(const table_base & t, const table_element & value, 
 | 
				
			||||||
            unsigned col);
 | 
					            unsigned col);
 | 
				
			||||||
        virtual table_mutator_fn * mk_filter_interpreted_fn(const table_base & t, app * condition);
 | 
					        virtual table_mutator_fn * mk_filter_interpreted_fn(const table_base & t, app * condition);
 | 
				
			||||||
 | 
					        virtual table_transformer_fn * mk_filter_interpreted_and_project_fn(const table_base & t,
 | 
				
			||||||
 | 
					            app * condition, unsigned removed_col_cnt, const unsigned * removed_cols);
 | 
				
			||||||
        virtual table_intersection_filter_fn * mk_filter_by_negation_fn(
 | 
					        virtual table_intersection_filter_fn * mk_filter_by_negation_fn(
 | 
				
			||||||
            const table_base & t, 
 | 
					            const table_base & t, 
 | 
				
			||||||
            const table_base & negated_obj, unsigned joined_col_cnt, 
 | 
					            const table_base & negated_obj, unsigned joined_col_cnt, 
 | 
				
			||||||
| 
						 | 
					@ -89,15 +99,6 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class check_table : public table_base {
 | 
					    class check_table : public table_base {
 | 
				
			||||||
        friend class check_table_plugin;
 | 
					        friend class check_table_plugin;
 | 
				
			||||||
        friend class check_table_plugin::join_fn;
 | 
					 | 
				
			||||||
        friend class check_table_plugin::union_fn;
 | 
					 | 
				
			||||||
        friend class check_table_plugin::transformer_fn;
 | 
					 | 
				
			||||||
        friend class check_table_plugin::rename_fn;
 | 
					 | 
				
			||||||
        friend class check_table_plugin::project_fn;
 | 
					 | 
				
			||||||
        friend class check_table_plugin::filter_equal_fn;
 | 
					 | 
				
			||||||
        friend class check_table_plugin::filter_identical_fn;
 | 
					 | 
				
			||||||
        friend class check_table_plugin::filter_interpreted_fn;
 | 
					 | 
				
			||||||
        friend class check_table_plugin::filter_by_negation_fn;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        table_base* m_checker;
 | 
					        table_base* m_checker;
 | 
				
			||||||
        table_base* m_tocheck;
 | 
					        table_base* m_tocheck;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -445,40 +445,8 @@ public:
 | 
				
			||||||
        ctx.insert(var);
 | 
					        ctx.insert(var);
 | 
				
			||||||
        m_dl_ctx->dlctx().register_variable(var);
 | 
					        m_dl_ctx->dlctx().register_variable(var);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class dl_push_cmd : public cmd {
 | 
					 | 
				
			||||||
    ref<dl_context>   m_ctx;    
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    dl_push_cmd(dl_context* ctx):
 | 
					 | 
				
			||||||
        cmd("fixedpoint-push"),
 | 
					 | 
				
			||||||
        m_ctx(ctx)
 | 
					 | 
				
			||||||
    {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    virtual char const * get_usage() const { return ""; }
 | 
					 | 
				
			||||||
    virtual char const * get_descr(cmd_context & ctx) const { return "push context on the fixedpoint engine"; }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    virtual void execute(cmd_context& ctx) {
 | 
					 | 
				
			||||||
        m_ctx->push();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class dl_pop_cmd : public cmd {
 | 
					 | 
				
			||||||
    ref<dl_context>   m_ctx;    
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    dl_pop_cmd(dl_context* ctx):
 | 
					 | 
				
			||||||
        cmd("fixedpoint-pop"),
 | 
					 | 
				
			||||||
        m_ctx(ctx)
 | 
					 | 
				
			||||||
    {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    virtual char const * get_usage() const { return ""; }
 | 
					 | 
				
			||||||
    virtual char const * get_descr(cmd_context & ctx) const { return "pop context on the fixedpoint engine"; }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    virtual void execute(cmd_context& ctx) {
 | 
					 | 
				
			||||||
        m_ctx->pop();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void install_dl_cmds_aux(cmd_context& ctx, dl_collected_cmds* collected_cmds) {
 | 
					static void install_dl_cmds_aux(cmd_context& ctx, dl_collected_cmds* collected_cmds) {
 | 
				
			||||||
    dl_context * dl_ctx = alloc(dl_context, ctx, collected_cmds);
 | 
					    dl_context * dl_ctx = alloc(dl_context, ctx, collected_cmds);
 | 
				
			||||||
| 
						 | 
					@ -486,10 +454,6 @@ static void install_dl_cmds_aux(cmd_context& ctx, dl_collected_cmds* collected_c
 | 
				
			||||||
    ctx.insert(alloc(dl_query_cmd, dl_ctx));
 | 
					    ctx.insert(alloc(dl_query_cmd, dl_ctx));
 | 
				
			||||||
    ctx.insert(alloc(dl_declare_rel_cmd, dl_ctx));
 | 
					    ctx.insert(alloc(dl_declare_rel_cmd, dl_ctx));
 | 
				
			||||||
    ctx.insert(alloc(dl_declare_var_cmd, dl_ctx));
 | 
					    ctx.insert(alloc(dl_declare_var_cmd, dl_ctx));
 | 
				
			||||||
#ifndef _EXTERNAL_RELEASE
 | 
					 | 
				
			||||||
    ctx.insert(alloc(dl_push_cmd, dl_ctx)); // not exposed to keep command-extensions simple.
 | 
					 | 
				
			||||||
    ctx.insert(alloc(dl_pop_cmd, dl_ctx));
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void install_dl_cmds(cmd_context & ctx) {
 | 
					void install_dl_cmds(cmd_context & ctx) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ namespace datalog {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void compiler::ensure_predicate_loaded(func_decl * pred, instruction_block & acc) {
 | 
					    void compiler::ensure_predicate_loaded(func_decl * pred, instruction_block & acc) {
 | 
				
			||||||
        pred2idx::entry * e = m_pred_regs.insert_if_not_there2(pred, UINT_MAX);
 | 
					        pred2idx::obj_map_entry * e = m_pred_regs.insert_if_not_there2(pred, UINT_MAX);
 | 
				
			||||||
        if(e->get_data().m_value!=UINT_MAX) {
 | 
					        if(e->get_data().m_value!=UINT_MAX) {
 | 
				
			||||||
            //predicate is already loaded
 | 
					            //predicate is already loaded
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
| 
						 | 
					@ -61,17 +61,30 @@ namespace datalog {
 | 
				
			||||||
    void compiler::make_join_project(reg_idx t1, reg_idx t2, const variable_intersection & vars, 
 | 
					    void compiler::make_join_project(reg_idx t1, reg_idx t2, const variable_intersection & vars, 
 | 
				
			||||||
            const unsigned_vector & removed_cols, reg_idx & result, instruction_block & acc) {
 | 
					            const unsigned_vector & removed_cols, reg_idx & result, instruction_block & acc) {
 | 
				
			||||||
        relation_signature aux_sig;
 | 
					        relation_signature aux_sig;
 | 
				
			||||||
        relation_signature::from_join(m_reg_signatures[t1], m_reg_signatures[t2], vars.size(), 
 | 
					        relation_signature sig1 = m_reg_signatures[t1];
 | 
				
			||||||
            vars.get_cols1(), vars.get_cols2(), aux_sig);
 | 
					        relation_signature sig2 = m_reg_signatures[t2];
 | 
				
			||||||
 | 
					        relation_signature::from_join(sig1, sig2, vars.size(), vars.get_cols1(), vars.get_cols2(), aux_sig);
 | 
				
			||||||
        relation_signature res_sig;
 | 
					        relation_signature res_sig;
 | 
				
			||||||
        relation_signature::from_project(aux_sig, removed_cols.size(), removed_cols.c_ptr(), 
 | 
					        relation_signature::from_project(aux_sig, removed_cols.size(), removed_cols.c_ptr(), 
 | 
				
			||||||
            res_sig);
 | 
					            res_sig);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        result = get_fresh_register(res_sig);
 | 
					        result = get_fresh_register(res_sig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        acc.push_back(instruction::mk_join_project(t1, t2, vars.size(), vars.get_cols1(), 
 | 
					        acc.push_back(instruction::mk_join_project(t1, t2, vars.size(), vars.get_cols1(), 
 | 
				
			||||||
            vars.get_cols2(), removed_cols.size(), removed_cols.c_ptr(), result));
 | 
					            vars.get_cols2(), removed_cols.size(), removed_cols.c_ptr(), result));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void compiler::make_filter_interpreted_and_project(reg_idx src, app_ref & cond,
 | 
				
			||||||
 | 
					            const unsigned_vector & removed_cols, reg_idx & result, instruction_block & acc) {
 | 
				
			||||||
 | 
					        SASSERT(!removed_cols.empty());
 | 
				
			||||||
 | 
					        relation_signature res_sig;
 | 
				
			||||||
 | 
					        relation_signature::from_project(m_reg_signatures[src], removed_cols.size(),
 | 
				
			||||||
 | 
					            removed_cols.c_ptr(), res_sig);
 | 
				
			||||||
 | 
					        result = get_fresh_register(res_sig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        acc.push_back(instruction::mk_filter_interpreted_and_project(src, cond,
 | 
				
			||||||
 | 
					            removed_cols.size(), removed_cols.c_ptr(), result));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void compiler::make_select_equal_and_project(reg_idx src, const relation_element & val, unsigned col,
 | 
					    void compiler::make_select_equal_and_project(reg_idx src, const relation_element & val, unsigned col,
 | 
				
			||||||
            reg_idx & result, instruction_block & acc) {
 | 
					            reg_idx & result, instruction_block & acc) {
 | 
				
			||||||
        relation_signature res_sig;
 | 
					        relation_signature res_sig;
 | 
				
			||||||
| 
						 | 
					@ -145,7 +158,7 @@ namespace datalog {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void compiler::make_add_constant_column(func_decl* head_pred, reg_idx src, const relation_sort & s, const relation_element & val,
 | 
					    void compiler::make_add_constant_column(func_decl* head_pred, reg_idx src, const relation_sort & s, const relation_element & val,
 | 
				
			||||||
            reg_idx & result, instruction_block & acc) {
 | 
					            reg_idx & result, bool & dealloc, instruction_block & acc) {
 | 
				
			||||||
        reg_idx singleton_table;
 | 
					        reg_idx singleton_table;
 | 
				
			||||||
        if(!m_constant_registers.find(s, val, singleton_table)) {
 | 
					        if(!m_constant_registers.find(s, val, singleton_table)) {
 | 
				
			||||||
            singleton_table = get_single_column_register(s);
 | 
					            singleton_table = get_single_column_register(s);
 | 
				
			||||||
| 
						 | 
					@ -154,16 +167,18 @@ namespace datalog {
 | 
				
			||||||
            m_constant_registers.insert(s, val, singleton_table);
 | 
					            m_constant_registers.insert(s, val, singleton_table);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(src==execution_context::void_register) {
 | 
					        if(src==execution_context::void_register) {
 | 
				
			||||||
            make_clone(singleton_table, result, acc);
 | 
					            result = singleton_table;
 | 
				
			||||||
 | 
					            dealloc = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            variable_intersection empty_vars(m_context.get_manager());
 | 
					            variable_intersection empty_vars(m_context.get_manager());
 | 
				
			||||||
            make_join(src, singleton_table, empty_vars, result, acc);
 | 
					            make_join(src, singleton_table, empty_vars, result, acc);
 | 
				
			||||||
 | 
					            dealloc = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void compiler::make_add_unbound_column(rule* compiled_rule, unsigned col_idx, func_decl* pred, reg_idx src, const relation_sort & s, reg_idx & result, 
 | 
					    void compiler::make_add_unbound_column(rule* compiled_rule, unsigned col_idx, func_decl* pred, reg_idx src, const relation_sort & s, reg_idx & result, 
 | 
				
			||||||
            instruction_block & acc) {
 | 
					            bool & dealloc, instruction_block & acc) {
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        TRACE("dl", tout << "Adding unbound column " << mk_pp(pred, m_context.get_manager()) << "\n";);
 | 
					        TRACE("dl", tout << "Adding unbound column " << mk_pp(pred, m_context.get_manager()) << "\n";);
 | 
				
			||||||
            IF_VERBOSE(3, { 
 | 
					            IF_VERBOSE(3, { 
 | 
				
			||||||
| 
						 | 
					@ -172,25 +187,35 @@ namespace datalog {
 | 
				
			||||||
                    verbose_stream() << "Compiling unsafe rule column " << col_idx << "\n" 
 | 
					                    verbose_stream() << "Compiling unsafe rule column " << col_idx << "\n" 
 | 
				
			||||||
                                     << mk_ismt2_pp(e, m_context.get_manager()) << "\n"; 
 | 
					                                     << mk_ismt2_pp(e, m_context.get_manager()) << "\n"; 
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
        reg_idx total_table = get_single_column_register(s);
 | 
					        reg_idx total_table;
 | 
				
			||||||
        relation_signature sig;
 | 
					        if (!m_total_registers.find(s, pred, total_table)) {
 | 
				
			||||||
        sig.push_back(s);
 | 
					            total_table = get_single_column_register(s);
 | 
				
			||||||
        acc.push_back(instruction::mk_total(sig, pred, total_table));        
 | 
					            relation_signature sig;
 | 
				
			||||||
 | 
					            sig.push_back(s);
 | 
				
			||||||
 | 
					            m_top_level_code.push_back(instruction::mk_total(sig, pred, total_table));
 | 
				
			||||||
 | 
					            m_total_registers.insert(s, pred, total_table);
 | 
				
			||||||
 | 
					        }       
 | 
				
			||||||
        if(src == execution_context::void_register) {
 | 
					        if(src == execution_context::void_register) {
 | 
				
			||||||
            result = total_table;
 | 
					            result = total_table;
 | 
				
			||||||
 | 
					            dealloc = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            variable_intersection empty_vars(m_context.get_manager());
 | 
					            variable_intersection empty_vars(m_context.get_manager());
 | 
				
			||||||
            make_join(src, total_table, empty_vars, result, acc);
 | 
					            make_join(src, total_table, empty_vars, result, acc);
 | 
				
			||||||
            make_dealloc_non_void(total_table, acc);
 | 
					            dealloc = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void compiler::make_full_relation(func_decl* pred, const relation_signature & sig, reg_idx & result, 
 | 
					    void compiler::make_full_relation(func_decl* pred, const relation_signature & sig, reg_idx & result, 
 | 
				
			||||||
            instruction_block & acc) {
 | 
					            instruction_block & acc) {
 | 
				
			||||||
 | 
					        SASSERT(sig.empty());
 | 
				
			||||||
        TRACE("dl", tout << "Adding unbound column " << mk_pp(pred, m_context.get_manager()) << "\n";);
 | 
					        TRACE("dl", tout << "Adding unbound column " << mk_pp(pred, m_context.get_manager()) << "\n";);
 | 
				
			||||||
 | 
					        if (m_empty_tables_registers.find(pred, result))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        result = get_fresh_register(sig);
 | 
					        result = get_fresh_register(sig);
 | 
				
			||||||
        acc.push_back(instruction::mk_total(sig, pred, result));
 | 
					        m_top_level_code.push_back(instruction::mk_total(sig, pred, result));
 | 
				
			||||||
 | 
					        m_empty_tables_registers.insert(pred, result);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,6 +257,7 @@ namespace datalog {
 | 
				
			||||||
        reg_idx    src, 
 | 
					        reg_idx    src, 
 | 
				
			||||||
        const svector<assembling_column_info> & acis0,
 | 
					        const svector<assembling_column_info> & acis0,
 | 
				
			||||||
        reg_idx &           result, 
 | 
					        reg_idx &           result, 
 | 
				
			||||||
 | 
					        bool & dealloc,
 | 
				
			||||||
        instruction_block & acc) {
 | 
					        instruction_block & acc) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TRACE("dl", tout << mk_pp(head_pred, m_context.get_manager()) << "\n";);
 | 
					        TRACE("dl", tout << mk_pp(head_pred, m_context.get_manager()) << "\n";);
 | 
				
			||||||
| 
						 | 
					@ -276,7 +302,9 @@ namespace datalog {
 | 
				
			||||||
        if(!src_cols_to_remove.empty()) {
 | 
					        if(!src_cols_to_remove.empty()) {
 | 
				
			||||||
            reg_idx new_curr;
 | 
					            reg_idx new_curr;
 | 
				
			||||||
            make_projection(curr, src_cols_to_remove.size(), src_cols_to_remove.c_ptr(), new_curr, acc);
 | 
					            make_projection(curr, src_cols_to_remove.size(), src_cols_to_remove.c_ptr(), new_curr, acc);
 | 
				
			||||||
            make_dealloc_non_void(curr, acc);
 | 
					            if (dealloc)
 | 
				
			||||||
 | 
					                make_dealloc_non_void(curr, acc);
 | 
				
			||||||
 | 
					            dealloc = true;
 | 
				
			||||||
            curr=new_curr;
 | 
					            curr=new_curr;
 | 
				
			||||||
            curr_sig = & m_reg_signatures[curr];
 | 
					            curr_sig = & m_reg_signatures[curr];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -297,16 +325,19 @@ namespace datalog {
 | 
				
			||||||
            unsigned bound_column_index;
 | 
					            unsigned bound_column_index;
 | 
				
			||||||
            if(acis[i].kind!=ACK_UNBOUND_VAR || !handled_unbound.find(acis[i].var_index,bound_column_index)) {
 | 
					            if(acis[i].kind!=ACK_UNBOUND_VAR || !handled_unbound.find(acis[i].var_index,bound_column_index)) {
 | 
				
			||||||
                reg_idx new_curr;
 | 
					                reg_idx new_curr;
 | 
				
			||||||
 | 
					                bool new_dealloc;
 | 
				
			||||||
                bound_column_index=curr_sig->size();
 | 
					                bound_column_index=curr_sig->size();
 | 
				
			||||||
                if(acis[i].kind==ACK_CONSTANT) {
 | 
					                if(acis[i].kind==ACK_CONSTANT) {
 | 
				
			||||||
                    make_add_constant_column(head_pred, curr, acis[i].domain, acis[i].constant, new_curr, acc);
 | 
					                    make_add_constant_column(head_pred, curr, acis[i].domain, acis[i].constant, new_curr, new_dealloc, acc);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    SASSERT(acis[i].kind==ACK_UNBOUND_VAR);
 | 
					                    SASSERT(acis[i].kind==ACK_UNBOUND_VAR);
 | 
				
			||||||
                    make_add_unbound_column(compiled_rule, i, head_pred, curr, acis[i].domain, new_curr, acc);
 | 
					                    make_add_unbound_column(compiled_rule, i, head_pred, curr, acis[i].domain, new_curr, new_dealloc, acc);
 | 
				
			||||||
                    handled_unbound.insert(acis[i].var_index,bound_column_index);
 | 
					                    handled_unbound.insert(acis[i].var_index,bound_column_index);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                make_dealloc_non_void(curr, acc);
 | 
					                if (dealloc)
 | 
				
			||||||
 | 
					                    make_dealloc_non_void(curr, acc);
 | 
				
			||||||
 | 
					                dealloc = new_dealloc;
 | 
				
			||||||
                curr=new_curr;
 | 
					                curr=new_curr;
 | 
				
			||||||
                curr_sig = & m_reg_signatures[curr];
 | 
					                curr_sig = & m_reg_signatures[curr];
 | 
				
			||||||
                SASSERT(bound_column_index==curr_sig->size()-1);
 | 
					                SASSERT(bound_column_index==curr_sig->size()-1);
 | 
				
			||||||
| 
						 | 
					@ -327,7 +358,9 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            reg_idx new_curr;
 | 
					            reg_idx new_curr;
 | 
				
			||||||
            make_duplicate_column(curr, col, new_curr, acc);
 | 
					            make_duplicate_column(curr, col, new_curr, acc);
 | 
				
			||||||
            make_dealloc_non_void(curr, acc);
 | 
					            if (dealloc)
 | 
				
			||||||
 | 
					                make_dealloc_non_void(curr, acc);
 | 
				
			||||||
 | 
					            dealloc = true;
 | 
				
			||||||
            curr=new_curr;
 | 
					            curr=new_curr;
 | 
				
			||||||
            curr_sig = & m_reg_signatures[curr];
 | 
					            curr_sig = & m_reg_signatures[curr];
 | 
				
			||||||
            unsigned bound_column_index=curr_sig->size()-1;
 | 
					            unsigned bound_column_index=curr_sig->size()-1;
 | 
				
			||||||
| 
						 | 
					@ -355,7 +388,9 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            reg_idx new_curr;
 | 
					            reg_idx new_curr;
 | 
				
			||||||
            make_rename(curr, permutation.size(), permutation.c_ptr(), new_curr, acc);
 | 
					            make_rename(curr, permutation.size(), permutation.c_ptr(), new_curr, acc);
 | 
				
			||||||
            make_dealloc_non_void(curr, acc);
 | 
					            if (dealloc)
 | 
				
			||||||
 | 
					                make_dealloc_non_void(curr, acc);
 | 
				
			||||||
 | 
					            dealloc = true;
 | 
				
			||||||
            curr=new_curr;
 | 
					            curr=new_curr;
 | 
				
			||||||
            curr_sig = & m_reg_signatures[curr];
 | 
					            curr_sig = & m_reg_signatures[curr];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -364,6 +399,7 @@ namespace datalog {
 | 
				
			||||||
            SASSERT(src==execution_context::void_register);
 | 
					            SASSERT(src==execution_context::void_register);
 | 
				
			||||||
            SASSERT(acis0.size()==0);
 | 
					            SASSERT(acis0.size()==0);
 | 
				
			||||||
            make_full_relation(head_pred, empty_signature, curr, acc);
 | 
					            make_full_relation(head_pred, empty_signature, curr, acc);
 | 
				
			||||||
 | 
					            dealloc = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        result=curr;
 | 
					        result=curr;
 | 
				
			||||||
| 
						 | 
					@ -397,6 +433,7 @@ namespace datalog {
 | 
				
			||||||
    void compiler::compile_rule_evaluation_run(rule * r, reg_idx head_reg, const reg_idx * tail_regs, 
 | 
					    void compiler::compile_rule_evaluation_run(rule * r, reg_idx head_reg, const reg_idx * tail_regs, 
 | 
				
			||||||
            reg_idx delta_reg, bool use_widening, instruction_block & acc) {
 | 
					            reg_idx delta_reg, bool use_widening, instruction_block & acc) {
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        ast_manager & m = m_context.get_manager();
 | 
				
			||||||
        m_instruction_observer.start_rule(r);
 | 
					        m_instruction_observer.start_rule(r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const app * h = r->get_head();
 | 
					        const app * h = r->get_head();
 | 
				
			||||||
| 
						 | 
					@ -409,12 +446,15 @@ namespace datalog {
 | 
				
			||||||
        SASSERT(pt_len<=2); //we require rules to be processed by the mk_simple_joins rule transformer plugin
 | 
					        SASSERT(pt_len<=2); //we require rules to be processed by the mk_simple_joins rule transformer plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        reg_idx single_res;
 | 
					        reg_idx single_res;
 | 
				
			||||||
        ptr_vector<expr> single_res_expr;
 | 
					        expr_ref_vector single_res_expr(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //used to save on filter_identical instructions where the check is already done 
 | 
					        //used to save on filter_identical instructions where the check is already done 
 | 
				
			||||||
        //by the join operation
 | 
					        //by the join operation
 | 
				
			||||||
        unsigned second_tail_arg_ofs;
 | 
					        unsigned second_tail_arg_ofs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // whether to dealloc the previous result
 | 
				
			||||||
 | 
					        bool dealloc = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(pt_len == 2) {
 | 
					        if(pt_len == 2) {
 | 
				
			||||||
            reg_idx t1_reg=tail_regs[0];
 | 
					            reg_idx t1_reg=tail_regs[0];
 | 
				
			||||||
            reg_idx t2_reg=tail_regs[1];
 | 
					            reg_idx t2_reg=tail_regs[1];
 | 
				
			||||||
| 
						 | 
					@ -471,8 +511,7 @@ namespace datalog {
 | 
				
			||||||
                expr * arg = a->get_arg(i);
 | 
					                expr * arg = a->get_arg(i);
 | 
				
			||||||
                if(is_app(arg)) {
 | 
					                if(is_app(arg)) {
 | 
				
			||||||
                    app * c = to_app(arg); //argument is a constant
 | 
					                    app * c = to_app(arg); //argument is a constant
 | 
				
			||||||
                    SASSERT(c->get_num_args()==0);
 | 
					                    SASSERT(m.is_value(c));
 | 
				
			||||||
                    SASSERT(m_context.get_decl_util().is_numeral_ext(arg));
 | 
					 | 
				
			||||||
                    reg_idx new_reg;
 | 
					                    reg_idx new_reg;
 | 
				
			||||||
                    make_select_equal_and_project(single_res, c, single_res_expr.size(), new_reg, acc);
 | 
					                    make_select_equal_and_project(single_res, c, single_res_expr.size(), new_reg, acc);
 | 
				
			||||||
                    if(single_res!=t_reg) {
 | 
					                    if(single_res!=t_reg) {
 | 
				
			||||||
| 
						 | 
					@ -487,8 +526,7 @@ namespace datalog {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if(single_res==t_reg) {
 | 
					            if(single_res==t_reg) {
 | 
				
			||||||
                //we may be modifying the register later, so we need a local copy
 | 
					                dealloc = false;
 | 
				
			||||||
                make_clone(t_reg, single_res, acc);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -499,7 +537,7 @@ namespace datalog {
 | 
				
			||||||
            single_res=execution_context::void_register;
 | 
					            single_res=execution_context::void_register;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        add_unbound_columns_for_negation(r, head_pred, single_res, single_res_expr, acc);
 | 
					        add_unbound_columns_for_negation(r, head_pred, single_res, single_res_expr, dealloc, acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int2ints var_indexes;
 | 
					        int2ints var_indexes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -510,11 +548,14 @@ namespace datalog {
 | 
				
			||||||
            unsigned srlen=single_res_expr.size();
 | 
					            unsigned srlen=single_res_expr.size();
 | 
				
			||||||
            SASSERT((single_res==execution_context::void_register) ? (srlen==0) : (srlen==m_reg_signatures[single_res].size()));
 | 
					            SASSERT((single_res==execution_context::void_register) ? (srlen==0) : (srlen==m_reg_signatures[single_res].size()));
 | 
				
			||||||
            for(unsigned i=0; i<srlen; i++) {
 | 
					            for(unsigned i=0; i<srlen; i++) {
 | 
				
			||||||
                expr * exp = single_res_expr[i];
 | 
					                expr * exp = single_res_expr[i].get();
 | 
				
			||||||
                if(is_app(exp)) {
 | 
					                if(is_app(exp)) {
 | 
				
			||||||
                    SASSERT(m_context.get_decl_util().is_numeral_ext(exp));
 | 
					                    SASSERT(m_context.get_decl_util().is_numeral_ext(exp));
 | 
				
			||||||
                    relation_element value = to_app(exp);
 | 
					                    relation_element value = to_app(exp);
 | 
				
			||||||
 | 
					                    if (!dealloc)
 | 
				
			||||||
 | 
					                        make_clone(filtered_res, filtered_res, acc);
 | 
				
			||||||
                    acc.push_back(instruction::mk_filter_equal(m_context.get_manager(), filtered_res, value, i));
 | 
					                    acc.push_back(instruction::mk_filter_equal(m_context.get_manager(), filtered_res, value, i));
 | 
				
			||||||
 | 
					                    dealloc = true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    SASSERT(is_var(exp));
 | 
					                    SASSERT(is_var(exp));
 | 
				
			||||||
| 
						 | 
					@ -541,7 +582,10 @@ namespace datalog {
 | 
				
			||||||
                //condition!)
 | 
					                //condition!)
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (!dealloc)
 | 
				
			||||||
 | 
					                make_clone(filtered_res, filtered_res, acc);
 | 
				
			||||||
            acc.push_back(instruction::mk_filter_identical(filtered_res, indexes.size(), indexes.c_ptr()));
 | 
					            acc.push_back(instruction::mk_filter_identical(filtered_res, indexes.size(), indexes.c_ptr()));
 | 
				
			||||||
 | 
					            dealloc = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //enforce negative predicates
 | 
					        //enforce negative predicates
 | 
				
			||||||
| 
						 | 
					@ -564,9 +608,12 @@ namespace datalog {
 | 
				
			||||||
                relation_sort arg_sort;
 | 
					                relation_sort arg_sort;
 | 
				
			||||||
                m_context.get_rel_context().get_rmanager().from_predicate(neg_pred, i, arg_sort);
 | 
					                m_context.get_rel_context().get_rmanager().from_predicate(neg_pred, i, arg_sort);
 | 
				
			||||||
                reg_idx new_reg;
 | 
					                reg_idx new_reg;
 | 
				
			||||||
                make_add_constant_column(head_pred, filtered_res, arg_sort, to_app(e), new_reg, acc);
 | 
					                bool new_dealloc;
 | 
				
			||||||
 | 
					                make_add_constant_column(head_pred, filtered_res, arg_sort, to_app(e), new_reg, new_dealloc, acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                make_dealloc_non_void(filtered_res, acc);
 | 
					                if (dealloc)
 | 
				
			||||||
 | 
					                    make_dealloc_non_void(filtered_res, acc);
 | 
				
			||||||
 | 
					                dealloc = new_dealloc;
 | 
				
			||||||
                filtered_res = new_reg;                // here filtered_res value gets changed !!
 | 
					                filtered_res = new_reg;                // here filtered_res value gets changed !!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                t_cols.push_back(single_res_expr.size());
 | 
					                t_cols.push_back(single_res_expr.size());
 | 
				
			||||||
| 
						 | 
					@ -576,18 +623,130 @@ namespace datalog {
 | 
				
			||||||
            SASSERT(t_cols.size()==neg_cols.size());
 | 
					            SASSERT(t_cols.size()==neg_cols.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            reg_idx neg_reg = m_pred_regs.find(neg_pred);
 | 
					            reg_idx neg_reg = m_pred_regs.find(neg_pred);
 | 
				
			||||||
 | 
					            if (!dealloc)
 | 
				
			||||||
 | 
					                make_clone(filtered_res, filtered_res, acc);
 | 
				
			||||||
            acc.push_back(instruction::mk_filter_by_negation(filtered_res, neg_reg, t_cols.size(),
 | 
					            acc.push_back(instruction::mk_filter_by_negation(filtered_res, neg_reg, t_cols.size(),
 | 
				
			||||||
                t_cols.c_ptr(), neg_cols.c_ptr()));
 | 
					                t_cols.c_ptr(), neg_cols.c_ptr()));
 | 
				
			||||||
 | 
					            dealloc = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //enforce interpreted tail predicates
 | 
					        // enforce interpreted tail predicates
 | 
				
			||||||
 | 
					        unsigned ft_len = r->get_tail_size(); // full tail
 | 
				
			||||||
 | 
					        ptr_vector<expr> tail;
 | 
				
			||||||
 | 
					        for (unsigned tail_index = ut_len; tail_index < ft_len; ++tail_index) {
 | 
				
			||||||
 | 
					            tail.push_back(r->get_tail(tail_index));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!tail.empty()) {
 | 
				
			||||||
 | 
					            app_ref filter_cond(tail.size() == 1 ? to_app(tail.back()) : m.mk_and(tail.size(), tail.c_ptr()), m);
 | 
				
			||||||
 | 
					            ptr_vector<sort> filter_vars;
 | 
				
			||||||
 | 
					            get_free_vars(filter_cond, filter_vars);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // create binding
 | 
				
			||||||
 | 
					            expr_ref_vector binding(m);
 | 
				
			||||||
 | 
					            binding.resize(filter_vars.size()+1);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            for (unsigned v = 0; v < filter_vars.size(); ++v) {
 | 
				
			||||||
 | 
					                if (!filter_vars[v])
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                int2ints::entry * entry = var_indexes.find_core(v);
 | 
				
			||||||
 | 
					                unsigned src_col;
 | 
				
			||||||
 | 
					                if (entry) {
 | 
				
			||||||
 | 
					                    src_col = entry->get_data().m_value.back();
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // we have an unbound variable, so we add an unbound column for it
 | 
				
			||||||
 | 
					                    relation_sort unbound_sort = filter_vars[v];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    reg_idx new_reg;
 | 
				
			||||||
 | 
					                    bool new_dealloc;
 | 
				
			||||||
 | 
					                    make_add_unbound_column(r, 0, head_pred, filtered_res, unbound_sort, new_reg, new_dealloc, acc);
 | 
				
			||||||
 | 
					                    if (dealloc)
 | 
				
			||||||
 | 
					                        make_dealloc_non_void(filtered_res, acc);
 | 
				
			||||||
 | 
					                    dealloc = new_dealloc;
 | 
				
			||||||
 | 
					                    filtered_res = new_reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    src_col = single_res_expr.size();
 | 
				
			||||||
 | 
					                    single_res_expr.push_back(m.mk_var(v, unbound_sort));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    entry = var_indexes.insert_if_not_there2(v, unsigned_vector());
 | 
				
			||||||
 | 
					                    entry->get_data().m_value.push_back(src_col);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                relation_sort var_sort = m_reg_signatures[filtered_res][src_col];
 | 
				
			||||||
 | 
					                binding[filter_vars.size()-v] = m.mk_var(src_col, var_sort);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // check if there are any columns to remove
 | 
				
			||||||
 | 
					            unsigned_vector remove_columns;
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                unsigned_vector var_idx_to_remove;
 | 
				
			||||||
 | 
					                ptr_vector<sort> vars;
 | 
				
			||||||
 | 
					                get_free_vars(r->get_head(), vars);
 | 
				
			||||||
 | 
					                for (int2ints::iterator I = var_indexes.begin(), E = var_indexes.end();
 | 
				
			||||||
 | 
					                    I != E; ++I) {
 | 
				
			||||||
 | 
					                    unsigned var_idx = I->m_key;
 | 
				
			||||||
 | 
					                    if (!vars.get(var_idx, 0)) {
 | 
				
			||||||
 | 
					                        unsigned_vector & cols = I->m_value;
 | 
				
			||||||
 | 
					                        for (unsigned i = 0; i < cols.size(); ++i) {
 | 
				
			||||||
 | 
					                            remove_columns.push_back(cols[i]);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        var_idx_to_remove.push_back(var_idx);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (unsigned i = 0; i < var_idx_to_remove.size(); ++i) {
 | 
				
			||||||
 | 
					                    var_indexes.remove(var_idx_to_remove[i]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // update column idx for after projection state
 | 
				
			||||||
 | 
					                if (!remove_columns.empty()) {
 | 
				
			||||||
 | 
					                    unsigned_vector offsets;
 | 
				
			||||||
 | 
					                    offsets.resize(single_res_expr.size(), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    for (unsigned i = 0; i < remove_columns.size(); ++i) {
 | 
				
			||||||
 | 
					                        for (unsigned col = remove_columns[i]; col < offsets.size(); ++col) {
 | 
				
			||||||
 | 
					                            ++offsets[col];
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    for (int2ints::iterator I = var_indexes.begin(), E = var_indexes.end();
 | 
				
			||||||
 | 
					                    I != E; ++I) {
 | 
				
			||||||
 | 
					                        unsigned_vector & cols = I->m_value;
 | 
				
			||||||
 | 
					                        for (unsigned i = 0; i < cols.size(); ++i) {
 | 
				
			||||||
 | 
					                            cols[i] -= offsets[cols[i]];
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            expr_ref renamed(m);
 | 
				
			||||||
 | 
					            m_context.get_var_subst()(filter_cond, binding.size(), binding.c_ptr(), renamed);
 | 
				
			||||||
 | 
					            app_ref app_renamed(to_app(renamed), m);
 | 
				
			||||||
 | 
					            if (remove_columns.empty()) {
 | 
				
			||||||
 | 
					                if (!dealloc)
 | 
				
			||||||
 | 
					                    make_clone(filtered_res, filtered_res, acc);
 | 
				
			||||||
 | 
					                acc.push_back(instruction::mk_filter_interpreted(filtered_res, app_renamed));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                reg_idx new_reg;
 | 
				
			||||||
 | 
					                std::sort(remove_columns.begin(), remove_columns.end());
 | 
				
			||||||
 | 
					                make_filter_interpreted_and_project(filtered_res, app_renamed, remove_columns, new_reg, acc);
 | 
				
			||||||
 | 
					                if (dealloc)
 | 
				
			||||||
 | 
					                    make_dealloc_non_void(filtered_res, acc);
 | 
				
			||||||
 | 
					                filtered_res = new_reg;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            dealloc = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					        // this version is potentially better for non-symbolic tables,
 | 
				
			||||||
 | 
					        // since it constraints each unbound column at a time (reducing the
 | 
				
			||||||
 | 
					        // size of intermediate results).
 | 
				
			||||||
        unsigned ft_len=r->get_tail_size(); //full tail
 | 
					        unsigned ft_len=r->get_tail_size(); //full tail
 | 
				
			||||||
        for(unsigned tail_index=ut_len; tail_index<ft_len; tail_index++) {
 | 
					        for(unsigned tail_index=ut_len; tail_index<ft_len; tail_index++) {
 | 
				
			||||||
            app * t = r->get_tail(tail_index);
 | 
					            app * t = r->get_tail(tail_index);
 | 
				
			||||||
            var_idx_set t_vars;
 | 
					            ptr_vector<sort> t_vars;
 | 
				
			||||||
            ast_manager & m = m_context.get_manager();
 | 
					            ::get_free_vars(t, t_vars);
 | 
				
			||||||
            collect_vars(m, t, t_vars);
 | 
					            
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(t_vars.empty()) {
 | 
					            if(t_vars.empty()) {
 | 
				
			||||||
                expr_ref simplified(m);
 | 
					                expr_ref simplified(m);
 | 
				
			||||||
                m_context.get_rewriter()(t, simplified);
 | 
					                m_context.get_rewriter()(t, simplified);
 | 
				
			||||||
| 
						 | 
					@ -601,46 +760,32 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //determine binding size
 | 
					            //determine binding size
 | 
				
			||||||
            unsigned max_var=0;
 | 
					            while (!t_vars.back()) {
 | 
				
			||||||
            var_idx_set::iterator vit = t_vars.begin();
 | 
					                t_vars.pop_back();
 | 
				
			||||||
            var_idx_set::iterator vend = t_vars.end();
 | 
					 | 
				
			||||||
            for(; vit!=vend; ++vit) {
 | 
					 | 
				
			||||||
                unsigned v = *vit;
 | 
					 | 
				
			||||||
                if(v>max_var) { max_var = v; }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            unsigned max_var = t_vars.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //create binding
 | 
					            //create binding
 | 
				
			||||||
            expr_ref_vector binding(m);
 | 
					            expr_ref_vector binding(m);
 | 
				
			||||||
            binding.resize(max_var+1);
 | 
					            binding.resize(max_var+1);
 | 
				
			||||||
            vit = t_vars.begin();
 | 
					            
 | 
				
			||||||
            for(; vit!=vend; ++vit) {
 | 
					            for(unsigned v = 0; v < t_vars.size(); ++v) {
 | 
				
			||||||
                unsigned v = *vit;
 | 
					                if (!t_vars[v]) {
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                int2ints::entry * e = var_indexes.find_core(v);
 | 
					                int2ints::entry * e = var_indexes.find_core(v);
 | 
				
			||||||
                if(!e) {
 | 
					                if(!e) {
 | 
				
			||||||
                    //we have an unbound variable, so we add an unbound column for it
 | 
					                    //we have an unbound variable, so we add an unbound column for it
 | 
				
			||||||
                    relation_sort unbound_sort = 0;
 | 
					                    relation_sort unbound_sort = t_vars[v];
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    for(unsigned hindex = 0; hindex<head_len; hindex++) {
 | 
					 | 
				
			||||||
                        expr * harg = h->get_arg(hindex);
 | 
					 | 
				
			||||||
                        if(!is_var(harg) || to_var(harg)->get_idx()!=v) {
 | 
					 | 
				
			||||||
                            continue;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        unbound_sort = to_var(harg)->get_sort();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    if(!unbound_sort) {
 | 
					 | 
				
			||||||
                        // the variable in the interpreted tail is neither bound in the 
 | 
					 | 
				
			||||||
                        // uninterpreted tail nor present in the head
 | 
					 | 
				
			||||||
                        std::stringstream sstm;
 | 
					 | 
				
			||||||
                        sstm << "rule with unbound variable #" << v << " in interpreted tail: ";                       
 | 
					 | 
				
			||||||
                        r->display(m_context, sstm);
 | 
					 | 
				
			||||||
                        throw default_exception(sstm.str());
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    reg_idx new_reg;
 | 
					                    reg_idx new_reg;
 | 
				
			||||||
                    TRACE("dl", tout << mk_pp(head_pred, m_context.get_manager()) << "\n";);
 | 
					                    TRACE("dl", tout << mk_pp(head_pred, m_context.get_manager()) << "\n";);
 | 
				
			||||||
                    make_add_unbound_column(r, 0, head_pred, filtered_res, unbound_sort, new_reg, acc);
 | 
					                    bool new_dealloc;
 | 
				
			||||||
 | 
					                    make_add_unbound_column(r, 0, head_pred, filtered_res, unbound_sort, new_reg, new_dealloc, acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    make_dealloc_non_void(filtered_res, acc);
 | 
					                    if (dealloc)
 | 
				
			||||||
 | 
					                        make_dealloc_non_void(filtered_res, acc);
 | 
				
			||||||
 | 
					                    dealloc = new_dealloc;
 | 
				
			||||||
                    filtered_res = new_reg;                // here filtered_res value gets changed !!
 | 
					                    filtered_res = new_reg;                // here filtered_res value gets changed !!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    unsigned unbound_column_index = single_res_expr.size();
 | 
					                    unsigned unbound_column_index = single_res_expr.size();
 | 
				
			||||||
| 
						 | 
					@ -658,8 +803,12 @@ namespace datalog {
 | 
				
			||||||
            expr_ref renamed(m);
 | 
					            expr_ref renamed(m);
 | 
				
			||||||
            m_context.get_var_subst()(t, binding.size(), binding.c_ptr(), renamed);
 | 
					            m_context.get_var_subst()(t, binding.size(), binding.c_ptr(), renamed);
 | 
				
			||||||
            app_ref app_renamed(to_app(renamed), m);
 | 
					            app_ref app_renamed(to_app(renamed), m);
 | 
				
			||||||
 | 
					            if (!dealloc)
 | 
				
			||||||
 | 
					                make_clone(filtered_res, filtered_res, acc);
 | 
				
			||||||
            acc.push_back(instruction::mk_filter_interpreted(filtered_res, app_renamed));
 | 
					            acc.push_back(instruction::mk_filter_interpreted(filtered_res, app_renamed));
 | 
				
			||||||
 | 
					            dealloc = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            //put together the columns of head relation
 | 
					            //put together the columns of head relation
 | 
				
			||||||
| 
						 | 
					@ -703,19 +852,20 @@ namespace datalog {
 | 
				
			||||||
            SASSERT(head_acis.size()==head_len);
 | 
					            SASSERT(head_acis.size()==head_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            reg_idx new_head_reg;
 | 
					            reg_idx new_head_reg;
 | 
				
			||||||
            make_assembling_code(r, head_pred, filtered_res, head_acis, new_head_reg, acc);
 | 
					            make_assembling_code(r, head_pred, filtered_res, head_acis, new_head_reg, dealloc, acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //update the head relation
 | 
					            //update the head relation
 | 
				
			||||||
            make_union(new_head_reg, head_reg, delta_reg, use_widening, acc);
 | 
					            make_union(new_head_reg, head_reg, delta_reg, use_widening, acc);
 | 
				
			||||||
            make_dealloc_non_void(new_head_reg, acc);
 | 
					            if (dealloc)
 | 
				
			||||||
 | 
					                make_dealloc_non_void(new_head_reg, acc);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    finish:
 | 
					//    finish:
 | 
				
			||||||
        m_instruction_observer.finish_rule();
 | 
					        m_instruction_observer.finish_rule();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void compiler::add_unbound_columns_for_negation(rule* r, func_decl* pred, reg_idx& single_res, ptr_vector<expr>& single_res_expr, 
 | 
					    void compiler::add_unbound_columns_for_negation(rule* r, func_decl* pred, reg_idx& single_res, expr_ref_vector& single_res_expr, 
 | 
				
			||||||
                                                    instruction_block & acc) {
 | 
					                                                    bool & dealloc, instruction_block & acc) {
 | 
				
			||||||
        uint_set pos_vars;
 | 
					        uint_set pos_vars;
 | 
				
			||||||
        u_map<expr*> neg_vars;
 | 
					        u_map<expr*> neg_vars;
 | 
				
			||||||
        ast_manager& m = m_context.get_manager();
 | 
					        ast_manager& m = m_context.get_manager();
 | 
				
			||||||
| 
						 | 
					@ -737,7 +887,7 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // populate positive variables:
 | 
					        // populate positive variables:
 | 
				
			||||||
        for (unsigned i = 0; i < single_res_expr.size(); ++i) {
 | 
					        for (unsigned i = 0; i < single_res_expr.size(); ++i) {
 | 
				
			||||||
            expr* e = single_res_expr[i];
 | 
					            expr* e = single_res_expr[i].get();
 | 
				
			||||||
            if (is_var(e)) {
 | 
					            if (is_var(e)) {
 | 
				
			||||||
                pos_vars.insert(to_var(e)->get_idx());
 | 
					                pos_vars.insert(to_var(e)->get_idx());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -749,7 +899,13 @@ namespace datalog {
 | 
				
			||||||
            expr* e = it->m_value;
 | 
					            expr* e = it->m_value;
 | 
				
			||||||
            if (!pos_vars.contains(v)) {
 | 
					            if (!pos_vars.contains(v)) {
 | 
				
			||||||
                single_res_expr.push_back(e);
 | 
					                single_res_expr.push_back(e);
 | 
				
			||||||
                make_add_unbound_column(r, v, pred, single_res, m.get_sort(e), single_res, acc);
 | 
					                reg_idx new_single_res;
 | 
				
			||||||
 | 
					                bool new_dealloc;
 | 
				
			||||||
 | 
					                make_add_unbound_column(r, v, pred, single_res, m.get_sort(e), new_single_res, new_dealloc, acc);
 | 
				
			||||||
 | 
					                if (dealloc)
 | 
				
			||||||
 | 
					                    make_dealloc_non_void(single_res, acc);
 | 
				
			||||||
 | 
					                dealloc = new_dealloc;
 | 
				
			||||||
 | 
					                single_res = new_single_res;
 | 
				
			||||||
                TRACE("dl", tout << "Adding unbound column: " << mk_pp(e, m) << "\n";);
 | 
					                TRACE("dl", tout << "Adding unbound column: " << mk_pp(e, m) << "\n";);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -761,7 +917,7 @@ namespace datalog {
 | 
				
			||||||
        typedef svector<tail_delta_info> tail_delta_infos;
 | 
					        typedef svector<tail_delta_info> tail_delta_infos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned rule_len = r->get_uninterpreted_tail_size();
 | 
					        unsigned rule_len = r->get_uninterpreted_tail_size();
 | 
				
			||||||
        reg_idx head_reg = m_pred_regs.find(r->get_head()->get_decl());
 | 
					        reg_idx head_reg = m_pred_regs.find(r->get_decl());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        svector<reg_idx> tail_regs;
 | 
					        svector<reg_idx> tail_regs;
 | 
				
			||||||
        tail_delta_infos tail_deltas;
 | 
					        tail_delta_infos tail_deltas;
 | 
				
			||||||
| 
						 | 
					@ -804,13 +960,13 @@ namespace datalog {
 | 
				
			||||||
        ast_mark m_visited;
 | 
					        ast_mark m_visited;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void traverse(T v) {
 | 
					        void traverse(T v) {
 | 
				
			||||||
            SASSERT(!m_stack_content.is_marked(v));
 | 
					            SASSERT(!m_stack_content.is_marked(v)); 
 | 
				
			||||||
            if(m_visited.is_marked(v) || m_removed.contains(v)) {
 | 
					            if(m_visited.is_marked(v) || m_removed.contains(v)) { 
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            m_stack.push_back(v);
 | 
					            m_stack.push_back(v);
 | 
				
			||||||
            m_stack_content.mark(v, true);
 | 
					            m_stack_content.mark(v, true); 
 | 
				
			||||||
            m_visited.mark(v, true);
 | 
					            m_visited.mark(v, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const item_set & deps = m_deps.get_deps(v);
 | 
					            const item_set & deps = m_deps.get_deps(v);
 | 
				
			||||||
| 
						 | 
					@ -818,7 +974,7 @@ namespace datalog {
 | 
				
			||||||
            item_set::iterator end = deps.end();
 | 
					            item_set::iterator end = deps.end();
 | 
				
			||||||
            for(; it!=end; ++it) {
 | 
					            for(; it!=end; ++it) {
 | 
				
			||||||
                T d = *it;
 | 
					                T d = *it;
 | 
				
			||||||
                if(m_stack_content.is_marked(d)) {
 | 
					                if(m_stack_content.is_marked(d)) { 
 | 
				
			||||||
                    //TODO: find the best vertex to remove in the cycle
 | 
					                    //TODO: find the best vertex to remove in the cycle
 | 
				
			||||||
                    m_removed.insert(v);
 | 
					                    m_removed.insert(v);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
| 
						 | 
					@ -828,8 +984,9 @@ namespace datalog {
 | 
				
			||||||
            SASSERT(m_stack.back()==v);
 | 
					            SASSERT(m_stack.back()==v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            m_stack.pop_back();
 | 
					            m_stack.pop_back();
 | 
				
			||||||
            m_stack_content.mark(v, false);
 | 
					            m_stack_content.mark(v, false); 
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        cycle_breaker(rule_dependencies & deps, item_set & removed) 
 | 
					        cycle_breaker(rule_dependencies & deps, item_set & removed) 
 | 
				
			||||||
            : m_deps(deps), m_removed(removed) { SASSERT(removed.empty()); }
 | 
					            : m_deps(deps), m_removed(removed) { SASSERT(removed.empty()); }
 | 
				
			||||||
| 
						 | 
					@ -885,13 +1042,47 @@ namespace datalog {
 | 
				
			||||||
            rule_vector::const_iterator rend = pred_rules.end();
 | 
					            rule_vector::const_iterator rend = pred_rules.end();
 | 
				
			||||||
            for(; rit!=rend; ++rit) {
 | 
					            for(; rit!=rend; ++rit) {
 | 
				
			||||||
                rule * r = *rit;
 | 
					                rule * r = *rit;
 | 
				
			||||||
                SASSERT(head_pred==r->get_head()->get_decl());
 | 
					                SASSERT(head_pred==r->get_decl());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                compile_rule_evaluation(r, input_deltas, d_head_reg, widen_predicate_in_loop, acc);
 | 
					                compile_rule_evaluation(r, input_deltas, d_head_reg, widen_predicate_in_loop, acc);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void compiler::compile_preds_init(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
 | 
				
			||||||
 | 
					            const pred2idx * input_deltas, const pred2idx & output_deltas, instruction_block & acc) {
 | 
				
			||||||
 | 
					        func_decl_vector::const_iterator hpit = head_preds.begin();
 | 
				
			||||||
 | 
					        func_decl_vector::const_iterator hpend = head_preds.end();
 | 
				
			||||||
 | 
					        reg_idx void_reg = execution_context::void_register;
 | 
				
			||||||
 | 
					        for(; hpit!=hpend; ++hpit) {
 | 
				
			||||||
 | 
					            func_decl * head_pred = *hpit;
 | 
				
			||||||
 | 
					            const rule_vector & pred_rules = m_rule_set.get_predicate_rules(head_pred);
 | 
				
			||||||
 | 
					            rule_vector::const_iterator rit = pred_rules.begin();
 | 
				
			||||||
 | 
					            rule_vector::const_iterator rend = pred_rules.end();
 | 
				
			||||||
 | 
					            unsigned stratum = m_rule_set.get_predicate_strat(head_pred);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for(; rit != rend; ++rit) {
 | 
				
			||||||
 | 
					                rule * r = *rit;
 | 
				
			||||||
 | 
					                SASSERT(head_pred==r->get_decl());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (unsigned i = 0; i < r->get_uninterpreted_tail_size(); ++i) {
 | 
				
			||||||
 | 
					                    unsigned stratum1 = m_rule_set.get_predicate_strat(r->get_decl(i));
 | 
				
			||||||
 | 
					                    if (stratum1 >= stratum) {
 | 
				
			||||||
 | 
					                        goto next_loop;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                compile_rule_evaluation(r, input_deltas, void_reg, false, acc);
 | 
				
			||||||
 | 
					            next_loop:
 | 
				
			||||||
 | 
					                ;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            reg_idx d_head_reg;
 | 
				
			||||||
 | 
					            if (output_deltas.find(head_pred, d_head_reg)) {
 | 
				
			||||||
 | 
					                acc.push_back(instruction::mk_clone(m_pred_regs.find(head_pred), d_head_reg));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void compiler::make_inloop_delta_transition(const pred2idx & global_head_deltas, 
 | 
					    void compiler::make_inloop_delta_transition(const pred2idx & global_head_deltas, 
 | 
				
			||||||
            const pred2idx & global_tail_deltas, const pred2idx & local_deltas, instruction_block & acc) {
 | 
					            const pred2idx & global_tail_deltas, const pred2idx & local_deltas, instruction_block & acc) {
 | 
				
			||||||
        //move global head deltas into tail ones
 | 
					        //move global head deltas into tail ones
 | 
				
			||||||
| 
						 | 
					@ -942,7 +1133,7 @@ namespace datalog {
 | 
				
			||||||
            const pred2idx * input_deltas, const pred2idx & output_deltas, 
 | 
					            const pred2idx * input_deltas, const pred2idx & output_deltas, 
 | 
				
			||||||
            bool add_saturation_marks, instruction_block & acc) {
 | 
					            bool add_saturation_marks, instruction_block & acc) {
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if(!output_deltas.empty()) {
 | 
					        if (!output_deltas.empty()) {
 | 
				
			||||||
            func_decl_set::iterator hpit = head_preds.begin();
 | 
					            func_decl_set::iterator hpit = head_preds.begin();
 | 
				
			||||||
            func_decl_set::iterator hpend = head_preds.end();
 | 
					            func_decl_set::iterator hpend = head_preds.end();
 | 
				
			||||||
            for(; hpit!=hpend; ++hpit) {
 | 
					            for(; hpit!=hpend; ++hpit) {
 | 
				
			||||||
| 
						 | 
					@ -956,12 +1147,17 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        func_decl_vector preds_vector;
 | 
					        func_decl_vector preds_vector;
 | 
				
			||||||
        func_decl_set global_deltas;
 | 
					        func_decl_set global_deltas_dummy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        detect_chains(head_preds, preds_vector, global_deltas);
 | 
					        detect_chains(head_preds, preds_vector, global_deltas_dummy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					          FIXME: right now we use all preds as global deltas for correctness purposes
 | 
				
			||||||
        func_decl_set local_deltas(head_preds);
 | 
					        func_decl_set local_deltas(head_preds);
 | 
				
			||||||
        set_difference(local_deltas, global_deltas);
 | 
					        set_difference(local_deltas, global_deltas);
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        func_decl_set local_deltas;
 | 
				
			||||||
 | 
					        func_decl_set global_deltas(head_preds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pred2idx d_global_src;  //these deltas serve as sources of tuples for rule evaluation inside the loop
 | 
					        pred2idx d_global_src;  //these deltas serve as sources of tuples for rule evaluation inside the loop
 | 
				
			||||||
        get_fresh_registers(global_deltas, d_global_src);
 | 
					        get_fresh_registers(global_deltas, d_global_src);
 | 
				
			||||||
| 
						 | 
					@ -979,7 +1175,8 @@ namespace datalog {
 | 
				
			||||||
        func_decl_set empty_func_decl_set;
 | 
					        func_decl_set empty_func_decl_set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //generate code for the initial run
 | 
					        //generate code for the initial run
 | 
				
			||||||
        compile_preds(preds_vector, empty_func_decl_set, input_deltas, d_global_src, acc);
 | 
					        // compile_preds(preds_vector, empty_func_decl_set, input_deltas, d_global_src, acc);
 | 
				
			||||||
 | 
					        compile_preds_init(preds_vector, empty_func_decl_set, input_deltas, d_global_src, acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (compile_with_widening()) {
 | 
					        if (compile_with_widening()) {
 | 
				
			||||||
            compile_loop(preds_vector, global_deltas, d_global_tgt, d_global_src, d_local, acc);
 | 
					            compile_loop(preds_vector, global_deltas, d_global_tgt, d_global_src, d_local, acc);
 | 
				
			||||||
| 
						 | 
					@ -1040,7 +1237,7 @@ namespace datalog {
 | 
				
			||||||
        rule_vector::const_iterator end = rules.end();
 | 
					        rule_vector::const_iterator end = rules.end();
 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					        for (; it != end; ++it) {
 | 
				
			||||||
            rule * r = *it;
 | 
					            rule * r = *it;
 | 
				
			||||||
            SASSERT(r->get_head()->get_decl()==head_pred);
 | 
					            SASSERT(r->get_decl()==head_pred);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            compile_rule_evaluation(r, input_deltas, output_delta, false, acc);
 | 
					            compile_rule_evaluation(r, input_deltas, output_delta, false, acc);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1113,7 +1310,7 @@ namespace datalog {
 | 
				
			||||||
        //load predicate data
 | 
					        //load predicate data
 | 
				
			||||||
        for(unsigned i=0;i<rule_cnt;i++) {
 | 
					        for(unsigned i=0;i<rule_cnt;i++) {
 | 
				
			||||||
            const rule * r = m_rule_set.get_rule(i);
 | 
					            const rule * r = m_rule_set.get_rule(i);
 | 
				
			||||||
            ensure_predicate_loaded(r->get_head()->get_decl(), acc);
 | 
					            ensure_predicate_loaded(r->get_decl(), acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            unsigned rule_len = r->get_uninterpreted_tail_size();
 | 
					            unsigned rule_len = r->get_uninterpreted_tail_size();
 | 
				
			||||||
            for(unsigned j=0;j<rule_len;j++) {
 | 
					            for(unsigned j=0;j<rule_len;j++) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ namespace datalog {
 | 
				
			||||||
        typedef hashtable<unsigned, u_hash, u_eq> int_set;
 | 
					        typedef hashtable<unsigned, u_hash, u_eq> int_set;
 | 
				
			||||||
        typedef u_map<unsigned> int2int;
 | 
					        typedef u_map<unsigned> int2int;
 | 
				
			||||||
        typedef u_map<unsigned_vector> int2ints;
 | 
					        typedef u_map<unsigned_vector> int2ints;
 | 
				
			||||||
        typedef map<func_decl *, reg_idx, ptr_hash<func_decl>,ptr_eq<func_decl> > pred2idx;
 | 
					        typedef obj_map<func_decl, reg_idx> pred2idx;
 | 
				
			||||||
        typedef unsigned_vector var_vector;
 | 
					        typedef unsigned_vector var_vector;
 | 
				
			||||||
        typedef ptr_vector<func_decl> func_decl_vector;
 | 
					        typedef ptr_vector<func_decl> func_decl_vector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,6 +114,8 @@ namespace datalog {
 | 
				
			||||||
        reg_idx m_new_reg;
 | 
					        reg_idx m_new_reg;
 | 
				
			||||||
        vector<relation_signature> m_reg_signatures;
 | 
					        vector<relation_signature> m_reg_signatures;
 | 
				
			||||||
        obj_pair_map<sort, app, reg_idx> m_constant_registers;
 | 
					        obj_pair_map<sort, app, reg_idx> m_constant_registers;
 | 
				
			||||||
 | 
					        obj_pair_map<sort, decl, reg_idx> m_total_registers;
 | 
				
			||||||
 | 
					        obj_map<decl, reg_idx> m_empty_tables_registers;
 | 
				
			||||||
        instruction_observer m_instruction_observer;
 | 
					        instruction_observer m_instruction_observer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
| 
						 | 
					@ -143,6 +145,8 @@ namespace datalog {
 | 
				
			||||||
            instruction_block & acc);
 | 
					            instruction_block & acc);
 | 
				
			||||||
        void make_join_project(reg_idx t1, reg_idx t2, const variable_intersection & vars, 
 | 
					        void make_join_project(reg_idx t1, reg_idx t2, const variable_intersection & vars, 
 | 
				
			||||||
            const unsigned_vector & removed_cols, reg_idx & result, instruction_block & acc);
 | 
					            const unsigned_vector & removed_cols, reg_idx & result, instruction_block & acc);
 | 
				
			||||||
 | 
					        void make_filter_interpreted_and_project(reg_idx src, app_ref & cond,
 | 
				
			||||||
 | 
					            const unsigned_vector & removed_cols, reg_idx & result, instruction_block & acc);
 | 
				
			||||||
        void make_select_equal_and_project(reg_idx src, const relation_element & val, unsigned col,
 | 
					        void make_select_equal_and_project(reg_idx src, const relation_element & val, unsigned col,
 | 
				
			||||||
            reg_idx & result, instruction_block & acc);
 | 
					            reg_idx & result, instruction_block & acc);
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
| 
						 | 
					@ -163,20 +167,20 @@ namespace datalog {
 | 
				
			||||||
           with empty signature.
 | 
					           with empty signature.
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
        void make_assembling_code(rule* compiled_rule, func_decl* head_pred, reg_idx src, const svector<assembling_column_info> & acis0,
 | 
					        void make_assembling_code(rule* compiled_rule, func_decl* head_pred, reg_idx src, const svector<assembling_column_info> & acis0,
 | 
				
			||||||
            reg_idx & result, instruction_block & acc);
 | 
					            reg_idx & result, bool & dealloc, instruction_block & acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void make_dealloc_non_void(reg_idx r, instruction_block & acc);
 | 
					        void make_dealloc_non_void(reg_idx r, instruction_block & acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void make_add_constant_column(func_decl* pred, reg_idx src, const relation_sort & s, const relation_element & val,
 | 
					        void make_add_constant_column(func_decl* pred, reg_idx src, const relation_sort & s, const relation_element & val,
 | 
				
			||||||
            reg_idx & result, instruction_block & acc);
 | 
					            reg_idx & result, bool & dealloc, instruction_block & acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void make_add_unbound_column(rule* compiled_rule, unsigned col_idx, func_decl* pred, reg_idx src, const relation_sort & s, reg_idx & result, 
 | 
					        void make_add_unbound_column(rule* compiled_rule, unsigned col_idx, func_decl* pred, reg_idx src, const relation_sort & s, reg_idx & result, 
 | 
				
			||||||
            instruction_block & acc);
 | 
					            bool & dealloc, instruction_block & acc);
 | 
				
			||||||
        void make_full_relation(func_decl* pred, const relation_signature & sig, reg_idx & result, 
 | 
					        void make_full_relation(func_decl* pred, const relation_signature & sig, reg_idx & result, 
 | 
				
			||||||
            instruction_block & acc);
 | 
					            instruction_block & acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void add_unbound_columns_for_negation(rule* compiled_rule, func_decl* pred, reg_idx& single_res, ptr_vector<expr>& single_res_expr,
 | 
					        void add_unbound_columns_for_negation(rule* compiled_rule, func_decl* pred, reg_idx& single_res, expr_ref_vector& single_res_expr,
 | 
				
			||||||
                                              instruction_block& acc);
 | 
					                                              bool & dealloc, instruction_block& acc);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        void make_duplicate_column(reg_idx src, unsigned col, reg_idx & result, instruction_block & acc);
 | 
					        void make_duplicate_column(reg_idx src, unsigned col, reg_idx & result, instruction_block & acc);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					@ -209,6 +213,12 @@ namespace datalog {
 | 
				
			||||||
        void compile_preds(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
 | 
					        void compile_preds(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
 | 
				
			||||||
            const pred2idx * input_deltas, const pred2idx & output_deltas, instruction_block & acc);
 | 
					            const pred2idx * input_deltas, const pred2idx & output_deltas, instruction_block & acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					           \brief Generate code to evaluate predicates in a stratum based on their non-recursive rules.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        void compile_preds_init(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
 | 
				
			||||||
 | 
					            const pred2idx * input_deltas, const pred2idx & output_deltas, instruction_block & acc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void make_inloop_delta_transition(const pred2idx & global_head_deltas, 
 | 
					        void make_inloop_delta_transition(const pred2idx & global_head_deltas, 
 | 
				
			||||||
            const pred2idx & global_tail_deltas, const pred2idx & local_deltas, instruction_block & acc);
 | 
					            const pred2idx & global_tail_deltas, const pred2idx & local_deltas, instruction_block & acc);
 | 
				
			||||||
        void compile_loop(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
 | 
					        void compile_loop(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,6 @@ Revision History:
 | 
				
			||||||
#include"for_each_expr.h"
 | 
					#include"for_each_expr.h"
 | 
				
			||||||
#include"ast_smt_pp.h"
 | 
					#include"ast_smt_pp.h"
 | 
				
			||||||
#include"ast_smt2_pp.h"
 | 
					#include"ast_smt2_pp.h"
 | 
				
			||||||
#include"expr_functors.h"
 | 
					 | 
				
			||||||
#include"dl_mk_partial_equiv.h"
 | 
					#include"dl_mk_partial_equiv.h"
 | 
				
			||||||
#include"dl_mk_bit_blast.h"
 | 
					#include"dl_mk_bit_blast.h"
 | 
				
			||||||
#include"dl_mk_array_blast.h"
 | 
					#include"dl_mk_array_blast.h"
 | 
				
			||||||
| 
						 | 
					@ -49,7 +48,6 @@ Revision History:
 | 
				
			||||||
#include"dl_mk_quantifier_abstraction.h"
 | 
					#include"dl_mk_quantifier_abstraction.h"
 | 
				
			||||||
#include"dl_mk_quantifier_instantiation.h"
 | 
					#include"dl_mk_quantifier_instantiation.h"
 | 
				
			||||||
#include"datatype_decl_plugin.h"
 | 
					#include"datatype_decl_plugin.h"
 | 
				
			||||||
#include"expr_abstract.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace datalog {
 | 
					namespace datalog {
 | 
				
			||||||
| 
						 | 
					@ -226,12 +224,17 @@ namespace datalog {
 | 
				
			||||||
        m_rewriter(m),
 | 
					        m_rewriter(m),
 | 
				
			||||||
        m_var_subst(m),
 | 
					        m_var_subst(m),
 | 
				
			||||||
        m_rule_manager(*this),
 | 
					        m_rule_manager(*this),
 | 
				
			||||||
 | 
					        m_elim_unused_vars(m),
 | 
				
			||||||
 | 
					        m_abstractor(m),
 | 
				
			||||||
 | 
					        m_contains_p(*this),
 | 
				
			||||||
 | 
					        m_check_pred(m_contains_p, m),
 | 
				
			||||||
        m_transf(*this),
 | 
					        m_transf(*this),
 | 
				
			||||||
        m_trail(*this),
 | 
					        m_trail(*this),
 | 
				
			||||||
        m_pinned(m),
 | 
					        m_pinned(m),
 | 
				
			||||||
        m_vars(m),
 | 
					        m_vars(m),
 | 
				
			||||||
        m_rule_set(*this),
 | 
					        m_rule_set(*this),
 | 
				
			||||||
        m_transformed_rule_set(*this),
 | 
					        m_transformed_rule_set(*this),
 | 
				
			||||||
 | 
					        m_rule_fmls_head(0),
 | 
				
			||||||
        m_rule_fmls(m),
 | 
					        m_rule_fmls(m),
 | 
				
			||||||
        m_background(m),
 | 
					        m_background(m),
 | 
				
			||||||
        m_mc(0),
 | 
					        m_mc(0),
 | 
				
			||||||
| 
						 | 
					@ -241,8 +244,6 @@ namespace datalog {
 | 
				
			||||||
        m_last_answer(m),
 | 
					        m_last_answer(m),
 | 
				
			||||||
        m_engine(LAST_ENGINE),
 | 
					        m_engine(LAST_ENGINE),
 | 
				
			||||||
        m_cancel(false) {
 | 
					        m_cancel(false) {
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        //register plugins for builtin tables
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context::~context() {
 | 
					    context::~context() {
 | 
				
			||||||
| 
						 | 
					@ -252,6 +253,9 @@ namespace datalog {
 | 
				
			||||||
    void context::reset() {
 | 
					    void context::reset() {
 | 
				
			||||||
        m_trail.reset();
 | 
					        m_trail.reset();
 | 
				
			||||||
        m_rule_set.reset();
 | 
					        m_rule_set.reset();
 | 
				
			||||||
 | 
					        m_rule_fmls_head = 0;
 | 
				
			||||||
 | 
					        m_rule_fmls.reset();
 | 
				
			||||||
 | 
					        m_rule_names.reset();
 | 
				
			||||||
        m_argument_var_names.reset();
 | 
					        m_argument_var_names.reset();
 | 
				
			||||||
        m_preds.reset();
 | 
					        m_preds.reset();
 | 
				
			||||||
        m_preds_by_name.reset();
 | 
					        m_preds_by_name.reset();
 | 
				
			||||||
| 
						 | 
					@ -270,15 +274,11 @@ namespace datalog {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context::sort_domain & context::get_sort_domain(relation_sort s) {
 | 
					    context::sort_domain & context::get_sort_domain(relation_sort s) {
 | 
				
			||||||
        sort_domain * dom;
 | 
					        return *m_sorts.find(s);
 | 
				
			||||||
        TRUSTME( m_sorts.find(s, dom) );
 | 
					 | 
				
			||||||
        return *dom;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const context::sort_domain & context::get_sort_domain(relation_sort s) const {
 | 
					    const context::sort_domain & context::get_sort_domain(relation_sort s) const {
 | 
				
			||||||
        sort_domain * dom;
 | 
					        return *m_sorts.find(s);
 | 
				
			||||||
        TRUSTME( m_sorts.find(s, dom) );
 | 
					 | 
				
			||||||
        return *dom;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::register_finite_sort(sort * s, sort_kind k) {
 | 
					    void context::register_finite_sort(sort * s, sort_kind k) {
 | 
				
			||||||
| 
						 | 
					@ -298,10 +298,6 @@ namespace datalog {
 | 
				
			||||||
        m_sorts.insert(s, dom);
 | 
					        m_sorts.insert(s, dom);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool context::is_predicate(func_decl * pred) const {
 | 
					 | 
				
			||||||
        return m_preds.contains(pred);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void context::register_variable(func_decl* var) {
 | 
					    void context::register_variable(func_decl* var) {
 | 
				
			||||||
        m_vars.push_back(m.mk_const(var));
 | 
					        m_vars.push_back(m.mk_const(var));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -309,18 +305,19 @@ namespace datalog {
 | 
				
			||||||
    expr_ref context::bind_variables(expr* fml, bool is_forall) {
 | 
					    expr_ref context::bind_variables(expr* fml, bool is_forall) {
 | 
				
			||||||
        expr_ref result(m);
 | 
					        expr_ref result(m);
 | 
				
			||||||
        app_ref_vector const & vars = m_vars;
 | 
					        app_ref_vector const & vars = m_vars;
 | 
				
			||||||
 | 
					        rule_manager& rm = get_rule_manager();
 | 
				
			||||||
        if (vars.empty()) {
 | 
					        if (vars.empty()) {
 | 
				
			||||||
            result = fml;
 | 
					            result = fml;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            ptr_vector<sort> sorts;
 | 
					            m_names.reset();
 | 
				
			||||||
            expr_abstract(m, 0, vars.size(), reinterpret_cast<expr*const*>(vars.c_ptr()), fml, result);
 | 
					            m_abstractor(0, vars.size(), reinterpret_cast<expr*const*>(vars.c_ptr()), fml, result);
 | 
				
			||||||
            get_free_vars(result, sorts);
 | 
					            rm.collect_vars(result);
 | 
				
			||||||
 | 
					            ptr_vector<sort>& sorts = rm.get_var_sorts();
 | 
				
			||||||
            if (sorts.empty()) {
 | 
					            if (sorts.empty()) {
 | 
				
			||||||
                result = fml;
 | 
					                result = fml;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
                svector<symbol> names;
 | 
					 | 
				
			||||||
                for (unsigned i = 0; i < sorts.size(); ++i) {
 | 
					                for (unsigned i = 0; i < sorts.size(); ++i) {
 | 
				
			||||||
                    if (!sorts[i]) {
 | 
					                    if (!sorts[i]) {
 | 
				
			||||||
                        if (i < vars.size()) { 
 | 
					                        if (i < vars.size()) { 
 | 
				
			||||||
| 
						 | 
					@ -331,29 +328,36 @@ namespace datalog {
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if (i < vars.size()) {
 | 
					                    if (i < vars.size()) {
 | 
				
			||||||
                        names.push_back(vars[i]->get_decl()->get_name());
 | 
					                        m_names.push_back(vars[i]->get_decl()->get_name());
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else {
 | 
					                    else {
 | 
				
			||||||
                        names.push_back(symbol(i));
 | 
					                        m_names.push_back(symbol(i));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                quantifier_ref q(m);
 | 
					                quantifier_ref q(m);
 | 
				
			||||||
                sorts.reverse();
 | 
					                sorts.reverse();
 | 
				
			||||||
                q = m.mk_quantifier(is_forall, sorts.size(), sorts.c_ptr(), names.c_ptr(), result); 
 | 
					                q = m.mk_quantifier(is_forall, sorts.size(), sorts.c_ptr(), m_names.c_ptr(), result); 
 | 
				
			||||||
                elim_unused_vars(m, q, result);
 | 
					                m_elim_unused_vars(q, result);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::register_predicate(func_decl * decl, bool named) {
 | 
					    void context::register_predicate(func_decl * decl, bool named) {
 | 
				
			||||||
        if (m_preds.contains(decl)) {
 | 
					        if (!is_predicate(decl)) {
 | 
				
			||||||
            return;
 | 
					            m_pinned.push_back(decl);
 | 
				
			||||||
 | 
					            m_preds.insert(decl);
 | 
				
			||||||
 | 
					            if (named) {
 | 
				
			||||||
 | 
					                m_preds_by_name.insert(decl->get_name(), decl);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        m_pinned.push_back(decl);
 | 
					    }
 | 
				
			||||||
        m_preds.insert(decl);
 | 
					
 | 
				
			||||||
        if (named) {
 | 
					    void context::restrict_predicates(func_decl_set const& preds) {
 | 
				
			||||||
            m_preds_by_name.insert(decl->get_name(), decl);
 | 
					        m_preds.reset();
 | 
				
			||||||
 | 
					        func_decl_set::iterator it = preds.begin(), end = preds.end();
 | 
				
			||||||
 | 
					        for (; it != end; ++it) {
 | 
				
			||||||
 | 
					            m_preds.insert(*it);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -447,21 +451,6 @@ namespace datalog {
 | 
				
			||||||
        return new_pred;
 | 
					        return new_pred;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::set_output_predicate(func_decl * pred) { 
 | 
					 | 
				
			||||||
        ensure_rel();
 | 
					 | 
				
			||||||
        m_rel->set_output_predicate(pred);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool context::is_output_predicate(func_decl * pred) {
 | 
					 | 
				
			||||||
        ensure_rel();
 | 
					 | 
				
			||||||
        return m_rel->is_output_predicate(pred); 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const decl_set & context::get_output_predicates() { 
 | 
					 | 
				
			||||||
        ensure_rel();
 | 
					 | 
				
			||||||
        return m_rel->get_output_predicates();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void context::add_rule(expr* rl, symbol const& name) {
 | 
					    void context::add_rule(expr* rl, symbol const& name) {
 | 
				
			||||||
        m_rule_fmls.push_back(rl);
 | 
					        m_rule_fmls.push_back(rl);
 | 
				
			||||||
        m_rule_names.push_back(name);
 | 
					        m_rule_names.push_back(name);
 | 
				
			||||||
| 
						 | 
					@ -469,16 +458,19 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::flush_add_rules() {
 | 
					    void context::flush_add_rules() {
 | 
				
			||||||
        datalog::rule_manager& rm = get_rule_manager();
 | 
					        datalog::rule_manager& rm = get_rule_manager();
 | 
				
			||||||
        datalog::rule_ref_vector rules(rm);
 | 
					 | 
				
			||||||
        scoped_proof_mode _scp(m, generate_proof_trace()?PGM_FINE:PGM_DISABLED);
 | 
					        scoped_proof_mode _scp(m, generate_proof_trace()?PGM_FINE:PGM_DISABLED);
 | 
				
			||||||
        for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
 | 
					        while (m_rule_fmls_head < m_rule_fmls.size()) {
 | 
				
			||||||
            expr* fml = m_rule_fmls[i].get();
 | 
					            expr* fml = m_rule_fmls[m_rule_fmls_head].get();
 | 
				
			||||||
            proof* p = generate_proof_trace()?m.mk_asserted(fml):0;
 | 
					            proof* p = generate_proof_trace()?m.mk_asserted(fml):0;
 | 
				
			||||||
            rm.mk_rule(fml, p, rules, m_rule_names[i]);
 | 
					            rm.mk_rule(fml, p, m_rule_set, m_rule_names[m_rule_fmls_head]);
 | 
				
			||||||
 | 
					            ++m_rule_fmls_head;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end();
 | 
				
			||||||
 | 
					        rule_ref r(m_rule_manager);
 | 
				
			||||||
 | 
					        for (; it != end; ++it) {
 | 
				
			||||||
 | 
					            r = *it;
 | 
				
			||||||
 | 
					            check_rule(r);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        add_rules(rules);
 | 
					 | 
				
			||||||
        m_rule_fmls.reset();
 | 
					 | 
				
			||||||
        m_rule_names.reset();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
| 
						 | 
					@ -487,25 +479,28 @@ namespace datalog {
 | 
				
			||||||
    // 
 | 
					    // 
 | 
				
			||||||
    void context::update_rule(expr* rl, symbol const& name) {
 | 
					    void context::update_rule(expr* rl, symbol const& name) {
 | 
				
			||||||
        datalog::rule_manager& rm = get_rule_manager();
 | 
					        datalog::rule_manager& rm = get_rule_manager();
 | 
				
			||||||
        datalog::rule_ref_vector rules(rm);
 | 
					 | 
				
			||||||
        proof* p = 0;
 | 
					        proof* p = 0;
 | 
				
			||||||
        if (generate_proof_trace()) {
 | 
					        if (generate_proof_trace()) {
 | 
				
			||||||
            p = m.mk_asserted(rl);
 | 
					            p = m.mk_asserted(rl);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        rm.mk_rule(rl, p, rules, name);
 | 
					        unsigned size_before = m_rule_set.get_num_rules();
 | 
				
			||||||
        if (rules.size() != 1) {
 | 
					        rm.mk_rule(rl, p, m_rule_set, name);
 | 
				
			||||||
 | 
					        unsigned size_after = m_rule_set.get_num_rules();
 | 
				
			||||||
 | 
					        if (size_before + 1 != size_after) {
 | 
				
			||||||
            std::stringstream strm;
 | 
					            std::stringstream strm;
 | 
				
			||||||
            strm << "Rule " << name << " has a non-trivial body. It cannot be modified";
 | 
					            strm << "Rule " << name << " has a non-trivial body. It cannot be modified";
 | 
				
			||||||
            throw default_exception(strm.str());
 | 
					            throw default_exception(strm.str());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        rule_ref r(rules[0].get(), rm);
 | 
					        // The new rule is inserted last:
 | 
				
			||||||
 | 
					        rule_ref r(m_rule_set.get_rule(size_before), rm);
 | 
				
			||||||
        rule_ref_vector const& rls = m_rule_set.get_rules();
 | 
					        rule_ref_vector const& rls = m_rule_set.get_rules();
 | 
				
			||||||
        rule* old_rule = 0;
 | 
					        rule* old_rule = 0;
 | 
				
			||||||
        for (unsigned i = 0; i < rls.size(); ++i) {
 | 
					        for (unsigned i = 0; i < size_before; ++i) {
 | 
				
			||||||
            if (rls[i]->name() == name) {
 | 
					            if (rls[i]->name() == name) {
 | 
				
			||||||
                if (old_rule) {                    
 | 
					                if (old_rule) {                    
 | 
				
			||||||
                    std::stringstream strm;
 | 
					                    std::stringstream strm;
 | 
				
			||||||
                    strm << "Rule " << name << " occurs twice. It cannot be modified";
 | 
					                    strm << "Rule " << name << " occurs twice. It cannot be modified";
 | 
				
			||||||
 | 
					                    m_rule_set.del_rule(r);
 | 
				
			||||||
                    throw default_exception(strm.str());
 | 
					                    throw default_exception(strm.str());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                old_rule = rls[i];                
 | 
					                old_rule = rls[i];                
 | 
				
			||||||
| 
						 | 
					@ -518,11 +513,11 @@ namespace datalog {
 | 
				
			||||||
                old_rule->display(*this, strm);
 | 
					                old_rule->display(*this, strm);
 | 
				
			||||||
                strm << "does not subsume new rule ";
 | 
					                strm << "does not subsume new rule ";
 | 
				
			||||||
                r->display(*this, strm);
 | 
					                r->display(*this, strm);
 | 
				
			||||||
 | 
					                m_rule_set.del_rule(r);
 | 
				
			||||||
                throw default_exception(strm.str());
 | 
					                throw default_exception(strm.str());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            m_rule_set.del_rule(old_rule);
 | 
					            m_rule_set.del_rule(old_rule);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        m_rule_set.add_rule(r);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool context::check_subsumes(rule const& stronger_rule, rule const& weaker_rule) {
 | 
					    bool context::check_subsumes(rule const& stronger_rule, rule const& weaker_rule) {
 | 
				
			||||||
| 
						 | 
					@ -559,6 +554,8 @@ namespace datalog {
 | 
				
			||||||
            throw default_exception("get_num_levels is not supported for bmc");
 | 
					            throw default_exception("get_num_levels is not supported for bmc");
 | 
				
			||||||
        case TAB_ENGINE:
 | 
					        case TAB_ENGINE:
 | 
				
			||||||
            throw default_exception("get_num_levels is not supported for tab");
 | 
					            throw default_exception("get_num_levels is not supported for tab");
 | 
				
			||||||
 | 
					        case CLP_ENGINE:
 | 
				
			||||||
 | 
					            throw default_exception("get_num_levels is not supported for clp");
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            throw default_exception("unknown engine");
 | 
					            throw default_exception("unknown engine");
 | 
				
			||||||
        } 
 | 
					        } 
 | 
				
			||||||
| 
						 | 
					@ -577,6 +574,8 @@ namespace datalog {
 | 
				
			||||||
            throw default_exception("operation is not supported for BMC engine");
 | 
					            throw default_exception("operation is not supported for BMC engine");
 | 
				
			||||||
        case TAB_ENGINE:
 | 
					        case TAB_ENGINE:
 | 
				
			||||||
            throw default_exception("operation is not supported for TAB engine");
 | 
					            throw default_exception("operation is not supported for TAB engine");
 | 
				
			||||||
 | 
					        case CLP_ENGINE:
 | 
				
			||||||
 | 
					            throw default_exception("operation is not supported for CLP engine");
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            throw default_exception("unknown engine");
 | 
					            throw default_exception("unknown engine");
 | 
				
			||||||
        } 
 | 
					        } 
 | 
				
			||||||
| 
						 | 
					@ -596,6 +595,8 @@ namespace datalog {
 | 
				
			||||||
            throw default_exception("operation is not supported for BMC engine");
 | 
					            throw default_exception("operation is not supported for BMC engine");
 | 
				
			||||||
        case TAB_ENGINE:
 | 
					        case TAB_ENGINE:
 | 
				
			||||||
            throw default_exception("operation is not supported for TAB engine");
 | 
					            throw default_exception("operation is not supported for TAB engine");
 | 
				
			||||||
 | 
					        case CLP_ENGINE:
 | 
				
			||||||
 | 
					            throw default_exception("operation is not supported for CLP engine");
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            throw default_exception("unknown engine");
 | 
					            throw default_exception("unknown engine");
 | 
				
			||||||
        } 
 | 
					        } 
 | 
				
			||||||
| 
						 | 
					@ -622,28 +623,16 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class context::contains_pred : public i_expr_pred {
 | 
					 | 
				
			||||||
        rule_manager const& m;
 | 
					 | 
				
			||||||
    public:
 | 
					 | 
				
			||||||
        contains_pred(rule_manager const& m): m(m) {}
 | 
					 | 
				
			||||||
        virtual ~contains_pred() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        virtual bool operator()(expr* e) {
 | 
					 | 
				
			||||||
            return is_app(e) && m.is_predicate(to_app(e));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::check_existential_tail(rule_ref& r) {
 | 
					    void context::check_existential_tail(rule_ref& r) {
 | 
				
			||||||
        unsigned ut_size = r->get_uninterpreted_tail_size();
 | 
					        unsigned ut_size = r->get_uninterpreted_tail_size();
 | 
				
			||||||
        unsigned t_size  = r->get_tail_size();   
 | 
					        unsigned t_size  = r->get_tail_size();   
 | 
				
			||||||
        contains_pred contains_p(get_rule_manager());
 | 
					 | 
				
			||||||
        check_pred check_pred(contains_p, get_manager());
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        TRACE("dl", r->display_smt2(get_manager(), tout); tout << "\n";);
 | 
					        TRACE("dl", r->display_smt2(get_manager(), tout); tout << "\n";);
 | 
				
			||||||
        for (unsigned i = ut_size; i < t_size; ++i) {
 | 
					        for (unsigned i = ut_size; i < t_size; ++i) {
 | 
				
			||||||
            app* t = r->get_tail(i);
 | 
					            app* t = r->get_tail(i);
 | 
				
			||||||
            TRACE("dl", tout << "checking: " << mk_ismt2_pp(t, get_manager()) << "\n";);
 | 
					            TRACE("dl", tout << "checking: " << mk_ismt2_pp(t, get_manager()) << "\n";);
 | 
				
			||||||
            if (check_pred(t)) {
 | 
					            if (m_check_pred(t)) {
 | 
				
			||||||
                std::ostringstream out;
 | 
					                std::ostringstream out;
 | 
				
			||||||
                out << "interpreted body " << mk_ismt2_pp(t, get_manager()) << " contains recursive predicate";
 | 
					                out << "interpreted body " << mk_ismt2_pp(t, get_manager()) << " contains recursive predicate";
 | 
				
			||||||
                throw default_exception(out.str());
 | 
					                throw default_exception(out.str());
 | 
				
			||||||
| 
						 | 
					@ -662,8 +651,7 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ast_manager& m = get_manager();
 | 
					        ast_manager& m = get_manager();
 | 
				
			||||||
        datalog::rule_manager& rm = get_rule_manager();
 | 
					        contains_pred contains_p(*this);
 | 
				
			||||||
        contains_pred contains_p(rm);
 | 
					 | 
				
			||||||
        check_pred check_pred(contains_p, get_manager());
 | 
					        check_pred check_pred(contains_p, get_manager());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (unsigned i = ut_size; i < t_size; ++i) {
 | 
					        for (unsigned i = ut_size; i < t_size; ++i) {
 | 
				
			||||||
| 
						 | 
					@ -676,7 +664,7 @@ namespace datalog {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            visited.mark(e, true);
 | 
					            visited.mark(e, true);
 | 
				
			||||||
            if (rm.is_predicate(e)) {
 | 
					            if (is_predicate(e)) {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (m.is_and(e) || m.is_or(e)) {
 | 
					            else if (m.is_and(e) || m.is_or(e)) {
 | 
				
			||||||
                todo.append(to_app(e)->get_num_args(), to_app(e)->get_args());
 | 
					                todo.append(to_app(e)->get_num_args(), to_app(e)->get_args());
 | 
				
			||||||
| 
						 | 
					@ -736,6 +724,10 @@ namespace datalog {
 | 
				
			||||||
            check_existential_tail(r);
 | 
					            check_existential_tail(r);
 | 
				
			||||||
            check_positive_predicates(r);
 | 
					            check_positive_predicates(r);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case CLP_ENGINE:
 | 
				
			||||||
 | 
					            check_existential_tail(r);
 | 
				
			||||||
 | 
					            check_positive_predicates(r);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            UNREACHABLE();
 | 
					            UNREACHABLE();
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					@ -749,14 +741,6 @@ namespace datalog {
 | 
				
			||||||
        m_rule_set.add_rule(r);
 | 
					        m_rule_set.add_rule(r);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::add_rules(rule_ref_vector& rules) {
 | 
					 | 
				
			||||||
        for (unsigned i = 0; i < rules.size(); ++i) {
 | 
					 | 
				
			||||||
            rule_ref rule(rules[i].get(), rules.get_manager());
 | 
					 | 
				
			||||||
            add_rule(rule);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void context::add_fact(func_decl * pred, const relation_fact & fact) {
 | 
					    void context::add_fact(func_decl * pred, const relation_fact & fact) {
 | 
				
			||||||
        if (get_engine() == DATALOG_ENGINE) {
 | 
					        if (get_engine() == DATALOG_ENGINE) {
 | 
				
			||||||
            ensure_rel();
 | 
					            ensure_rel();
 | 
				
			||||||
| 
						 | 
					@ -771,10 +755,9 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::add_fact(app * head) {
 | 
					    void context::add_fact(app * head) {
 | 
				
			||||||
        SASSERT(is_fact(head));
 | 
					        SASSERT(is_fact(head));
 | 
				
			||||||
 | 
					 | 
				
			||||||
        relation_fact fact(get_manager());
 | 
					        relation_fact fact(get_manager());
 | 
				
			||||||
        unsigned n=head->get_num_args();
 | 
					        unsigned n = head->get_num_args();
 | 
				
			||||||
        for (unsigned i=0; i<n; i++) {
 | 
					        for (unsigned i = 0; i < n; i++) {
 | 
				
			||||||
            fact.push_back(to_app(head->get_arg(i)));
 | 
					            fact.push_back(to_app(head->get_arg(i)));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        add_fact(head->get_decl(), fact);
 | 
					        add_fact(head->get_decl(), fact);
 | 
				
			||||||
| 
						 | 
					@ -838,21 +821,32 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::transform_rules() {
 | 
					    void context::transform_rules() {
 | 
				
			||||||
        m_transf.reset();
 | 
					        m_transf.reset();
 | 
				
			||||||
        m_transf.register_plugin(alloc(mk_filter_rules,*this));
 | 
					        m_transf.register_plugin(alloc(mk_coi_filter, *this));
 | 
				
			||||||
        m_transf.register_plugin(alloc(mk_simple_joins,*this));
 | 
					        m_transf.register_plugin(alloc(mk_filter_rules, *this));        
 | 
				
			||||||
 | 
					        m_transf.register_plugin(alloc(mk_simple_joins, *this));
 | 
				
			||||||
        if (unbound_compressor()) {
 | 
					        if (unbound_compressor()) {
 | 
				
			||||||
            m_transf.register_plugin(alloc(mk_unbound_compressor,*this));
 | 
					            m_transf.register_plugin(alloc(mk_unbound_compressor, *this));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (similarity_compressor()) {
 | 
					        if (similarity_compressor()) {
 | 
				
			||||||
            m_transf.register_plugin(alloc(mk_similarity_compressor, *this, 
 | 
					            m_transf.register_plugin(alloc(mk_similarity_compressor, *this)); 
 | 
				
			||||||
                                         similarity_compressor_threshold()));
 | 
					        }
 | 
				
			||||||
 | 
					        m_transf.register_plugin(alloc(mk_partial_equivalence_transformer, *this));
 | 
				
			||||||
 | 
					        m_transf.register_plugin(alloc(mk_rule_inliner, *this));
 | 
				
			||||||
 | 
					        m_transf.register_plugin(alloc(mk_interp_tail_simplifier, *this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (get_params().bit_blast()) {
 | 
				
			||||||
 | 
					            m_transf.register_plugin(alloc(mk_bit_blast, *this, 22000));
 | 
				
			||||||
 | 
					            m_transf.register_plugin(alloc(mk_interp_tail_simplifier, *this, 21000));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        m_transf.register_plugin(alloc(datalog::mk_partial_equivalence_transformer, *this));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        transform_rules(m_transf);
 | 
					        transform_rules(m_transf);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void context::transform_rules(rule_transformer::plugin* plugin) {
 | 
				
			||||||
 | 
					        rule_transformer transformer(*this);
 | 
				
			||||||
 | 
					        transformer.register_plugin(plugin);
 | 
				
			||||||
 | 
					        transform_rules(transformer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void context::transform_rules(rule_transformer& transf) {
 | 
					    void context::transform_rules(rule_transformer& transf) {
 | 
				
			||||||
        SASSERT(m_closed); //we must finish adding rules before we start transforming them
 | 
					        SASSERT(m_closed); //we must finish adding rules before we start transforming them
 | 
				
			||||||
| 
						 | 
					@ -866,15 +860,16 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::replace_rules(rule_set & rs) {
 | 
					    void context::replace_rules(rule_set const & rs) {
 | 
				
			||||||
        SASSERT(!m_closed);
 | 
					        SASSERT(!m_closed);
 | 
				
			||||||
        m_rule_set.reset();
 | 
					        m_rule_set.replace_rules(rs);
 | 
				
			||||||
        m_rule_set.add_rules(rs);
 | 
					        if (m_rel) {
 | 
				
			||||||
 | 
					            m_rel->restrict_predicates(get_predicates());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::record_transformed_rules() {
 | 
					    void context::record_transformed_rules() {
 | 
				
			||||||
        m_transformed_rule_set.reset();
 | 
					        m_transformed_rule_set.replace_rules(m_rule_set);
 | 
				
			||||||
        m_transformed_rule_set.add_rules(m_rule_set);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::apply_default_transformation() {
 | 
					    void context::apply_default_transformation() {
 | 
				
			||||||
| 
						 | 
					@ -925,16 +920,6 @@ namespace datalog {
 | 
				
			||||||
        if (m_pdr.get()) m_pdr->updt_params();        
 | 
					        if (m_pdr.get()) m_pdr->updt_params();        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::collect_predicates(decl_set& res) {
 | 
					 | 
				
			||||||
        ensure_rel();
 | 
					 | 
				
			||||||
        m_rel->collect_predicates(res);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void context::restrict_predicates(decl_set const& res) {
 | 
					 | 
				
			||||||
        ensure_rel();
 | 
					 | 
				
			||||||
        m_rel->restrict_predicates(res);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    expr_ref context::get_background_assertion() {
 | 
					    expr_ref context::get_background_assertion() {
 | 
				
			||||||
        expr_ref result(m);
 | 
					        expr_ref result(m);
 | 
				
			||||||
        switch (m_background.size()) {
 | 
					        switch (m_background.size()) {
 | 
				
			||||||
| 
						 | 
					@ -980,18 +965,21 @@ namespace datalog {
 | 
				
			||||||
        engine_type_proc(ast_manager& m): m(m), a(m), dt(m), m_engine(DATALOG_ENGINE) {}
 | 
					        engine_type_proc(ast_manager& m): m(m), a(m), dt(m), m_engine(DATALOG_ENGINE) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        DL_ENGINE get_engine() const { return m_engine; }
 | 
					        DL_ENGINE get_engine() const { return m_engine; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void operator()(expr* e) {
 | 
					        void operator()(expr* e) {
 | 
				
			||||||
            if (is_quantifier(e)) {
 | 
					            if (is_quantifier(e)) {
 | 
				
			||||||
                m_engine = QPDR_ENGINE;
 | 
					                m_engine = QPDR_ENGINE;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (a.is_int_real(e) && m_engine != QPDR_ENGINE) {
 | 
					            else if (m_engine != QPDR_ENGINE) {
 | 
				
			||||||
                m_engine = PDR_ENGINE;
 | 
					                if (a.is_int_real(e)) {
 | 
				
			||||||
            }
 | 
					                    m_engine = PDR_ENGINE;
 | 
				
			||||||
            else if (is_var(e) && m.is_bool(e)) {
 | 
					                }
 | 
				
			||||||
                m_engine = PDR_ENGINE;
 | 
					                else if (is_var(e) && m.is_bool(e)) {
 | 
				
			||||||
            }
 | 
					                    m_engine = PDR_ENGINE;
 | 
				
			||||||
            else if (dt.is_datatype(m.get_sort(e))) {
 | 
					                }
 | 
				
			||||||
                m_engine = PDR_ENGINE;
 | 
					                else if (dt.is_datatype(m.get_sort(e))) {
 | 
				
			||||||
 | 
					                    m_engine = PDR_ENGINE;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					@ -1017,11 +1005,14 @@ namespace datalog {
 | 
				
			||||||
        else if (e == symbol("tab")) {
 | 
					        else if (e == symbol("tab")) {
 | 
				
			||||||
            m_engine = TAB_ENGINE;
 | 
					            m_engine = TAB_ENGINE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        else if (e == symbol("clp")) {
 | 
				
			||||||
 | 
					            m_engine = CLP_ENGINE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (m_engine == LAST_ENGINE) {
 | 
					        if (m_engine == LAST_ENGINE) {
 | 
				
			||||||
            expr_fast_mark1 mark;
 | 
					            expr_fast_mark1 mark;
 | 
				
			||||||
            engine_type_proc proc(m);
 | 
					            engine_type_proc proc(m);
 | 
				
			||||||
            m_engine = DATALOG_ENGINE;
 | 
					            m_engine = DATALOG_ENGINE;            
 | 
				
			||||||
            for (unsigned i = 0; m_engine == DATALOG_ENGINE && i < m_rule_set.get_num_rules(); ++i) {
 | 
					            for (unsigned i = 0; m_engine == DATALOG_ENGINE && i < m_rule_set.get_num_rules(); ++i) {
 | 
				
			||||||
                rule * r = m_rule_set.get_rule(i);
 | 
					                rule * r = m_rule_set.get_rule(i);
 | 
				
			||||||
                quick_for_each_expr(proc, mark, r->get_head());
 | 
					                quick_for_each_expr(proc, mark, r->get_head());
 | 
				
			||||||
| 
						 | 
					@ -1030,42 +1021,45 @@ namespace datalog {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                m_engine = proc.get_engine();
 | 
					                m_engine = proc.get_engine();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            for (unsigned i = m_rule_fmls_head; m_engine == DATALOG_ENGINE && i < m_rule_fmls.size(); ++i) {
 | 
				
			||||||
 | 
					                expr* fml = m_rule_fmls[i].get();
 | 
				
			||||||
 | 
					                while (is_quantifier(fml)) {
 | 
				
			||||||
 | 
					                    fml = to_quantifier(fml)->get_expr();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                quick_for_each_expr(proc, mark, fml);
 | 
				
			||||||
 | 
					                m_engine = proc.get_engine();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    lbool context::query(expr* query) {
 | 
					    lbool context::query(expr* query) {
 | 
				
			||||||
        new_query();
 | 
					        m_mc = mk_skip_model_converter();
 | 
				
			||||||
        rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end();
 | 
					        m_last_status = OK;
 | 
				
			||||||
        rule_ref r(m_rule_manager);
 | 
					        m_last_answer = 0;
 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					        switch (get_engine()) {
 | 
				
			||||||
            r = *it;
 | 
					 | 
				
			||||||
            check_rule(r);
 | 
					 | 
				
			||||||
        }        
 | 
					 | 
				
			||||||
        switch(get_engine()) {
 | 
					 | 
				
			||||||
        case DATALOG_ENGINE:
 | 
					        case DATALOG_ENGINE:
 | 
				
			||||||
 | 
					            flush_add_rules();
 | 
				
			||||||
            return rel_query(query);
 | 
					            return rel_query(query);
 | 
				
			||||||
        case PDR_ENGINE:
 | 
					        case PDR_ENGINE:
 | 
				
			||||||
        case QPDR_ENGINE:
 | 
					        case QPDR_ENGINE:
 | 
				
			||||||
 | 
					            flush_add_rules();
 | 
				
			||||||
            return pdr_query(query);
 | 
					            return pdr_query(query);
 | 
				
			||||||
        case BMC_ENGINE:
 | 
					        case BMC_ENGINE:
 | 
				
			||||||
        case QBMC_ENGINE:
 | 
					        case QBMC_ENGINE:
 | 
				
			||||||
 | 
					            flush_add_rules();
 | 
				
			||||||
            return bmc_query(query);
 | 
					            return bmc_query(query);
 | 
				
			||||||
        case TAB_ENGINE:
 | 
					        case TAB_ENGINE:
 | 
				
			||||||
 | 
					            flush_add_rules();
 | 
				
			||||||
            return tab_query(query);
 | 
					            return tab_query(query);
 | 
				
			||||||
 | 
					        case CLP_ENGINE:
 | 
				
			||||||
 | 
					            flush_add_rules();
 | 
				
			||||||
 | 
					            return clp_query(query);
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            UNREACHABLE();
 | 
					            UNREACHABLE();
 | 
				
			||||||
            return rel_query(query);
 | 
					            return rel_query(query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::new_query() {
 | 
					 | 
				
			||||||
        m_mc = mk_skip_model_converter();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        flush_add_rules();
 | 
					 | 
				
			||||||
        m_last_status = OK;
 | 
					 | 
				
			||||||
        m_last_answer = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    model_ref context::get_model() {
 | 
					    model_ref context::get_model() {
 | 
				
			||||||
        switch(get_engine()) {
 | 
					        switch(get_engine()) {
 | 
				
			||||||
        case PDR_ENGINE:
 | 
					        case PDR_ENGINE:
 | 
				
			||||||
| 
						 | 
					@ -1116,11 +1110,22 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void context::ensure_clp() {
 | 
				
			||||||
 | 
					        if (!m_clp.get()) {
 | 
				
			||||||
 | 
					            m_clp = alloc(clp, *this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    lbool context::tab_query(expr* query) {
 | 
					    lbool context::tab_query(expr* query) {
 | 
				
			||||||
        ensure_tab();
 | 
					        ensure_tab();
 | 
				
			||||||
        return m_tab->query(query);
 | 
					        return m_tab->query(query);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lbool context::clp_query(expr* query) {
 | 
				
			||||||
 | 
					        ensure_clp();
 | 
				
			||||||
 | 
					        return m_clp->query(query);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void context::ensure_rel() {
 | 
					    void context::ensure_rel() {
 | 
				
			||||||
        if (!m_rel.get()) {
 | 
					        if (!m_rel.get()) {
 | 
				
			||||||
            m_rel = alloc(rel_context, *this);
 | 
					            m_rel = alloc(rel_context, *this);
 | 
				
			||||||
| 
						 | 
					@ -1161,6 +1166,10 @@ namespace datalog {
 | 
				
			||||||
            ensure_tab();
 | 
					            ensure_tab();
 | 
				
			||||||
            m_last_answer = m_tab->get_answer();
 | 
					            m_last_answer = m_tab->get_answer();
 | 
				
			||||||
            return m_last_answer.get();
 | 
					            return m_last_answer.get();
 | 
				
			||||||
 | 
					        case CLP_ENGINE:
 | 
				
			||||||
 | 
					            ensure_clp();
 | 
				
			||||||
 | 
					            m_last_answer = m_clp->get_answer();
 | 
				
			||||||
 | 
					            return m_last_answer.get();
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            UNREACHABLE();
 | 
					            UNREACHABLE();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1186,6 +1195,10 @@ namespace datalog {
 | 
				
			||||||
            ensure_tab();
 | 
					            ensure_tab();
 | 
				
			||||||
            m_tab->display_certificate(out);
 | 
					            m_tab->display_certificate(out);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
 | 
					        case CLP_ENGINE:
 | 
				
			||||||
 | 
					            ensure_clp();
 | 
				
			||||||
 | 
					            m_clp->display_certificate(out);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
        default: 
 | 
					        default: 
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }        
 | 
					        }        
 | 
				
			||||||
| 
						 | 
					@ -1273,14 +1286,13 @@ namespace datalog {
 | 
				
			||||||
    void context::get_rules_as_formulas(expr_ref_vector& rules, svector<symbol>& names) {
 | 
					    void context::get_rules_as_formulas(expr_ref_vector& rules, svector<symbol>& names) {
 | 
				
			||||||
        expr_ref fml(m);
 | 
					        expr_ref fml(m);
 | 
				
			||||||
        datalog::rule_manager& rm = get_rule_manager();
 | 
					        datalog::rule_manager& rm = get_rule_manager();
 | 
				
			||||||
        datalog::rule_ref_vector rule_refs(rm);
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // ensure that rules are all using bound variables.
 | 
					        // ensure that rules are all using bound variables.
 | 
				
			||||||
        for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
 | 
					        for (unsigned i = m_rule_fmls_head; i < m_rule_fmls.size(); ++i) {
 | 
				
			||||||
            ptr_vector<sort> sorts;
 | 
					            ptr_vector<sort> sorts;
 | 
				
			||||||
            get_free_vars(m_rule_fmls[i].get(), sorts);
 | 
					            get_free_vars(m_rule_fmls[i].get(), sorts);
 | 
				
			||||||
            if (!sorts.empty()) {
 | 
					            if (!sorts.empty()) {
 | 
				
			||||||
                rm.mk_rule(m_rule_fmls[i].get(), 0, rule_refs, m_rule_names[i]);
 | 
					                rm.mk_rule(m_rule_fmls[i].get(), 0, m_rule_set, m_rule_names[i]);
 | 
				
			||||||
                m_rule_fmls[i] = m_rule_fmls.back();
 | 
					                m_rule_fmls[i] = m_rule_fmls.back();
 | 
				
			||||||
                m_rule_names[i] = m_rule_names.back();
 | 
					                m_rule_names[i] = m_rule_names.back();
 | 
				
			||||||
                m_rule_fmls.pop_back();
 | 
					                m_rule_fmls.pop_back();
 | 
				
			||||||
| 
						 | 
					@ -1288,14 +1300,13 @@ namespace datalog {
 | 
				
			||||||
                --i;
 | 
					                --i;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        add_rules(rule_refs);
 | 
					 | 
				
			||||||
        rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end();
 | 
					        rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end();
 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					        for (; it != end; ++it) {
 | 
				
			||||||
            (*it)->to_formula(fml);
 | 
					            (*it)->to_formula(fml);
 | 
				
			||||||
            rules.push_back(fml);
 | 
					            rules.push_back(fml);
 | 
				
			||||||
            names.push_back((*it)->name());
 | 
					            names.push_back((*it)->name());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
 | 
					        for (unsigned i = m_rule_fmls_head; i < m_rule_fmls.size(); ++i) {
 | 
				
			||||||
            rules.push_back(m_rule_fmls[i].get());
 | 
					            rules.push_back(m_rule_fmls[i].get());
 | 
				
			||||||
            names.push_back(m_rule_names[i]);            
 | 
					            names.push_back(m_rule_names[i]);            
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,9 @@ Revision History:
 | 
				
			||||||
#include"model2expr.h"
 | 
					#include"model2expr.h"
 | 
				
			||||||
#include"smt_params.h"
 | 
					#include"smt_params.h"
 | 
				
			||||||
#include"dl_rule_transformer.h"
 | 
					#include"dl_rule_transformer.h"
 | 
				
			||||||
 | 
					#include"expr_abstract.h"
 | 
				
			||||||
 | 
					#include"expr_functors.h"
 | 
				
			||||||
 | 
					#include"clp_context.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace datalog {
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,6 +79,18 @@ namespace datalog {
 | 
				
			||||||
        typedef obj_map<const func_decl, svector<symbol> > pred2syms;
 | 
					        typedef obj_map<const func_decl, svector<symbol> > pred2syms;
 | 
				
			||||||
        typedef obj_map<const sort, sort_domain*> sort_domain_map;
 | 
					        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;
 | 
					        ast_manager &      m;
 | 
				
			||||||
        smt_params &       m_fparams;
 | 
					        smt_params &       m_fparams;
 | 
				
			||||||
        params_ref         m_params_ref;
 | 
					        params_ref         m_params_ref;
 | 
				
			||||||
| 
						 | 
					@ -84,16 +99,22 @@ namespace datalog {
 | 
				
			||||||
        th_rewriter        m_rewriter;
 | 
					        th_rewriter        m_rewriter;
 | 
				
			||||||
        var_subst          m_var_subst;
 | 
					        var_subst          m_var_subst;
 | 
				
			||||||
        rule_manager       m_rule_manager;
 | 
					        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;
 | 
					        rule_transformer   m_transf;
 | 
				
			||||||
        trail_stack<context> m_trail;
 | 
					        trail_stack<context> m_trail;
 | 
				
			||||||
        ast_ref_vector     m_pinned;
 | 
					        ast_ref_vector     m_pinned;
 | 
				
			||||||
        app_ref_vector     m_vars;
 | 
					        app_ref_vector     m_vars;
 | 
				
			||||||
 | 
					        svector<symbol>    m_names;
 | 
				
			||||||
        sort_domain_map    m_sorts;
 | 
					        sort_domain_map    m_sorts;
 | 
				
			||||||
        func_decl_set      m_preds;
 | 
					        func_decl_set      m_preds;
 | 
				
			||||||
        sym2decl           m_preds_by_name;
 | 
					        sym2decl           m_preds_by_name;
 | 
				
			||||||
        pred2syms          m_argument_var_names;
 | 
					        pred2syms          m_argument_var_names;
 | 
				
			||||||
        rule_set           m_rule_set;
 | 
					        rule_set           m_rule_set;
 | 
				
			||||||
        rule_set           m_transformed_rule_set;
 | 
					        rule_set           m_transformed_rule_set;
 | 
				
			||||||
 | 
					        unsigned           m_rule_fmls_head;
 | 
				
			||||||
        expr_ref_vector    m_rule_fmls;
 | 
					        expr_ref_vector    m_rule_fmls;
 | 
				
			||||||
        svector<symbol>    m_rule_names;
 | 
					        svector<symbol>    m_rule_names;
 | 
				
			||||||
        expr_ref_vector    m_background;
 | 
					        expr_ref_vector    m_background;
 | 
				
			||||||
| 
						 | 
					@ -104,6 +125,7 @@ namespace datalog {
 | 
				
			||||||
        scoped_ptr<bmc>                 m_bmc;
 | 
					        scoped_ptr<bmc>                 m_bmc;
 | 
				
			||||||
        scoped_ptr<rel_context>         m_rel;
 | 
					        scoped_ptr<rel_context>         m_rel;
 | 
				
			||||||
        scoped_ptr<tab>                 m_tab;
 | 
					        scoped_ptr<tab>                 m_tab;
 | 
				
			||||||
 | 
					        scoped_ptr<clp>                 m_clp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool               m_closed;
 | 
					        bool               m_closed;
 | 
				
			||||||
        bool               m_saturation_was_run;
 | 
					        bool               m_saturation_was_run;
 | 
				
			||||||
| 
						 | 
					@ -185,7 +207,17 @@ namespace datalog {
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        void register_predicate(func_decl * pred, bool named);
 | 
					        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;
 | 
					           \brief If a predicate name has a \c func_decl object assigned, return pointer to it;
 | 
				
			||||||
| 
						 | 
					@ -238,11 +270,9 @@ namespace datalog {
 | 
				
			||||||
        void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt, 
 | 
					        void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt, 
 | 
				
			||||||
            symbol const *  relation_names);
 | 
					            symbol const *  relation_names);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void set_output_predicate(func_decl * pred);
 | 
					        void set_output_predicate(func_decl * pred) { m_rule_set.set_output_predicate(pred); }
 | 
				
			||||||
        bool is_output_predicate(func_decl * pred);
 | 
					 | 
				
			||||||
        const decl_set & get_output_predicates();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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_rules_as_formulas(expr_ref_vector& fmls, svector<symbol>& names);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -252,7 +282,6 @@ namespace datalog {
 | 
				
			||||||
        bool has_facts(func_decl * pred) const;
 | 
					        bool has_facts(func_decl * pred) const;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        void add_rule(rule_ref& r);
 | 
					        void add_rule(rule_ref& r);
 | 
				
			||||||
        void add_rules(rule_ref_vector& rs);
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        void assert_expr(expr* e);
 | 
					        void assert_expr(expr* e);
 | 
				
			||||||
        expr_ref get_background_assertion();
 | 
					        expr_ref get_background_assertion();
 | 
				
			||||||
| 
						 | 
					@ -330,7 +359,8 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void transform_rules(); 
 | 
					        void transform_rules(); 
 | 
				
			||||||
        void transform_rules(rule_transformer& transf); 
 | 
					        void transform_rules(rule_transformer& transf); 
 | 
				
			||||||
        void replace_rules(rule_set & rs);
 | 
					        void transform_rules(rule_transformer::plugin* plugin);
 | 
				
			||||||
 | 
					        void replace_rules(rule_set const& rs);
 | 
				
			||||||
        void record_transformed_rules();
 | 
					        void record_transformed_rules();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void apply_default_transformation(); 
 | 
					        void apply_default_transformation(); 
 | 
				
			||||||
| 
						 | 
					@ -339,14 +369,6 @@ namespace datalog {
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        void updt_params(params_ref const& p);
 | 
					        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 {
 | 
					        void display_rules(std::ostream & out) const {
 | 
				
			||||||
            m_rule_set.display(out);
 | 
					            m_rule_set.display(out);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -457,9 +479,9 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void ensure_tab();
 | 
					        void ensure_tab();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void ensure_rel();
 | 
					        void ensure_clp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void new_query();
 | 
					        void ensure_rel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        lbool rel_query(expr* query);
 | 
					        lbool rel_query(expr* query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -469,6 +491,8 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        lbool tab_query(expr* query);
 | 
					        lbool tab_query(expr* query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lbool clp_query(expr* query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void check_quantifier_free(rule_ref& r);        
 | 
					        void check_quantifier_free(rule_ref& r);        
 | 
				
			||||||
        void check_uninterpreted_free(rule_ref& r);
 | 
					        void check_uninterpreted_free(rule_ref& r);
 | 
				
			||||||
        void check_existential_tail(rule_ref& r);
 | 
					        void check_existential_tail(rule_ref& r);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ namespace datalog {
 | 
				
			||||||
        for(unsigned i=0; i<n; i++) {
 | 
					        for(unsigned i=0; i<n; i++) {
 | 
				
			||||||
            if(table_columns[i]) {
 | 
					            if(table_columns[i]) {
 | 
				
			||||||
                table_sort t_sort;
 | 
					                table_sort t_sort;
 | 
				
			||||||
                TRUSTME( rmgr.relation_sort_to_table(s[i], t_sort) );
 | 
					                VERIFY( rmgr.relation_sort_to_table(s[i], t_sort) );
 | 
				
			||||||
                table_sig.push_back(t_sort);
 | 
					                table_sig.push_back(t_sort);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
| 
						 | 
					@ -1291,8 +1291,8 @@ namespace datalog {
 | 
				
			||||||
                m_renaming_for_inner_rel(m_manager) {
 | 
					                m_renaming_for_inner_rel(m_manager) {
 | 
				
			||||||
            relation_manager & rmgr = r.get_manager();
 | 
					            relation_manager & rmgr = r.get_manager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            idx_set cond_columns;
 | 
					            rule_manager& rm = r.get_context().get_rule_manager();
 | 
				
			||||||
            collect_vars(m_manager, m_cond, cond_columns);
 | 
					            idx_set& cond_columns = rm.collect_vars(m_cond);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            unsigned sig_sz = r.get_signature().size();
 | 
					            unsigned sig_sz = r.get_signature().size();
 | 
				
			||||||
            for(unsigned i=0; i<sig_sz; i++) {
 | 
					            for(unsigned i=0; i<sig_sz; i++) {
 | 
				
			||||||
| 
						 | 
					@ -1789,7 +1789,7 @@ namespace datalog {
 | 
				
			||||||
                m_sig2table[i]=m_table_sig.size();
 | 
					                m_sig2table[i]=m_table_sig.size();
 | 
				
			||||||
                table_sort srt;
 | 
					                table_sort srt;
 | 
				
			||||||
                //the table columns must have table-friendly sorts
 | 
					                //the table columns must have table-friendly sorts
 | 
				
			||||||
                TRUSTME( get_manager().relation_sort_to_table(rel_sig[i], srt) );
 | 
					                VERIFY( get_manager().relation_sort_to_table(rel_sig[i], srt) );
 | 
				
			||||||
                m_table_sig.push_back(srt);
 | 
					                m_table_sig.push_back(srt);
 | 
				
			||||||
                m_table2sig.push_back(i);
 | 
					                m_table2sig.push_back(i);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            struct hash {
 | 
					            struct hash {
 | 
				
			||||||
                unsigned operator()(const rel_spec & o) const {
 | 
					                unsigned operator()(const rel_spec & o) const {
 | 
				
			||||||
                    return o.m_inner_kind^int_vector_hash(o.m_table_cols);
 | 
					                    return o.m_inner_kind^svector_hash<bool_hash>()(o.m_table_cols);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -359,21 +359,7 @@ namespace datalog {
 | 
				
			||||||
                r2.get_signature().output(ctx.get_rel_context().get_manager(), tout);
 | 
					                r2.get_signature().output(ctx.get_rel_context().get_manager(), tout);
 | 
				
			||||||
                tout<<":"<<r2.get_size_estimate_rows()<<" ->\n";);
 | 
					                tout<<":"<<r2.get_size_estimate_rows()<<" ->\n";);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try {
 | 
					            ctx.set_reg(m_res, (*fn)(r1, r2));
 | 
				
			||||||
                ctx.set_reg(m_res, (*fn)(r1, r2));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            catch(...)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                std::string annotation;
 | 
					 | 
				
			||||||
                unsigned sz;
 | 
					 | 
				
			||||||
                ctx.get_register_annotation(m_rel1, annotation);
 | 
					 | 
				
			||||||
                sz = ctx.reg(m_rel1)?ctx.reg(m_rel1)->get_size_estimate_rows():0;
 | 
					 | 
				
			||||||
                std::cout << m_rel1 << "\t" << sz << "\t" << annotation << "\n";
 | 
					 | 
				
			||||||
                ctx.get_register_annotation(m_rel2, annotation);
 | 
					 | 
				
			||||||
                sz = ctx.reg(m_rel2)?ctx.reg(m_rel2)->get_size_estimate_rows():0;
 | 
					 | 
				
			||||||
                std::cout << m_rel2 << "\t" << sz << "\t" << annotation << "\n";
 | 
					 | 
				
			||||||
                throw;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            TRACE("dl", 
 | 
					            TRACE("dl", 
 | 
				
			||||||
                ctx.reg(m_res)->get_signature().output(ctx.get_rel_context().get_manager(), tout);
 | 
					                ctx.reg(m_res)->get_signature().output(ctx.get_rel_context().get_manager(), tout);
 | 
				
			||||||
| 
						 | 
					@ -452,7 +438,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class instr_filter_identical : public instruction {
 | 
					    class instr_filter_identical : public instruction {
 | 
				
			||||||
        typedef vector<unsigned> column_vector;
 | 
					        typedef unsigned_vector column_vector;
 | 
				
			||||||
        reg_idx m_reg;
 | 
					        reg_idx m_reg;
 | 
				
			||||||
        column_vector m_cols;
 | 
					        column_vector m_cols;
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
| 
						 | 
					@ -540,6 +526,64 @@ namespace datalog {
 | 
				
			||||||
        return alloc(instr_filter_interpreted, reg, condition);
 | 
					        return alloc(instr_filter_interpreted, reg, condition);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class instr_filter_interpreted_and_project : public instruction {
 | 
				
			||||||
 | 
					        reg_idx m_src;
 | 
				
			||||||
 | 
					        reg_idx m_res;
 | 
				
			||||||
 | 
					        app_ref m_cond;
 | 
				
			||||||
 | 
					        unsigned_vector m_cols;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        instr_filter_interpreted_and_project(reg_idx src, app_ref & condition,
 | 
				
			||||||
 | 
					            unsigned col_cnt, const unsigned * removed_cols, reg_idx result)
 | 
				
			||||||
 | 
					            : m_src(src), m_cond(condition), m_cols(col_cnt, removed_cols),
 | 
				
			||||||
 | 
					              m_res(result) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual bool perform(execution_context & ctx) {
 | 
				
			||||||
 | 
					            if (!ctx.reg(m_src)) {
 | 
				
			||||||
 | 
					                ctx.make_empty(m_res);
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            relation_transformer_fn * fn;
 | 
				
			||||||
 | 
					            relation_base & reg = *ctx.reg(m_src);
 | 
				
			||||||
 | 
					            if (!find_fn(reg, fn)) {
 | 
				
			||||||
 | 
					                fn = reg.get_manager().mk_filter_interpreted_and_project_fn(reg, m_cond, m_cols.size(), m_cols.c_ptr());
 | 
				
			||||||
 | 
					                if (!fn) {
 | 
				
			||||||
 | 
					                    throw default_exception(
 | 
				
			||||||
 | 
					                        "trying to perform unsupported filter_interpreted_and_project operation on a relation of kind %s",
 | 
				
			||||||
 | 
					                        reg.get_plugin().get_name().bare_str());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                store_fn(reg, fn);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ctx.set_reg(m_res, (*fn)(reg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (ctx.eager_emptiness_checking() && ctx.reg(m_res)->empty()) {
 | 
				
			||||||
 | 
					                ctx.make_empty(m_res);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
 | 
				
			||||||
 | 
					            out << "filter_interpreted_and_project " << m_src << " into " << m_res;
 | 
				
			||||||
 | 
					            out << " using " << mk_pp(m_cond, m_cond.get_manager());
 | 
				
			||||||
 | 
					            out << " deleting columns ";
 | 
				
			||||||
 | 
					            print_container(m_cols, out);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual void make_annotations(execution_context & ctx) {
 | 
				
			||||||
 | 
					            std::stringstream s;
 | 
				
			||||||
 | 
					            std::string a = "rel_src";
 | 
				
			||||||
 | 
					            ctx.get_register_annotation(m_src, a);
 | 
				
			||||||
 | 
					            s << "filter_interpreted_and_project " << mk_pp(m_cond, m_cond.get_manager());
 | 
				
			||||||
 | 
					            ctx.set_register_annotation(m_res, s.str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    instruction * instruction::mk_filter_interpreted_and_project(reg_idx reg, app_ref & condition,
 | 
				
			||||||
 | 
					        unsigned col_cnt, const unsigned * removed_cols, reg_idx result) {
 | 
				
			||||||
 | 
					        return alloc(instr_filter_interpreted_and_project, reg, condition, col_cnt, removed_cols, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class instr_union : public instruction {
 | 
					    class instr_union : public instruction {
 | 
				
			||||||
        reg_idx m_src;
 | 
					        reg_idx m_src;
 | 
				
			||||||
| 
						 | 
					@ -606,6 +650,7 @@ namespace datalog {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SASSERT(r_src.get_signature().size() == r_tgt.get_signature().size());
 | 
				
			||||||
            TRACE("dl_verbose", r_tgt.display(tout <<"pre-union:"););
 | 
					            TRACE("dl_verbose", r_tgt.display(tout <<"pre-union:"););
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (*fn)(r_tgt, r_src, r_delta);
 | 
					            (*fn)(r_tgt, r_src, r_delta);
 | 
				
			||||||
| 
						 | 
					@ -651,7 +696,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class instr_project_rename : public instruction {
 | 
					    class instr_project_rename : public instruction {
 | 
				
			||||||
        typedef vector<unsigned> column_vector;
 | 
					        typedef unsigned_vector column_vector;
 | 
				
			||||||
        bool m_projection;
 | 
					        bool m_projection;
 | 
				
			||||||
        reg_idx m_src;
 | 
					        reg_idx m_src;
 | 
				
			||||||
        column_vector m_cols;
 | 
					        column_vector m_cols;
 | 
				
			||||||
| 
						 | 
					@ -723,7 +768,8 @@ namespace datalog {
 | 
				
			||||||
        instr_join_project(reg_idx rel1, reg_idx rel2, unsigned joined_col_cnt, const unsigned * cols1, 
 | 
					        instr_join_project(reg_idx rel1, reg_idx rel2, unsigned joined_col_cnt, const unsigned * cols1, 
 | 
				
			||||||
            const unsigned * cols2, unsigned removed_col_cnt, const unsigned * removed_cols, reg_idx result)
 | 
					            const unsigned * cols2, unsigned removed_col_cnt, const unsigned * removed_cols, reg_idx result)
 | 
				
			||||||
            : m_rel1(rel1), m_rel2(rel2), m_cols1(joined_col_cnt, cols1), 
 | 
					            : m_rel1(rel1), m_rel2(rel2), m_cols1(joined_col_cnt, cols1), 
 | 
				
			||||||
            m_cols2(joined_col_cnt, cols2), m_removed_cols(removed_col_cnt, removed_cols), m_res(result) {}
 | 
					            m_cols2(joined_col_cnt, cols2), m_removed_cols(removed_col_cnt, removed_cols), m_res(result) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        virtual bool perform(execution_context & ctx) {
 | 
					        virtual bool perform(execution_context & ctx) {
 | 
				
			||||||
            ctx.make_empty(m_res);
 | 
					            ctx.make_empty(m_res);
 | 
				
			||||||
            if (!ctx.reg(m_rel1) || !ctx.reg(m_rel2)) {
 | 
					            if (!ctx.reg(m_rel1) || !ctx.reg(m_rel2)) {
 | 
				
			||||||
| 
						 | 
					@ -830,7 +876,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class instr_filter_by_negation : public instruction {
 | 
					    class instr_filter_by_negation : public instruction {
 | 
				
			||||||
        typedef vector<unsigned> column_vector;
 | 
					        typedef unsigned_vector column_vector;
 | 
				
			||||||
        reg_idx m_tgt;
 | 
					        reg_idx m_tgt;
 | 
				
			||||||
        reg_idx m_neg_rel;
 | 
					        reg_idx m_neg_rel;
 | 
				
			||||||
        column_vector m_cols1;
 | 
					        column_vector m_cols1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -260,6 +260,8 @@ namespace datalog {
 | 
				
			||||||
        static instruction * mk_filter_equal(ast_manager & m, reg_idx reg, const relation_element & value, unsigned col);
 | 
					        static instruction * mk_filter_equal(ast_manager & m, reg_idx reg, const relation_element & value, unsigned col);
 | 
				
			||||||
        static instruction * mk_filter_identical(reg_idx reg, unsigned col_cnt, const unsigned * identical_cols);
 | 
					        static instruction * mk_filter_identical(reg_idx reg, unsigned col_cnt, const unsigned * identical_cols);
 | 
				
			||||||
        static instruction * mk_filter_interpreted(reg_idx reg, app_ref & condition);
 | 
					        static instruction * mk_filter_interpreted(reg_idx reg, app_ref & condition);
 | 
				
			||||||
 | 
					        static instruction * mk_filter_interpreted_and_project(reg_idx src, app_ref & condition,
 | 
				
			||||||
 | 
					            unsigned col_cnt, const unsigned * removed_cols, reg_idx result);
 | 
				
			||||||
        static instruction * mk_union(reg_idx src, reg_idx tgt, reg_idx delta);
 | 
					        static instruction * mk_union(reg_idx src, reg_idx tgt, reg_idx delta);
 | 
				
			||||||
        static instruction * mk_widen(reg_idx src, reg_idx tgt, reg_idx delta);
 | 
					        static instruction * mk_widen(reg_idx src, reg_idx tgt, reg_idx delta);
 | 
				
			||||||
        static instruction * mk_projection(reg_idx src, unsigned col_cnt, const unsigned * removed_cols, 
 | 
					        static instruction * mk_projection(reg_idx src, unsigned col_cnt, const unsigned * removed_cols, 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,11 +99,9 @@ namespace datalog {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
    class interval_relation_plugin::rename_fn : public convenient_relation_rename_fn {
 | 
					    class interval_relation_plugin::rename_fn : public convenient_relation_rename_fn {
 | 
				
			||||||
        interval_relation_plugin& m_plugin;
 | 
					 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        rename_fn(interval_relation_plugin& p, const relation_signature & orig_sig, unsigned cycle_len, const unsigned * cycle) 
 | 
					        rename_fn(const relation_signature & orig_sig, unsigned cycle_len, const unsigned * cycle) 
 | 
				
			||||||
            : convenient_relation_rename_fn(orig_sig, cycle_len, cycle),
 | 
					            : convenient_relation_rename_fn(orig_sig, cycle_len, cycle) {
 | 
				
			||||||
              m_plugin(p){
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual relation_base * operator()(const relation_base & _r) {
 | 
					        virtual relation_base * operator()(const relation_base & _r) {
 | 
				
			||||||
| 
						 | 
					@ -120,7 +118,7 @@ namespace datalog {
 | 
				
			||||||
        if(!check_kind(r)) {
 | 
					        if(!check_kind(r)) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return alloc(rename_fn, *this, r.get_signature(), cycle_len, permutation_cycle);
 | 
					        return alloc(rename_fn, r.get_signature(), cycle_len, permutation_cycle);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
     
 | 
					     
 | 
				
			||||||
    interval interval_relation_plugin::unite(interval const& src1, interval const& src2) {
 | 
					    interval interval_relation_plugin::unite(interval const& src1, interval const& src2) {
 | 
				
			||||||
| 
						 | 
					@ -194,11 +192,9 @@ namespace datalog {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class interval_relation_plugin::union_fn : public relation_union_fn {
 | 
					    class interval_relation_plugin::union_fn : public relation_union_fn {
 | 
				
			||||||
        interval_relation_plugin& m_plugin;
 | 
					 | 
				
			||||||
        bool                      m_is_widen;
 | 
					        bool                      m_is_widen;
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        union_fn(interval_relation_plugin& p, bool is_widen) :
 | 
					        union_fn(bool is_widen) :
 | 
				
			||||||
            m_plugin(p),
 | 
					 | 
				
			||||||
            m_is_widen(is_widen) {            
 | 
					            m_is_widen(is_widen) {            
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,7 +219,7 @@ namespace datalog {
 | 
				
			||||||
        if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) {
 | 
					        if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return alloc(union_fn, *this, false);
 | 
					        return alloc(union_fn, false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    relation_union_fn * interval_relation_plugin::mk_widen_fn(
 | 
					    relation_union_fn * interval_relation_plugin::mk_widen_fn(
 | 
				
			||||||
| 
						 | 
					@ -232,7 +228,7 @@ namespace datalog {
 | 
				
			||||||
        if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) {
 | 
					        if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return alloc(union_fn, *this, true);
 | 
					        return alloc(union_fn, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class interval_relation_plugin::filter_identical_fn : public relation_mutator_fn {
 | 
					    class interval_relation_plugin::filter_identical_fn : public relation_mutator_fn {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,7 +145,6 @@ namespace datalog {
 | 
				
			||||||
        expr_ref_vector conjs(m), new_conjs(m);
 | 
					        expr_ref_vector conjs(m), new_conjs(m);
 | 
				
			||||||
        expr_ref tmp(m);
 | 
					        expr_ref tmp(m);
 | 
				
			||||||
        expr_safe_replace sub(m);
 | 
					        expr_safe_replace sub(m);
 | 
				
			||||||
        uint_set lhs_vars, rhs_vars;
 | 
					 | 
				
			||||||
        bool change = false;
 | 
					        bool change = false;
 | 
				
			||||||
        bool inserted = false;
 | 
					        bool inserted = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,10 +160,8 @@ namespace datalog {
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            if (is_store_def(e, x, y)) {
 | 
					            if (is_store_def(e, x, y)) {
 | 
				
			||||||
                // enforce topological order consistency:
 | 
					                // enforce topological order consistency:
 | 
				
			||||||
                uint_set lhs;
 | 
					                uint_set lhs = rm.collect_vars(x);
 | 
				
			||||||
                collect_vars(m, x, lhs_vars);
 | 
					                uint_set rhs_vars = rm.collect_vars(y);
 | 
				
			||||||
                collect_vars(m, y, rhs_vars);
 | 
					 | 
				
			||||||
                lhs = lhs_vars;
 | 
					 | 
				
			||||||
                lhs &= rhs_vars;
 | 
					                lhs &= rhs_vars;
 | 
				
			||||||
                if (!lhs.empty()) {
 | 
					                if (!lhs.empty()) {
 | 
				
			||||||
                    TRACE("dl", tout << "unusable equality " << mk_pp(e, m) << "\n";);
 | 
					                    TRACE("dl", tout << "unusable equality " << mk_pp(e, m) << "\n";);
 | 
				
			||||||
| 
						 | 
					@ -182,7 +179,6 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        rule_ref_vector new_rules(rm);
 | 
					 | 
				
			||||||
        expr_ref fml1(m), fml2(m), body(m), head(m);
 | 
					        expr_ref fml1(m), fml2(m), body(m), head(m);
 | 
				
			||||||
        r.to_formula(fml1);
 | 
					        r.to_formula(fml1);
 | 
				
			||||||
        body = m.mk_and(new_conjs.size(), new_conjs.c_ptr());
 | 
					        body = m.mk_and(new_conjs.size(), new_conjs.c_ptr());
 | 
				
			||||||
| 
						 | 
					@ -199,12 +195,12 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fml2 = m.mk_implies(body, head);
 | 
					        fml2 = m.mk_implies(body, head);
 | 
				
			||||||
        proof_ref p(m);
 | 
					        proof_ref p(m);
 | 
				
			||||||
 | 
					        rule_set new_rules(m_ctx);
 | 
				
			||||||
        rm.mk_rule(fml2, p, new_rules, r.name());
 | 
					        rm.mk_rule(fml2, p, new_rules, r.name());
 | 
				
			||||||
        SASSERT(new_rules.size() == 1);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TRACE("dl", new_rules[0]->display(m_ctx, tout << "new rule\n"););
 | 
					        TRACE("dl", new_rules.last()->display(m_ctx, tout << "new rule\n"););
 | 
				
			||||||
        rule_ref new_rule(rm);
 | 
					        rule_ref new_rule(rm);
 | 
				
			||||||
        if (m_simplifier.transform_rule(new_rules[0].get(), new_rule)) {
 | 
					        if (m_simplifier.transform_rule(new_rules.last(), new_rule)) {
 | 
				
			||||||
            rules.add_rule(new_rule.get());
 | 
					            rules.add_rule(new_rule.get());
 | 
				
			||||||
            rm.mk_rule_rewrite_proof(r, *new_rule.get());
 | 
					            rm.mk_rule_rewrite_proof(r, *new_rule.get());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -214,6 +210,7 @@ namespace datalog {
 | 
				
			||||||
    rule_set * mk_array_blast::operator()(rule_set const & source) {
 | 
					    rule_set * mk_array_blast::operator()(rule_set const & source) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rule_set* rules = alloc(rule_set, m_ctx);
 | 
					        rule_set* rules = alloc(rule_set, m_ctx);
 | 
				
			||||||
 | 
					        rules->inherit_predicates(source);
 | 
				
			||||||
        rule_set::iterator it = source.begin(), end = source.end();
 | 
					        rule_set::iterator it = source.begin(), end = source.end();
 | 
				
			||||||
        bool change = false;
 | 
					        bool change = false;
 | 
				
			||||||
        for (; !m_ctx.canceled() && it != end; ++it) {
 | 
					        for (; !m_ctx.canceled() && it != end; ++it) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										78
									
								
								src/muz_qe/dl_mk_backwards.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/muz_qe/dl_mk_backwards.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,78 @@
 | 
				
			||||||
 | 
					/*++
 | 
				
			||||||
 | 
					Copyright (c) 2013 Microsoft Corporation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Module Name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dl_mk_backwards.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Abstract:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Create Horn clauses for backwards flow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Author:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Nikolaj Bjorner (nbjorner) 2013-04-17
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Revision History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include"dl_mk_backwards.h"
 | 
				
			||||||
 | 
					#include"dl_context.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mk_backwards::mk_backwards(context & ctx, unsigned priority):
 | 
				
			||||||
 | 
					        plugin(priority),
 | 
				
			||||||
 | 
					        m(ctx.get_manager()),
 | 
				
			||||||
 | 
					        m_ctx(ctx) {        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mk_backwards::~mk_backwards() { }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    rule_set * mk_backwards::operator()(rule_set const & source) {
 | 
				
			||||||
 | 
					        context& ctx = source.get_context();
 | 
				
			||||||
 | 
					        rule_manager& rm = source.get_rule_manager();
 | 
				
			||||||
 | 
					        rule_set * result = alloc(rule_set, ctx);
 | 
				
			||||||
 | 
					        unsigned sz = source.get_num_rules();
 | 
				
			||||||
 | 
					        rule_ref new_rule(rm);
 | 
				
			||||||
 | 
					        app_ref_vector tail(m);
 | 
				
			||||||
 | 
					        app_ref head(m);
 | 
				
			||||||
 | 
					        svector<bool> neg;
 | 
				
			||||||
 | 
					        app_ref query(m);
 | 
				
			||||||
 | 
					        query = m.mk_fresh_const("Q", m.mk_bool_sort());
 | 
				
			||||||
 | 
					        result->set_output_predicate(query->get_decl());
 | 
				
			||||||
 | 
					        m_ctx.register_predicate(query->get_decl(), false);
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < sz; ++i) {            
 | 
				
			||||||
 | 
					            tail.reset();
 | 
				
			||||||
 | 
					            neg.reset();
 | 
				
			||||||
 | 
					            rule & r = *source.get_rule(i);
 | 
				
			||||||
 | 
					            unsigned utsz = r.get_uninterpreted_tail_size();
 | 
				
			||||||
 | 
					            unsigned tsz = r.get_tail_size();
 | 
				
			||||||
 | 
					            if (!source.is_output_predicate(r.get_decl())) {
 | 
				
			||||||
 | 
					                tail.push_back(r.get_head());
 | 
				
			||||||
 | 
					                neg.push_back(false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            for (unsigned j = utsz; j < tsz; ++j) {
 | 
				
			||||||
 | 
					                tail.push_back(r.get_tail(j));
 | 
				
			||||||
 | 
					                neg.push_back(false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            for (unsigned j = 0; j <= utsz; ++j) {                
 | 
				
			||||||
 | 
					                if (j == utsz && j > 0) {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (j == utsz) {
 | 
				
			||||||
 | 
					                    head = query;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    head = r.get_tail(j);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                new_rule = rm.mk(head, tail.size(), tail.c_ptr(), neg.c_ptr(), r.name(), true);
 | 
				
			||||||
 | 
					                result->add_rule(new_rule);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        TRACE("dl", result->display(tout););
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/muz_qe/dl_mk_backwards.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/muz_qe/dl_mk_backwards.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					/*++
 | 
				
			||||||
 | 
					Copyright (c) 2013 Microsoft Corporation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Module Name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dl_mk_backwards.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Abstract:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Create Horn clauses for backwards flow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Author:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Nikolaj Bjorner (nbjorner) 2013-04-17
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Revision History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--*/
 | 
				
			||||||
 | 
					#ifndef _DL_MK_BACKWARDS_H_
 | 
				
			||||||
 | 
					#define _DL_MK_BACKWARDS_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include"dl_rule_transformer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class mk_backwards : public rule_transformer::plugin {
 | 
				
			||||||
 | 
					        ast_manager& m;
 | 
				
			||||||
 | 
					        context&     m_ctx;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        mk_backwards(context & ctx, unsigned priority = 33000);
 | 
				
			||||||
 | 
					        ~mk_backwards();        
 | 
				
			||||||
 | 
					        rule_set * operator()(rule_set const & source);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _DL_MK_BACKWARDS_H_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,43 +108,50 @@ namespace datalog {
 | 
				
			||||||
    class expand_mkbv_cfg : public default_rewriter_cfg {
 | 
					    class expand_mkbv_cfg : public default_rewriter_cfg {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context&             m_context;
 | 
					        context&             m_context;
 | 
				
			||||||
        rule_ref_vector&     m_rules;
 | 
					 | 
				
			||||||
        ast_manager&         m;
 | 
					        ast_manager&         m;
 | 
				
			||||||
        bv_util              m_util;
 | 
					        bv_util              m_util;
 | 
				
			||||||
        expr_ref_vector      m_args, m_f_vars, m_g_vars;
 | 
					        expr_ref_vector      m_args, m_f_vars, m_g_vars;
 | 
				
			||||||
        func_decl_ref_vector m_old_funcs;
 | 
					        func_decl_ref_vector m_old_funcs;
 | 
				
			||||||
        func_decl_ref_vector m_new_funcs;
 | 
					        func_decl_ref_vector m_new_funcs;
 | 
				
			||||||
 | 
					        rule_set const*      m_src;
 | 
				
			||||||
 | 
					        rule_set*            m_dst;
 | 
				
			||||||
        obj_map<func_decl,func_decl*> m_pred2blast;
 | 
					        obj_map<func_decl,func_decl*> m_pred2blast;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expand_mkbv_cfg(context& ctx, rule_ref_vector& rules): 
 | 
					        expand_mkbv_cfg(context& ctx):
 | 
				
			||||||
            m_context(ctx), 
 | 
					            m_context(ctx), 
 | 
				
			||||||
            m_rules(rules),
 | 
					 | 
				
			||||||
            m(ctx.get_manager()),
 | 
					            m(ctx.get_manager()),
 | 
				
			||||||
            m_util(m),
 | 
					            m_util(m),
 | 
				
			||||||
            m_args(m), 
 | 
					            m_args(m), 
 | 
				
			||||||
            m_f_vars(m),
 | 
					            m_f_vars(m),
 | 
				
			||||||
            m_g_vars(m),
 | 
					            m_g_vars(m),
 | 
				
			||||||
            m_old_funcs(m),
 | 
					            m_old_funcs(m),
 | 
				
			||||||
            m_new_funcs(m)
 | 
					            m_new_funcs(m),
 | 
				
			||||||
 | 
					            m_src(0),
 | 
				
			||||||
 | 
					            m_dst(0)
 | 
				
			||||||
        {}
 | 
					        {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ~expand_mkbv_cfg() {}
 | 
					        ~expand_mkbv_cfg() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void set_src(rule_set const* src) { m_src = src; }
 | 
				
			||||||
 | 
					        void set_dst(rule_set* dst) { m_dst = dst; }
 | 
				
			||||||
        func_decl_ref_vector const& old_funcs() const { return m_old_funcs; }
 | 
					        func_decl_ref_vector const& old_funcs() const { return m_old_funcs; }
 | 
				
			||||||
        func_decl_ref_vector const& new_funcs() const { return m_new_funcs; }
 | 
					        func_decl_ref_vector const& new_funcs() const { return m_new_funcs; }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { 
 | 
					        br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { 
 | 
				
			||||||
            rule_manager& rm = m_context.get_rule_manager();
 | 
					            if (num == 0) {
 | 
				
			||||||
            bool found = false;
 | 
					                if (m_src->is_output_predicate(f))
 | 
				
			||||||
            for (unsigned j = 0; !found && j < num; ++j) {
 | 
					                    m_dst->set_output_predicate(f);
 | 
				
			||||||
                found = m_util.is_mkbv(args[j]);                
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (!found) {
 | 
					 | 
				
			||||||
                return BR_FAILED;
 | 
					                return BR_FAILED;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (unsigned i = 0; i < num; ++i) {
 | 
				
			||||||
 | 
					                if (!m_util.is_mkbv(args[i]))
 | 
				
			||||||
 | 
					                    return BR_FAILED;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // 
 | 
					            // 
 | 
				
			||||||
            // f(mk_bv(args),...)
 | 
					            // f(mk_bv(args),...)
 | 
				
			||||||
            // 
 | 
					            // 
 | 
				
			||||||
| 
						 | 
					@ -183,14 +190,7 @@ namespace datalog {
 | 
				
			||||||
                m_new_funcs.push_back(g);
 | 
					                m_new_funcs.push_back(g);
 | 
				
			||||||
                m_pred2blast.insert(f, g);
 | 
					                m_pred2blast.insert(f, g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Create rule f(mk_mkbv(args)) :- g(args)
 | 
					                m_dst->inherit_predicate(*m_src, f, g);
 | 
				
			||||||
 | 
					 | 
				
			||||||
                fml = m.mk_implies(m.mk_app(g, m_g_vars.size(), m_g_vars.c_ptr()), m.mk_app(f, m_f_vars.size(), m_f_vars.c_ptr()));
 | 
					 | 
				
			||||||
                proof_ref pr(m);
 | 
					 | 
				
			||||||
                if (m_context.generate_proof_trace()) {
 | 
					 | 
				
			||||||
                    pr = m.mk_asserted(fml); // or a def?
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                rm.mk_rule(fml, pr, m_rules, g->get_name());
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            result = m.mk_app(g, m_args.size(), m_args.c_ptr());
 | 
					            result = m.mk_app(g, m_args.size(), m_args.c_ptr());
 | 
				
			||||||
            result_pr = 0;
 | 
					            result_pr = 0;
 | 
				
			||||||
| 
						 | 
					@ -200,9 +200,9 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct expand_mkbv : public rewriter_tpl<expand_mkbv_cfg> {
 | 
					    struct expand_mkbv : public rewriter_tpl<expand_mkbv_cfg> {
 | 
				
			||||||
        expand_mkbv_cfg m_cfg;
 | 
					        expand_mkbv_cfg m_cfg;
 | 
				
			||||||
        expand_mkbv(ast_manager& m, context& ctx, rule_ref_vector& rules):
 | 
					        expand_mkbv(ast_manager& m, context& ctx):
 | 
				
			||||||
            rewriter_tpl<expand_mkbv_cfg>(m, m.proofs_enabled(), m_cfg),
 | 
					            rewriter_tpl<expand_mkbv_cfg>(m, m.proofs_enabled(), m_cfg),
 | 
				
			||||||
            m_cfg(ctx, rules) {
 | 
					            m_cfg(ctx) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,7 +212,6 @@ namespace datalog {
 | 
				
			||||||
        context &	     m_context;
 | 
					        context &	     m_context;
 | 
				
			||||||
        ast_manager &        m;
 | 
					        ast_manager &        m;
 | 
				
			||||||
        params_ref           m_params;
 | 
					        params_ref           m_params;
 | 
				
			||||||
        rule_ref_vector      m_rules;
 | 
					 | 
				
			||||||
        mk_interp_tail_simplifier m_simplifier;
 | 
					        mk_interp_tail_simplifier m_simplifier;
 | 
				
			||||||
        bit_blaster_rewriter m_blaster;
 | 
					        bit_blaster_rewriter m_blaster;
 | 
				
			||||||
        expand_mkbv          m_rewriter;
 | 
					        expand_mkbv          m_rewriter;
 | 
				
			||||||
| 
						 | 
					@ -239,19 +238,14 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void reset() {
 | 
					 | 
				
			||||||
            m_rules.reset();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        impl(context& ctx):
 | 
					        impl(context& ctx):
 | 
				
			||||||
            m_context(ctx),
 | 
					            m_context(ctx),
 | 
				
			||||||
            m(ctx.get_manager()),
 | 
					            m(ctx.get_manager()),
 | 
				
			||||||
            m_params(ctx.get_params().p),
 | 
					            m_params(ctx.get_params().p),
 | 
				
			||||||
            m_rules(ctx.get_rule_manager()),
 | 
					 | 
				
			||||||
            m_simplifier(ctx),
 | 
					            m_simplifier(ctx),
 | 
				
			||||||
            m_blaster(ctx.get_manager(), m_params),
 | 
					            m_blaster(ctx.get_manager(), m_params),
 | 
				
			||||||
            m_rewriter(ctx.get_manager(), ctx, m_rules) {
 | 
					            m_rewriter(ctx.get_manager(), ctx) {
 | 
				
			||||||
            m_params.set_bool("blast_full", true);
 | 
					            m_params.set_bool("blast_full", true);
 | 
				
			||||||
            m_params.set_bool("blast_quant", true);
 | 
					            m_params.set_bool("blast_quant", true);
 | 
				
			||||||
            m_blaster.updt_params(m_params);
 | 
					            m_blaster.updt_params(m_params);
 | 
				
			||||||
| 
						 | 
					@ -265,27 +259,34 @@ namespace datalog {
 | 
				
			||||||
            rule_manager& rm = m_context.get_rule_manager();
 | 
					            rule_manager& rm = m_context.get_rule_manager();
 | 
				
			||||||
            unsigned sz = source.get_num_rules();
 | 
					            unsigned sz = source.get_num_rules();
 | 
				
			||||||
            expr_ref fml(m);            
 | 
					            expr_ref fml(m);            
 | 
				
			||||||
            reset();
 | 
					            rule_set * result = alloc(rule_set, m_context);   
 | 
				
			||||||
            rule_set * result = alloc(rule_set, m_context);        
 | 
					            m_rewriter.m_cfg.set_src(&source);
 | 
				
			||||||
 | 
					            m_rewriter.m_cfg.set_dst(result);
 | 
				
			||||||
            for (unsigned i = 0; !m_context.canceled() && i < sz; ++i) {
 | 
					            for (unsigned i = 0; !m_context.canceled() && i < sz; ++i) {
 | 
				
			||||||
                rule * r = source.get_rule(i);
 | 
					                rule * r = source.get_rule(i);
 | 
				
			||||||
                r->to_formula(fml);                
 | 
					                r->to_formula(fml);
 | 
				
			||||||
                if (blast(r, fml)) {
 | 
					                if (blast(r, fml)) {
 | 
				
			||||||
                    proof_ref pr(m);
 | 
					                    proof_ref pr(m);
 | 
				
			||||||
                    if (m_context.generate_proof_trace()) {
 | 
					                    if (m_context.generate_proof_trace()) {
 | 
				
			||||||
                        pr = m.mk_asserted(fml); // loses original proof of r.
 | 
					                        pr = m.mk_asserted(fml); // loses original proof of r.
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    rm.mk_rule(fml, pr, m_rules, r->name());
 | 
					                    // TODO add logic for pc:
 | 
				
			||||||
 | 
					                    // 1. replace fresh predicates by non-bit-blasted predicates
 | 
				
			||||||
 | 
					                    // 2. replace pr by the proof of r.
 | 
				
			||||||
 | 
					                    rm.mk_rule(fml, pr, *result, r->name());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    m_rules.push_back(r);
 | 
					                    result->add_rule(r);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            for (unsigned i = 0; i < m_rules.size(); ++i) {
 | 
					 | 
				
			||||||
                result->add_rule(m_rules.get(i));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // copy output predicates without any rule (bit-blasting not really needed)
 | 
				
			||||||
 | 
					            const func_decl_set& decls = source.get_output_predicates();
 | 
				
			||||||
 | 
					            for (func_decl_set::iterator I = decls.begin(), E = decls.end(); I != E; ++I) {
 | 
				
			||||||
 | 
					                if (!source.contains(*I))
 | 
				
			||||||
 | 
					                    result->set_output_predicate(*I);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            if (m_context.get_model_converter()) {               
 | 
					            if (m_context.get_model_converter()) {               
 | 
				
			||||||
                filter_model_converter* fmc = alloc(filter_model_converter, m);
 | 
					                filter_model_converter* fmc = alloc(filter_model_converter, m);
 | 
				
			||||||
                bit_blast_model_converter* bvmc = alloc(bit_blast_model_converter, m);
 | 
					                bit_blast_model_converter* bvmc = alloc(bit_blast_model_converter, m);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,6 +173,7 @@ namespace datalog {
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    rule_set * mk_coalesce::operator()(rule_set const & source) {
 | 
					    rule_set * mk_coalesce::operator()(rule_set const & source) {
 | 
				
			||||||
        rule_set* rules = alloc(rule_set, m_ctx);
 | 
					        rule_set* rules = alloc(rule_set, m_ctx);
 | 
				
			||||||
 | 
					        rules->inherit_predicates(source);
 | 
				
			||||||
        rule_set::decl2rules::iterator it = source.begin_grouped_rules(), end = source.end_grouped_rules();
 | 
					        rule_set::decl2rules::iterator it = source.begin_grouped_rules(), end = source.end_grouped_rules();
 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					        for (; it != end; ++it) {
 | 
				
			||||||
            rule_ref_vector d_rules(rm);
 | 
					            rule_ref_vector d_rules(rm);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rule_set * mk_coi_filter::operator()(rule_set const & source)
 | 
					    rule_set * mk_coi_filter::operator()(rule_set const & source)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (source.get_num_rules()==0) {
 | 
					        if (source.empty()) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ namespace datalog {
 | 
				
			||||||
        decl_set pruned_preds;
 | 
					        decl_set pruned_preds;
 | 
				
			||||||
        ptr_vector<func_decl> todo;
 | 
					        ptr_vector<func_decl> todo;
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const decl_set& output_preds = m_context.get_output_predicates();
 | 
					            const decl_set& output_preds = source.get_output_predicates();
 | 
				
			||||||
            decl_set::iterator oend = output_preds.end();
 | 
					            decl_set::iterator oend = output_preds.end();
 | 
				
			||||||
            for (decl_set::iterator it = output_preds.begin(); it!=oend; ++it) {
 | 
					            for (decl_set::iterator it = output_preds.begin(); it!=oend; ++it) {
 | 
				
			||||||
                todo.push_back(*it);
 | 
					                todo.push_back(*it);
 | 
				
			||||||
| 
						 | 
					@ -70,6 +70,7 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        scoped_ptr<rule_set> res = alloc(rule_set, m_context);
 | 
					        scoped_ptr<rule_set> res = alloc(rule_set, m_context);
 | 
				
			||||||
 | 
					        res->inherit_predicates(source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rule_set::iterator rend = source.end();
 | 
					        rule_set::iterator rend = source.end();
 | 
				
			||||||
        for (rule_set::iterator rit = source.begin(); rit!=rend; ++rit) {
 | 
					        for (rule_set::iterator rit = source.begin(); rit!=rend; ++rit) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,8 +80,8 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual bool can_handle_signature(const relation_signature & s) {
 | 
					        virtual bool can_handle_signature(const relation_signature & s) {
 | 
				
			||||||
            unsigned n=s.size();
 | 
					            unsigned n=s.size();
 | 
				
			||||||
            for(unsigned i=0; i<n; i++) {
 | 
					            for (unsigned i=0; i<n; i++) {
 | 
				
			||||||
                if(!get_context().get_decl_util().is_rule_sort(s[i])) {
 | 
					                if (!get_context().get_decl_util().is_rule_sort(s[i])) {
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,7 @@ namespace datalog {
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
            DEBUG_CODE(
 | 
					            DEBUG_CODE(
 | 
				
			||||||
                unsigned sz = s.size();
 | 
					                unsigned sz = s.size();
 | 
				
			||||||
                for(unsigned i=0;i<sz; i++) {
 | 
					                for (unsigned i=0;i<sz; i++) {
 | 
				
			||||||
                    SASSERT( p.get_context().get_decl_util().is_rule_sort(s[i]) );
 | 
					                    SASSERT( p.get_context().get_decl_util().is_rule_sort(s[i]) );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
| 
						 | 
					@ -162,13 +162,13 @@ namespace datalog {
 | 
				
			||||||
            m_data.resize(get_signature().size());
 | 
					            m_data.resize(get_signature().size());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        void unite_with_data(const relation_fact & f) {
 | 
					        void unite_with_data(const relation_fact & f) {
 | 
				
			||||||
            if(empty()) {
 | 
					            if (empty()) {
 | 
				
			||||||
                assign_data(f);
 | 
					                assign_data(f);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            unsigned n=get_signature().size();
 | 
					            unsigned n=get_signature().size();
 | 
				
			||||||
            SASSERT(f.size()==n);
 | 
					            SASSERT(f.size()==n);
 | 
				
			||||||
            for(unsigned i=0; i<n; i++) {
 | 
					            for (unsigned i=0; i<n; i++) {
 | 
				
			||||||
                SASSERT(!is_undefined(i));
 | 
					                SASSERT(!is_undefined(i));
 | 
				
			||||||
                m_data[i] = get_plugin().mk_union(m_data[i], f[i]);
 | 
					                m_data[i] = get_plugin().mk_union(m_data[i], f[i]);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -193,12 +193,12 @@ namespace datalog {
 | 
				
			||||||
            return m_data[col_idx]==0;
 | 
					            return m_data[col_idx]==0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        bool no_undefined() const {
 | 
					        bool no_undefined() const {
 | 
				
			||||||
            if(empty()) {
 | 
					            if (empty()) {
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            unsigned n = get_signature().size();
 | 
					            unsigned n = get_signature().size();
 | 
				
			||||||
            for(unsigned i=0; i<n; i++) {
 | 
					            for (unsigned i=0; i<n; i++) {
 | 
				
			||||||
                if(is_undefined(i)) {
 | 
					                if (is_undefined(i)) {
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -231,14 +231,14 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual relation_base * complement(func_decl* pred) const {
 | 
					        virtual relation_base * complement(func_decl* pred) const {
 | 
				
			||||||
            explanation_relation * res = static_cast<explanation_relation *>(get_plugin().mk_empty(get_signature()));
 | 
					            explanation_relation * res = static_cast<explanation_relation *>(get_plugin().mk_empty(get_signature()));
 | 
				
			||||||
            if(empty()) {
 | 
					            if (empty()) {
 | 
				
			||||||
                res->set_undefined();
 | 
					                res->set_undefined();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return res;
 | 
					            return res;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void display_explanation(app * expl, std::ostream & out) const {
 | 
					        void display_explanation(app * expl, std::ostream & out) const {
 | 
				
			||||||
            if(expl) {
 | 
					            if (expl) {
 | 
				
			||||||
                //TODO: some nice explanation output
 | 
					                //TODO: some nice explanation output
 | 
				
			||||||
                ast_smt_pp pp(get_plugin().get_ast_manager());
 | 
					                ast_smt_pp pp(get_plugin().get_ast_manager());
 | 
				
			||||||
                pp.display_expr_smt2(out, expl);
 | 
					                pp.display_expr_smt2(out, expl);
 | 
				
			||||||
| 
						 | 
					@ -249,13 +249,13 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void display(std::ostream & out) const {
 | 
					        virtual void display(std::ostream & out) const {
 | 
				
			||||||
            if(empty()) {
 | 
					            if (empty()) {
 | 
				
			||||||
                out << "<empty explanation relation>\n";
 | 
					                out << "<empty explanation relation>\n";
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            unsigned sz = get_signature().size();
 | 
					            unsigned sz = get_signature().size();
 | 
				
			||||||
            for(unsigned i=0; i<sz; i++) {
 | 
					            for (unsigned i=0; i<sz; i++) {
 | 
				
			||||||
                if(i!=0) {
 | 
					                if (i!=0) {
 | 
				
			||||||
                    out << ", ";
 | 
					                    out << ", ";
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                display_explanation(m_data[0], out);
 | 
					                display_explanation(m_data[0], out);
 | 
				
			||||||
| 
						 | 
					@ -305,7 +305,7 @@ namespace datalog {
 | 
				
			||||||
            explanation_relation_plugin & plugin = r1.get_plugin();
 | 
					            explanation_relation_plugin & plugin = r1.get_plugin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            explanation_relation * res = static_cast<explanation_relation *>(plugin.mk_empty(get_result_signature()));
 | 
					            explanation_relation * res = static_cast<explanation_relation *>(plugin.mk_empty(get_result_signature()));
 | 
				
			||||||
            if(!r1.empty() && !r2.empty()) {
 | 
					            if (!r1.empty() && !r2.empty()) {
 | 
				
			||||||
                res->m_empty = false;
 | 
					                res->m_empty = false;
 | 
				
			||||||
                SASSERT(res->m_data.empty());
 | 
					                SASSERT(res->m_data.empty());
 | 
				
			||||||
                res->m_data.append(r1.m_data);
 | 
					                res->m_data.append(r1.m_data);
 | 
				
			||||||
| 
						 | 
					@ -317,10 +317,10 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    relation_join_fn * explanation_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2,
 | 
					    relation_join_fn * explanation_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2,
 | 
				
			||||||
            unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) {
 | 
					            unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) {
 | 
				
			||||||
        if(&r1.get_plugin()!=this || &r2.get_plugin()!=this) {
 | 
					        if (&r1.get_plugin()!=this || &r2.get_plugin()!=this) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(col_cnt!=0) {
 | 
					        if (col_cnt!=0) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return alloc(join_fn, r1.get_signature(), r2.get_signature());
 | 
					        return alloc(join_fn, r1.get_signature(), r2.get_signature());
 | 
				
			||||||
| 
						 | 
					@ -337,7 +337,7 @@ namespace datalog {
 | 
				
			||||||
            explanation_relation_plugin & plugin = r.get_plugin();
 | 
					            explanation_relation_plugin & plugin = r.get_plugin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            explanation_relation * res = static_cast<explanation_relation *>(plugin.mk_empty(get_result_signature()));
 | 
					            explanation_relation * res = static_cast<explanation_relation *>(plugin.mk_empty(get_result_signature()));
 | 
				
			||||||
            if(!r.empty()) {
 | 
					            if (!r.empty()) {
 | 
				
			||||||
                relation_fact proj_data = r.m_data;
 | 
					                relation_fact proj_data = r.m_data;
 | 
				
			||||||
                project_out_vector_columns(proj_data, m_removed_cols);
 | 
					                project_out_vector_columns(proj_data, m_removed_cols);
 | 
				
			||||||
                res->assign_data(proj_data);
 | 
					                res->assign_data(proj_data);
 | 
				
			||||||
| 
						 | 
					@ -348,7 +348,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    relation_transformer_fn * explanation_relation_plugin::mk_project_fn(const relation_base & r, unsigned col_cnt, 
 | 
					    relation_transformer_fn * explanation_relation_plugin::mk_project_fn(const relation_base & r, unsigned col_cnt, 
 | 
				
			||||||
            const unsigned * removed_cols) {
 | 
					            const unsigned * removed_cols) {
 | 
				
			||||||
        if(&r.get_plugin()!=this) {
 | 
					        if (&r.get_plugin()!=this) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return alloc(project_fn, r.get_signature(), col_cnt, removed_cols);
 | 
					        return alloc(project_fn, r.get_signature(), col_cnt, removed_cols);
 | 
				
			||||||
| 
						 | 
					@ -365,7 +365,7 @@ namespace datalog {
 | 
				
			||||||
            explanation_relation_plugin & plugin = r.get_plugin();
 | 
					            explanation_relation_plugin & plugin = r.get_plugin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            explanation_relation * res = static_cast<explanation_relation *>(plugin.mk_empty(get_result_signature()));
 | 
					            explanation_relation * res = static_cast<explanation_relation *>(plugin.mk_empty(get_result_signature()));
 | 
				
			||||||
            if(!r.empty()) {
 | 
					            if (!r.empty()) {
 | 
				
			||||||
                relation_fact permutated_data = r.m_data;
 | 
					                relation_fact permutated_data = r.m_data;
 | 
				
			||||||
                permutate_by_cycle(permutated_data, m_cycle);
 | 
					                permutate_by_cycle(permutated_data, m_cycle);
 | 
				
			||||||
                res->assign_data(permutated_data);
 | 
					                res->assign_data(permutated_data);
 | 
				
			||||||
| 
						 | 
					@ -389,16 +389,16 @@ namespace datalog {
 | 
				
			||||||
            explanation_relation * delta = delta0 ? static_cast<explanation_relation *>(delta0) : 0;
 | 
					            explanation_relation * delta = delta0 ? static_cast<explanation_relation *>(delta0) : 0;
 | 
				
			||||||
            explanation_relation_plugin & plugin = tgt.get_plugin();
 | 
					            explanation_relation_plugin & plugin = tgt.get_plugin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!src.no_undefined() || !tgt.no_undefined() || (delta && !delta->no_undefined())) {
 | 
					            if (!src.no_undefined() || !tgt.no_undefined() || (delta && !delta->no_undefined())) {
 | 
				
			||||||
                UNREACHABLE();
 | 
					                UNREACHABLE();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if(src.empty()) {
 | 
					            if (src.empty()) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if(plugin.m_relation_level_explanations) {
 | 
					            if (plugin.m_relation_level_explanations) {
 | 
				
			||||||
                tgt.unite_with_data(src.m_data);
 | 
					                tgt.unite_with_data(src.m_data);
 | 
				
			||||||
                if(delta) {
 | 
					                if (delta) {
 | 
				
			||||||
                    if(!m_delta_union_fun) {
 | 
					                    if (!m_delta_union_fun) {
 | 
				
			||||||
                        m_delta_union_fun = plugin.get_manager().mk_union_fn(*delta, src);
 | 
					                        m_delta_union_fun = plugin.get_manager().mk_union_fn(*delta, src);
 | 
				
			||||||
                        SASSERT(m_delta_union_fun);
 | 
					                        SASSERT(m_delta_union_fun);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -406,9 +406,9 @@ namespace datalog {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
                if(tgt.empty()) {
 | 
					                if (tgt.empty()) {
 | 
				
			||||||
                    tgt.assign_data(src.m_data);
 | 
					                    tgt.assign_data(src.m_data);
 | 
				
			||||||
                    if(delta && delta->empty()) {
 | 
					                    if (delta && delta->empty()) {
 | 
				
			||||||
                        delta->assign_data(src.m_data);
 | 
					                        delta->assign_data(src.m_data);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -423,11 +423,11 @@ namespace datalog {
 | 
				
			||||||
            explanation_relation & tgt = static_cast<explanation_relation &>(tgt0);
 | 
					            explanation_relation & tgt = static_cast<explanation_relation &>(tgt0);
 | 
				
			||||||
            explanation_relation * delta = delta0 ? static_cast<explanation_relation *>(delta0) : 0;
 | 
					            explanation_relation * delta = delta0 ? static_cast<explanation_relation *>(delta0) : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(src.empty()) {
 | 
					            if (src.empty()) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            tgt.set_undefined();
 | 
					            tgt.set_undefined();
 | 
				
			||||||
            if(delta) {
 | 
					            if (delta) {
 | 
				
			||||||
                delta->set_undefined();
 | 
					                delta->set_undefined();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -435,10 +435,10 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    relation_union_fn * explanation_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, 
 | 
					    relation_union_fn * explanation_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, 
 | 
				
			||||||
            const relation_base * delta) {
 | 
					            const relation_base * delta) {
 | 
				
			||||||
        if(!check_kind(tgt) || (delta && !check_kind(*delta))) {
 | 
					        if (!check_kind(tgt) || (delta && !check_kind(*delta))) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(!check_kind(src)) {
 | 
					        if (!check_kind(src)) {
 | 
				
			||||||
            //this is to handle the product relation
 | 
					            //this is to handle the product relation
 | 
				
			||||||
            return alloc(foreign_union_fn);
 | 
					            return alloc(foreign_union_fn);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -460,7 +460,7 @@ namespace datalog {
 | 
				
			||||||
        virtual void operator()(relation_base & r0) {
 | 
					        virtual void operator()(relation_base & r0) {
 | 
				
			||||||
            explanation_relation & r = static_cast<explanation_relation &>(r0);
 | 
					            explanation_relation & r = static_cast<explanation_relation &>(r0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!r.is_undefined(m_col_idx)) {
 | 
					            if (!r.is_undefined(m_col_idx)) {
 | 
				
			||||||
                UNREACHABLE();
 | 
					                UNREACHABLE();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -468,7 +468,7 @@ namespace datalog {
 | 
				
			||||||
            ptr_vector<expr> subst_arg;
 | 
					            ptr_vector<expr> subst_arg;
 | 
				
			||||||
            subst_arg.resize(sz, 0);
 | 
					            subst_arg.resize(sz, 0);
 | 
				
			||||||
            unsigned ofs = sz-1;
 | 
					            unsigned ofs = sz-1;
 | 
				
			||||||
            for(unsigned i=0; i<sz; i++) {
 | 
					            for (unsigned i=0; i<sz; i++) {
 | 
				
			||||||
                SASSERT(!r.is_undefined(i) || !contains_var(m_new_rule, i));
 | 
					                SASSERT(!r.is_undefined(i) || !contains_var(m_new_rule, i));
 | 
				
			||||||
                subst_arg[ofs-i] = r.m_data.get(i);
 | 
					                subst_arg[ofs-i] = r.m_data.get(i);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -480,26 +480,26 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    relation_mutator_fn * explanation_relation_plugin::mk_filter_interpreted_fn(const relation_base & r, 
 | 
					    relation_mutator_fn * explanation_relation_plugin::mk_filter_interpreted_fn(const relation_base & r, 
 | 
				
			||||||
            app * cond) {
 | 
					            app * cond) {
 | 
				
			||||||
        if(&r.get_plugin()!=this) {
 | 
					        if (&r.get_plugin()!=this) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ast_manager & m = get_ast_manager();
 | 
					        ast_manager & m = get_ast_manager();
 | 
				
			||||||
        if(!m.is_eq(cond)) {
 | 
					        if (!m.is_eq(cond)) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        expr * arg1 = cond->get_arg(0);
 | 
					        expr * arg1 = cond->get_arg(0);
 | 
				
			||||||
        expr * arg2 = cond->get_arg(1);
 | 
					        expr * arg2 = cond->get_arg(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(is_var(arg2)) {
 | 
					        if (is_var(arg2)) {
 | 
				
			||||||
            std::swap(arg1, arg2);
 | 
					            std::swap(arg1, arg2);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!is_var(arg1) || !is_app(arg2)) {
 | 
					        if (!is_var(arg1) || !is_app(arg2)) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var * col_var = to_var(arg1);
 | 
					        var * col_var = to_var(arg1);
 | 
				
			||||||
        app * new_rule = to_app(arg2);
 | 
					        app * new_rule = to_app(arg2);
 | 
				
			||||||
        if(!get_context().get_decl_util().is_rule_sort(col_var->get_sort())) {
 | 
					        if (!get_context().get_decl_util().is_rule_sort(col_var->get_sort())) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        unsigned col_idx = col_var->get_idx();
 | 
					        unsigned col_idx = col_var->get_idx();
 | 
				
			||||||
| 
						 | 
					@ -511,7 +511,7 @@ namespace datalog {
 | 
				
			||||||
    class explanation_relation_plugin::negation_filter_fn : public relation_intersection_filter_fn {
 | 
					    class explanation_relation_plugin::negation_filter_fn : public relation_intersection_filter_fn {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        virtual void operator()(relation_base & r, const relation_base & neg) {
 | 
					        virtual void operator()(relation_base & r, const relation_base & neg) {
 | 
				
			||||||
            if(!neg.empty()) {
 | 
					            if (!neg.empty()) {
 | 
				
			||||||
                r.reset();
 | 
					                r.reset();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -520,43 +520,42 @@ namespace datalog {
 | 
				
			||||||
    relation_intersection_filter_fn * explanation_relation_plugin::mk_filter_by_negation_fn(const relation_base & r, 
 | 
					    relation_intersection_filter_fn * explanation_relation_plugin::mk_filter_by_negation_fn(const relation_base & r, 
 | 
				
			||||||
            const relation_base & neg, unsigned joined_col_cnt, const unsigned * t_cols, 
 | 
					            const relation_base & neg, unsigned joined_col_cnt, const unsigned * t_cols, 
 | 
				
			||||||
            const unsigned * negated_cols) {
 | 
					            const unsigned * negated_cols) {
 | 
				
			||||||
        if(&r.get_plugin()!=this || &neg.get_plugin()!=this) {
 | 
					        if (&r.get_plugin()!=this || &neg.get_plugin()!=this) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return alloc(negation_filter_fn);
 | 
					        return alloc(negation_filter_fn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class explanation_relation_plugin::intersection_filter_fn : public relation_intersection_filter_fn {
 | 
					    class explanation_relation_plugin::intersection_filter_fn : public relation_intersection_filter_fn {
 | 
				
			||||||
        explanation_relation_plugin & m_plugin;
 | 
					 | 
				
			||||||
        func_decl_ref m_union_decl;
 | 
					        func_decl_ref m_union_decl;
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        intersection_filter_fn(explanation_relation_plugin & plugin)
 | 
					        intersection_filter_fn(explanation_relation_plugin & plugin)
 | 
				
			||||||
            : m_plugin(plugin), m_union_decl(plugin.m_union_decl) {}
 | 
					            : m_union_decl(plugin.m_union_decl) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void operator()(relation_base & tgt0, const relation_base & src0) {
 | 
					        virtual void operator()(relation_base & tgt0, const relation_base & src0) {
 | 
				
			||||||
            explanation_relation & tgt = static_cast<explanation_relation &>(tgt0);
 | 
					            explanation_relation & tgt = static_cast<explanation_relation &>(tgt0);
 | 
				
			||||||
            const explanation_relation & src = static_cast<const explanation_relation &>(src0);
 | 
					            const explanation_relation & src = static_cast<const explanation_relation &>(src0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(src.empty()) {
 | 
					            if (src.empty()) {
 | 
				
			||||||
                tgt.reset();
 | 
					                tgt.reset();
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if(tgt.empty()) {
 | 
					            if (tgt.empty()) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            unsigned sz = tgt.get_signature().size();
 | 
					            unsigned sz = tgt.get_signature().size();
 | 
				
			||||||
            for(unsigned i=0; i<sz; i++) {
 | 
					            for (unsigned i=0; i<sz; i++) {
 | 
				
			||||||
                if(src.is_undefined(i)) {
 | 
					                if (src.is_undefined(i)) {
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                app * curr_src = src.m_data.get(i);
 | 
					                app * curr_src = src.m_data.get(i);
 | 
				
			||||||
                if(tgt.is_undefined(i)) {
 | 
					                if (tgt.is_undefined(i)) {
 | 
				
			||||||
                    tgt.m_data.set(i, curr_src);
 | 
					                    tgt.m_data.set(i, curr_src);
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                app * curr_tgt = tgt.m_data.get(i);
 | 
					                app * curr_tgt = tgt.m_data.get(i);
 | 
				
			||||||
                if(curr_tgt->get_decl()==m_union_decl.get()) {
 | 
					                if (curr_tgt->get_decl()==m_union_decl.get()) {
 | 
				
			||||||
                    if(curr_tgt->get_arg(0)==curr_src || curr_tgt->get_arg(1)==curr_src) {
 | 
					                    if (curr_tgt->get_arg(0)==curr_src || curr_tgt->get_arg(1)==curr_src) {
 | 
				
			||||||
                        tgt.m_data.set(i, curr_src);
 | 
					                        tgt.m_data.set(i, curr_src);
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -570,18 +569,18 @@ namespace datalog {
 | 
				
			||||||
    relation_intersection_filter_fn * explanation_relation_plugin::mk_filter_by_intersection_fn(
 | 
					    relation_intersection_filter_fn * explanation_relation_plugin::mk_filter_by_intersection_fn(
 | 
				
			||||||
            const relation_base & tgt, const relation_base & src, unsigned joined_col_cnt, 
 | 
					            const relation_base & tgt, const relation_base & src, unsigned joined_col_cnt, 
 | 
				
			||||||
            const unsigned * tgt_cols, const unsigned * src_cols) {
 | 
					            const unsigned * tgt_cols, const unsigned * src_cols) {
 | 
				
			||||||
        if(&tgt.get_plugin()!=this || &src.get_plugin()!=this) {
 | 
					        if (&tgt.get_plugin()!=this || &src.get_plugin()!=this) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //this checks the join is one to one on all columns
 | 
					        //this checks the join is one to one on all columns
 | 
				
			||||||
        if(tgt.get_signature()!=src.get_signature()
 | 
					        if (tgt.get_signature()!=src.get_signature()
 | 
				
			||||||
            || joined_col_cnt!=tgt.get_signature().size()
 | 
					            || joined_col_cnt!=tgt.get_signature().size()
 | 
				
			||||||
            || !containers_equal(tgt_cols, tgt_cols+joined_col_cnt, src_cols, src_cols+joined_col_cnt)) {
 | 
					            || !containers_equal(tgt_cols, tgt_cols+joined_col_cnt, src_cols, src_cols+joined_col_cnt)) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        counter ctr;
 | 
					        counter ctr;
 | 
				
			||||||
        ctr.count(joined_col_cnt, tgt_cols);
 | 
					        ctr.count(joined_col_cnt, tgt_cols);
 | 
				
			||||||
        if(ctr.get_max_counter_value()>1 || (joined_col_cnt && ctr.get_max_positive()!=joined_col_cnt-1)) {
 | 
					        if (ctr.get_max_counter_value()>1 || (joined_col_cnt && ctr.get_max_positive()!=joined_col_cnt-1)) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return alloc(intersection_filter_fn, *this);
 | 
					        return alloc(intersection_filter_fn, *this);
 | 
				
			||||||
| 
						 | 
					@ -595,23 +594,23 @@ namespace datalog {
 | 
				
			||||||
    // -----------------------------------
 | 
					    // -----------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk_explanations::mk_explanations(context & ctx, bool relation_level) 
 | 
					    mk_explanations::mk_explanations(context & ctx) 
 | 
				
			||||||
            : plugin(50000),
 | 
					        : plugin(50000),
 | 
				
			||||||
            m_manager(ctx.get_manager()),
 | 
					          m_manager(ctx.get_manager()),
 | 
				
			||||||
            m_context(ctx),
 | 
					          m_context(ctx),
 | 
				
			||||||
            m_decl_util(ctx.get_decl_util()),
 | 
					          m_decl_util(ctx.get_decl_util()),
 | 
				
			||||||
            m_relation_level(relation_level),
 | 
					          m_relation_level(ctx.explanations_on_relation_level()),
 | 
				
			||||||
            m_pinned(m_manager) {
 | 
					          m_pinned(m_manager) {
 | 
				
			||||||
        m_e_sort = m_decl_util.mk_rule_sort();
 | 
					        m_e_sort = m_decl_util.mk_rule_sort();
 | 
				
			||||||
        m_pinned.push_back(m_e_sort);
 | 
					        m_pinned.push_back(m_e_sort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        relation_manager & rmgr = ctx.get_rel_context().get_rmanager();
 | 
					        relation_manager & rmgr = ctx.get_rel_context().get_rmanager();
 | 
				
			||||||
        symbol er_symbol = explanation_relation_plugin::get_name(relation_level);
 | 
					        symbol er_symbol = explanation_relation_plugin::get_name(m_relation_level);
 | 
				
			||||||
        m_er_plugin = static_cast<explanation_relation_plugin *>(rmgr.get_relation_plugin(er_symbol));
 | 
					        m_er_plugin = static_cast<explanation_relation_plugin *>(rmgr.get_relation_plugin(er_symbol));
 | 
				
			||||||
        if(!m_er_plugin) {
 | 
					        if (!m_er_plugin) {
 | 
				
			||||||
            m_er_plugin = alloc(explanation_relation_plugin, relation_level, rmgr);
 | 
					            m_er_plugin = alloc(explanation_relation_plugin, m_relation_level, rmgr);
 | 
				
			||||||
            rmgr.register_plugin(m_er_plugin);
 | 
					            rmgr.register_plugin(m_er_plugin);
 | 
				
			||||||
            if(!m_relation_level) {
 | 
					            if (!m_relation_level) {
 | 
				
			||||||
                DEBUG_CODE(
 | 
					                DEBUG_CODE(
 | 
				
			||||||
                    finite_product_relation_plugin * dummy;
 | 
					                    finite_product_relation_plugin * dummy;
 | 
				
			||||||
                    SASSERT(!rmgr.try_get_finite_product_relation_plugin(*m_er_plugin, dummy));
 | 
					                    SASSERT(!rmgr.try_get_finite_product_relation_plugin(*m_er_plugin, dummy));
 | 
				
			||||||
| 
						 | 
					@ -620,7 +619,7 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        DEBUG_CODE(
 | 
					        DEBUG_CODE(
 | 
				
			||||||
            if(!m_relation_level) {
 | 
					            if (!m_relation_level) {
 | 
				
			||||||
                finite_product_relation_plugin * dummy;
 | 
					                finite_product_relation_plugin * dummy;
 | 
				
			||||||
                SASSERT(rmgr.try_get_finite_product_relation_plugin(*m_er_plugin, dummy));
 | 
					                SASSERT(rmgr.try_get_finite_product_relation_plugin(*m_er_plugin, dummy));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -668,7 +667,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    func_decl * mk_explanations::get_e_decl(func_decl * orig_decl) {
 | 
					    func_decl * mk_explanations::get_e_decl(func_decl * orig_decl) {
 | 
				
			||||||
        decl_map::obj_map_entry * e = m_e_decl_map.insert_if_not_there2(orig_decl, 0);
 | 
					        decl_map::obj_map_entry * e = m_e_decl_map.insert_if_not_there2(orig_decl, 0);
 | 
				
			||||||
        if(e->get_data().m_value==0) {
 | 
					        if (e->get_data().m_value==0) {
 | 
				
			||||||
            relation_signature e_domain;
 | 
					            relation_signature e_domain;
 | 
				
			||||||
            e_domain.append(orig_decl->get_arity(), orig_decl->get_domain());
 | 
					            e_domain.append(orig_decl->get_arity(), orig_decl->get_domain());
 | 
				
			||||||
            e_domain.push_back(m_e_sort);
 | 
					            e_domain.push_back(m_e_sort);
 | 
				
			||||||
| 
						 | 
					@ -677,7 +676,7 @@ namespace datalog {
 | 
				
			||||||
            m_pinned.push_back(new_decl);
 | 
					            m_pinned.push_back(new_decl);
 | 
				
			||||||
            e->get_data().m_value = new_decl;
 | 
					            e->get_data().m_value = new_decl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(m_relation_level) {
 | 
					            if (m_relation_level) {
 | 
				
			||||||
                assign_rel_level_kind(new_decl, orig_decl);
 | 
					                assign_rel_level_kind(new_decl, orig_decl);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -716,13 +715,13 @@ namespace datalog {
 | 
				
			||||||
        app_ref_vector e_tail(m_manager);
 | 
					        app_ref_vector e_tail(m_manager);
 | 
				
			||||||
        svector<bool> neg_flags;
 | 
					        svector<bool> neg_flags;
 | 
				
			||||||
        unsigned pos_tail_sz = r->get_positive_tail_size();
 | 
					        unsigned pos_tail_sz = r->get_positive_tail_size();
 | 
				
			||||||
        for(unsigned i=0; i<pos_tail_sz; i++) {
 | 
					        for (unsigned i=0; i<pos_tail_sz; i++) {
 | 
				
			||||||
            unsigned e_var = next_var++;
 | 
					            unsigned e_var = next_var++;
 | 
				
			||||||
            e_tail.push_back(get_e_lit(r->get_tail(i), e_var));
 | 
					            e_tail.push_back(get_e_lit(r->get_tail(i), e_var));
 | 
				
			||||||
            neg_flags.push_back(false);
 | 
					            neg_flags.push_back(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        unsigned tail_sz = r->get_tail_size();
 | 
					        unsigned tail_sz = r->get_tail_size();
 | 
				
			||||||
        for(unsigned i=pos_tail_sz; i<tail_sz; i++) {
 | 
					        for (unsigned i=pos_tail_sz; i<tail_sz; i++) {
 | 
				
			||||||
            e_tail.push_back(r->get_tail(i));
 | 
					            e_tail.push_back(r->get_tail(i));
 | 
				
			||||||
            neg_flags.push_back(r->is_neg_tail(i));
 | 
					            neg_flags.push_back(r->is_neg_tail(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -730,9 +729,9 @@ namespace datalog {
 | 
				
			||||||
        symbol rule_repr = get_rule_symbol(r);
 | 
					        symbol rule_repr = get_rule_symbol(r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expr_ref_vector rule_expr_args(m_manager);
 | 
					        expr_ref_vector rule_expr_args(m_manager);
 | 
				
			||||||
        for(unsigned tail_idx=0; tail_idx<pos_tail_sz; tail_idx++) {
 | 
					        for (unsigned tail_idx=0; tail_idx<pos_tail_sz; tail_idx++) {
 | 
				
			||||||
            app * tail = e_tail.get(tail_idx);
 | 
					            app * tail = e_tail.get(tail_idx);
 | 
				
			||||||
            if(true || m_relation_level) {
 | 
					            if (true || m_relation_level) {
 | 
				
			||||||
                //this adds the explanation term of the tail
 | 
					                //this adds the explanation term of the tail
 | 
				
			||||||
                rule_expr_args.push_back(tail->get_arg(tail->get_num_args()-1));
 | 
					                rule_expr_args.push_back(tail->get_arg(tail->get_num_args()-1));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -754,37 +753,32 @@ namespace datalog {
 | 
				
			||||||
        return m_context.get_rule_manager().mk(e_head, e_tail.size(), e_tail.c_ptr(), neg_flags.c_ptr());
 | 
					        return m_context.get_rule_manager().mk(e_head, e_tail.size(), e_tail.c_ptr(), neg_flags.c_ptr());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_explanations::transform_rules(const rule_set & orig, rule_set & tgt) {
 | 
					    void mk_explanations::transform_rules(const rule_set & src, rule_set & dst) {
 | 
				
			||||||
        rule_set::iterator rit = orig.begin();
 | 
					        rule_set::iterator rit = src.begin();
 | 
				
			||||||
        rule_set::iterator rend = orig.end();
 | 
					        rule_set::iterator rend = src.end();
 | 
				
			||||||
        for(; rit!=rend; ++rit) {
 | 
					        for (; rit!=rend; ++rit) {
 | 
				
			||||||
            rule * e_rule = get_e_rule(*rit);
 | 
					            rule * e_rule = get_e_rule(*rit);
 | 
				
			||||||
            tgt.add_rule(e_rule);
 | 
					            dst.add_rule(e_rule);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //add rules that will (for output predicates) copy facts from explained relations back to
 | 
					        //add rules that will (for output predicates) copy facts from explained relations back to
 | 
				
			||||||
        //the original ones
 | 
					        //the original ones
 | 
				
			||||||
        expr_ref_vector lit_args(m_manager);
 | 
					        expr_ref_vector lit_args(m_manager);
 | 
				
			||||||
        decl_set::iterator pit = m_original_preds.begin();
 | 
					        decl_set::iterator pit = src.get_output_predicates().begin();
 | 
				
			||||||
        decl_set::iterator pend = m_original_preds.end();
 | 
					        decl_set::iterator pend = src.get_output_predicates().end();
 | 
				
			||||||
        for(; pit!=pend; ++pit) {
 | 
					        for (; pit != pend; ++pit) {
 | 
				
			||||||
            func_decl * orig_decl = *pit;
 | 
					            func_decl * orig_decl = *pit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!m_context.is_output_predicate(orig_decl)) {
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            lit_args.reset();
 | 
					            lit_args.reset();
 | 
				
			||||||
            unsigned arity = orig_decl->get_arity();
 | 
					            unsigned arity = orig_decl->get_arity();
 | 
				
			||||||
            for(unsigned i=0; i<arity; i++) {
 | 
					            for (unsigned i=0; i<arity; i++) {
 | 
				
			||||||
                lit_args.push_back(m_manager.mk_var(i, orig_decl->get_domain(i)));
 | 
					                lit_args.push_back(m_manager.mk_var(i, orig_decl->get_domain(i)));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            app_ref orig_lit(m_manager.mk_app(orig_decl, lit_args.c_ptr()), m_manager);
 | 
					            app_ref orig_lit(m_manager.mk_app(orig_decl, lit_args.c_ptr()), m_manager);
 | 
				
			||||||
            app_ref e_lit(get_e_lit(orig_lit, arity), m_manager);
 | 
					            app_ref e_lit(get_e_lit(orig_lit, arity), m_manager);
 | 
				
			||||||
            app * tail[] = { e_lit.get() };
 | 
					            app * tail[] = { e_lit.get() };
 | 
				
			||||||
            tgt.add_rule(m_context.get_rule_manager().mk(orig_lit, 1, tail, 0));
 | 
					            dst.add_rule(m_context.get_rule_manager().mk(orig_lit, 1, tail, 0));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_explanations::translate_rel_level_relation(relation_manager & rmgr, relation_base & orig, 
 | 
					    void mk_explanations::translate_rel_level_relation(relation_manager & rmgr, relation_base & orig, 
 | 
				
			||||||
| 
						 | 
					@ -799,7 +793,7 @@ namespace datalog {
 | 
				
			||||||
        sieve_relation * srels[] = { 
 | 
					        sieve_relation * srels[] = { 
 | 
				
			||||||
            static_cast<sieve_relation *>(&prod_rel[0]),
 | 
					            static_cast<sieve_relation *>(&prod_rel[0]),
 | 
				
			||||||
            static_cast<sieve_relation *>(&prod_rel[1]) };
 | 
					            static_cast<sieve_relation *>(&prod_rel[1]) };
 | 
				
			||||||
        if(&srels[0]->get_inner().get_plugin()==m_er_plugin) {
 | 
					        if (&srels[0]->get_inner().get_plugin()==m_er_plugin) {
 | 
				
			||||||
            std::swap(srels[0], srels[1]);
 | 
					            std::swap(srels[0], srels[1]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        SASSERT(&srels[0]->get_inner().get_plugin()==&orig.get_plugin());
 | 
					        SASSERT(&srels[0]->get_inner().get_plugin()==&orig.get_plugin());
 | 
				
			||||||
| 
						 | 
					@ -821,10 +815,9 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_explanations::transform_facts(relation_manager & rmgr) {
 | 
					    void mk_explanations::transform_facts(relation_manager & rmgr, rule_set const& src, rule_set& dst) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!m_e_fact_relation) {
 | 
				
			||||||
        if(!m_e_fact_relation) {
 | 
					 | 
				
			||||||
            relation_signature expl_singleton_sig;
 | 
					            relation_signature expl_singleton_sig;
 | 
				
			||||||
            expl_singleton_sig.push_back(m_e_sort);
 | 
					            expl_singleton_sig.push_back(m_e_sort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -836,29 +829,26 @@ namespace datalog {
 | 
				
			||||||
            SASSERT(&expl_singleton->get_plugin()==m_er_plugin);
 | 
					            SASSERT(&expl_singleton->get_plugin()==m_er_plugin);
 | 
				
			||||||
            m_e_fact_relation = static_cast<explanation_relation *>(expl_singleton);
 | 
					            m_e_fact_relation = static_cast<explanation_relation *>(expl_singleton);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        func_decl_set const& predicates = m_context.get_predicates();
 | 
				
			||||||
 | 
					        decl_set::iterator it = predicates.begin();
 | 
				
			||||||
 | 
					        decl_set::iterator end = predicates.end();
 | 
				
			||||||
        decl_set::iterator it = m_original_preds.begin();
 | 
					        for (; it!=end; ++it) {
 | 
				
			||||||
        decl_set::iterator end = m_original_preds.end();
 | 
					 | 
				
			||||||
        for(; it!=end; ++it) {
 | 
					 | 
				
			||||||
            func_decl * orig_decl = *it;
 | 
					            func_decl * orig_decl = *it;
 | 
				
			||||||
            func_decl * e_decl = get_e_decl(orig_decl);
 | 
					            func_decl * e_decl = get_e_decl(orig_decl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(m_context.is_output_predicate(orig_decl)) {
 | 
					            if (!rmgr.try_get_relation(orig_decl) &&
 | 
				
			||||||
                m_context.set_output_predicate(e_decl);
 | 
					                !src.contains(orig_decl)) {
 | 
				
			||||||
            }
 | 
					                // there are no facts or rules for this predicate
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(!rmgr.try_get_relation(orig_decl)) {
 | 
					 | 
				
			||||||
                //there are no facts for this predicate
 | 
					 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            dst.inherit_predicate(src, orig_decl, e_decl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            relation_base & orig_rel = rmgr.get_relation(orig_decl);
 | 
					            relation_base & orig_rel = rmgr.get_relation(orig_decl);
 | 
				
			||||||
            relation_base & e_rel = rmgr.get_relation(e_decl);
 | 
					            relation_base & e_rel = rmgr.get_relation(e_decl);
 | 
				
			||||||
            SASSERT(e_rel.empty()); //the e_rel should be a new relation
 | 
					            SASSERT(e_rel.empty()); //the e_rel should be a new relation
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            if(m_relation_level) {
 | 
					            if (m_relation_level) {
 | 
				
			||||||
                translate_rel_level_relation(rmgr, orig_rel, e_rel);
 | 
					                translate_rel_level_relation(rmgr, orig_rel, e_rel);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
| 
						 | 
					@ -869,18 +859,19 @@ namespace datalog {
 | 
				
			||||||
                SASSERT(union_fun);
 | 
					                SASSERT(union_fun);
 | 
				
			||||||
                (*union_fun)(e_rel, *aux_extended_rel);
 | 
					                (*union_fun)(e_rel, *aux_extended_rel);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rule_set * mk_explanations::operator()(rule_set const & source) {
 | 
					    rule_set * mk_explanations::operator()(rule_set const & source) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(source.get_num_rules()==0) {
 | 
					        if (source.empty()) {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!m_context.generate_explanations()) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        m_context.collect_predicates(m_original_preds);
 | 
					 | 
				
			||||||
        rule_set * res = alloc(rule_set, m_context);
 | 
					        rule_set * res = alloc(rule_set, m_context);
 | 
				
			||||||
        transform_facts(m_context.get_rel_context().get_rmanager());
 | 
					        transform_facts(m_context.get_rel_context().get_rmanager(), source, *res);
 | 
				
			||||||
        transform_rules(source, *res);
 | 
					        transform_rules(source, *res);
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,19 +32,13 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        typedef obj_map<func_decl, func_decl *> decl_map;
 | 
					        typedef obj_map<func_decl, func_decl *> decl_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ast_manager & m_manager;
 | 
					        ast_manager &  m_manager;
 | 
				
			||||||
        context & m_context;
 | 
					        context &      m_context;
 | 
				
			||||||
        dl_decl_util & m_decl_util;
 | 
					        dl_decl_util & m_decl_util;
 | 
				
			||||||
 | 
					        bool           m_relation_level;
 | 
				
			||||||
        bool m_relation_level;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        decl_set m_original_preds;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ast_ref_vector m_pinned;
 | 
					        ast_ref_vector m_pinned;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        explanation_relation_plugin * m_er_plugin;
 | 
					        explanation_relation_plugin * m_er_plugin;
 | 
				
			||||||
 | 
					        sort *         m_e_sort;
 | 
				
			||||||
        sort * m_e_sort;
 | 
					 | 
				
			||||||
        scoped_rel<explanation_relation> m_e_fact_relation;
 | 
					        scoped_rel<explanation_relation> m_e_fact_relation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        decl_map m_e_decl_map;
 | 
					        decl_map m_e_decl_map;
 | 
				
			||||||
| 
						 | 
					@ -62,15 +56,15 @@ namespace datalog {
 | 
				
			||||||
        void assign_rel_level_kind(func_decl * e_decl, func_decl * orig);
 | 
					        void assign_rel_level_kind(func_decl * e_decl, func_decl * orig);
 | 
				
			||||||
        void translate_rel_level_relation(relation_manager & rmgr, relation_base & orig, relation_base & e_rel);
 | 
					        void translate_rel_level_relation(relation_manager & rmgr, relation_base & orig, relation_base & e_rel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void transform_rules(const rule_set & orig, rule_set & tgt);
 | 
					        void transform_rules(const rule_set & src, rule_set & dst);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        void transform_facts(relation_manager & rmgr);
 | 
					        void transform_facts(relation_manager & rmgr, rule_set const& src, rule_set& dst);
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
           If relation_level is true, the explanation will not be stored for each fact,
 | 
					           If relation_level is true, the explanation will not be stored for each fact,
 | 
				
			||||||
           but we will rather store history of the whole relation.
 | 
					           but we will rather store history of the whole relation.
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
        mk_explanations(context & ctx, bool relation_level);
 | 
					        mk_explanations(context & ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
           \brief Return explanation predicate that corresponds to \c orig_decl.
 | 
					           \brief Return explanation predicate that corresponds to \c orig_decl.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,379 +0,0 @@
 | 
				
			||||||
/*++
 | 
					 | 
				
			||||||
Copyright (c) 2012 Microsoft Corporation
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Module Name:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    dl_mk_extract_quantifiers.cpp
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Abstract:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Remove universal quantifiers over interpreted predicates in the body.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Author:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Nikolaj Bjorner (nbjorner) 2012-11-21
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Revision History:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
--*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include"dl_mk_extract_quantifiers.h"
 | 
					 | 
				
			||||||
#include"ast_pp.h"
 | 
					 | 
				
			||||||
#include"dl_bmc_engine.h"
 | 
					 | 
				
			||||||
#include"smt_quantifier.h"
 | 
					 | 
				
			||||||
#include"smt_context.h"
 | 
					 | 
				
			||||||
#include"for_each_expr.h"
 | 
					 | 
				
			||||||
#include "expr_abstract.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace datalog {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    mk_extract_quantifiers::mk_extract_quantifiers(context & ctx) : 
 | 
					 | 
				
			||||||
        rule_transformer::plugin(101, false),
 | 
					 | 
				
			||||||
        m_ctx(ctx),
 | 
					 | 
				
			||||||
        m(ctx.get_manager()),
 | 
					 | 
				
			||||||
        rm(ctx.get_rule_manager()),
 | 
					 | 
				
			||||||
        m_query_pred(m)
 | 
					 | 
				
			||||||
    {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    mk_extract_quantifiers::~mk_extract_quantifiers() {
 | 
					 | 
				
			||||||
        reset();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void mk_extract_quantifiers::set_query(func_decl* q) {
 | 
					 | 
				
			||||||
        m_query_pred = q;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void mk_extract_quantifiers::ensure_predicate(expr* e, unsigned& max_var, app_ref_vector& tail) {
 | 
					 | 
				
			||||||
        SASSERT(is_app(e));
 | 
					 | 
				
			||||||
        SASSERT(to_app(e)->get_decl()->get_family_id() == null_family_id);
 | 
					 | 
				
			||||||
        app* a = to_app(e);
 | 
					 | 
				
			||||||
        expr_ref_vector args(m);        
 | 
					 | 
				
			||||||
        for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
					 | 
				
			||||||
            expr* arg = a->get_arg(i);
 | 
					 | 
				
			||||||
            if (is_var(arg) || m.is_value(arg)) {
 | 
					 | 
				
			||||||
                args.push_back(arg);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                expr_ref new_var(m);
 | 
					 | 
				
			||||||
                new_var = m.mk_var(++max_var, m.get_sort(arg));
 | 
					 | 
				
			||||||
                args.push_back(new_var);
 | 
					 | 
				
			||||||
                tail.push_back(m.mk_eq(new_var, arg));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        tail.push_back(m.mk_app(a->get_decl(), args.size(), args.c_ptr()));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    class mk_extract_quantifiers::collect_insts {
 | 
					 | 
				
			||||||
        ast_manager&     m;
 | 
					 | 
				
			||||||
        ptr_vector<expr>        m_binding;
 | 
					 | 
				
			||||||
        vector<expr_ref_vector> m_bindings;
 | 
					 | 
				
			||||||
        ptr_vector<quantifier>  m_quantifiers;
 | 
					 | 
				
			||||||
    public:
 | 
					 | 
				
			||||||
        collect_insts(ast_manager& m): m(m) { }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void operator()(expr* n) {
 | 
					 | 
				
			||||||
            expr* not_q_or_i, *e1, *e2, *e3;
 | 
					 | 
				
			||||||
            if (m.is_quant_inst(n, not_q_or_i, m_binding)) {
 | 
					 | 
				
			||||||
                VERIFY(m.is_or(not_q_or_i, e1, e2));
 | 
					 | 
				
			||||||
                VERIFY(m.is_not(e1, e3));
 | 
					 | 
				
			||||||
                SASSERT(is_quantifier(e3));
 | 
					 | 
				
			||||||
                m_quantifiers.push_back(to_quantifier(e3));
 | 
					 | 
				
			||||||
                m_bindings.push_back(expr_ref_vector(m,m_binding.size(), m_binding.c_ptr()));
 | 
					 | 
				
			||||||
                m_binding.reset();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if ((m.is_rewrite(n, e1, e2) ||
 | 
					 | 
				
			||||||
                      (m.is_rewrite_star(n) && 
 | 
					 | 
				
			||||||
                       (e3 = to_app(n)->get_arg(to_app(n)->get_num_args()-1),
 | 
					 | 
				
			||||||
                        e1 = to_app(e3)->get_arg(0),
 | 
					 | 
				
			||||||
                        e2 = to_app(e3)->get_arg(1),
 | 
					 | 
				
			||||||
                        true))) &&
 | 
					 | 
				
			||||||
                     is_quantifier(e1) && m.is_false(e2)) {
 | 
					 | 
				
			||||||
                quantifier* q = to_quantifier(e1);
 | 
					 | 
				
			||||||
                m_quantifiers.push_back(q);
 | 
					 | 
				
			||||||
                m_bindings.push_back(expr_ref_vector(m));
 | 
					 | 
				
			||||||
                expr_ref_vector& b = m_bindings.back();
 | 
					 | 
				
			||||||
                for (unsigned i = 0; i < q->get_num_decls(); ++i) {
 | 
					 | 
				
			||||||
                    b.push_back(m.mk_fresh_const("V", q->get_decl_sort(i)));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void reset() {
 | 
					 | 
				
			||||||
            m_quantifiers.reset();
 | 
					 | 
				
			||||||
            m_bindings.reset();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        unsigned size() const { return m_quantifiers.size(); }
 | 
					 | 
				
			||||||
        ptr_vector<quantifier> const& quantifiers() const { return m_quantifiers; }
 | 
					 | 
				
			||||||
        vector<expr_ref_vector> const& bindings() const { return m_bindings; }        
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /*
 | 
					 | 
				
			||||||
     * forall y . P1(x,y) & 
 | 
					 | 
				
			||||||
     * forall y . P2(x,y) & 
 | 
					 | 
				
			||||||
     * Body[x] & 
 | 
					 | 
				
			||||||
     * ~H[x]
 | 
					 | 
				
			||||||
     * forall y . y != binding1 => ~ P1(x,y)
 | 
					 | 
				
			||||||
     * forall y . y != binding2 => ~ P2(x,y)
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    void mk_extract_quantifiers::extract(rule& r, rule_set& new_rules) {
 | 
					 | 
				
			||||||
        unsigned utsz = r.get_uninterpreted_tail_size();
 | 
					 | 
				
			||||||
        expr_ref_vector conjs(m);
 | 
					 | 
				
			||||||
        quantifier_ref_vector qs(m);
 | 
					 | 
				
			||||||
        for (unsigned i = utsz; i < r.get_tail_size(); ++i) {
 | 
					 | 
				
			||||||
            conjs.push_back(r.get_tail(i));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        datalog::flatten_and(conjs);
 | 
					 | 
				
			||||||
        for (unsigned j = 0; j < conjs.size(); ++j) {
 | 
					 | 
				
			||||||
            expr* e = conjs[j].get();
 | 
					 | 
				
			||||||
            quantifier* q;
 | 
					 | 
				
			||||||
            if (rule_manager::is_forall(m, e, q)) {
 | 
					 | 
				
			||||||
                qs.push_back(q);
 | 
					 | 
				
			||||||
                conjs[j] = conjs.back();
 | 
					 | 
				
			||||||
                conjs.pop_back();
 | 
					 | 
				
			||||||
                --j;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (qs.empty()) {
 | 
					 | 
				
			||||||
            new_rules.add_rule(&r);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            expr_ref fml(m);
 | 
					 | 
				
			||||||
            expr_ref_vector bindings(m);
 | 
					 | 
				
			||||||
            obj_map<quantifier, expr_ref_vector*> insts;
 | 
					 | 
				
			||||||
            for (unsigned i = 0; i < qs.size(); ++i) {
 | 
					 | 
				
			||||||
                insts.insert(qs[i].get(), alloc(expr_ref_vector, m));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            unsigned max_inst = 10; // TODO configuration.
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            for (unsigned i = 0; i < max_inst; ++i) {
 | 
					 | 
				
			||||||
                app_ref_vector sub(m);
 | 
					 | 
				
			||||||
                rule2formula(r, insts, fml, sub);
 | 
					 | 
				
			||||||
                bool new_binding = find_instantiations_proof_based(fml, sub, insts, bindings);
 | 
					 | 
				
			||||||
                if (!new_binding) {
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            expr_ref_vector fmls(m);
 | 
					 | 
				
			||||||
            for (unsigned i = 0; i < utsz; ++i) {
 | 
					 | 
				
			||||||
                fmls.push_back(r.get_tail(i));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            fmls.append(bindings);
 | 
					 | 
				
			||||||
            fmls.append(conjs);
 | 
					 | 
				
			||||||
            fml = m.mk_implies(m.mk_and(fmls.size(), fmls.c_ptr()), r.get_head());
 | 
					 | 
				
			||||||
            TRACE("dl", tout << "new rule\n" << mk_pp(fml, m) << "\n";);
 | 
					 | 
				
			||||||
            rule_ref_vector rules(rm);
 | 
					 | 
				
			||||||
            proof_ref pr(m);
 | 
					 | 
				
			||||||
            if (m_ctx.generate_proof_trace()) {
 | 
					 | 
				
			||||||
                scoped_proof _scp(m);
 | 
					 | 
				
			||||||
                expr_ref fml1(m);
 | 
					 | 
				
			||||||
                r.to_formula(fml1);
 | 
					 | 
				
			||||||
                pr = m.mk_rewrite(fml1, fml);
 | 
					 | 
				
			||||||
                pr = m.mk_modus_ponens(r.get_proof(), pr);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            rm.mk_rule(fml, pr, rules, r.name());
 | 
					 | 
				
			||||||
            for (unsigned i = 0; i < rules.size(); ++i) {
 | 
					 | 
				
			||||||
                new_rules.add_rule(rules[i].get());
 | 
					 | 
				
			||||||
                m_quantifiers.insert(rules[i].get(), alloc(quantifier_ref_vector, qs));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            obj_map<quantifier, expr_ref_vector*>::iterator it = insts.begin(), end = insts.end();
 | 
					 | 
				
			||||||
            for (; it != end; ++it) {
 | 
					 | 
				
			||||||
                dealloc(it->m_value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void mk_extract_quantifiers::rule2formula(
 | 
					 | 
				
			||||||
        rule& r,
 | 
					 | 
				
			||||||
        obj_map<quantifier, expr_ref_vector*> const& insts,
 | 
					 | 
				
			||||||
        expr_ref& fml,
 | 
					 | 
				
			||||||
        app_ref_vector& sub)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        expr_ref body(m);
 | 
					 | 
				
			||||||
        expr_ref_vector fmls(m);
 | 
					 | 
				
			||||||
        ptr_vector<sort> sorts;
 | 
					 | 
				
			||||||
        var_subst vs(m, false);
 | 
					 | 
				
			||||||
        obj_map<quantifier, expr_ref_vector*>::iterator it = insts.begin(), end = insts.end();
 | 
					 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					 | 
				
			||||||
            quantifier* q = it->m_key;
 | 
					 | 
				
			||||||
            expr_ref_vector& eqs = *it->m_value;
 | 
					 | 
				
			||||||
            expr_ref_vector disj(m);
 | 
					 | 
				
			||||||
            disj.append(eqs);
 | 
					 | 
				
			||||||
            disj.push_back(m.mk_not(q->get_expr()));
 | 
					 | 
				
			||||||
            body = m.mk_or(disj.size(), disj.c_ptr());
 | 
					 | 
				
			||||||
            fml = m.update_quantifier(q, body);
 | 
					 | 
				
			||||||
            fmls.push_back(fml); 
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fml = m.mk_or(fmls.size(), fmls.c_ptr());
 | 
					 | 
				
			||||||
        fmls.reset();
 | 
					 | 
				
			||||||
        fmls.push_back(fml);
 | 
					 | 
				
			||||||
        for (unsigned i = 0; i < r.get_tail_size(); ++i) {
 | 
					 | 
				
			||||||
            SASSERT(!r.is_neg_tail(i));
 | 
					 | 
				
			||||||
            fmls.push_back(r.get_tail(i));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fmls.push_back(m.mk_not(r.get_head()));
 | 
					 | 
				
			||||||
        fml = m.mk_and(fmls.size(), fmls.c_ptr());
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        get_free_vars(fml, sorts);
 | 
					 | 
				
			||||||
        for (unsigned i = 0; i < sorts.size(); ++i) {
 | 
					 | 
				
			||||||
            if (!sorts[i]) {
 | 
					 | 
				
			||||||
                sorts[i] = m.mk_bool_sort();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            sub.push_back(m.mk_const(symbol(i), sorts[i]));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        vs(fml, sub.size(), (expr*const*)sub.c_ptr(), fml);        
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    bool mk_extract_quantifiers::find_instantiations_proof_based(
 | 
					 | 
				
			||||||
        expr*                        fml,
 | 
					 | 
				
			||||||
        app_ref_vector const&        var_inst,
 | 
					 | 
				
			||||||
        obj_map<quantifier, expr_ref_vector*>& insts,
 | 
					 | 
				
			||||||
        expr_ref_vector&             bindings)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        datalog::scoped_proof _scp(m);
 | 
					 | 
				
			||||||
        smt_params fparams;
 | 
					 | 
				
			||||||
        fparams.m_mbqi = true; // false
 | 
					 | 
				
			||||||
        fparams.m_soft_timeout = 1000;
 | 
					 | 
				
			||||||
        smt::kernel solver(m, fparams);
 | 
					 | 
				
			||||||
        solver.assert_expr(fml);
 | 
					 | 
				
			||||||
        IF_VERBOSE(1, verbose_stream() << "check\n";);
 | 
					 | 
				
			||||||
        lbool result = solver.check();
 | 
					 | 
				
			||||||
        IF_VERBOSE(1, verbose_stream() << "checked\n";);
 | 
					 | 
				
			||||||
        TRACE("dl", tout << result << "\n";);
 | 
					 | 
				
			||||||
        if (result != l_false) {
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }  
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        map<symbol, quantifier*, symbol_hash_proc, symbol_eq_proc> qid_map;
 | 
					 | 
				
			||||||
        quantifier* q;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        obj_map<quantifier, expr_ref_vector*>::iterator it = insts.begin(), end = insts.end();
 | 
					 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					 | 
				
			||||||
            q = it->m_key;
 | 
					 | 
				
			||||||
            qid_map.insert(q->get_qid(), q);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        proof* p = solver.get_proof();
 | 
					 | 
				
			||||||
        TRACE("dl", tout << mk_pp(p, m) << "\n";);
 | 
					 | 
				
			||||||
        collect_insts collector(m);
 | 
					 | 
				
			||||||
        for_each_expr(collector, p);
 | 
					 | 
				
			||||||
        ptr_vector<quantifier> const& quants = collector.quantifiers();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (unsigned i = 0; i < collector.size(); ++i) {
 | 
					 | 
				
			||||||
            symbol qid = quants[i]->get_qid();
 | 
					 | 
				
			||||||
            if (!qid_map.find(qid, q)) {
 | 
					 | 
				
			||||||
                TRACE("dl", tout << "Could not find quantifier " << mk_pp(quants[i], m) << "\n";);
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            expr_ref_vector const& binding = collector.bindings()[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            TRACE("dl", tout << "Instantiating:\n" << mk_pp(quants[i], m) << "\n";
 | 
					 | 
				
			||||||
                  for (unsigned j = 0; j < binding.size(); ++j) {
 | 
					 | 
				
			||||||
                      tout << mk_pp(binding[j], m) << " ";
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
                  tout << "\n";);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            expr_ref_vector instantiation(m);
 | 
					 | 
				
			||||||
            for (unsigned j = 0; j < binding.size(); ++j) {
 | 
					 | 
				
			||||||
                instantiation.push_back(binding[j]);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            add_binding(var_inst, bindings, q, instantiation, insts);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return collector.size() > 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void mk_extract_quantifiers::add_binding(
 | 
					 | 
				
			||||||
        app_ref_vector const&        var_inst,
 | 
					 | 
				
			||||||
        expr_ref_vector&             bindings,
 | 
					 | 
				
			||||||
        quantifier*                  q, 
 | 
					 | 
				
			||||||
        expr_ref_vector const&       instantiation,
 | 
					 | 
				
			||||||
        obj_map<quantifier, expr_ref_vector*>& insts)
 | 
					 | 
				
			||||||
    {      
 | 
					 | 
				
			||||||
        if (instantiation.size() == q->get_num_decls()) {
 | 
					 | 
				
			||||||
            // Full binding. 
 | 
					 | 
				
			||||||
            apply_binding(var_inst, bindings, q, instantiation, insts);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
     
 | 
					 | 
				
			||||||
    void mk_extract_quantifiers::apply_binding(
 | 
					 | 
				
			||||||
        app_ref_vector const&        var_inst,
 | 
					 | 
				
			||||||
        expr_ref_vector&             bindings,
 | 
					 | 
				
			||||||
        quantifier*                  q, 
 | 
					 | 
				
			||||||
        expr_ref_vector const&       instantiation,
 | 
					 | 
				
			||||||
        obj_map<quantifier, expr_ref_vector*>& insts)
 | 
					 | 
				
			||||||
    {          
 | 
					 | 
				
			||||||
        datalog::scoped_no_proof _scp(m);
 | 
					 | 
				
			||||||
        expr_ref e(m);
 | 
					 | 
				
			||||||
        expr_ref_vector eqs(m);
 | 
					 | 
				
			||||||
        var_subst vs(m, false);
 | 
					 | 
				
			||||||
        inv_var_shifter invsh(m);
 | 
					 | 
				
			||||||
        vs(q->get_expr(), instantiation.size(), instantiation.c_ptr(), e);
 | 
					 | 
				
			||||||
        invsh(e, q->get_num_decls(), e);
 | 
					 | 
				
			||||||
        expr_ref_vector inst(m);
 | 
					 | 
				
			||||||
        inst.append(var_inst.size(), (expr*const*)var_inst.c_ptr());
 | 
					 | 
				
			||||||
        inst.reverse();
 | 
					 | 
				
			||||||
        expr_abstract(m, 0, inst.size(), inst.c_ptr(), e, e);
 | 
					 | 
				
			||||||
        bindings.push_back(e);        
 | 
					 | 
				
			||||||
        for (unsigned i = 0; i < instantiation.size(); ++i) {
 | 
					 | 
				
			||||||
            e = instantiation[i];
 | 
					 | 
				
			||||||
            e = m.mk_eq(m.mk_var(i, q->get_decl_sort(i)), e);
 | 
					 | 
				
			||||||
            eqs.push_back(e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        e = m.mk_and(eqs.size(), eqs.c_ptr());
 | 
					 | 
				
			||||||
        insts.find(q)->push_back(e);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        TRACE("dl", tout << mk_pp(q, m) << "\n";
 | 
					 | 
				
			||||||
              tout << "instantiation: ";
 | 
					 | 
				
			||||||
              for (unsigned i = 0; i < instantiation.size(); ++i) {
 | 
					 | 
				
			||||||
                  tout << mk_pp(instantiation[i], m) << " ";
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
              tout << "\n";
 | 
					 | 
				
			||||||
              tout << "inst: ";
 | 
					 | 
				
			||||||
              for (unsigned i = 0; i < var_inst.size(); ++i) {
 | 
					 | 
				
			||||||
                  tout << mk_pp(var_inst[i], m) << " ";
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
              tout << "\n";
 | 
					 | 
				
			||||||
              tout << mk_pp(bindings.back(), m) << "\n";
 | 
					 | 
				
			||||||
              tout << "eqs: " << mk_pp(e, m) << "\n";
 | 
					 | 
				
			||||||
              );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void mk_extract_quantifiers::reset() {
 | 
					 | 
				
			||||||
        obj_map<rule const, quantifier_ref_vector*>::iterator it = m_quantifiers.begin(),
 | 
					 | 
				
			||||||
            end = m_quantifiers.end();
 | 
					 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					 | 
				
			||||||
            dealloc(it->m_value);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        m_has_quantifiers = false;
 | 
					 | 
				
			||||||
        m_quantifiers.reset();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    rule_set * mk_extract_quantifiers::operator()(rule_set const & source) {
 | 
					 | 
				
			||||||
        reset();
 | 
					 | 
				
			||||||
        rule_set::iterator it = source.begin(), end = source.end();
 | 
					 | 
				
			||||||
        for (; !m_has_quantifiers && it != end; ++it) {
 | 
					 | 
				
			||||||
            m_has_quantifiers = (*it)->has_quantifiers();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (!m_has_quantifiers) {
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        rule_set* rules = alloc(rule_set, m_ctx);
 | 
					 | 
				
			||||||
        it = source.begin();
 | 
					 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					 | 
				
			||||||
            extract(**it, *rules);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return rules;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,99 +0,0 @@
 | 
				
			||||||
/*++
 | 
					 | 
				
			||||||
Copyright (c) 2012 Microsoft Corporation
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Module Name:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    dl_mk_extract_quantifiers.h
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Abstract:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Replace universal quantifiers over interpreted predicates in the body
 | 
					 | 
				
			||||||
    by instantiations mined using bounded model checking search.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Author:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Nikolaj Bjorner (nbjorner) 2012-11-21
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Revision History:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
--*/
 | 
					 | 
				
			||||||
#ifndef _DL_MK_EXTRACT_QUANTIFIERS_H_
 | 
					 | 
				
			||||||
#define _DL_MK_EXTRACT_QUANTIFIERS_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include"dl_context.h"
 | 
					 | 
				
			||||||
#include"dl_rule_set.h"
 | 
					 | 
				
			||||||
#include"dl_rule_transformer.h"
 | 
					 | 
				
			||||||
#include"obj_pair_hashtable.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace datalog {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
       \brief Extract universal quantifiers from rules.
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    class mk_extract_quantifiers : public rule_transformer::plugin {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        class collect_insts;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        context&                                    m_ctx;
 | 
					 | 
				
			||||||
        ast_manager&                                m;
 | 
					 | 
				
			||||||
        rule_manager&                               rm;
 | 
					 | 
				
			||||||
        func_decl_ref                               m_query_pred;        
 | 
					 | 
				
			||||||
        bool                                        m_has_quantifiers;
 | 
					 | 
				
			||||||
        obj_map<rule const, quantifier_ref_vector*> m_quantifiers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void reset();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void extract(rule& r, rule_set& new_rules);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void rule2formula(
 | 
					 | 
				
			||||||
            rule& r,
 | 
					 | 
				
			||||||
            obj_map<quantifier, expr_ref_vector*> const& insts,
 | 
					 | 
				
			||||||
            expr_ref& fml,
 | 
					 | 
				
			||||||
            app_ref_vector& sub);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void add_binding(
 | 
					 | 
				
			||||||
            app_ref_vector const&        var_inst,
 | 
					 | 
				
			||||||
            expr_ref_vector&             bindings,
 | 
					 | 
				
			||||||
            quantifier*                  q, 
 | 
					 | 
				
			||||||
            expr_ref_vector const&       instantiation,
 | 
					 | 
				
			||||||
            obj_map<quantifier, expr_ref_vector*>& insts);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void apply_binding(
 | 
					 | 
				
			||||||
            app_ref_vector const&        var_inst,
 | 
					 | 
				
			||||||
            expr_ref_vector&             bindings,
 | 
					 | 
				
			||||||
            quantifier*                  q, 
 | 
					 | 
				
			||||||
            expr_ref_vector const&       instantiation,
 | 
					 | 
				
			||||||
            obj_map<quantifier, expr_ref_vector*>& insts);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public:
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
           \brief Create rule transformer that extracts universal quantifiers (over recursive predicates).
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        mk_extract_quantifiers(context & ctx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        virtual ~mk_extract_quantifiers();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void set_query(func_decl* q);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        rule_set * operator()(rule_set const & source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bool has_quantifiers() { return m_has_quantifiers; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        obj_map<rule const, quantifier_ref_vector*>& quantifiers() { return m_quantifiers; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void ensure_predicate(expr* e, unsigned& max_var, app_ref_vector& tail);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bool find_instantiations_proof_based(
 | 
					 | 
				
			||||||
            expr*                        fml,
 | 
					 | 
				
			||||||
            app_ref_vector const&        var_inst,
 | 
					 | 
				
			||||||
            obj_map<quantifier, expr_ref_vector*>& insts,
 | 
					 | 
				
			||||||
            expr_ref_vector&             bindings);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* _DL_MK_EXTRACT_QUANTIFIERS_H_ */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -27,10 +27,12 @@ namespace datalog {
 | 
				
			||||||
    mk_filter_rules::mk_filter_rules(context & ctx):
 | 
					    mk_filter_rules::mk_filter_rules(context & ctx):
 | 
				
			||||||
            plugin(2000),
 | 
					            plugin(2000),
 | 
				
			||||||
            m_context(ctx),
 | 
					            m_context(ctx),
 | 
				
			||||||
            m_manager(ctx.get_manager()),
 | 
					            m(ctx.get_manager()),
 | 
				
			||||||
 | 
					            rm(ctx.get_rule_manager()),
 | 
				
			||||||
            m_result(0), 
 | 
					            m_result(0), 
 | 
				
			||||||
            m_pinned(m_manager) {
 | 
					            m_pinned(m) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk_filter_rules::~mk_filter_rules() {
 | 
					    mk_filter_rules::~mk_filter_rules() {
 | 
				
			||||||
        ptr_vector<filter_key> to_dealloc;
 | 
					        ptr_vector<filter_key> to_dealloc;
 | 
				
			||||||
        filter_cache::iterator it = m_tail2filter.begin();
 | 
					        filter_cache::iterator it = m_tail2filter.begin();
 | 
				
			||||||
| 
						 | 
					@ -50,15 +52,15 @@ namespace datalog {
 | 
				
			||||||
       \brief Return true if \c pred is a cadidate for a "filter" rule.
 | 
					       \brief Return true if \c pred is a cadidate for a "filter" rule.
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    bool mk_filter_rules::is_candidate(app * pred) {
 | 
					    bool mk_filter_rules::is_candidate(app * pred) {
 | 
				
			||||||
        if (!m_context.get_rule_manager().is_predicate(pred)) {
 | 
					        if (!m_context.is_predicate(pred)) {
 | 
				
			||||||
            TRACE("mk_filter_rules", tout << mk_pp(pred, m_manager) << "\nis not a candidate because it is interpreted.\n";);
 | 
					            TRACE("mk_filter_rules", tout << mk_pp(pred, m) << "\nis not a candidate because it is interpreted.\n";);
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var_idx_set used_vars;
 | 
					        var_idx_set used_vars;
 | 
				
			||||||
        unsigned n  = pred->get_num_args();
 | 
					        unsigned n  = pred->get_num_args();
 | 
				
			||||||
        for (unsigned i = 0; i < n; i++) {
 | 
					        for (unsigned i = 0; i < n; i++) {
 | 
				
			||||||
            expr * arg = pred->get_arg(i);
 | 
					            expr * arg = pred->get_arg(i);
 | 
				
			||||||
            if (m_manager.is_value(arg))
 | 
					            if (m.is_value(arg))
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            SASSERT(is_var(arg));
 | 
					            SASSERT(is_var(arg));
 | 
				
			||||||
            unsigned vidx = to_var(arg)->get_idx();
 | 
					            unsigned vidx = to_var(arg)->get_idx();
 | 
				
			||||||
| 
						 | 
					@ -73,10 +75,10 @@ namespace datalog {
 | 
				
			||||||
       \brief Create a "filter" (if it doesn't exist already) for the given predicate.
 | 
					       \brief Create a "filter" (if it doesn't exist already) for the given predicate.
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    func_decl *  mk_filter_rules::mk_filter_decl(app * pred, var_idx_set const & non_local_vars) {
 | 
					    func_decl *  mk_filter_rules::mk_filter_decl(app * pred, var_idx_set const & non_local_vars) {
 | 
				
			||||||
        sort_ref_buffer filter_domain(m_manager);
 | 
					        sort_ref_buffer filter_domain(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        filter_key * key = alloc(filter_key, m_manager);
 | 
					        filter_key * key = alloc(filter_key, m);
 | 
				
			||||||
        mk_new_rule_tail(m_manager, pred, non_local_vars, filter_domain, key->filter_args, key->new_pred);
 | 
					        mk_new_rule_tail(m, pred, non_local_vars, filter_domain, key->filter_args, key->new_pred);
 | 
				
			||||||
        func_decl * filter_decl = 0;
 | 
					        func_decl * filter_decl = 0;
 | 
				
			||||||
        if (!m_tail2filter.find(key, filter_decl)) {
 | 
					        if (!m_tail2filter.find(key, filter_decl)) {
 | 
				
			||||||
            filter_decl = m_context.mk_fresh_head_predicate(pred->get_decl()->get_name(), symbol("filter"), 
 | 
					            filter_decl = m_context.mk_fresh_head_predicate(pred->get_decl()->get_name(), symbol("filter"), 
 | 
				
			||||||
| 
						 | 
					@ -84,8 +86,8 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            m_pinned.push_back(filter_decl);
 | 
					            m_pinned.push_back(filter_decl);
 | 
				
			||||||
            m_tail2filter.insert(key, filter_decl);
 | 
					            m_tail2filter.insert(key, filter_decl);
 | 
				
			||||||
            app_ref filter_head(m_manager);
 | 
					            app_ref filter_head(m);
 | 
				
			||||||
            filter_head = m_manager.mk_app(filter_decl, key->filter_args.size(), key->filter_args.c_ptr());
 | 
					            filter_head = m.mk_app(filter_decl, key->filter_args.size(), key->filter_args.c_ptr());
 | 
				
			||||||
            app * filter_tail = key->new_pred;
 | 
					            app * filter_tail = key->new_pred;
 | 
				
			||||||
            rule * filter_rule = m_context.get_rule_manager().mk(filter_head, 1, &filter_tail, (const bool *)0);
 | 
					            rule * filter_rule = m_context.get_rule_manager().mk(filter_head, 1, &filter_tail, (const bool *)0);
 | 
				
			||||||
            filter_rule->set_accounting_parent_object(m_context, m_current);
 | 
					            filter_rule->set_accounting_parent_object(m_context, m_current);
 | 
				
			||||||
| 
						 | 
					@ -103,16 +105,15 @@ namespace datalog {
 | 
				
			||||||
    void mk_filter_rules::process(rule * r) {
 | 
					    void mk_filter_rules::process(rule * r) {
 | 
				
			||||||
        m_current = r;
 | 
					        m_current = r;
 | 
				
			||||||
        app * new_head = r->get_head();
 | 
					        app * new_head = r->get_head();
 | 
				
			||||||
        app_ref_vector new_tail(m_manager);
 | 
					        app_ref_vector new_tail(m);
 | 
				
			||||||
        svector<bool>  new_is_negated;
 | 
					        svector<bool>  new_is_negated;
 | 
				
			||||||
        unsigned sz = r->get_tail_size();
 | 
					        unsigned sz = r->get_tail_size();
 | 
				
			||||||
        bool rule_modified = false;
 | 
					        bool rule_modified = false;
 | 
				
			||||||
        for (unsigned i = 0; i < sz; i++) {
 | 
					        for (unsigned i = 0; i < sz; i++) {
 | 
				
			||||||
            app * tail = r->get_tail(i);
 | 
					            app * tail = r->get_tail(i);
 | 
				
			||||||
            if (is_candidate(tail)) {
 | 
					            if (is_candidate(tail)) {
 | 
				
			||||||
                TRACE("mk_filter_rules", tout << "is_candidate: " << mk_pp(tail, m_manager) << "\n";);
 | 
					                TRACE("mk_filter_rules", tout << "is_candidate: " << mk_pp(tail, m) << "\n";);
 | 
				
			||||||
                var_idx_set non_local_vars;
 | 
					                var_idx_set non_local_vars = rm.collect_rule_vars_ex(r, tail);
 | 
				
			||||||
                collect_non_local_vars(m_manager, r, tail, non_local_vars);
 | 
					 | 
				
			||||||
                func_decl * filter_decl = mk_filter_decl(tail, non_local_vars);
 | 
					                func_decl * filter_decl = mk_filter_decl(tail, non_local_vars);
 | 
				
			||||||
                ptr_buffer<expr> new_args;
 | 
					                ptr_buffer<expr> new_args;
 | 
				
			||||||
                var_idx_set used_vars;
 | 
					                var_idx_set used_vars;
 | 
				
			||||||
| 
						 | 
					@ -128,7 +129,7 @@ namespace datalog {
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                SASSERT(new_args.size() == filter_decl->get_arity());
 | 
					                SASSERT(new_args.size() == filter_decl->get_arity());
 | 
				
			||||||
                new_tail.push_back(m_manager.mk_app(filter_decl, new_args.size(), new_args.c_ptr()));
 | 
					                new_tail.push_back(m.mk_app(filter_decl, new_args.size(), new_args.c_ptr()));
 | 
				
			||||||
                rule_modified = true;
 | 
					                rule_modified = true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
| 
						 | 
					@ -151,19 +152,18 @@ namespace datalog {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rule_set * mk_filter_rules::operator()(rule_set const & source) {
 | 
					    rule_set * mk_filter_rules::operator()(rule_set const & source) {
 | 
				
			||||||
        // TODO mc, pc
 | 
					 | 
				
			||||||
        m_tail2filter.reset();
 | 
					        m_tail2filter.reset();
 | 
				
			||||||
        m_result           = alloc(rule_set, m_context);
 | 
					        m_result           = alloc(rule_set, m_context);
 | 
				
			||||||
        m_modified         = false;
 | 
					        m_modified         = false;
 | 
				
			||||||
        unsigned num_rules = source.get_num_rules();
 | 
					        unsigned num_rules = source.get_num_rules();
 | 
				
			||||||
        for (unsigned i = 0; i < num_rules; i++) {
 | 
					        for (unsigned i = 0; i < num_rules; i++) {
 | 
				
			||||||
            rule * r = source.get_rule(i);
 | 
					            process(source.get_rule(i));
 | 
				
			||||||
            process(r);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(!m_modified) {
 | 
					        if(!m_modified) {
 | 
				
			||||||
            dealloc(m_result);
 | 
					            dealloc(m_result);
 | 
				
			||||||
            return static_cast<rule_set *>(0);
 | 
					            return static_cast<rule_set *>(0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        m_result->inherit_predicates(source);
 | 
				
			||||||
        return m_result;
 | 
					        return m_result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,17 +45,22 @@ namespace datalog {
 | 
				
			||||||
            filter_key(ast_manager & m) : new_pred(m), filter_args(m) {}
 | 
					            filter_key(ast_manager & m) : new_pred(m), filter_args(m) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            unsigned hash() const {
 | 
					            unsigned hash() const {
 | 
				
			||||||
                return new_pred->hash() ^ int_vector_hash(filter_args);
 | 
					                unsigned r = new_pred->hash();
 | 
				
			||||||
 | 
					                for (unsigned i = 0; i < filter_args.size(); ++i) {
 | 
				
			||||||
 | 
					                    r ^= filter_args[i]->hash();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return r;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            bool operator==(const filter_key & o) const {
 | 
					            bool operator==(const filter_key & o) const {
 | 
				
			||||||
                return o.new_pred==new_pred && vectors_equal(o.filter_args, filter_args);
 | 
					                return o.new_pred==new_pred && vectors_equal(o.filter_args, filter_args);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        typedef map<filter_key*, func_decl*, obj_ptr_hash<filter_key>, deref_eq<filter_key> > filter_cache;
 | 
					        typedef obj_map<filter_key, func_decl*> filter_cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context &                                 m_context;
 | 
					        context &                                 m_context;
 | 
				
			||||||
        ast_manager &                             m_manager;
 | 
					        ast_manager &                             m;
 | 
				
			||||||
 | 
					        rule_manager &                            rm;
 | 
				
			||||||
        filter_cache                              m_tail2filter;
 | 
					        filter_cache                              m_tail2filter;
 | 
				
			||||||
        rule_set *                                m_result;
 | 
					        rule_set *                                m_result;
 | 
				
			||||||
        rule *                                    m_current;
 | 
					        rule *                                    m_current;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,24 +67,23 @@ namespace datalog {
 | 
				
			||||||
    void mk_interp_tail_simplifier::rule_substitution::get_result(rule_ref & res) {
 | 
					    void mk_interp_tail_simplifier::rule_substitution::get_result(rule_ref & res) {
 | 
				
			||||||
        SASSERT(m_rule);
 | 
					        SASSERT(m_rule);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app_ref new_head(m);
 | 
					        apply(m_rule->get_head(), m_head);
 | 
				
			||||||
        apply(m_rule->get_head(), new_head);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app_ref_vector tail(m);
 | 
					        m_tail.reset();
 | 
				
			||||||
        svector<bool> tail_neg;
 | 
					        m_neg.reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned tail_len = m_rule->get_tail_size();
 | 
					        unsigned tail_len = m_rule->get_tail_size();
 | 
				
			||||||
        for (unsigned i=0; i<tail_len; i++) {
 | 
					        for (unsigned i=0; i<tail_len; i++) {
 | 
				
			||||||
            app_ref new_tail_el(m);
 | 
					            app_ref new_tail_el(m);
 | 
				
			||||||
            apply(m_rule->get_tail(i), new_tail_el);
 | 
					            apply(m_rule->get_tail(i), new_tail_el);
 | 
				
			||||||
            tail.push_back(new_tail_el);
 | 
					            m_tail.push_back(new_tail_el);
 | 
				
			||||||
            tail_neg.push_back(m_rule->is_neg_tail(i));
 | 
					            m_neg.push_back(m_rule->is_neg_tail(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        mk_rule_inliner::remove_duplicate_tails(tail, tail_neg);
 | 
					        mk_rule_inliner::remove_duplicate_tails(m_tail, m_neg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SASSERT(tail.size() == tail_neg.size());
 | 
					        SASSERT(m_tail.size() == m_neg.size());
 | 
				
			||||||
        res = m_context.get_rule_manager().mk(new_head, tail.size(), tail.c_ptr(), tail_neg.c_ptr());
 | 
					        res = m_context.get_rule_manager().mk(m_head, m_tail.size(), m_tail.c_ptr(), m_neg.c_ptr());
 | 
				
			||||||
        res->set_accounting_parent_object(m_context, m_rule);
 | 
					        res->set_accounting_parent_object(m_context, m_rule);
 | 
				
			||||||
        res->norm_vars(res.get_manager());
 | 
					        res->norm_vars(res.get_manager());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -362,14 +361,37 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class mk_interp_tail_simplifier::normalizer_rw : public rewriter_tpl<normalizer_cfg> {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        normalizer_rw(ast_manager& m, normalizer_cfg& cfg): rewriter_tpl<normalizer_cfg>(m, false, cfg) {}
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mk_interp_tail_simplifier::mk_interp_tail_simplifier(context & ctx, unsigned priority)
 | 
				
			||||||
 | 
					            : plugin(priority),
 | 
				
			||||||
 | 
					              m(ctx.get_manager()),
 | 
				
			||||||
 | 
					              m_context(ctx),
 | 
				
			||||||
 | 
					              m_simp(ctx.get_rewriter()),
 | 
				
			||||||
 | 
					              a(m),
 | 
				
			||||||
 | 
					              m_rule_subst(ctx),
 | 
				
			||||||
 | 
					              m_tail(m), 
 | 
				
			||||||
 | 
					              m_itail_members(m),
 | 
				
			||||||
 | 
					              m_conj(m) {
 | 
				
			||||||
 | 
					        m_cfg = alloc(normalizer_cfg, m);
 | 
				
			||||||
 | 
					        m_rw = alloc(normalizer_rw, m, *m_cfg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mk_interp_tail_simplifier::~mk_interp_tail_simplifier() {
 | 
				
			||||||
 | 
					        dealloc(m_rw);
 | 
				
			||||||
 | 
					        dealloc(m_cfg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_interp_tail_simplifier::simplify_expr(app * a, expr_ref& res)
 | 
					    void mk_interp_tail_simplifier::simplify_expr(app * a, expr_ref& res)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        expr_ref simp1_res(m);
 | 
					        expr_ref simp1_res(m);
 | 
				
			||||||
        m_simp(a, simp1_res);
 | 
					        m_simp(a, simp1_res);
 | 
				
			||||||
        normalizer_cfg r_cfg(m);
 | 
					        (*m_rw)(simp1_res.get(), res);
 | 
				
			||||||
        rewriter_tpl<normalizer_cfg> rwr(m, false, r_cfg);
 | 
					 | 
				
			||||||
        expr_ref dl_form_e(m);
 | 
					 | 
				
			||||||
        rwr(simp1_res.get(), res);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*if (simp1_res.get()!=res.get()) {
 | 
					        /*if (simp1_res.get()!=res.get()) {
 | 
				
			||||||
            std::cout<<"pre norm:\n"<<mk_pp(simp1_res.get(),m)<<"post norm:\n"<<mk_pp(res.get(),m)<<"\n";
 | 
					            std::cout<<"pre norm:\n"<<mk_pp(simp1_res.get(),m)<<"post norm:\n"<<mk_pp(res.get(),m)<<"\n";
 | 
				
			||||||
| 
						 | 
					@ -385,15 +407,15 @@ namespace datalog {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ptr_vector<expr> todo;
 | 
					        m_todo.reset();
 | 
				
			||||||
 | 
					        m_leqs.reset();
 | 
				
			||||||
        for (unsigned i = u_len; i < len; i++) {
 | 
					        for (unsigned i = u_len; i < len; i++) {
 | 
				
			||||||
            todo.push_back(r->get_tail(i));
 | 
					            m_todo.push_back(r->get_tail(i));
 | 
				
			||||||
            SASSERT(!r->is_neg_tail(i));
 | 
					            SASSERT(!r->is_neg_tail(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        m_rule_subst.reset(r);
 | 
					        m_rule_subst.reset(r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        obj_hashtable<expr> leqs;
 | 
					 | 
				
			||||||
        expr_ref_vector trail(m);
 | 
					        expr_ref_vector trail(m);
 | 
				
			||||||
        expr_ref tmp1(m), tmp2(m);
 | 
					        expr_ref tmp1(m), tmp2(m);
 | 
				
			||||||
        bool found_something = false;
 | 
					        bool found_something = false;
 | 
				
			||||||
| 
						 | 
					@ -401,10 +423,10 @@ namespace datalog {
 | 
				
			||||||
#define TRY_UNIFY(_x,_y) if (m_rule_subst.unify(_x,_y)) { found_something = true; }
 | 
					#define TRY_UNIFY(_x,_y) if (m_rule_subst.unify(_x,_y)) { found_something = true; }
 | 
				
			||||||
#define IS_FLEX(_x) (is_var(_x) || m.is_value(_x))
 | 
					#define IS_FLEX(_x) (is_var(_x) || m.is_value(_x))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while (!todo.empty()) {
 | 
					        while (!m_todo.empty()) {
 | 
				
			||||||
            expr * arg1, *arg2;
 | 
					            expr * arg1, *arg2;
 | 
				
			||||||
            expr * t0 = todo.back();
 | 
					            expr * t0 = m_todo.back();
 | 
				
			||||||
            todo.pop_back();
 | 
					            m_todo.pop_back();
 | 
				
			||||||
            expr* t = t0;
 | 
					            expr* t = t0;
 | 
				
			||||||
            bool neg = m.is_not(t, t);
 | 
					            bool neg = m.is_not(t, t);
 | 
				
			||||||
            if (is_var(t)) {
 | 
					            if (is_var(t)) {
 | 
				
			||||||
| 
						 | 
					@ -412,7 +434,7 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (!neg && m.is_and(t)) {
 | 
					            else if (!neg && m.is_and(t)) {
 | 
				
			||||||
                app* a = to_app(t);
 | 
					                app* a = to_app(t);
 | 
				
			||||||
                todo.append(a->get_num_args(), a->get_args());
 | 
					                m_todo.append(a->get_num_args(), a->get_args());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (!neg && m.is_eq(t, arg1, arg2) && IS_FLEX(arg1) && IS_FLEX(arg2)) {
 | 
					            else if (!neg && m.is_eq(t, arg1, arg2) && IS_FLEX(arg1) && IS_FLEX(arg2)) {
 | 
				
			||||||
                TRY_UNIFY(arg1, arg2);
 | 
					                TRY_UNIFY(arg1, arg2);
 | 
				
			||||||
| 
						 | 
					@ -440,12 +462,12 @@ namespace datalog {
 | 
				
			||||||
            else if (!neg && (a.is_le(t, arg1, arg2) || a.is_ge(t, arg2, arg1))) {
 | 
					            else if (!neg && (a.is_le(t, arg1, arg2) || a.is_ge(t, arg2, arg1))) {
 | 
				
			||||||
                tmp1 = a.mk_sub(arg1, arg2);
 | 
					                tmp1 = a.mk_sub(arg1, arg2);
 | 
				
			||||||
                tmp2 = a.mk_sub(arg2, arg1);
 | 
					                tmp2 = a.mk_sub(arg2, arg1);
 | 
				
			||||||
                if (false && leqs.contains(tmp2) && IS_FLEX(arg1) && IS_FLEX(arg2)) {
 | 
					                if (false && m_leqs.contains(tmp2) && IS_FLEX(arg1) && IS_FLEX(arg2)) {
 | 
				
			||||||
                    TRY_UNIFY(arg1, arg2);
 | 
					                    TRY_UNIFY(arg1, arg2);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    trail.push_back(tmp1);
 | 
					                    trail.push_back(tmp1);
 | 
				
			||||||
                    leqs.insert(tmp1);
 | 
					                    m_leqs.insert(tmp1);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -485,12 +507,12 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        app_ref head(r->get_head(), m);
 | 
					        app_ref head(r->get_head(), m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app_ref_vector tail(m);
 | 
					        m_tail.reset();
 | 
				
			||||||
        svector<bool> tail_neg;
 | 
					        m_tail_neg.reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (unsigned i=0; i<u_len; i++) {
 | 
					        for (unsigned i=0; i<u_len; i++) {
 | 
				
			||||||
            tail.push_back(r->get_tail(i));
 | 
					            m_tail.push_back(r->get_tail(i));
 | 
				
			||||||
            tail_neg.push_back(r->is_neg_tail(i));
 | 
					            m_tail_neg.push_back(r->is_neg_tail(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool modified = false;
 | 
					        bool modified = false;
 | 
				
			||||||
| 
						 | 
					@ -502,12 +524,12 @@ namespace datalog {
 | 
				
			||||||
            SASSERT(!r->is_neg_tail(u_len));
 | 
					            SASSERT(!r->is_neg_tail(u_len));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            expr_ref_vector itail_members(m);
 | 
					            m_itail_members.reset();
 | 
				
			||||||
            for (unsigned i=u_len; i<len; i++) {
 | 
					            for (unsigned i=u_len; i<len; i++) {
 | 
				
			||||||
                itail_members.push_back(r->get_tail(i));
 | 
					                m_itail_members.push_back(r->get_tail(i));
 | 
				
			||||||
                SASSERT(!r->is_neg_tail(i));
 | 
					                SASSERT(!r->is_neg_tail(i));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            itail = m.mk_and(itail_members.size(), itail_members.c_ptr());
 | 
					            itail = m.mk_and(m_itail_members.size(), m_itail_members.c_ptr());
 | 
				
			||||||
            modified = true;
 | 
					            modified = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -523,21 +545,21 @@ namespace datalog {
 | 
				
			||||||
        SASSERT(m.is_bool(simp_res));
 | 
					        SASSERT(m.is_bool(simp_res));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (modified) {
 | 
					        if (modified) {
 | 
				
			||||||
            expr_ref_vector conjs(m);
 | 
					            m_conj.reset();
 | 
				
			||||||
            flatten_and(simp_res, conjs);
 | 
					            flatten_and(simp_res, m_conj);
 | 
				
			||||||
            for (unsigned i = 0; i < conjs.size(); ++i) {
 | 
					            for (unsigned i = 0; i < m_conj.size(); ++i) {
 | 
				
			||||||
                expr* e = conjs[i].get();
 | 
					                expr* e = m_conj[i].get();
 | 
				
			||||||
                if (is_app(e)) {
 | 
					                if (is_app(e)) {
 | 
				
			||||||
                    tail.push_back(to_app(e));
 | 
					                    m_tail.push_back(to_app(e));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    tail.push_back(m.mk_eq(e, m.mk_true()));
 | 
					                    m_tail.push_back(m.mk_eq(e, m.mk_true()));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                tail_neg.push_back(false);
 | 
					                m_tail_neg.push_back(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SASSERT(tail.size() == tail_neg.size());
 | 
					            SASSERT(m_tail.size() == m_tail_neg.size());
 | 
				
			||||||
            res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr());
 | 
					            res = m_context.get_rule_manager().mk(head, m_tail.size(), m_tail.c_ptr(), m_tail_neg.c_ptr());
 | 
				
			||||||
            res->set_accounting_parent_object(m_context, r);
 | 
					            res->set_accounting_parent_object(m_context, r);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
| 
						 | 
					@ -583,7 +605,9 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rule_set * res = alloc(rule_set, m_context);
 | 
					        rule_set * res = alloc(rule_set, m_context);
 | 
				
			||||||
        if (!transform_rules(source, *res)) {
 | 
					        if (transform_rules(source, *res)) {
 | 
				
			||||||
 | 
					            res->inherit_predicates(source);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
            dealloc(res);
 | 
					            dealloc(res);
 | 
				
			||||||
            res = 0;
 | 
					            res = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,15 +34,17 @@ namespace datalog {
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            ast_manager& m;
 | 
					            ast_manager& m;
 | 
				
			||||||
            context& m_context;
 | 
					            context& m_context;
 | 
				
			||||||
            substitution m_subst;
 | 
					            substitution   m_subst;
 | 
				
			||||||
            unifier m_unif;
 | 
					            unifier        m_unif;
 | 
				
			||||||
 | 
					            app_ref        m_head;
 | 
				
			||||||
            rule * m_rule;
 | 
					            app_ref_vector m_tail;
 | 
				
			||||||
 | 
					            svector<bool>  m_neg;
 | 
				
			||||||
 | 
					            rule *         m_rule;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            void apply(app * a, app_ref& res);
 | 
					            void apply(app * a, app_ref& res);
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            rule_substitution(context & ctx)
 | 
					            rule_substitution(context & ctx)
 | 
				
			||||||
                : m(ctx.get_manager()), m_context(ctx), m_subst(m), m_unif(m), m_rule(0) {}
 | 
					                : m(ctx.get_manager()), m_context(ctx), m_subst(m), m_unif(m), m_head(m), m_tail(m), m_rule(0) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /**
 | 
					            /**
 | 
				
			||||||
            Reset substitution and get it ready for working with rule r.
 | 
					            Reset substitution and get it ready for working with rule r.
 | 
				
			||||||
| 
						 | 
					@ -61,13 +63,23 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class normalizer_cfg;
 | 
				
			||||||
 | 
					        class normalizer_rw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ast_manager &     m;
 | 
					        ast_manager &     m;
 | 
				
			||||||
        context &         m_context;
 | 
					        context &         m_context;
 | 
				
			||||||
        th_rewriter &     m_simp;
 | 
					        th_rewriter &     m_simp;
 | 
				
			||||||
        arith_util        a;
 | 
					        arith_util        a;
 | 
				
			||||||
        rule_substitution m_rule_subst;
 | 
					        rule_substitution m_rule_subst;
 | 
				
			||||||
 | 
					        ptr_vector<expr> m_todo;
 | 
				
			||||||
 | 
					        obj_hashtable<expr> m_leqs;
 | 
				
			||||||
 | 
					        app_ref_vector    m_tail;
 | 
				
			||||||
 | 
					        expr_ref_vector   m_itail_members;
 | 
				
			||||||
 | 
					        expr_ref_vector   m_conj;
 | 
				
			||||||
 | 
					        svector<bool>     m_tail_neg;
 | 
				
			||||||
 | 
					        normalizer_cfg*   m_cfg;
 | 
				
			||||||
 | 
					        normalizer_rw*    m_rw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class normalizer_cfg;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void simplify_expr(app * a, expr_ref& res);
 | 
					        void simplify_expr(app * a, expr_ref& res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,13 +89,8 @@ namespace datalog {
 | 
				
			||||||
        /** Return true if something was modified */
 | 
					        /** Return true if something was modified */
 | 
				
			||||||
        bool transform_rules(const rule_set & orig, rule_set & tgt);
 | 
					        bool transform_rules(const rule_set & orig, rule_set & tgt);
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        mk_interp_tail_simplifier(context & ctx, unsigned priority=40000)
 | 
					        mk_interp_tail_simplifier(context & ctx, unsigned priority=40000);
 | 
				
			||||||
            : plugin(priority),
 | 
					        virtual ~mk_interp_tail_simplifier();
 | 
				
			||||||
            m(ctx.get_manager()),
 | 
					 | 
				
			||||||
            m_context(ctx),
 | 
					 | 
				
			||||||
            m_simp(ctx.get_rewriter()),
 | 
					 | 
				
			||||||
            a(m),
 | 
					 | 
				
			||||||
            m_rule_subst(ctx) {}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**If rule should be retained, assign transformed version to res and return true;
 | 
					        /**If rule should be retained, assign transformed version to res and return true;
 | 
				
			||||||
        if rule can be deleted, return false.
 | 
					        if rule can be deleted, return false.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,9 @@ Revision History:
 | 
				
			||||||
#include"dl_mk_karr_invariants.h"
 | 
					#include"dl_mk_karr_invariants.h"
 | 
				
			||||||
#include"expr_safe_replace.h"
 | 
					#include"expr_safe_replace.h"
 | 
				
			||||||
#include"bool_rewriter.h"
 | 
					#include"bool_rewriter.h"
 | 
				
			||||||
 | 
					#include"dl_mk_backwards.h"
 | 
				
			||||||
 | 
					#include"dl_mk_loop_counter.h"
 | 
				
			||||||
 | 
					#include "for_each_expr.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace datalog {
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +48,8 @@ namespace datalog {
 | 
				
			||||||
        m(ctx.get_manager()), 
 | 
					        m(ctx.get_manager()), 
 | 
				
			||||||
        rm(ctx.get_rule_manager()),
 | 
					        rm(ctx.get_rule_manager()),
 | 
				
			||||||
        m_inner_ctx(m, ctx.get_fparams()),
 | 
					        m_inner_ctx(m, ctx.get_fparams()),
 | 
				
			||||||
        a(m) {
 | 
					        a(m),
 | 
				
			||||||
 | 
					        m_pinned(m) {
 | 
				
			||||||
            params_ref params;
 | 
					            params_ref params;
 | 
				
			||||||
            params.set_sym("default_relation", symbol("karr_relation"));
 | 
					            params.set_sym("default_relation", symbol("karr_relation"));
 | 
				
			||||||
            params.set_sym("engine", symbol("datalog"));
 | 
					            params.set_sym("engine", symbol("datalog"));
 | 
				
			||||||
| 
						 | 
					@ -199,48 +203,90 @@ namespace datalog {
 | 
				
			||||||
                return 0;
 | 
					                return 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        mk_loop_counter lc(m_ctx);
 | 
				
			||||||
 | 
					        mk_backwards bwd(m_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        scoped_ptr<rule_set> src_loop = lc(source);
 | 
				
			||||||
 | 
					        TRACE("dl", src_loop->display(tout << "source loop\n"););
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        get_invariants(*src_loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // figure out whether to update same rules as used for saturation.
 | 
				
			||||||
 | 
					        scoped_ptr<rule_set> rev_source = bwd(*src_loop);
 | 
				
			||||||
 | 
					        get_invariants(*rev_source);        
 | 
				
			||||||
 | 
					        scoped_ptr<rule_set> src_annot = update_rules(*src_loop);
 | 
				
			||||||
 | 
					        rule_set* rules = lc.revert(*src_annot);
 | 
				
			||||||
 | 
					        rules->inherit_predicates(source);
 | 
				
			||||||
 | 
					        TRACE("dl", rules->display(tout););
 | 
				
			||||||
 | 
					        m_pinned.reset();
 | 
				
			||||||
 | 
					        m_fun2inv.reset();
 | 
				
			||||||
 | 
					        return rules;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void mk_karr_invariants::get_invariants(rule_set const& src) {
 | 
				
			||||||
 | 
					        m_inner_ctx.reset();
 | 
				
			||||||
        rel_context& rctx = m_inner_ctx.get_rel_context();
 | 
					        rel_context& rctx = m_inner_ctx.get_rel_context();
 | 
				
			||||||
        ptr_vector<func_decl> heads;
 | 
					        ptr_vector<func_decl> heads;
 | 
				
			||||||
        m_inner_ctx.ensure_opened();
 | 
					        func_decl_set const& predicates = m_ctx.get_predicates();
 | 
				
			||||||
        it = source.begin();
 | 
					        for (func_decl_set::iterator fit = predicates.begin(); fit != predicates.end(); ++fit) {
 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					            m_inner_ctx.register_predicate(*fit, false);
 | 
				
			||||||
            rule_ref r(*it, m_inner_ctx.get_rule_manager());
 | 
					 | 
				
			||||||
            m_inner_ctx.add_rule(r);
 | 
					 | 
				
			||||||
            m_inner_ctx.register_predicate(r->get_decl(), false);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        m_inner_ctx.ensure_opened();
 | 
				
			||||||
 | 
					        m_inner_ctx.replace_rules(src);
 | 
				
			||||||
        m_inner_ctx.close();
 | 
					        m_inner_ctx.close();
 | 
				
			||||||
        rule_set::decl2rules::iterator dit  = source.begin_grouped_rules();
 | 
					        rule_set::decl2rules::iterator dit  = src.begin_grouped_rules();
 | 
				
			||||||
        rule_set::decl2rules::iterator dend = source.end_grouped_rules();
 | 
					        rule_set::decl2rules::iterator dend = src.end_grouped_rules();
 | 
				
			||||||
        for (; dit != dend; ++dit) {
 | 
					        for (; dit != dend; ++dit) {
 | 
				
			||||||
            heads.push_back(dit->m_key);
 | 
					            heads.push_back(dit->m_key);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        m_inner_ctx.rel_query(heads.size(), heads.c_ptr());
 | 
					        m_inner_ctx.rel_query(heads.size(), heads.c_ptr());
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        rule_set* rules = alloc(rule_set, m_ctx);
 | 
					        // retrieve invariants.
 | 
				
			||||||
        it = source.begin();            
 | 
					        dit = src.begin_grouped_rules();
 | 
				
			||||||
 | 
					        for (; dit != dend; ++dit) {
 | 
				
			||||||
 | 
					            func_decl* p = dit->m_key;
 | 
				
			||||||
 | 
					            relation_base* rb = rctx.try_get_relation(p);
 | 
				
			||||||
 | 
					            if (rb) {
 | 
				
			||||||
 | 
					                expr_ref fml(m);
 | 
				
			||||||
 | 
					                rb->to_formula(fml);                
 | 
				
			||||||
 | 
					                if (m.is_true(fml)) {
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                expr* inv = 0;
 | 
				
			||||||
 | 
					                if (m_fun2inv.find(p, inv)) {
 | 
				
			||||||
 | 
					                    fml = m.mk_and(inv, fml);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                m_pinned.push_back(fml);
 | 
				
			||||||
 | 
					                m_fun2inv.insert(p, fml);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rule_set* mk_karr_invariants::update_rules(rule_set const& src) {
 | 
				
			||||||
 | 
					        scoped_ptr<rule_set> dst = alloc(rule_set, m_ctx);
 | 
				
			||||||
 | 
					        rule_set::iterator it = src.begin(), end = src.end();
 | 
				
			||||||
        for (; it != end; ++it) {
 | 
					        for (; it != end; ++it) {
 | 
				
			||||||
            update_body(rctx, *rules, **it);
 | 
					            update_body(*dst, **it);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (m_ctx.get_model_converter()) {
 | 
					        if (m_ctx.get_model_converter()) {
 | 
				
			||||||
            add_invariant_model_converter* kmc = alloc(add_invariant_model_converter, m);
 | 
					            add_invariant_model_converter* kmc = alloc(add_invariant_model_converter, m);
 | 
				
			||||||
            rule_set::decl2rules::iterator git  = source.begin_grouped_rules();
 | 
					            rule_set::decl2rules::iterator git  = src.begin_grouped_rules();
 | 
				
			||||||
            rule_set::decl2rules::iterator gend = source.end_grouped_rules();
 | 
					            rule_set::decl2rules::iterator gend = src.end_grouped_rules();
 | 
				
			||||||
            for (; git != gend; ++git) {
 | 
					            for (; git != gend; ++git) {
 | 
				
			||||||
                func_decl* p = git->m_key;
 | 
					                func_decl* p = git->m_key;
 | 
				
			||||||
                expr_ref fml(m);
 | 
					                expr* fml = 0;
 | 
				
			||||||
                relation_base* rb = rctx.try_get_relation(p);
 | 
					                if (m_fun2inv.find(p, fml)) {
 | 
				
			||||||
                if (rb) {
 | 
					 | 
				
			||||||
                    rb->to_formula(fml);
 | 
					 | 
				
			||||||
                    kmc->add(p, fml);                    
 | 
					                    kmc->add(p, fml);                    
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            m_ctx.add_model_converter(kmc);
 | 
					            m_ctx.add_model_converter(kmc);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        TRACE("dl", rules->display(tout););
 | 
					
 | 
				
			||||||
        return rules;
 | 
					        dst->inherit_predicates(src);
 | 
				
			||||||
 | 
					        return dst.detach();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_karr_invariants::update_body(rel_context& rctx, rule_set& rules, rule& r) { 
 | 
					    void mk_karr_invariants::update_body(rule_set& rules, rule& r) { 
 | 
				
			||||||
        unsigned utsz = r.get_uninterpreted_tail_size();
 | 
					        unsigned utsz = r.get_uninterpreted_tail_size();
 | 
				
			||||||
        unsigned tsz  = r.get_tail_size();
 | 
					        unsigned tsz  = r.get_tail_size();
 | 
				
			||||||
        app_ref_vector tail(m);
 | 
					        app_ref_vector tail(m);
 | 
				
			||||||
| 
						 | 
					@ -249,17 +295,17 @@ namespace datalog {
 | 
				
			||||||
            tail.push_back(r.get_tail(i));
 | 
					            tail.push_back(r.get_tail(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        for (unsigned i = 0; i < utsz; ++i) {
 | 
					        for (unsigned i = 0; i < utsz; ++i) {
 | 
				
			||||||
            func_decl* q = r.get_decl(i);            
 | 
					            func_decl* q = r.get_decl(i); 
 | 
				
			||||||
            relation_base* rb = rctx.try_get_relation(r.get_decl(i));
 | 
					            expr* fml = 0;
 | 
				
			||||||
            if (rb) {
 | 
					            if (m_fun2inv.find(q, fml)) {
 | 
				
			||||||
                rb->to_formula(fml);
 | 
					 | 
				
			||||||
                expr_safe_replace rep(m);
 | 
					                expr_safe_replace rep(m);
 | 
				
			||||||
                for (unsigned j = 0; j < q->get_arity(); ++j) {
 | 
					                for (unsigned j = 0; j < q->get_arity(); ++j) {
 | 
				
			||||||
                    rep.insert(m.mk_var(j, q->get_domain(j)), 
 | 
					                    rep.insert(m.mk_var(j, q->get_domain(j)), 
 | 
				
			||||||
                               r.get_tail(i)->get_arg(j));
 | 
					                               r.get_tail(i)->get_arg(j));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                rep(fml);
 | 
					                expr_ref tmp(fml, m);
 | 
				
			||||||
                tail.push_back(to_app(fml));
 | 
					                rep(tmp);
 | 
				
			||||||
 | 
					                tail.push_back(to_app(tmp));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        rule* new_rule = &r;
 | 
					        rule* new_rule = &r;
 | 
				
			||||||
| 
						 | 
					@ -937,11 +983,8 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class karr_relation_plugin::union_fn : public relation_union_fn {
 | 
					    class karr_relation_plugin::union_fn : public relation_union_fn {
 | 
				
			||||||
        karr_relation_plugin& m_plugin;
 | 
					 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        union_fn(karr_relation_plugin& p) :
 | 
					        union_fn() {}
 | 
				
			||||||
            m_plugin(p) {            
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) {
 | 
					        virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -965,7 +1008,7 @@ namespace datalog {
 | 
				
			||||||
        if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) {
 | 
					        if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return alloc(union_fn, *this);
 | 
					        return alloc(union_fn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class karr_relation_plugin::filter_identical_fn : public relation_mutator_fn {
 | 
					    class karr_relation_plugin::filter_identical_fn : public relation_mutator_fn {
 | 
				
			||||||
| 
						 | 
					@ -1006,16 +1049,17 @@ namespace datalog {
 | 
				
			||||||
    class karr_relation_plugin::filter_equal_fn : public relation_mutator_fn {
 | 
					    class karr_relation_plugin::filter_equal_fn : public relation_mutator_fn {
 | 
				
			||||||
        unsigned m_col;
 | 
					        unsigned m_col;
 | 
				
			||||||
        rational m_value;
 | 
					        rational m_value;
 | 
				
			||||||
 | 
					        bool    m_valid;
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        filter_equal_fn(relation_manager & m, const relation_element & value, unsigned col) 
 | 
					        filter_equal_fn(relation_manager & m, const relation_element & value, unsigned col) 
 | 
				
			||||||
            : m_col(col) {
 | 
					            : m_col(col) {
 | 
				
			||||||
            arith_util arith(m.get_context().get_manager());
 | 
					            arith_util arith(m.get_context().get_manager());
 | 
				
			||||||
            VERIFY(arith.is_numeral(value, m_value));            
 | 
					            m_valid = arith.is_numeral(value, m_value) && m_value.is_int();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void operator()(relation_base & _r) {
 | 
					        virtual void operator()(relation_base & _r) {
 | 
				
			||||||
            karr_relation & r = get(_r);
 | 
					            karr_relation & r = get(_r);
 | 
				
			||||||
            if (m_value.is_int()) {
 | 
					            if (m_valid) {
 | 
				
			||||||
                r.get_ineqs();
 | 
					                r.get_ineqs();
 | 
				
			||||||
                vector<rational> row;
 | 
					                vector<rational> row;
 | 
				
			||||||
                row.resize(r.get_signature().size());
 | 
					                row.resize(r.get_signature().size());
 | 
				
			||||||
| 
						 | 
					@ -1031,7 +1075,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    relation_mutator_fn * karr_relation_plugin::mk_filter_equal_fn(const relation_base & r, 
 | 
					    relation_mutator_fn * karr_relation_plugin::mk_filter_equal_fn(const relation_base & r, 
 | 
				
			||||||
        const relation_element & value, unsigned col) {
 | 
					        const relation_element & value, unsigned col) {
 | 
				
			||||||
        if(check_kind(r)) {
 | 
					        if (check_kind(r)) {
 | 
				
			||||||
            return alloc(filter_equal_fn, get_manager(), value, col);
 | 
					            return alloc(filter_equal_fn, get_manager(), value, col);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,8 +55,13 @@ namespace datalog {
 | 
				
			||||||
        rule_manager&   rm;
 | 
					        rule_manager&   rm;
 | 
				
			||||||
        context         m_inner_ctx;
 | 
					        context         m_inner_ctx;
 | 
				
			||||||
        arith_util      a;
 | 
					        arith_util      a;
 | 
				
			||||||
        void update_body(rel_context& rctx, rule_set& result, rule& r);
 | 
					        obj_map<func_decl, expr*>      m_fun2inv;
 | 
				
			||||||
 | 
					        ast_ref_vector m_pinned;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void get_invariants(rule_set const& src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void update_body(rule_set& result, rule& r);
 | 
				
			||||||
 | 
					        rule_set* update_rules(rule_set const& src);
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        mk_karr_invariants(context & ctx, unsigned priority);
 | 
					        mk_karr_invariants(context & ctx, unsigned priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,12 +94,7 @@ namespace datalog {
 | 
				
			||||||
        {}            
 | 
					        {}            
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        virtual bool can_handle_signature(const relation_signature & sig) {
 | 
					        virtual bool can_handle_signature(const relation_signature & sig) {
 | 
				
			||||||
            for (unsigned i = 0; i < sig.size(); ++i) {
 | 
					            return true;
 | 
				
			||||||
                if (a.is_int(sig[i])) {
 | 
					 | 
				
			||||||
                    return true;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static symbol get_name() { return symbol("karr_relation"); }
 | 
					        static symbol get_name() { return symbol("karr_relation"); }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,13 +25,14 @@ namespace datalog {
 | 
				
			||||||
    mk_loop_counter::mk_loop_counter(context & ctx, unsigned priority):
 | 
					    mk_loop_counter::mk_loop_counter(context & ctx, unsigned priority):
 | 
				
			||||||
        plugin(priority),
 | 
					        plugin(priority),
 | 
				
			||||||
        m(ctx.get_manager()),
 | 
					        m(ctx.get_manager()),
 | 
				
			||||||
 | 
					        m_ctx(ctx),
 | 
				
			||||||
        a(m),
 | 
					        a(m),
 | 
				
			||||||
        m_refs(m) {        
 | 
					        m_refs(m) {        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk_loop_counter::~mk_loop_counter() { }
 | 
					    mk_loop_counter::~mk_loop_counter() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app_ref mk_loop_counter::add_arg(app* fn, unsigned idx) {
 | 
					    app_ref mk_loop_counter::add_arg(rule_set const& src, rule_set& dst, app* fn, unsigned idx) {
 | 
				
			||||||
        expr_ref_vector args(m);
 | 
					        expr_ref_vector args(m);
 | 
				
			||||||
        func_decl* new_fn, *old_fn = fn->get_decl();
 | 
					        func_decl* new_fn, *old_fn = fn->get_decl();
 | 
				
			||||||
        args.append(fn->get_num_args(), fn->get_args());
 | 
					        args.append(fn->get_num_args(), fn->get_args());
 | 
				
			||||||
| 
						 | 
					@ -45,17 +46,29 @@ namespace datalog {
 | 
				
			||||||
            m_old2new.insert(old_fn, new_fn);
 | 
					            m_old2new.insert(old_fn, new_fn);
 | 
				
			||||||
            m_new2old.insert(new_fn, old_fn);
 | 
					            m_new2old.insert(new_fn, old_fn);
 | 
				
			||||||
            m_refs.push_back(new_fn);
 | 
					            m_refs.push_back(new_fn);
 | 
				
			||||||
 | 
					            m_ctx.register_predicate(new_fn, false);
 | 
				
			||||||
 | 
					            if (src.is_output_predicate(old_fn)) {
 | 
				
			||||||
 | 
					                dst.set_output_predicate(new_fn);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return app_ref(m.mk_app(new_fn, args.size(), args.c_ptr()), m);
 | 
					        return app_ref(m.mk_app(new_fn, args.size(), args.c_ptr()), m);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    app_ref mk_loop_counter::del_arg(app* fn) {        
 | 
				
			||||||
 | 
					        expr_ref_vector args(m);
 | 
				
			||||||
 | 
					        func_decl* old_fn, *new_fn = fn->get_decl();
 | 
				
			||||||
 | 
					        SASSERT(fn->get_num_args() > 0);
 | 
				
			||||||
 | 
					        args.append(fn->get_num_args()-1, fn->get_args());
 | 
				
			||||||
 | 
					        VERIFY (m_new2old.find(new_fn, old_fn));
 | 
				
			||||||
 | 
					        return app_ref(m.mk_app(old_fn, args.size(), args.c_ptr()), m);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    rule_set * mk_loop_counter::operator()(rule_set const & source) {
 | 
					    rule_set * mk_loop_counter::operator()(rule_set const & source) {
 | 
				
			||||||
        m_refs.reset();
 | 
					        m_refs.reset();
 | 
				
			||||||
        m_old2new.reset();
 | 
					        m_old2new.reset();
 | 
				
			||||||
        m_new2old.reset();
 | 
					        m_new2old.reset();
 | 
				
			||||||
        context& ctx = source.get_context();
 | 
					 | 
				
			||||||
        rule_manager& rm = source.get_rule_manager();
 | 
					        rule_manager& rm = source.get_rule_manager();
 | 
				
			||||||
        rule_set * result = alloc(rule_set, ctx);
 | 
					        rule_set * result = alloc(rule_set, m_ctx);
 | 
				
			||||||
        unsigned sz = source.get_num_rules();
 | 
					        unsigned sz = source.get_num_rules();
 | 
				
			||||||
        rule_ref new_rule(rm);
 | 
					        rule_ref new_rule(rm);
 | 
				
			||||||
        app_ref_vector tail(m);
 | 
					        app_ref_vector tail(m);
 | 
				
			||||||
| 
						 | 
					@ -70,16 +83,14 @@ namespace datalog {
 | 
				
			||||||
            unsigned utsz = r.get_uninterpreted_tail_size();
 | 
					            unsigned utsz = r.get_uninterpreted_tail_size();
 | 
				
			||||||
            unsigned tsz = r.get_tail_size();
 | 
					            unsigned tsz = r.get_tail_size();
 | 
				
			||||||
            for (unsigned j = 0; j < utsz; ++j, ++cnt) {
 | 
					            for (unsigned j = 0; j < utsz; ++j, ++cnt) {
 | 
				
			||||||
                tail.push_back(add_arg(r.get_tail(j), cnt));                
 | 
					                tail.push_back(add_arg(source, *result, r.get_tail(j), cnt));                
 | 
				
			||||||
                neg.push_back(r.is_neg_tail(j));
 | 
					                neg.push_back(r.is_neg_tail(j));
 | 
				
			||||||
                ctx.register_predicate(tail.back()->get_decl(), false);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            for (unsigned j = utsz; j < tsz; ++j) {
 | 
					            for (unsigned j = utsz; j < tsz; ++j) {
 | 
				
			||||||
                tail.push_back(r.get_tail(j));
 | 
					                tail.push_back(r.get_tail(j));
 | 
				
			||||||
                neg.push_back(false);
 | 
					                neg.push_back(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            head = add_arg(r.get_head(), cnt);
 | 
					            head = add_arg(source, *result, r.get_head(), cnt);
 | 
				
			||||||
            ctx.register_predicate(head->get_decl(), false);
 | 
					 | 
				
			||||||
            // set the loop counter to be an increment of the previous 
 | 
					            // set the loop counter to be an increment of the previous 
 | 
				
			||||||
            bool found = false;
 | 
					            bool found = false;
 | 
				
			||||||
            unsigned last = head->get_num_args()-1;
 | 
					            unsigned last = head->get_num_args()-1;
 | 
				
			||||||
| 
						 | 
					@ -110,4 +121,38 @@ namespace datalog {
 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rule_set * mk_loop_counter::revert(rule_set const & source) {
 | 
				
			||||||
 | 
					        context& ctx = source.get_context();
 | 
				
			||||||
 | 
					        rule_manager& rm = source.get_rule_manager();
 | 
				
			||||||
 | 
					        rule_set * result = alloc(rule_set, ctx);
 | 
				
			||||||
 | 
					        unsigned sz = source.get_num_rules();
 | 
				
			||||||
 | 
					        rule_ref new_rule(rm);
 | 
				
			||||||
 | 
					        app_ref_vector tail(m);
 | 
				
			||||||
 | 
					        app_ref head(m);
 | 
				
			||||||
 | 
					        svector<bool> neg;
 | 
				
			||||||
 | 
					        for (unsigned i = 0; i < sz; ++i) {            
 | 
				
			||||||
 | 
					            tail.reset();
 | 
				
			||||||
 | 
					            neg.reset();
 | 
				
			||||||
 | 
					            rule & r = *source.get_rule(i);
 | 
				
			||||||
 | 
					            unsigned utsz = r.get_uninterpreted_tail_size();
 | 
				
			||||||
 | 
					            unsigned tsz = r.get_tail_size();
 | 
				
			||||||
 | 
					            for (unsigned j = 0; j < utsz; ++j) {
 | 
				
			||||||
 | 
					                tail.push_back(del_arg(r.get_tail(j)));
 | 
				
			||||||
 | 
					                neg.push_back(r.is_neg_tail(j));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            for (unsigned j = utsz; j < tsz; ++j) {
 | 
				
			||||||
 | 
					                tail.push_back(r.get_tail(j));
 | 
				
			||||||
 | 
					                neg.push_back(false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            head = del_arg(r.get_head());
 | 
				
			||||||
 | 
					            new_rule = rm.mk(head, tail.size(), tail.c_ptr(), neg.c_ptr(), r.name(), true);
 | 
				
			||||||
 | 
					            result->add_rule(new_rule);            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // model converter: ...
 | 
				
			||||||
 | 
					        // proof converter: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,12 +26,14 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class mk_loop_counter : public rule_transformer::plugin {
 | 
					    class mk_loop_counter : public rule_transformer::plugin {
 | 
				
			||||||
        ast_manager& m;
 | 
					        ast_manager& m;
 | 
				
			||||||
 | 
					        context&     m_ctx;
 | 
				
			||||||
        arith_util   a;
 | 
					        arith_util   a;
 | 
				
			||||||
        func_decl_ref_vector m_refs;
 | 
					        func_decl_ref_vector m_refs;
 | 
				
			||||||
        obj_map<func_decl, func_decl*> m_new2old;
 | 
					        obj_map<func_decl, func_decl*> m_new2old;
 | 
				
			||||||
        obj_map<func_decl, func_decl*> m_old2new;
 | 
					        obj_map<func_decl, func_decl*> m_old2new;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app_ref add_arg(app* fn, unsigned idx);        
 | 
					        app_ref add_arg(rule_set const& src, rule_set& dst, app* fn, unsigned idx);        
 | 
				
			||||||
 | 
					        app_ref del_arg(app* fn);        
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        mk_loop_counter(context & ctx, unsigned priority = 33000);
 | 
					        mk_loop_counter(context & ctx, unsigned priority = 33000);
 | 
				
			||||||
        ~mk_loop_counter();
 | 
					        ~mk_loop_counter();
 | 
				
			||||||
| 
						 | 
					@ -39,6 +41,8 @@ namespace datalog {
 | 
				
			||||||
        rule_set * operator()(rule_set const & source);
 | 
					        rule_set * operator()(rule_set const & source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        func_decl* get_old(func_decl* f) const { return m_new2old.find(f); }
 | 
					        func_decl* get_old(func_decl* f) const { return m_new2old.find(f); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rule_set * revert(rule_set const& source);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,13 +24,13 @@ Revision History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace datalog {
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk_magic_sets::mk_magic_sets(context & ctx, rule * goal_rule) :
 | 
					    mk_magic_sets::mk_magic_sets(context & ctx, func_decl* goal) :
 | 
				
			||||||
        plugin(10000, true),
 | 
					        plugin(10000, true),
 | 
				
			||||||
        m_context(ctx),
 | 
					        m_context(ctx),
 | 
				
			||||||
        m_manager(ctx.get_manager()),
 | 
					        m(ctx.get_manager()),
 | 
				
			||||||
        m_rules(ctx.get_rule_manager()),
 | 
					        rm(ctx.get_rule_manager()),
 | 
				
			||||||
        m_pinned(m_manager),
 | 
					        m_pinned(m), 
 | 
				
			||||||
        m_goal_rule(goal_rule, ctx.get_rule_manager()) {
 | 
					        m_goal(goal, m) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_magic_sets::reset() {
 | 
					    void mk_magic_sets::reset() {
 | 
				
			||||||
| 
						 | 
					@ -39,14 +39,13 @@ namespace datalog {
 | 
				
			||||||
        m_adorned_preds.reset();
 | 
					        m_adorned_preds.reset();
 | 
				
			||||||
        m_adornments.reset();
 | 
					        m_adornments.reset();
 | 
				
			||||||
        m_magic_preds.reset();
 | 
					        m_magic_preds.reset();
 | 
				
			||||||
        m_rules.reset();
 | 
					 | 
				
			||||||
        m_pinned.reset();
 | 
					        m_pinned.reset();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_magic_sets::adornment::populate(app * lit, const var_idx_set & bound_vars) {
 | 
					    void mk_magic_sets::adornment::populate(app * lit, const var_idx_set & bound_vars) {
 | 
				
			||||||
        SASSERT(empty());
 | 
					        SASSERT(empty());
 | 
				
			||||||
        unsigned arity = lit->get_num_args();
 | 
					        unsigned arity = lit->get_num_args();
 | 
				
			||||||
        for(unsigned i=0; i<arity; i++) {
 | 
					        for (unsigned i = 0; i < arity; i++) {
 | 
				
			||||||
            const expr * arg = lit->get_arg(i);
 | 
					            const expr * arg = lit->get_arg(i);
 | 
				
			||||||
            bool bound = !is_var(arg) || bound_vars.contains(to_var(arg)->get_idx());
 | 
					            bool bound = !is_var(arg) || bound_vars.contains(to_var(arg)->get_idx());
 | 
				
			||||||
            push_back(bound ? AD_BOUND : AD_FREE);
 | 
					            push_back(bound ? AD_BOUND : AD_FREE);
 | 
				
			||||||
| 
						 | 
					@ -57,17 +56,8 @@ namespace datalog {
 | 
				
			||||||
        std::string res;
 | 
					        std::string res;
 | 
				
			||||||
        const_iterator eit = begin();
 | 
					        const_iterator eit = begin();
 | 
				
			||||||
        const_iterator eend = end();
 | 
					        const_iterator eend = end();
 | 
				
			||||||
        for(; eit!=eend; ++eit) {
 | 
					        for (; eit != eend; ++eit) {
 | 
				
			||||||
            switch(*eit) {
 | 
					            res += (*eit == AD_BOUND)?'b':'f';
 | 
				
			||||||
            case AD_BOUND:
 | 
					 | 
				
			||||||
                res+='b';
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case AD_FREE:
 | 
					 | 
				
			||||||
                res+='f';
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                UNREACHABLE();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -75,14 +65,13 @@ namespace datalog {
 | 
				
			||||||
    unsigned get_bound_arg_count(app * lit, const var_idx_set & bound_vars) {
 | 
					    unsigned get_bound_arg_count(app * lit, const var_idx_set & bound_vars) {
 | 
				
			||||||
        unsigned res = 0;
 | 
					        unsigned res = 0;
 | 
				
			||||||
        unsigned n = lit->get_num_args();
 | 
					        unsigned n = lit->get_num_args();
 | 
				
			||||||
        for(unsigned i=0; i<n; i++) {
 | 
					        for (unsigned i = 0; i < n; i++) {
 | 
				
			||||||
            const expr * arg = lit->get_arg(i);
 | 
					            const expr * arg = lit->get_arg(i);
 | 
				
			||||||
            if(is_var(arg) && !bound_vars.contains(to_var(arg)->get_idx())) {
 | 
					            if (!is_var(arg) || bound_vars.contains(to_var(arg)->get_idx())) {
 | 
				
			||||||
                continue;
 | 
					                SASSERT(is_var(arg) || is_app(arg));
 | 
				
			||||||
 | 
					                SASSERT(!is_app(arg) || to_app(arg)->get_num_args()==0);
 | 
				
			||||||
 | 
					                res++;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            SASSERT(is_var(arg) || is_app(arg));
 | 
					 | 
				
			||||||
            SASSERT(!is_app(arg) || to_app(arg)->get_num_args()==0);
 | 
					 | 
				
			||||||
            res++;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -91,10 +80,10 @@ namespace datalog {
 | 
				
			||||||
        func_decl * pred = lit->get_decl();
 | 
					        func_decl * pred = lit->get_decl();
 | 
				
			||||||
        float res = 1;
 | 
					        float res = 1;
 | 
				
			||||||
        unsigned n = lit->get_num_args();
 | 
					        unsigned n = lit->get_num_args();
 | 
				
			||||||
        for(unsigned i=0; i<n; i++) {
 | 
					        for (unsigned i = 0; i < n; i++) {
 | 
				
			||||||
            const expr * arg = lit->get_arg(i);
 | 
					            const expr * arg = lit->get_arg(i);
 | 
				
			||||||
            if(is_var(arg) && !bound_vars.contains(to_var(arg)->get_idx())) {
 | 
					            if (is_var(arg) && !bound_vars.contains(to_var(arg)->get_idx())) {
 | 
				
			||||||
                res*=m_context.get_sort_size_estimate(pred->get_domain(i));
 | 
					                res *= m_context.get_sort_size_estimate(pred->get_domain(i));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            //res-=1;
 | 
					            //res-=1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -111,22 +100,22 @@ namespace datalog {
 | 
				
			||||||
        float best_cost;
 | 
					        float best_cost;
 | 
				
			||||||
        int candidate_index = -1;
 | 
					        int candidate_index = -1;
 | 
				
			||||||
        unsigned n = cont.size();
 | 
					        unsigned n = cont.size();
 | 
				
			||||||
        for(unsigned i=0; i<n; i++) {
 | 
					        for (unsigned i=0; i<n; i++) {
 | 
				
			||||||
            app * lit = r->get_tail(cont[i]);
 | 
					            app * lit = r->get_tail(cont[i]);
 | 
				
			||||||
            unsigned bound_cnt = get_bound_arg_count(lit, bound_vars);
 | 
					            unsigned bound_cnt = get_bound_arg_count(lit, bound_vars);
 | 
				
			||||||
            if(bound_cnt==0) {
 | 
					            if (bound_cnt==0) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            float cost = get_unbound_cost(lit, bound_vars);
 | 
					            float cost = get_unbound_cost(lit, bound_vars);
 | 
				
			||||||
            if(candidate_index==-1 || cost<best_cost) {
 | 
					            if (candidate_index==-1 || cost<best_cost) {
 | 
				
			||||||
                best_cost = cost;
 | 
					                best_cost = cost;
 | 
				
			||||||
                candidate_index = i;
 | 
					                candidate_index = i;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(candidate_index==-1) {
 | 
					        if (candidate_index==-1) {
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(candidate_index != static_cast<int>(n-1)) {
 | 
					        if (candidate_index != static_cast<int>(n-1)) {
 | 
				
			||||||
            std::swap(cont[candidate_index], cont[n-1]);
 | 
					            std::swap(cont[candidate_index], cont[n-1]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        unsigned res = cont.back();
 | 
					        unsigned res = cont.back();
 | 
				
			||||||
| 
						 | 
					@ -137,12 +126,12 @@ namespace datalog {
 | 
				
			||||||
    app * mk_magic_sets::adorn_literal(app * lit, const var_idx_set & bound_vars) {
 | 
					    app * mk_magic_sets::adorn_literal(app * lit, const var_idx_set & bound_vars) {
 | 
				
			||||||
        SASSERT(!m_extentional.contains(lit->get_decl()));
 | 
					        SASSERT(!m_extentional.contains(lit->get_decl()));
 | 
				
			||||||
        func_decl * old_pred = lit->get_decl();
 | 
					        func_decl * old_pred = lit->get_decl();
 | 
				
			||||||
        SASSERT(m_manager.is_bool(old_pred->get_range()));
 | 
					        SASSERT(m.is_bool(old_pred->get_range()));
 | 
				
			||||||
        adornment_desc adn(old_pred);
 | 
					        adornment_desc adn(old_pred);
 | 
				
			||||||
        adn.m_adornment.populate(lit, bound_vars);
 | 
					        adn.m_adornment.populate(lit, bound_vars);
 | 
				
			||||||
        adornment_map::entry * e = m_adorned_preds.insert_if_not_there2(adn, 0);
 | 
					        adornment_map::entry * e = m_adorned_preds.insert_if_not_there2(adn, 0);
 | 
				
			||||||
        func_decl * new_pred = e->get_data().m_value;
 | 
					        func_decl * new_pred = e->get_data().m_value;
 | 
				
			||||||
        if(new_pred==0) {
 | 
					        if (new_pred==0) {
 | 
				
			||||||
            std::string suffix = "ad_"+adn.m_adornment.to_string();
 | 
					            std::string suffix = "ad_"+adn.m_adornment.to_string();
 | 
				
			||||||
            new_pred = m_context.mk_fresh_head_predicate(
 | 
					            new_pred = m_context.mk_fresh_head_predicate(
 | 
				
			||||||
                old_pred->get_name(), symbol(suffix.c_str()), 
 | 
					                old_pred->get_name(), symbol(suffix.c_str()), 
 | 
				
			||||||
| 
						 | 
					@ -152,34 +141,34 @@ namespace datalog {
 | 
				
			||||||
            m_todo.push_back(adn);
 | 
					            m_todo.push_back(adn);
 | 
				
			||||||
            m_adornments.insert(new_pred, adn.m_adornment);
 | 
					            m_adornments.insert(new_pred, adn.m_adornment);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        app * res = m_manager.mk_app(new_pred, lit->get_args());
 | 
					        app * res = m.mk_app(new_pred, lit->get_args());
 | 
				
			||||||
        m_pinned.push_back(res);
 | 
					        m_pinned.push_back(res);
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    app * mk_magic_sets::create_magic_literal(app * l) {
 | 
					    app * mk_magic_sets::create_magic_literal(app * l) {
 | 
				
			||||||
        func_decl * l_pred = l->get_decl();
 | 
					        func_decl * l_pred = l->get_decl();
 | 
				
			||||||
        SASSERT(m_manager.is_bool(l_pred->get_range()));
 | 
					        SASSERT(m.is_bool(l_pred->get_range()));
 | 
				
			||||||
        pred_adornment_map::obj_map_entry * ae = m_adornments.find_core(l_pred);
 | 
					        pred_adornment_map::obj_map_entry * ae = m_adornments.find_core(l_pred);
 | 
				
			||||||
        SASSERT(ae);
 | 
					        SASSERT(ae);
 | 
				
			||||||
        const adornment & adn = ae->get_data().m_value;
 | 
					        const adornment & adn = ae->get_data().m_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned l_arity = l->get_num_args();
 | 
					        unsigned l_arity = l->get_num_args();
 | 
				
			||||||
        ptr_vector<expr> bound_args;
 | 
					        ptr_vector<expr> bound_args;
 | 
				
			||||||
        for(unsigned i=0; i<l_arity; i++) {
 | 
					        for (unsigned i=0; i<l_arity; i++) {
 | 
				
			||||||
            if(adn[i]==AD_BOUND) {
 | 
					            if (adn[i]==AD_BOUND) {
 | 
				
			||||||
                bound_args.push_back(l->get_arg(i));
 | 
					                bound_args.push_back(l->get_arg(i));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pred2pred::obj_map_entry * e = m_magic_preds.insert_if_not_there2(l_pred, 0);
 | 
					        pred2pred::obj_map_entry * e = m_magic_preds.insert_if_not_there2(l_pred, 0);
 | 
				
			||||||
        func_decl * mag_pred = e->get_data().m_value;
 | 
					        func_decl * mag_pred = e->get_data().m_value;
 | 
				
			||||||
        if(mag_pred==0) {
 | 
					        if (mag_pred==0) {
 | 
				
			||||||
            unsigned mag_arity = bound_args.size();
 | 
					            unsigned mag_arity = bound_args.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ptr_vector<sort> mag_domain;
 | 
					            ptr_vector<sort> mag_domain;
 | 
				
			||||||
            for(unsigned i=0; i<l_arity; i++) {
 | 
					            for (unsigned i=0; i<l_arity; i++) {
 | 
				
			||||||
                if(adn[i]==AD_BOUND) {
 | 
					                if (adn[i]==AD_BOUND) {
 | 
				
			||||||
                    mag_domain.push_back(l_pred->get_domain(i));
 | 
					                    mag_domain.push_back(l_pred->get_domain(i));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -190,12 +179,12 @@ namespace datalog {
 | 
				
			||||||
            e->get_data().m_value = mag_pred;
 | 
					            e->get_data().m_value = mag_pred;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app * res = m_manager.mk_app(mag_pred, bound_args.c_ptr());
 | 
					        app * res = m.mk_app(mag_pred, bound_args.c_ptr());
 | 
				
			||||||
        m_pinned.push_back(res);
 | 
					        m_pinned.push_back(res);
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_magic_sets::create_magic_rules(app * head, unsigned tail_cnt, app * const * tail, bool const* negated) {
 | 
					    void mk_magic_sets::create_magic_rules(app * head, unsigned tail_cnt, app * const * tail, bool const* negated, rule_set& result) {
 | 
				
			||||||
        //TODO: maybe include relevant interpreted predicates from the original rule
 | 
					        //TODO: maybe include relevant interpreted predicates from the original rule
 | 
				
			||||||
        ptr_vector<app> new_tail;
 | 
					        ptr_vector<app> new_tail;
 | 
				
			||||||
        svector<bool> negations;
 | 
					        svector<bool> negations;
 | 
				
			||||||
| 
						 | 
					@ -204,26 +193,26 @@ namespace datalog {
 | 
				
			||||||
        negations.push_back(false);
 | 
					        negations.push_back(false);
 | 
				
			||||||
        negations.append(tail_cnt, negated);
 | 
					        negations.append(tail_cnt, negated);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for(unsigned i=0; i<tail_cnt; i++) {
 | 
					        for (unsigned i=0; i<tail_cnt; i++) {
 | 
				
			||||||
            if(m_extentional.contains(tail[i]->get_decl())) {
 | 
					            if (m_extentional.contains(tail[i]->get_decl())) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            app * mag_head = create_magic_literal(tail[i]);
 | 
					            app * mag_head = create_magic_literal(tail[i]);
 | 
				
			||||||
            rule * r = m_context.get_rule_manager().mk(mag_head, i+1, new_tail.c_ptr(), negations.c_ptr());
 | 
					            rule * r = m_context.get_rule_manager().mk(mag_head, i+1, new_tail.c_ptr(), negations.c_ptr());
 | 
				
			||||||
            TRACE("dl", r->display(m_context,tout); );
 | 
					            TRACE("dl", r->display(m_context,tout); );
 | 
				
			||||||
            m_rules.push_back(r);
 | 
					            result.add_rule(r);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_magic_sets::transform_rule(const adornment & head_adornment,  rule * r) {
 | 
					    void mk_magic_sets::transform_rule(const adornment & head_adornment,  rule * r, rule_set& result) {
 | 
				
			||||||
        app * head = r->get_head();
 | 
					        app * head = r->get_head();
 | 
				
			||||||
        unsigned head_len = head->get_num_args();
 | 
					        unsigned head_len = head->get_num_args();
 | 
				
			||||||
        SASSERT(head_len==head_adornment.size());
 | 
					        SASSERT(head_len==head_adornment.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var_idx_set bound_vars;
 | 
					        var_idx_set bound_vars;
 | 
				
			||||||
        for(unsigned i=0; i<head_len; i++) {
 | 
					        for (unsigned i=0; i<head_len; i++) {
 | 
				
			||||||
            expr * arg = head->get_arg(i);
 | 
					            expr * arg = head->get_arg(i);
 | 
				
			||||||
            if(head_adornment[i]==AD_BOUND && is_var(arg)) {
 | 
					            if (head_adornment[i]==AD_BOUND && is_var(arg)) {
 | 
				
			||||||
                bound_vars.insert(to_var(arg)->get_idx());
 | 
					                bound_vars.insert(to_var(arg)->get_idx());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -231,9 +220,9 @@ namespace datalog {
 | 
				
			||||||
        unsigned processed_tail_len = r->get_uninterpreted_tail_size();
 | 
					        unsigned processed_tail_len = r->get_uninterpreted_tail_size();
 | 
				
			||||||
        unsigned_vector exten_tails;
 | 
					        unsigned_vector exten_tails;
 | 
				
			||||||
        unsigned_vector inten_tails;
 | 
					        unsigned_vector inten_tails;
 | 
				
			||||||
        for(unsigned i=0; i<processed_tail_len; i++) {
 | 
					        for (unsigned i=0; i<processed_tail_len; i++) {
 | 
				
			||||||
            app * t = r->get_tail(i);
 | 
					            app * t = r->get_tail(i);
 | 
				
			||||||
            if(m_extentional.contains(t->get_decl())) {
 | 
					            if (m_extentional.contains(t->get_decl())) {
 | 
				
			||||||
                exten_tails.push_back(i);
 | 
					                exten_tails.push_back(i);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
| 
						 | 
					@ -243,17 +232,17 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ptr_vector<app> new_tail;
 | 
					        ptr_vector<app> new_tail;
 | 
				
			||||||
        svector<bool> negations;
 | 
					        svector<bool> negations;
 | 
				
			||||||
        while(new_tail.size()!=processed_tail_len) {
 | 
					        while (new_tail.size()!=processed_tail_len) {
 | 
				
			||||||
            bool intentional = false;
 | 
					            bool intentional = false;
 | 
				
			||||||
            int curr_index = pop_bound(exten_tails, r, bound_vars);
 | 
					            int curr_index = pop_bound(exten_tails, r, bound_vars);
 | 
				
			||||||
            if(curr_index==-1) {
 | 
					            if (curr_index==-1) {
 | 
				
			||||||
                curr_index = pop_bound(inten_tails, r,bound_vars);
 | 
					                curr_index = pop_bound(inten_tails, r,bound_vars);
 | 
				
			||||||
                if(curr_index!=-1) {
 | 
					                if (curr_index!=-1) {
 | 
				
			||||||
                    intentional = true;
 | 
					                    intentional = true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if(curr_index==-1) {
 | 
					            if (curr_index==-1) {
 | 
				
			||||||
                if(!exten_tails.empty()) {
 | 
					                if (!exten_tails.empty()) {
 | 
				
			||||||
                    curr_index = exten_tails.back();
 | 
					                    curr_index = exten_tails.back();
 | 
				
			||||||
                    exten_tails.pop_back();
 | 
					                    exten_tails.pop_back();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -266,24 +255,24 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            SASSERT(curr_index!=-1);
 | 
					            SASSERT(curr_index!=-1);
 | 
				
			||||||
            app * curr = r->get_tail(curr_index);
 | 
					            app * curr = r->get_tail(curr_index);
 | 
				
			||||||
            if(intentional) {
 | 
					            if (intentional) {
 | 
				
			||||||
                curr = adorn_literal(curr, bound_vars);
 | 
					                curr = adorn_literal(curr, bound_vars);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            new_tail.push_back(curr);
 | 
					            new_tail.push_back(curr);
 | 
				
			||||||
            negations.push_back(r->is_neg_tail(curr_index));
 | 
					            negations.push_back(r->is_neg_tail(curr_index));
 | 
				
			||||||
            collect_vars(m_manager, curr, bound_vars);
 | 
					            bound_vars |= rm.collect_vars(curr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        func_decl * new_head_pred;
 | 
					        func_decl * new_head_pred;
 | 
				
			||||||
        VERIFY( m_adorned_preds.find(adornment_desc(head->get_decl(), head_adornment), new_head_pred) );
 | 
					        VERIFY( m_adorned_preds.find(adornment_desc(head->get_decl(), head_adornment), new_head_pred) );
 | 
				
			||||||
        app * new_head = m_manager.mk_app(new_head_pred, head->get_args());
 | 
					        app * new_head = m.mk_app(new_head_pred, head->get_args());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SASSERT(new_tail.size()==r->get_uninterpreted_tail_size());
 | 
					        SASSERT(new_tail.size()==r->get_uninterpreted_tail_size());
 | 
				
			||||||
        create_magic_rules(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr());
 | 
					        create_magic_rules(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr(), result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned tail_len = r->get_tail_size();
 | 
					        unsigned tail_len = r->get_tail_size();
 | 
				
			||||||
        for(unsigned i=processed_tail_len; i<tail_len; i++) {
 | 
					        for (unsigned i=processed_tail_len; i<tail_len; i++) {
 | 
				
			||||||
            new_tail.push_back(r->get_tail(i));
 | 
					            new_tail.push_back(r->get_tail(i));
 | 
				
			||||||
            negations.push_back(r->is_neg_tail(i));
 | 
					            negations.push_back(r->is_neg_tail(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -292,43 +281,51 @@ namespace datalog {
 | 
				
			||||||
        negations.push_back(false);
 | 
					        negations.push_back(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rule * nr = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr());
 | 
					        rule * nr = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr());
 | 
				
			||||||
        m_rules.push_back(nr);
 | 
					        result.add_rule(nr);
 | 
				
			||||||
        nr->set_accounting_parent_object(m_context, r);
 | 
					        nr->set_accounting_parent_object(m_context, r);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void mk_magic_sets::create_transfer_rule(const adornment_desc & d) {
 | 
					    void mk_magic_sets::create_transfer_rule(const adornment_desc & d, rule_set& result) {
 | 
				
			||||||
        func_decl * adn_pred;
 | 
					        func_decl * adn_pred = m_adorned_preds.find(d);
 | 
				
			||||||
        TRUSTME( m_adorned_preds.find(d, adn_pred) );
 | 
					 | 
				
			||||||
        unsigned arity = adn_pred->get_arity();
 | 
					        unsigned arity = adn_pred->get_arity();
 | 
				
			||||||
        SASSERT(arity==d.m_pred->get_arity());
 | 
					        SASSERT(arity == d.m_pred->get_arity());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ptr_vector<expr> args;
 | 
					        ptr_vector<expr> args;
 | 
				
			||||||
        for(unsigned i=0; i<arity; i++) {
 | 
					        for (unsigned i=0; i<arity; i++) {
 | 
				
			||||||
            args.push_back(m_manager.mk_var(i, adn_pred->get_domain(i)));
 | 
					            args.push_back(m.mk_var(i, adn_pred->get_domain(i)));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app * lit = m_manager.mk_app(d.m_pred, args.c_ptr());
 | 
					        app * lit = m.mk_app(d.m_pred, args.c_ptr());
 | 
				
			||||||
        app * adn_lit = m_manager.mk_app(adn_pred, args.c_ptr());
 | 
					        app * adn_lit = m.mk_app(adn_pred, args.c_ptr());
 | 
				
			||||||
        app * mag_lit = create_magic_literal(adn_lit);
 | 
					        app * mag_lit = create_magic_literal(adn_lit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app * tail[] = {lit, mag_lit};
 | 
					        app * tail[] = {lit, mag_lit};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rule * r = m_context.get_rule_manager().mk(adn_lit, 2, tail, 0);
 | 
					        rule * r = m_context.get_rule_manager().mk(adn_lit, 2, tail, 0);
 | 
				
			||||||
        m_rules.push_back(r);
 | 
					        result.add_rule(r);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rule_set * mk_magic_sets::operator()(rule_set const & source) {
 | 
					    rule_set * mk_magic_sets::operator()(rule_set const & source) {
 | 
				
			||||||
        SASSERT(!m_context.get_model_converter());
 | 
					
 | 
				
			||||||
 | 
					        if (!m_context.magic_sets_for_queries()) {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        SASSERT(source.contains(m_goal));
 | 
				
			||||||
 | 
					        SASSERT(source.get_predicate_rules(m_goal).size() == 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        app * goal_head = source.get_predicate_rules(m_goal)[0]->get_head();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned init_rule_cnt = source.get_num_rules();
 | 
					        unsigned init_rule_cnt = source.get_num_rules();
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            func_decl_set intentional;
 | 
					            func_decl_set intentional;
 | 
				
			||||||
            for(unsigned i=0; i<init_rule_cnt; i++) {
 | 
					            for (unsigned i=0; i<init_rule_cnt; i++) {
 | 
				
			||||||
                intentional.insert(source.get_rule(i)->get_head()->get_decl());
 | 
					                func_decl* pred = source.get_rule(i)->get_decl();
 | 
				
			||||||
 | 
					                intentional.insert(pred);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            //now we iterate through all predicates and collect the set of extentional ones
 | 
					            //now we iterate through all predicates and collect the set of extentional ones
 | 
				
			||||||
            const rule_dependencies * deps;
 | 
					            const rule_dependencies * deps;
 | 
				
			||||||
            rule_dependencies computed_deps(m_context);
 | 
					            rule_dependencies computed_deps(m_context);
 | 
				
			||||||
            if(source.is_closed()) {
 | 
					            if (source.is_closed()) {
 | 
				
			||||||
                deps = &source.get_dependencies();
 | 
					                deps = &source.get_dependencies();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
| 
						 | 
					@ -337,9 +334,9 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            rule_dependencies::iterator it = deps->begin();
 | 
					            rule_dependencies::iterator it = deps->begin();
 | 
				
			||||||
            rule_dependencies::iterator end = deps->end();
 | 
					            rule_dependencies::iterator end = deps->end();
 | 
				
			||||||
            for(; it!=end; ++it) {
 | 
					            for (; it!=end; ++it) {
 | 
				
			||||||
                func_decl * pred = it->m_key;
 | 
					                func_decl * pred = it->m_key;
 | 
				
			||||||
                if(intentional.contains(pred)) {
 | 
					                if (intentional.contains(pred)) {
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                SASSERT(it->m_value->empty());//extentional predicates have no dependency
 | 
					                SASSERT(it->m_value->empty());//extentional predicates have no dependency
 | 
				
			||||||
| 
						 | 
					@ -347,48 +344,39 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SASSERT(m_rules.empty());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        app * goal_head = m_goal_rule->get_head();
 | 
					 | 
				
			||||||
        //adornment goal_adn;
 | 
					        //adornment goal_adn;
 | 
				
			||||||
        //goal_adn.populate(goal_head, );
 | 
					        //goal_adn.populate(goal_head, );
 | 
				
			||||||
        var_idx_set empty_var_idx_set;
 | 
					        var_idx_set empty_var_idx_set;
 | 
				
			||||||
        adorn_literal(goal_head, empty_var_idx_set);
 | 
					        adorn_literal(goal_head, empty_var_idx_set);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while(!m_todo.empty()) {
 | 
					        rule_set * result = alloc(rule_set, m_context);
 | 
				
			||||||
 | 
					        result->inherit_predicates(source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (!m_todo.empty()) {
 | 
				
			||||||
            adornment_desc task = m_todo.back();
 | 
					            adornment_desc task = m_todo.back();
 | 
				
			||||||
            m_todo.pop_back();
 | 
					            m_todo.pop_back();
 | 
				
			||||||
            const rule_vector & pred_rules = source.get_predicate_rules(task.m_pred);
 | 
					            const rule_vector & pred_rules = source.get_predicate_rules(task.m_pred);
 | 
				
			||||||
            rule_vector::const_iterator it = pred_rules.begin();
 | 
					            rule_vector::const_iterator it = pred_rules.begin();
 | 
				
			||||||
            rule_vector::const_iterator end = pred_rules.end();
 | 
					            rule_vector::const_iterator end = pred_rules.end();
 | 
				
			||||||
            for(; it!=end; ++it) {
 | 
					            for (; it != end; ++it) {
 | 
				
			||||||
                rule * r = *it;
 | 
					                rule * r = *it;
 | 
				
			||||||
                transform_rule(task.m_adornment, r);
 | 
					                transform_rule(task.m_adornment, r, *result);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if(!m_context.get_rel_context().get_relation(task.m_pred).empty()) {
 | 
					            if (!m_context.get_rel_context().get_relation(task.m_pred).empty()) {
 | 
				
			||||||
                //we need a rule to copy facts that are already in a relation into the adorned
 | 
					                //we need a rule to copy facts that are already in a relation into the adorned
 | 
				
			||||||
                //relation (since out intentional predicates can have facts, not only rules)
 | 
					                //relation (since out intentional predicates can have facts, not only rules)
 | 
				
			||||||
                create_transfer_rule(task);
 | 
					                create_transfer_rule(task, *result);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app * adn_goal_head = adorn_literal(goal_head, empty_var_idx_set);
 | 
					        app * adn_goal_head = adorn_literal(goal_head, empty_var_idx_set);
 | 
				
			||||||
        app * mag_goal_head = create_magic_literal(adn_goal_head);
 | 
					        app * mag_goal_head = create_magic_literal(adn_goal_head);
 | 
				
			||||||
        SASSERT(mag_goal_head->is_ground());
 | 
					        SASSERT(mag_goal_head->is_ground());
 | 
				
			||||||
        //SASSERT(is_fact(m_manager, mag_goal_head));
 | 
					 | 
				
			||||||
        //m_context.add_fact(mag_goal_head);
 | 
					 | 
				
			||||||
        rule * mag_goal_rule = m_context.get_rule_manager().mk(mag_goal_head, 0, 0, 0);
 | 
					        rule * mag_goal_rule = m_context.get_rule_manager().mk(mag_goal_head, 0, 0, 0);
 | 
				
			||||||
        m_rules.push_back(mag_goal_rule);
 | 
					        result->add_rule(mag_goal_rule);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rule * back_to_goal_rule = m_context.get_rule_manager().mk(goal_head, 1, &adn_goal_head, 0);
 | 
					        rule * back_to_goal_rule = m_context.get_rule_manager().mk(goal_head, 1, &adn_goal_head, 0);
 | 
				
			||||||
        m_rules.push_back(back_to_goal_rule);
 | 
					        result->add_rule(back_to_goal_rule);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        rule_set * result = static_cast<rule_set *>(0);
 | 
					 | 
				
			||||||
        result = alloc(rule_set, m_context);
 | 
					 | 
				
			||||||
        unsigned fin_rule_cnt = m_rules.size();
 | 
					 | 
				
			||||||
        for(unsigned i=0; i<fin_rule_cnt; i++) {
 | 
					 | 
				
			||||||
            result->add_rule(m_rules.get(i));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,11 @@ namespace datalog {
 | 
				
			||||||
            AD_BOUND
 | 
					            AD_BOUND
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct a_flag_hash {
 | 
				
			||||||
 | 
					            typedef a_flag data;
 | 
				
			||||||
 | 
					            unsigned operator()(a_flag x) const { return x; }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct adornment : public svector<a_flag> {
 | 
					        struct adornment : public svector<a_flag> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            void populate(app * lit, const var_idx_set & bound_vars);
 | 
					            void populate(app * lit, const var_idx_set & bound_vars);
 | 
				
			||||||
| 
						 | 
					@ -71,7 +76,7 @@ namespace datalog {
 | 
				
			||||||
                return m_pred==o.m_pred && m_adornment==o.m_adornment;
 | 
					                return m_pred==o.m_pred && m_adornment==o.m_adornment;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            unsigned hash() const {
 | 
					            unsigned hash() const {
 | 
				
			||||||
                return m_pred->hash()^int_vector_hash(m_adornment);
 | 
					                return m_pred->hash()^svector_hash<a_flag_hash>()(m_adornment);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,21 +93,21 @@ namespace datalog {
 | 
				
			||||||
        typedef obj_map<func_decl, adornment> pred_adornment_map;
 | 
					        typedef obj_map<func_decl, adornment> pred_adornment_map;
 | 
				
			||||||
        typedef obj_map<func_decl, func_decl *> pred2pred;
 | 
					        typedef obj_map<func_decl, func_decl *> pred2pred;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context &			m_context;
 | 
					        context &	       m_context;
 | 
				
			||||||
        ast_manager &       m_manager;
 | 
					        ast_manager &          m;
 | 
				
			||||||
        rule_ref_vector     m_rules;
 | 
					        rule_manager&          rm;
 | 
				
			||||||
        ast_ref_vector      m_pinned;
 | 
					        ast_ref_vector         m_pinned;
 | 
				
			||||||
        rule_ref            m_goal_rule;
 | 
					 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
           \brief Predicates from the original set that appear in a head of a rule
 | 
					           \brief Predicates from the original set that appear in a head of a rule
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        func_decl_set       m_extentional;
 | 
					        func_decl_set          m_extentional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //adornment_set m_processed;
 | 
					        //adornment_set m_processed;
 | 
				
			||||||
        vector<adornment_desc> m_todo;
 | 
					        vector<adornment_desc> m_todo;
 | 
				
			||||||
        adornment_map m_adorned_preds;
 | 
					        adornment_map          m_adorned_preds;
 | 
				
			||||||
        pred_adornment_map m_adornments;
 | 
					        pred_adornment_map     m_adornments;
 | 
				
			||||||
        pred2pred m_magic_preds;
 | 
					        pred2pred              m_magic_preds;
 | 
				
			||||||
 | 
					        func_decl_ref          m_goal;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        void reset();
 | 
					        void reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,16 +115,16 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int pop_bound(unsigned_vector & cont, rule * r, const var_idx_set & bound_vars);
 | 
					        int pop_bound(unsigned_vector & cont, rule * r, const var_idx_set & bound_vars);
 | 
				
			||||||
        app * create_magic_literal(app * l);
 | 
					        app * create_magic_literal(app * l);
 | 
				
			||||||
        void create_magic_rules(app * head, unsigned tail_cnt, app * const * tail, bool const* negated);
 | 
					        void create_magic_rules(app * head, unsigned tail_cnt, app * const * tail, bool const* negated, rule_set& result);
 | 
				
			||||||
        app * adorn_literal(app * lit, const var_idx_set & bound_vars);
 | 
					        app * adorn_literal(app * lit, const var_idx_set & bound_vars);
 | 
				
			||||||
        void transform_rule(const adornment & head_adornment,  rule * r);
 | 
					        void transform_rule(const adornment & head_adornment,  rule * r, rule_set& result);
 | 
				
			||||||
        void create_transfer_rule(const adornment_desc & d);
 | 
					        void create_transfer_rule(const adornment_desc & d, rule_set& result);
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
           \brief Create magic sets rule transformer for \c goal_rule. When applying the transformer,
 | 
					           \brief Create magic sets rule transformer for \c goal_rule. When applying the transformer,
 | 
				
			||||||
           the \c goal_rule must be present in the \c rule_set that is being transformed.
 | 
					           the \c goal_rule must be present in the \c rule_set that is being transformed.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        mk_magic_sets(context & ctx, rule * goal_rule);
 | 
					        mk_magic_sets(context & ctx, func_decl* goal);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        rule_set * operator()(rule_set const & source);
 | 
					        rule_set * operator()(rule_set const & source);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ Revision History:
 | 
				
			||||||
namespace datalog {
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool mk_partial_equivalence_transformer::is_symmetry(rule const* r) {
 | 
					    bool mk_partial_equivalence_transformer::is_symmetry(rule const* r) {
 | 
				
			||||||
        func_decl* p = r->get_head()->get_decl();
 | 
					        func_decl* p = r->get_decl();
 | 
				
			||||||
        return 
 | 
					        return 
 | 
				
			||||||
            p->get_arity() == 2 &&
 | 
					            p->get_arity() == 2 &&
 | 
				
			||||||
            p->get_domain(0) == p->get_domain(1) &&
 | 
					            p->get_domain(0) == p->get_domain(1) &&
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool mk_partial_equivalence_transformer::is_transitivity(rule const* r) {
 | 
					    bool mk_partial_equivalence_transformer::is_transitivity(rule const* r) {
 | 
				
			||||||
        func_decl* p = r->get_head()->get_decl();
 | 
					        func_decl* p = r->get_decl();
 | 
				
			||||||
        if (p->get_arity() != 2 ||
 | 
					        if (p->get_arity() != 2 ||
 | 
				
			||||||
            p->get_domain(0) != p->get_domain(1) ||
 | 
					            p->get_domain(0) != p->get_domain(1) ||
 | 
				
			||||||
            r->get_tail_size() != 2 ||
 | 
					            r->get_tail_size() != 2 ||
 | 
				
			||||||
| 
						 | 
					@ -144,6 +144,7 @@ namespace datalog {
 | 
				
			||||||
            dealloc(res);
 | 
					            dealloc(res);
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        res->inherit_predicates(source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,9 +147,10 @@ namespace datalog {
 | 
				
			||||||
    mk_quantifier_abstraction::~mk_quantifier_abstraction() {        
 | 
					    mk_quantifier_abstraction::~mk_quantifier_abstraction() {        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    func_decl* mk_quantifier_abstraction::declare_pred(func_decl* old_p) {
 | 
					    func_decl* mk_quantifier_abstraction::declare_pred(rule_set const& rules, rule_set& dst, func_decl* old_p) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (m_ctx.is_output_predicate(old_p)) {
 | 
					        if (rules.is_output_predicate(old_p)) {
 | 
				
			||||||
 | 
					            dst.inherit_predicate(rules, old_p, old_p);
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,8 +211,8 @@ namespace datalog {
 | 
				
			||||||
        return new_p;
 | 
					        return new_p;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app_ref mk_quantifier_abstraction::mk_head(app* p, unsigned idx) {
 | 
					    app_ref mk_quantifier_abstraction::mk_head(rule_set const& rules, rule_set& dst, app* p, unsigned idx) {
 | 
				
			||||||
        func_decl* new_p = declare_pred(p->get_decl());
 | 
					        func_decl* new_p = declare_pred(rules, dst, p->get_decl());
 | 
				
			||||||
        if (!new_p) {
 | 
					        if (!new_p) {
 | 
				
			||||||
            return app_ref(p, m);
 | 
					            return app_ref(p, m);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -239,9 +240,9 @@ namespace datalog {
 | 
				
			||||||
        return app_ref(m.mk_app(new_p, args.size(), args.c_ptr()), m);        
 | 
					        return app_ref(m.mk_app(new_p, args.size(), args.c_ptr()), m);        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app_ref mk_quantifier_abstraction::mk_tail(app* p) {
 | 
					    app_ref mk_quantifier_abstraction::mk_tail(rule_set const& rules, rule_set& dst, app* p) {
 | 
				
			||||||
        func_decl* old_p = p->get_decl();
 | 
					        func_decl* old_p = p->get_decl();
 | 
				
			||||||
        func_decl* new_p = declare_pred(old_p);
 | 
					        func_decl* new_p = declare_pred(rules, dst, old_p);
 | 
				
			||||||
        if (!new_p) {
 | 
					        if (!new_p) {
 | 
				
			||||||
            return app_ref(p, m);
 | 
					            return app_ref(p, m);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -332,18 +333,17 @@ namespace datalog {
 | 
				
			||||||
            unsigned utsz = r.get_uninterpreted_tail_size();
 | 
					            unsigned utsz = r.get_uninterpreted_tail_size();
 | 
				
			||||||
            unsigned tsz = r.get_tail_size();
 | 
					            unsigned tsz = r.get_tail_size();
 | 
				
			||||||
            for (unsigned j = 0; j < utsz; ++j) {
 | 
					            for (unsigned j = 0; j < utsz; ++j) {
 | 
				
			||||||
                tail.push_back(mk_tail(r.get_tail(j)));
 | 
					                tail.push_back(mk_tail(source, *result, r.get_tail(j)));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            for (unsigned j = utsz; j < tsz; ++j) {
 | 
					            for (unsigned j = utsz; j < tsz; ++j) {
 | 
				
			||||||
                tail.push_back(r.get_tail(j));
 | 
					                tail.push_back(r.get_tail(j));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            head = mk_head(r.get_head(), cnt);
 | 
					            head = mk_head(source, *result, r.get_head(), cnt);
 | 
				
			||||||
            fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), head);
 | 
					            fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), head);
 | 
				
			||||||
            rule_ref_vector added_rules(rm);
 | 
					            rule_ref_vector added_rules(rm);
 | 
				
			||||||
            proof_ref pr(m);
 | 
					            proof_ref pr(m);
 | 
				
			||||||
            rm.mk_rule(fml, pr, added_rules);
 | 
					            rm.mk_rule(fml, pr, *result);
 | 
				
			||||||
            result->add_rules(added_rules.size(), added_rules.c_ptr());
 | 
					            TRACE("dl", result->last()->display(m_ctx, tout););
 | 
				
			||||||
            TRACE("dl", added_rules.back()->display(m_ctx, tout););
 | 
					 | 
				
			||||||
        }        
 | 
					        }        
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // proof converter: proofs are not necessarily preserved using this transformation.
 | 
					        // proof converter: proofs are not necessarily preserved using this transformation.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,9 +43,9 @@ namespace datalog {
 | 
				
			||||||
        obj_map<func_decl, func_decl*> m_old2new;
 | 
					        obj_map<func_decl, func_decl*> m_old2new;
 | 
				
			||||||
        qa_model_converter*            m_mc;
 | 
					        qa_model_converter*            m_mc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        func_decl* declare_pred(func_decl* old_p);
 | 
					        func_decl* declare_pred(rule_set const& rules, rule_set& dst, func_decl* old_p);
 | 
				
			||||||
        app_ref mk_head(app* p, unsigned idx);
 | 
					        app_ref mk_head(rule_set const& rules, rule_set& dst, app* p, unsigned idx);
 | 
				
			||||||
        app_ref mk_tail(app* p);
 | 
					        app_ref mk_tail(rule_set const& rules, rule_set& dst, app* p);
 | 
				
			||||||
        expr*   mk_select(expr* a, unsigned num_args, expr* const* args);
 | 
					        expr*   mk_select(expr* a, unsigned num_args, expr* const* args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,20 +232,20 @@ namespace datalog {
 | 
				
			||||||
        fml = m.mk_implies(fml, r.get_head());
 | 
					        fml = m.mk_implies(fml, r.get_head());
 | 
				
			||||||
        TRACE("dl", r.display(m_ctx, tout); tout << mk_pp(fml, m) << "\n";);
 | 
					        TRACE("dl", r.display(m_ctx, tout); tout << mk_pp(fml, m) << "\n";);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        rule_ref_vector added_rules(rm);
 | 
					        rule_set added_rules(m_ctx);
 | 
				
			||||||
        proof_ref pr(m); 
 | 
					        proof_ref pr(m); 
 | 
				
			||||||
        rm.mk_rule(fml, pr, added_rules);
 | 
					        rm.mk_rule(fml, pr, added_rules);
 | 
				
			||||||
        if (r.get_proof()) {
 | 
					        if (r.get_proof()) {
 | 
				
			||||||
            // use def-axiom to encode that new rule is a weakening of the original.
 | 
					            // use def-axiom to encode that new rule is a weakening of the original.
 | 
				
			||||||
            proof* p1 = r.get_proof();
 | 
					            proof* p1 = r.get_proof();
 | 
				
			||||||
            for (unsigned i = 0; i < added_rules.size(); ++i) {
 | 
					            for (unsigned i = 0; i < added_rules.get_num_rules(); ++i) {
 | 
				
			||||||
                rule* r2 = added_rules[i].get();
 | 
					                rule* r2 = added_rules.get_rule(i);
 | 
				
			||||||
                r2->to_formula(fml);
 | 
					                r2->to_formula(fml);
 | 
				
			||||||
                pr = m.mk_modus_ponens(m.mk_def_axiom(m.mk_implies(m.get_fact(p1), fml)), p1);
 | 
					                pr = m.mk_modus_ponens(m.mk_def_axiom(m.mk_implies(m.get_fact(p1), fml)), p1);
 | 
				
			||||||
                r2->set_proof(m, pr);
 | 
					                r2->set_proof(m, pr);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        rules.add_rules(added_rules.size(), added_rules.c_ptr());
 | 
					        rules.add_rules(added_rules);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    rule_set * mk_quantifier_instantiation::operator()(rule_set const & source) {
 | 
					    rule_set * mk_quantifier_instantiation::operator()(rule_set const & source) {
 | 
				
			||||||
| 
						 | 
					@ -286,7 +286,10 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // model convertion: identity function.
 | 
					        // model convertion: identity function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!instantiated) {
 | 
					        if (instantiated) {
 | 
				
			||||||
 | 
					            result->inherit_predicates(source);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
            dealloc(result);
 | 
					            dealloc(result);
 | 
				
			||||||
            result = 0;
 | 
					            result = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,10 +230,10 @@ namespace datalog {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool mk_rule_inliner::inlining_allowed(func_decl * pred)
 | 
					    bool mk_rule_inliner::inlining_allowed(rule_set const& source, func_decl * pred)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (//these three conditions are important for soundness
 | 
					        if (//these three conditions are important for soundness
 | 
				
			||||||
            m_context.is_output_predicate(pred) ||
 | 
					            source.is_output_predicate(pred) ||
 | 
				
			||||||
            m_preds_with_facts.contains(pred) ||
 | 
					            m_preds_with_facts.contains(pred) ||
 | 
				
			||||||
            m_preds_with_neg_occurrence.contains(pred) ||
 | 
					            m_preds_with_neg_occurrence.contains(pred) ||
 | 
				
			||||||
            //this condition is used for breaking of cycles among inlined rules
 | 
					            //this condition is used for breaking of cycles among inlined rules
 | 
				
			||||||
| 
						 | 
					@ -260,7 +260,7 @@ namespace datalog {
 | 
				
			||||||
        unsigned rcnt = orig.get_num_rules();
 | 
					        unsigned rcnt = orig.get_num_rules();
 | 
				
			||||||
        for (unsigned i=0; i<rcnt; i++) {
 | 
					        for (unsigned i=0; i<rcnt; i++) {
 | 
				
			||||||
            rule * r = orig.get_rule(i);
 | 
					            rule * r = orig.get_rule(i);
 | 
				
			||||||
            if (inlining_allowed(r->get_decl())) {
 | 
					            if (inlining_allowed(orig, r->get_decl())) {
 | 
				
			||||||
                res->add_rule(r);
 | 
					                res->add_rule(r);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -324,7 +324,7 @@ namespace datalog {
 | 
				
			||||||
                unsigned pt_len = r->get_positive_tail_size();
 | 
					                unsigned pt_len = r->get_positive_tail_size();
 | 
				
			||||||
                for (unsigned ti = 0; ti<pt_len; ++ti) {
 | 
					                for (unsigned ti = 0; ti<pt_len; ++ti) {
 | 
				
			||||||
                    func_decl * tail_pred = r->get_decl(ti);
 | 
					                    func_decl * tail_pred = r->get_decl(ti);
 | 
				
			||||||
                    if (!inlining_allowed(tail_pred)) {
 | 
					                    if (!inlining_allowed(orig, tail_pred)) {
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    unsigned tail_pred_head_cnt = m_head_pred_ctr.get(tail_pred);
 | 
					                    unsigned tail_pred_head_cnt = m_head_pred_ctr.get(tail_pred);
 | 
				
			||||||
| 
						 | 
					@ -359,7 +359,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            func_decl * head_pred = r->get_decl();
 | 
					            func_decl * head_pred = r->get_decl();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (inlining_allowed(head_pred)) {
 | 
					            if (inlining_allowed(orig, head_pred)) {
 | 
				
			||||||
                //we have already processed inlined rules
 | 
					                //we have already processed inlined rules
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -368,7 +368,7 @@ namespace datalog {
 | 
				
			||||||
            unsigned pt_len = r->get_positive_tail_size();
 | 
					            unsigned pt_len = r->get_positive_tail_size();
 | 
				
			||||||
            for (unsigned ti = 0; ti<pt_len; ++ti) {
 | 
					            for (unsigned ti = 0; ti<pt_len; ++ti) {
 | 
				
			||||||
                func_decl * pred = r->get_decl(ti);
 | 
					                func_decl * pred = r->get_decl(ti);
 | 
				
			||||||
                if (!inlining_allowed(pred)) {
 | 
					                if (!inlining_allowed(orig, pred)) {
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (m_head_pred_ctr.get(pred)<=1) {
 | 
					                if (m_head_pred_ctr.get(pred)<=1) {
 | 
				
			||||||
| 
						 | 
					@ -417,14 +417,14 @@ namespace datalog {
 | 
				
			||||||
            const rule_vector& pred_rules = candidate_inlined_set->get_predicate_rules(pred);
 | 
					            const rule_vector& pred_rules = candidate_inlined_set->get_predicate_rules(pred);
 | 
				
			||||||
            rule_vector::const_iterator iend = pred_rules.end();
 | 
					            rule_vector::const_iterator iend = pred_rules.end();
 | 
				
			||||||
            for (rule_vector::const_iterator iit = pred_rules.begin(); iit!=iend; ++iit) {
 | 
					            for (rule_vector::const_iterator iit = pred_rules.begin(); iit!=iend; ++iit) {
 | 
				
			||||||
                transform_rule(*iit, m_inlined_rules);
 | 
					                transform_rule(orig, *iit, m_inlined_rules);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TRACE("dl", tout << "inlined rules after mutual inlining:\n" << m_inlined_rules;  );
 | 
					        TRACE("dl", tout << "inlined rules after mutual inlining:\n" << m_inlined_rules;  );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool mk_rule_inliner::transform_rule(rule * r0, rule_set& tgt) {
 | 
					    bool mk_rule_inliner::transform_rule(rule_set const& orig, rule * r0, rule_set& tgt) {
 | 
				
			||||||
        bool modified = false;
 | 
					        bool modified = false;
 | 
				
			||||||
        rule_ref_vector todo(m_rm);
 | 
					        rule_ref_vector todo(m_rm);
 | 
				
			||||||
        todo.push_back(r0);
 | 
					        todo.push_back(r0);
 | 
				
			||||||
| 
						 | 
					@ -436,7 +436,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            unsigned i = 0;
 | 
					            unsigned i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for  (; i < pt_len && !inlining_allowed(r->get_decl(i)); ++i) {};
 | 
					            for  (; i < pt_len && !inlining_allowed(orig, r->get_decl(i)); ++i) {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SASSERT(!has_quantifier(*r.get()));
 | 
					            SASSERT(!has_quantifier(*r.get()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -478,12 +478,12 @@ namespace datalog {
 | 
				
			||||||
            // this relation through inlining, 
 | 
					            // this relation through inlining, 
 | 
				
			||||||
            // so we don't add its rules to the result
 | 
					            // so we don't add its rules to the result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            something_done |= !inlining_allowed(pred) && transform_rule(r, tgt);
 | 
					            something_done |= !inlining_allowed(orig, pred) && transform_rule(orig, r, tgt);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (something_done && m_mc) {
 | 
					        if (something_done && m_mc) {
 | 
				
			||||||
            for (rule_set::iterator rit = orig.begin(); rit!=rend; ++rit) {
 | 
					            for (rule_set::iterator rit = orig.begin(); rit!=rend; ++rit) {
 | 
				
			||||||
                if (inlining_allowed((*rit)->get_decl())) {
 | 
					                if (inlining_allowed(orig, (*rit)->get_decl())) {
 | 
				
			||||||
                    datalog::del_rule(m_mc, **rit);
 | 
					                    datalog::del_rule(m_mc, **rit);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -505,9 +505,6 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned head_arity = head_pred->get_arity();
 | 
					        unsigned head_arity = head_pred->get_arity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //var_idx_set head_vars;
 | 
					 | 
				
			||||||
        //var_idx_set same_strat_vars;
 | 
					 | 
				
			||||||
        //collect_vars(m, r->get_head(), head_vars);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned pt_len = r->get_positive_tail_size();
 | 
					        unsigned pt_len = r->get_positive_tail_size();
 | 
				
			||||||
        for (unsigned ti=0; ti<pt_len; ++ti) {
 | 
					        for (unsigned ti=0; ti<pt_len; ++ti) {
 | 
				
			||||||
| 
						 | 
					@ -518,7 +515,6 @@ namespace datalog {
 | 
				
			||||||
            SASSERT(pred_strat<=head_strat);
 | 
					            SASSERT(pred_strat<=head_strat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (pred_strat==head_strat) {
 | 
					            if (pred_strat==head_strat) {
 | 
				
			||||||
                //collect_vars(m, r->get_head(), same_strat_vars);
 | 
					 | 
				
			||||||
                if (pred->get_arity()>head_arity
 | 
					                if (pred->get_arity()>head_arity
 | 
				
			||||||
                    || (pred->get_arity()==head_arity && pred->get_id()>=head_pred->get_id()) ) {
 | 
					                    || (pred->get_arity()==head_arity && pred->get_id()>=head_pred->get_id()) ) {
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
| 
						 | 
					@ -667,7 +663,7 @@ namespace datalog {
 | 
				
			||||||
        return et->get_data().m_value;
 | 
					        return et->get_data().m_value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_rule_inliner::add_rule(rule* r, unsigned i) {
 | 
					    void mk_rule_inliner::add_rule(rule_set const& source, rule* r, unsigned i) {
 | 
				
			||||||
        svector<bool>& can_remove = m_head_visitor.can_remove();
 | 
					        svector<bool>& can_remove = m_head_visitor.can_remove();
 | 
				
			||||||
        svector<bool>& can_expand = m_head_visitor.can_expand();
 | 
					        svector<bool>& can_expand = m_head_visitor.can_expand();
 | 
				
			||||||
        app* head = r->get_head();
 | 
					        app* head = r->get_head();
 | 
				
			||||||
| 
						 | 
					@ -676,7 +672,7 @@ namespace datalog {
 | 
				
			||||||
        m_head_index.insert(head);
 | 
					        m_head_index.insert(head);
 | 
				
			||||||
        m_pinned.push_back(r);
 | 
					        m_pinned.push_back(r);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        if (m_context.is_output_predicate(headd) ||
 | 
					        if (source.is_output_predicate(headd) ||
 | 
				
			||||||
            m_preds_with_facts.contains(headd)) {
 | 
					            m_preds_with_facts.contains(headd)) {
 | 
				
			||||||
            can_remove.set(i, false);
 | 
					            can_remove.set(i, false);
 | 
				
			||||||
            TRACE("dl", output_predicate(m_context, head, tout << "cannot remove: " << i << " "); tout << "\n";);
 | 
					            TRACE("dl", output_predicate(m_context, head, tout << "cannot remove: " << i << " "); tout << "\n";);
 | 
				
			||||||
| 
						 | 
					@ -692,7 +688,7 @@ namespace datalog {
 | 
				
			||||||
            tl_sz == 1
 | 
					            tl_sz == 1
 | 
				
			||||||
            && r->get_positive_tail_size() == 1 
 | 
					            && r->get_positive_tail_size() == 1 
 | 
				
			||||||
            && !m_preds_with_facts.contains(r->get_decl(0)) 
 | 
					            && !m_preds_with_facts.contains(r->get_decl(0)) 
 | 
				
			||||||
            && !m_context.is_output_predicate(r->get_decl(0));
 | 
					            && !source.is_output_predicate(r->get_decl(0));
 | 
				
			||||||
        can_expand.set(i, can_exp);
 | 
					        can_expand.set(i, can_exp);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -710,7 +706,6 @@ namespace datalog {
 | 
				
			||||||
#define PRT(_x_) ((_x_)?"T":"F")
 | 
					#define PRT(_x_) ((_x_)?"T":"F")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool mk_rule_inliner::inline_linear(scoped_ptr<rule_set>& rules) {
 | 
					    bool mk_rule_inliner::inline_linear(scoped_ptr<rule_set>& rules) {
 | 
				
			||||||
        scoped_ptr<rule_set> res = alloc(rule_set, m_context);
 | 
					 | 
				
			||||||
        bool done_something = false;        
 | 
					        bool done_something = false;        
 | 
				
			||||||
        unsigned sz = rules->get_num_rules();
 | 
					        unsigned sz = rules->get_num_rules();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -731,7 +726,7 @@ namespace datalog {
 | 
				
			||||||
        svector<bool>& can_expand = m_head_visitor.can_expand();
 | 
					        svector<bool>& can_expand = m_head_visitor.can_expand();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (unsigned i = 0; i < sz; ++i) {
 | 
					        for (unsigned i = 0; i < sz; ++i) {
 | 
				
			||||||
            add_rule(acc[i].get(), i);
 | 
					            add_rule(*rules, acc[i].get(), i);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // initialize substitution.
 | 
					        // initialize substitution.
 | 
				
			||||||
| 
						 | 
					@ -808,7 +803,7 @@ namespace datalog {
 | 
				
			||||||
                TRACE("dl", r->display(m_context, tout); r2->display(m_context, tout); rl_res->display(m_context, tout); );
 | 
					                TRACE("dl", r->display(m_context, tout); r2->display(m_context, tout); rl_res->display(m_context, tout); );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                del_rule(r, i);
 | 
					                del_rule(r, i);
 | 
				
			||||||
                add_rule(rl_res.get(), i);
 | 
					                add_rule(*rules, rl_res.get(), i);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                r = rl_res;
 | 
					                r = rl_res;
 | 
				
			||||||
| 
						 | 
					@ -828,13 +823,15 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (done_something) {
 | 
					        if (done_something) {
 | 
				
			||||||
            rules = alloc(rule_set, m_context);
 | 
					            scoped_ptr<rule_set> res = alloc(rule_set, m_context);
 | 
				
			||||||
            for (unsigned i = 0; i < sz; ++i) {
 | 
					            for (unsigned i = 0; i < sz; ++i) {
 | 
				
			||||||
                if (valid.get(i)) {
 | 
					                if (valid.get(i)) {
 | 
				
			||||||
                    rules->add_rule(acc[i].get());
 | 
					                    res->add_rule(acc[i].get());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            TRACE("dl", rules->display(tout););
 | 
					            res->inherit_predicates(*rules);
 | 
				
			||||||
 | 
					            TRACE("dl", res->display(tout););
 | 
				
			||||||
 | 
					            rules = res.detach();
 | 
				
			||||||
        }        
 | 
					        }        
 | 
				
			||||||
        return done_something;
 | 
					        return done_something;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -871,8 +868,14 @@ namespace datalog {
 | 
				
			||||||
            // try eager inlining
 | 
					            // try eager inlining
 | 
				
			||||||
            if (do_eager_inlining(res)) {
 | 
					            if (do_eager_inlining(res)) {
 | 
				
			||||||
                something_done = true;
 | 
					                something_done = true;
 | 
				
			||||||
            }
 | 
					            }            
 | 
				
			||||||
            TRACE("dl", res->display(tout << "after eager inlining\n"););
 | 
					            TRACE("dl", res->display(tout << "after eager inlining\n"););
 | 
				
			||||||
 | 
					        }    
 | 
				
			||||||
 | 
					        if (something_done) {
 | 
				
			||||||
 | 
					            res->inherit_predicates(source);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            res = alloc(rule_set, source);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (m_context.get_params().inline_linear() && inline_linear(res)) {
 | 
					        if (m_context.get_params().inline_linear() && inline_linear(res)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool try_to_inline_rule(rule& tgt, rule& src, unsigned tail_index, rule_ref& res);
 | 
					        bool try_to_inline_rule(rule& tgt, rule& src, unsigned tail_index, rule_ref& res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool inlining_allowed(func_decl * pred);
 | 
					        bool inlining_allowed(rule_set const& orig, func_decl * pred);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void count_pred_occurrences(rule_set const & orig);
 | 
					        void count_pred_occurrences(rule_set const & orig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,7 +143,7 @@ namespace datalog {
 | 
				
			||||||
        bool forbid_multiple_multipliers(const rule_set & orig, rule_set const & proposed_inlined_rules);
 | 
					        bool forbid_multiple_multipliers(const rule_set & orig, rule_set const & proposed_inlined_rules);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /** Return true if the rule was modified */
 | 
					        /** Return true if the rule was modified */
 | 
				
			||||||
        bool transform_rule(rule * r, rule_set& tgt);
 | 
					        bool transform_rule(rule_set const& orig, rule * r, rule_set& tgt);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /** Return true if some transformation was performed */
 | 
					        /** Return true if some transformation was performed */
 | 
				
			||||||
        bool transform_rules(const rule_set & orig, rule_set & tgt);
 | 
					        bool transform_rules(const rule_set & orig, rule_set & tgt);
 | 
				
			||||||
| 
						 | 
					@ -174,7 +174,7 @@ namespace datalog {
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        bool inline_linear(scoped_ptr<rule_set>& rules);
 | 
					        bool inline_linear(scoped_ptr<rule_set>& rules);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void add_rule(rule* r, unsigned i);
 | 
					        void add_rule(rule_set const& rule_set, rule* r, unsigned i);
 | 
				
			||||||
        void del_rule(rule* r, unsigned i);
 | 
					        void del_rule(rule* r, unsigned i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,16 +23,17 @@ Revision History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace datalog {
 | 
					namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk_similarity_compressor::mk_similarity_compressor(context & ctx, unsigned threshold_count) :
 | 
					    mk_similarity_compressor::mk_similarity_compressor(context & ctx) :
 | 
				
			||||||
            plugin(5000),
 | 
					        plugin(5000),
 | 
				
			||||||
            m_context(ctx),
 | 
					        m_context(ctx),
 | 
				
			||||||
            m_manager(ctx.get_manager()),
 | 
					        m_manager(ctx.get_manager()),
 | 
				
			||||||
            m_threshold_count(threshold_count),
 | 
					        m_threshold_count(ctx.similarity_compressor_threshold()),
 | 
				
			||||||
            m_result_rules(ctx.get_rule_manager()),
 | 
					        m_result_rules(ctx.get_rule_manager()),
 | 
				
			||||||
            m_pinned(m_manager) {
 | 
					        m_modified(false),
 | 
				
			||||||
        SASSERT(threshold_count>1);
 | 
					        m_pinned(m_manager) {
 | 
				
			||||||
 | 
					        SASSERT(m_threshold_count>1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    void mk_similarity_compressor::reset() {
 | 
					    void mk_similarity_compressor::reset() {
 | 
				
			||||||
        m_rules.reset();
 | 
					        m_rules.reset();
 | 
				
			||||||
        m_result_rules.reset();
 | 
					        m_result_rules.reset();
 | 
				
			||||||
| 
						 | 
					@ -43,10 +44,10 @@ namespace datalog {
 | 
				
			||||||
       Allows to traverse head and positive tails in a single for loop starting from -1
 | 
					       Allows to traverse head and positive tails in a single for loop starting from -1
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static app * get_by_tail_index(rule * r, int idx) {
 | 
					    static app * get_by_tail_index(rule * r, int idx) {
 | 
				
			||||||
        if(idx==-1) {
 | 
					        if (idx < 0) {
 | 
				
			||||||
            return r->get_head();
 | 
					            return r->get_head();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        SASSERT(idx<static_cast<int>(r->get_positive_tail_size()));
 | 
					        SASSERT(idx < static_cast<int>(r->get_positive_tail_size()));
 | 
				
			||||||
        return r->get_tail(idx);
 | 
					        return r->get_tail(idx);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,19 +56,25 @@ namespace datalog {
 | 
				
			||||||
        return (a>b) ? 1 : ( (a==b) ? 0 : -1);
 | 
					        return (a>b) ? 1 : ( (a==b) ? 0 : -1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename T>
 | 
				
			||||||
 | 
					    static int aux_compare(T* a, T* b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static int compare_var_args(app* t1, app* t2) {
 | 
					    static int compare_var_args(app* t1, app* t2) {
 | 
				
			||||||
        SASSERT(t1->get_num_args()==t2->get_num_args());
 | 
					        SASSERT(t1->get_num_args()==t2->get_num_args());
 | 
				
			||||||
        int res;
 | 
					        int res;
 | 
				
			||||||
        unsigned n = t1->get_num_args();
 | 
					        unsigned n = t1->get_num_args();
 | 
				
			||||||
        for(unsigned i=0; i<n; i++) {
 | 
					        for (unsigned i = 0; i < n; i++) {
 | 
				
			||||||
            expr * a1 = t1->get_arg(i);
 | 
					            expr * a1 = t1->get_arg(i);
 | 
				
			||||||
            expr * a2 = t2->get_arg(i);
 | 
					            expr * a2 = t2->get_arg(i);
 | 
				
			||||||
 | 
					 | 
				
			||||||
            res = aux_compare(is_var(a1), is_var(a2));
 | 
					            res = aux_compare(is_var(a1), is_var(a2));
 | 
				
			||||||
            if(res!=0) { return res; }
 | 
					            if (res != 0) { 
 | 
				
			||||||
            if(is_var(a1)) {
 | 
					                return res; 
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (is_var(a1)) {
 | 
				
			||||||
                res = aux_compare(to_var(a1)->get_idx(), to_var(a2)->get_idx());
 | 
					                res = aux_compare(to_var(a1)->get_idx(), to_var(a2)->get_idx());
 | 
				
			||||||
                if(res!=0) { return res; }
 | 
					                if (res != 0) { 
 | 
				
			||||||
 | 
					                    return res; 
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
| 
						 | 
					@ -77,16 +84,16 @@ namespace datalog {
 | 
				
			||||||
        SASSERT(t1->get_num_args()==t2->get_num_args());
 | 
					        SASSERT(t1->get_num_args()==t2->get_num_args());
 | 
				
			||||||
        int res;
 | 
					        int res;
 | 
				
			||||||
        unsigned n = t1->get_num_args();
 | 
					        unsigned n = t1->get_num_args();
 | 
				
			||||||
        for(unsigned i=0; i<n; i++) {
 | 
					        for (unsigned i=0; i<n; i++) {
 | 
				
			||||||
            if(is_var(t1->get_arg(i))) {
 | 
					            if (is_var(t1->get_arg(i))) {
 | 
				
			||||||
                SASSERT(t1->get_arg(i)==t2->get_arg(i));
 | 
					                SASSERT(t1->get_arg(i) == t2->get_arg(i));
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if((skip_countdown--)==0) {
 | 
					            if ((skip_countdown--) == 0) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            res = aux_compare(t1->get_arg(i), t2->get_arg(i));
 | 
					            res = aux_compare(t1->get_arg(i)->get_id(), t2->get_arg(i)->get_id());
 | 
				
			||||||
            if(res!=0) { return res; }
 | 
					            if (res!=0) { return res; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -100,26 +107,26 @@ namespace datalog {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static int rough_compare(rule * r1, rule * r2) {
 | 
					    static int rough_compare(rule * r1, rule * r2) {
 | 
				
			||||||
        int res = aux_compare(r1->get_tail_size(), r2->get_tail_size());
 | 
					        int res = aux_compare(r1->get_tail_size(), r2->get_tail_size());
 | 
				
			||||||
        if(res!=0) { return res; }
 | 
					        if (res!=0) { return res; }
 | 
				
			||||||
        res = aux_compare(r1->get_uninterpreted_tail_size(), r2->get_uninterpreted_tail_size());
 | 
					        res = aux_compare(r1->get_uninterpreted_tail_size(), r2->get_uninterpreted_tail_size());
 | 
				
			||||||
        if(res!=0) { return res; }
 | 
					        if (res!=0) { return res; }
 | 
				
			||||||
        res = aux_compare(r1->get_positive_tail_size(), r2->get_positive_tail_size());
 | 
					        res = aux_compare(r1->get_positive_tail_size(), r2->get_positive_tail_size());
 | 
				
			||||||
        if(res!=0) { return res; }
 | 
					        if (res!=0) { return res; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int pos_tail_sz = r1->get_positive_tail_size();
 | 
					        int pos_tail_sz = r1->get_positive_tail_size();
 | 
				
			||||||
        for(int i=-1; i<pos_tail_sz; i++) {
 | 
					        for (int i=-1; i<pos_tail_sz; i++) {
 | 
				
			||||||
            app * t1 = get_by_tail_index(r1, i);
 | 
					            app * t1 = get_by_tail_index(r1, i);
 | 
				
			||||||
            app * t2 = get_by_tail_index(r2, i);
 | 
					            app * t2 = get_by_tail_index(r2, i);
 | 
				
			||||||
            res = aux_compare(t1->get_decl(), t2->get_decl());
 | 
					            res = aux_compare(t1->get_decl()->get_id(), t2->get_decl()->get_id());
 | 
				
			||||||
            if(res!=0) { return res; }
 | 
					            if (res!=0) { return res; }
 | 
				
			||||||
            res = compare_var_args(t1, t2);
 | 
					            res = compare_var_args(t1, t2);
 | 
				
			||||||
            if(res!=0) { return res; }
 | 
					            if (res!=0) { return res; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned tail_sz = r1->get_tail_size();
 | 
					        unsigned tail_sz = r1->get_tail_size();
 | 
				
			||||||
        for(unsigned i=pos_tail_sz; i<tail_sz; i++) {
 | 
					        for (unsigned i=pos_tail_sz; i<tail_sz; i++) {
 | 
				
			||||||
            res = aux_compare(r1->get_tail(i), r2->get_tail(i));
 | 
					            res = aux_compare(r1->get_tail(i)->get_id(), r2->get_tail(i)->get_id());
 | 
				
			||||||
            if(res!=0) { return res; }
 | 
					            if (res!=0) { return res; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
| 
						 | 
					@ -132,9 +139,9 @@ namespace datalog {
 | 
				
			||||||
    static int total_compare(rule * r1, rule * r2, int skipped_arg_index = INT_MAX) {
 | 
					    static int total_compare(rule * r1, rule * r2, int skipped_arg_index = INT_MAX) {
 | 
				
			||||||
        SASSERT(rough_compare(r1, r2)==0);
 | 
					        SASSERT(rough_compare(r1, r2)==0);
 | 
				
			||||||
        int pos_tail_sz = r1->get_positive_tail_size();
 | 
					        int pos_tail_sz = r1->get_positive_tail_size();
 | 
				
			||||||
        for(int i=-1; i<pos_tail_sz; i++) {
 | 
					        for (int i=-1; i<pos_tail_sz; i++) {
 | 
				
			||||||
            int res = compare_args(get_by_tail_index(r1, i), get_by_tail_index(r2, i), skipped_arg_index);
 | 
					            int res = compare_args(get_by_tail_index(r1, i), get_by_tail_index(r2, i), skipped_arg_index);
 | 
				
			||||||
            if(res!=0) { return res; }
 | 
					            if (res!=0) { return res; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -167,8 +174,8 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static void collect_const_indexes(app * t, int tail_index, info_vector & res) {
 | 
					    static void collect_const_indexes(app * t, int tail_index, info_vector & res) {
 | 
				
			||||||
        unsigned n = t->get_num_args();
 | 
					        unsigned n = t->get_num_args();
 | 
				
			||||||
        for(unsigned i=0; i<n; i++) {
 | 
					        for (unsigned i=0; i<n; i++) {
 | 
				
			||||||
            if(is_var(t->get_arg(i))) {
 | 
					            if (is_var(t->get_arg(i))) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            res.push_back(const_info(tail_index, i));
 | 
					            res.push_back(const_info(tail_index, i));
 | 
				
			||||||
| 
						 | 
					@ -178,7 +185,7 @@ namespace datalog {
 | 
				
			||||||
    static void collect_const_indexes(rule * r, info_vector & res) {
 | 
					    static void collect_const_indexes(rule * r, info_vector & res) {
 | 
				
			||||||
        collect_const_indexes(r->get_head(), -1, res);
 | 
					        collect_const_indexes(r->get_head(), -1, res);
 | 
				
			||||||
        unsigned pos_tail_sz = r->get_positive_tail_size();
 | 
					        unsigned pos_tail_sz = r->get_positive_tail_size();
 | 
				
			||||||
        for(unsigned i=0; i<pos_tail_sz; i++) {
 | 
					        for (unsigned i=0; i<pos_tail_sz; i++) {
 | 
				
			||||||
            collect_const_indexes(r->get_tail(i), i, res);
 | 
					            collect_const_indexes(r->get_tail(i), i, res);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -187,9 +194,9 @@ namespace datalog {
 | 
				
			||||||
    static void collect_orphan_consts(rule * r, const info_vector & const_infos, T & tgt) {
 | 
					    static void collect_orphan_consts(rule * r, const info_vector & const_infos, T & tgt) {
 | 
				
			||||||
        unsigned const_cnt = const_infos.size();
 | 
					        unsigned const_cnt = const_infos.size();
 | 
				
			||||||
        tgt.reset();
 | 
					        tgt.reset();
 | 
				
			||||||
        for(unsigned i=0; i<const_cnt; i++) {
 | 
					        for (unsigned i=0; i<const_cnt; i++) {
 | 
				
			||||||
            const_info inf = const_infos[i];
 | 
					            const_info inf = const_infos[i];
 | 
				
			||||||
            if(inf.has_parent()) {
 | 
					            if (inf.has_parent()) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            app * pred = get_by_tail_index(r, inf.tail_index());
 | 
					            app * pred = get_by_tail_index(r, inf.tail_index());
 | 
				
			||||||
| 
						 | 
					@ -201,9 +208,9 @@ namespace datalog {
 | 
				
			||||||
    static void collect_orphan_sorts(rule * r, const info_vector & const_infos, T & tgt) {
 | 
					    static void collect_orphan_sorts(rule * r, const info_vector & const_infos, T & tgt) {
 | 
				
			||||||
        unsigned const_cnt = const_infos.size();
 | 
					        unsigned const_cnt = const_infos.size();
 | 
				
			||||||
        tgt.reset();
 | 
					        tgt.reset();
 | 
				
			||||||
        for(unsigned i=0; i<const_cnt; i++) {
 | 
					        for (unsigned i=0; i<const_cnt; i++) {
 | 
				
			||||||
            const_info inf = const_infos[i];
 | 
					            const_info inf = const_infos[i];
 | 
				
			||||||
            if(inf.has_parent()) {
 | 
					            if (inf.has_parent()) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            app * pred = get_by_tail_index(r, inf.tail_index());
 | 
					            app * pred = get_by_tail_index(r, inf.tail_index());
 | 
				
			||||||
| 
						 | 
					@ -224,25 +231,25 @@ namespace datalog {
 | 
				
			||||||
        collect_orphan_consts(r, const_infos, vals);
 | 
					        collect_orphan_consts(r, const_infos, vals);
 | 
				
			||||||
        SASSERT(vals.size()==const_cnt);
 | 
					        SASSERT(vals.size()==const_cnt);
 | 
				
			||||||
        rule_vector::iterator it = first;
 | 
					        rule_vector::iterator it = first;
 | 
				
			||||||
        for(; it!=after_last; ++it) {
 | 
					        for (; it!=after_last; ++it) {
 | 
				
			||||||
            for(unsigned i=0; i<const_cnt; i++) {
 | 
					            for (unsigned i=0; i<const_cnt; i++) {
 | 
				
			||||||
                app * pred = get_by_tail_index(*it, const_infos[i].tail_index());
 | 
					                app * pred = get_by_tail_index(*it, const_infos[i].tail_index());
 | 
				
			||||||
                app * val = to_app(pred->get_arg(const_infos[i].arg_index()));
 | 
					                app * val = to_app(pred->get_arg(const_infos[i].arg_index()));
 | 
				
			||||||
                if(vals[i]!=val) {
 | 
					                if (vals[i]!=val) {
 | 
				
			||||||
                    vals[i] = 0;
 | 
					                    vals[i] = 0;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        unsigned removed_cnt = 0;
 | 
					        unsigned removed_cnt = 0;
 | 
				
			||||||
        for(unsigned i=0; i<const_cnt; i++) {
 | 
					        for (unsigned i=0; i<const_cnt; i++) {
 | 
				
			||||||
            if(vals[i]!=0) {
 | 
					            if (vals[i]!=0) {
 | 
				
			||||||
                removed_cnt++;
 | 
					                removed_cnt++;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if(removed_cnt!=0) {
 | 
					            else if (removed_cnt!=0) {
 | 
				
			||||||
                const_infos[i-removed_cnt] = const_infos[i];
 | 
					                const_infos[i-removed_cnt] = const_infos[i];
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(removed_cnt!=0) {
 | 
					        if (removed_cnt!=0) {
 | 
				
			||||||
            const_infos.shrink(const_cnt-removed_cnt);
 | 
					            const_infos.shrink(const_cnt-removed_cnt);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -263,21 +270,21 @@ namespace datalog {
 | 
				
			||||||
        collect_orphan_sorts(r, const_infos, sorts);
 | 
					        collect_orphan_sorts(r, const_infos, sorts);
 | 
				
			||||||
        SASSERT(vals.size()==const_cnt);
 | 
					        SASSERT(vals.size()==const_cnt);
 | 
				
			||||||
        vector<unsigned_vector> possible_parents(const_cnt);
 | 
					        vector<unsigned_vector> possible_parents(const_cnt);
 | 
				
			||||||
        for(unsigned i=1; i<const_cnt; i++) {
 | 
					        for (unsigned i=1; i<const_cnt; i++) {
 | 
				
			||||||
            for(unsigned j=0; j<i; j++) {
 | 
					            for (unsigned j=0; j<i; j++) {
 | 
				
			||||||
                if(vals[i]==vals[j] && sorts[i]==sorts[j]) {
 | 
					                if (vals[i]==vals[j] && sorts[i]==sorts[j]) {
 | 
				
			||||||
                    possible_parents[i].push_back(j);
 | 
					                    possible_parents[i].push_back(j);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        rule_vector::iterator it = first;
 | 
					        rule_vector::iterator it = first;
 | 
				
			||||||
        for(; it!=after_last; ++it) {
 | 
					        for (; it!=after_last; ++it) {
 | 
				
			||||||
            collect_orphan_consts(*it, const_infos, vals);
 | 
					            collect_orphan_consts(*it, const_infos, vals);
 | 
				
			||||||
            for(unsigned i=1; i<const_cnt; i++) {
 | 
					            for (unsigned i=1; i<const_cnt; i++) {
 | 
				
			||||||
                unsigned_vector & ppars = possible_parents[i];
 | 
					                unsigned_vector & ppars = possible_parents[i];
 | 
				
			||||||
                unsigned j=0;
 | 
					                unsigned j=0;
 | 
				
			||||||
                while(j<ppars.size()) {
 | 
					                while(j<ppars.size()) {
 | 
				
			||||||
                    if(vals[i]!=vals[ppars[j]]) {
 | 
					                    if (vals[i]!=vals[ppars[j]]) {
 | 
				
			||||||
                        ppars[j] = ppars.back();
 | 
					                        ppars[j] = ppars.back();
 | 
				
			||||||
                        ppars.pop_back();
 | 
					                        ppars.pop_back();
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -287,16 +294,16 @@ namespace datalog {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        for(unsigned i=0; i<const_cnt; i++) {
 | 
					        for (unsigned i=0; i<const_cnt; i++) {
 | 
				
			||||||
            unsigned parent = i;
 | 
					            unsigned parent = i;
 | 
				
			||||||
            unsigned_vector & ppars = possible_parents[i];
 | 
					            unsigned_vector & ppars = possible_parents[i];
 | 
				
			||||||
            unsigned ppars_sz = ppars.size();
 | 
					            unsigned ppars_sz = ppars.size();
 | 
				
			||||||
            for(unsigned j=0; j<ppars_sz; j++) {
 | 
					            for (unsigned j=0; j<ppars_sz; j++) {
 | 
				
			||||||
                if(ppars[j]<parent) {
 | 
					                if (ppars[j]<parent) {
 | 
				
			||||||
                    parent = ppars[j];
 | 
					                    parent = ppars[j];
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if(parent!=i) {
 | 
					            if (parent!=i) {
 | 
				
			||||||
                const_infos[i].set_parent_index(parent);
 | 
					                const_infos[i].set_parent_index(parent);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -305,7 +312,7 @@ namespace datalog {
 | 
				
			||||||
    static unsigned get_constant_count(rule * r) {
 | 
					    static unsigned get_constant_count(rule * r) {
 | 
				
			||||||
        unsigned res = r->get_head()->get_num_args() - count_variable_arguments(r->get_head());
 | 
					        unsigned res = r->get_head()->get_num_args() - count_variable_arguments(r->get_head());
 | 
				
			||||||
        unsigned pos_tail_sz = r->get_positive_tail_size();
 | 
					        unsigned pos_tail_sz = r->get_positive_tail_size();
 | 
				
			||||||
        for(unsigned i=0; i<pos_tail_sz; i++) {
 | 
					        for (unsigned i=0; i<pos_tail_sz; i++) {
 | 
				
			||||||
            res+= r->get_tail(i)->get_num_args() - count_variable_arguments(r->get_tail(i));
 | 
					            res+= r->get_tail(i)->get_num_args() - count_variable_arguments(r->get_tail(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
| 
						 | 
					@ -313,7 +320,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static bool initial_comparator(rule * r1, rule * r2) {
 | 
					    static bool initial_comparator(rule * r1, rule * r2) {
 | 
				
			||||||
        int res = rough_compare(r1, r2);
 | 
					        int res = rough_compare(r1, r2);
 | 
				
			||||||
        if(res!=0) { return res>0; }
 | 
					        if (res!=0) { return res>0; }
 | 
				
			||||||
        return total_compare(r1, r2)>0;
 | 
					        return total_compare(r1, r2)>0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -348,7 +355,7 @@ namespace datalog {
 | 
				
			||||||
        ptr_vector<sort> aux_domain;
 | 
					        ptr_vector<sort> aux_domain;
 | 
				
			||||||
        collect_orphan_sorts(r, const_infos, aux_domain);
 | 
					        collect_orphan_sorts(r, const_infos, aux_domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        func_decl* head_pred = r->get_head()->get_decl();
 | 
					        func_decl* head_pred = r->get_decl();
 | 
				
			||||||
        symbol const& name_prefix = head_pred->get_name();
 | 
					        symbol const& name_prefix = head_pred->get_name();
 | 
				
			||||||
        std::string name_suffix = "sc_" + to_string(const_cnt);
 | 
					        std::string name_suffix = "sc_" + to_string(const_cnt);
 | 
				
			||||||
        func_decl * aux_pred = m_context.mk_fresh_head_predicate(name_prefix, symbol(name_suffix.c_str()), 
 | 
					        func_decl * aux_pred = m_context.mk_fresh_head_predicate(name_prefix, symbol(name_suffix.c_str()), 
 | 
				
			||||||
| 
						 | 
					@ -357,7 +364,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        relation_fact val_fact(m_manager, const_cnt);
 | 
					        relation_fact val_fact(m_manager, const_cnt);
 | 
				
			||||||
        rule_vector::iterator it = first;
 | 
					        rule_vector::iterator it = first;
 | 
				
			||||||
        for(; it!=after_last; ++it) {
 | 
					        for (; it!=after_last; ++it) {
 | 
				
			||||||
            collect_orphan_consts(*it, const_infos, val_fact);
 | 
					            collect_orphan_consts(*it, const_infos, val_fact);
 | 
				
			||||||
            m_context.add_fact(aux_pred, val_fact);
 | 
					            m_context.add_fact(aux_pred, val_fact);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -367,7 +374,7 @@ namespace datalog {
 | 
				
			||||||
        ptr_vector<app> new_tail;
 | 
					        ptr_vector<app> new_tail;
 | 
				
			||||||
        svector<bool> new_negs;
 | 
					        svector<bool> new_negs;
 | 
				
			||||||
        unsigned tail_sz = r->get_tail_size();
 | 
					        unsigned tail_sz = r->get_tail_size();
 | 
				
			||||||
        for(unsigned i=0; i<tail_sz; i++) {
 | 
					        for (unsigned i=0; i<tail_sz; i++) {
 | 
				
			||||||
            new_tail.push_back(r->get_tail(i));
 | 
					            new_tail.push_back(r->get_tail(i));
 | 
				
			||||||
            new_negs.push_back(r->is_neg_tail(i));
 | 
					            new_negs.push_back(r->is_neg_tail(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -375,7 +382,7 @@ namespace datalog {
 | 
				
			||||||
        rule_counter ctr;
 | 
					        rule_counter ctr;
 | 
				
			||||||
        ctr.count_rule_vars(m_manager, r);
 | 
					        ctr.count_rule_vars(m_manager, r);
 | 
				
			||||||
        unsigned max_var_idx, new_var_idx_base;
 | 
					        unsigned max_var_idx, new_var_idx_base;
 | 
				
			||||||
        if(ctr.get_max_positive(max_var_idx)) {
 | 
					        if (ctr.get_max_positive(max_var_idx)) {
 | 
				
			||||||
            new_var_idx_base = max_var_idx+1;
 | 
					            new_var_idx_base = max_var_idx+1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
| 
						 | 
					@ -387,15 +394,15 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned aux_column_index = 0;
 | 
					        unsigned aux_column_index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for(unsigned i=0; i<const_cnt; ) {
 | 
					        for (unsigned i=0; i<const_cnt; ) {
 | 
				
			||||||
            int tail_idx = const_infos[i].tail_index();
 | 
					            int tail_idx = const_infos[i].tail_index();
 | 
				
			||||||
            app * & mod_tail = (tail_idx==-1) ? new_head : new_tail[tail_idx];
 | 
					            app * & mod_tail = (tail_idx==-1) ? new_head : new_tail[tail_idx];
 | 
				
			||||||
            ptr_vector<expr> mod_args(mod_tail->get_num_args(), mod_tail->get_args());
 | 
					            ptr_vector<expr> mod_args(mod_tail->get_num_args(), mod_tail->get_args());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for(; i<const_cnt && const_infos[i].tail_index()==tail_idx; i++) { //here the outer loop counter is modified
 | 
					            for (; i<const_cnt && const_infos[i].tail_index()==tail_idx; i++) { //here the outer loop counter is modified
 | 
				
			||||||
                const_info & inf = const_infos[i];
 | 
					                const_info & inf = const_infos[i];
 | 
				
			||||||
                var * mod_var;
 | 
					                var * mod_var;
 | 
				
			||||||
                if(!inf.has_parent()) {
 | 
					                if (!inf.has_parent()) {
 | 
				
			||||||
                    mod_var = m_manager.mk_var(new_var_idx_base+aux_column_index, 
 | 
					                    mod_var = m_manager.mk_var(new_var_idx_base+aux_column_index, 
 | 
				
			||||||
                        aux_domain[aux_column_index]);
 | 
					                        aux_domain[aux_column_index]);
 | 
				
			||||||
                    aux_column_index++;
 | 
					                    aux_column_index++;
 | 
				
			||||||
| 
						 | 
					@ -426,7 +433,7 @@ namespace datalog {
 | 
				
			||||||
        m_modified = true;
 | 
					        m_modified = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void mk_similarity_compressor::process_class(rule_vector::iterator first, 
 | 
					    void mk_similarity_compressor::process_class(rule_set const& source, rule_vector::iterator first, 
 | 
				
			||||||
            rule_vector::iterator after_last) {
 | 
					            rule_vector::iterator after_last) {
 | 
				
			||||||
        SASSERT(first!=after_last);
 | 
					        SASSERT(first!=after_last);
 | 
				
			||||||
        //remove duplicates
 | 
					        //remove duplicates
 | 
				
			||||||
| 
						 | 
					@ -435,7 +442,7 @@ namespace datalog {
 | 
				
			||||||
            rule_vector::iterator prev = it;
 | 
					            rule_vector::iterator prev = it;
 | 
				
			||||||
            ++it;
 | 
					            ++it;
 | 
				
			||||||
            while(it!=after_last) {
 | 
					            while(it!=after_last) {
 | 
				
			||||||
                if(it!=after_last && total_compare(*prev, *it)==0) {
 | 
					                if (it!=after_last && total_compare(*prev, *it)==0) {
 | 
				
			||||||
                    --after_last;
 | 
					                    --after_last;
 | 
				
			||||||
                    std::swap(*it, *after_last);
 | 
					                    std::swap(*it, *after_last);
 | 
				
			||||||
                    m_modified = true;
 | 
					                    m_modified = true;
 | 
				
			||||||
| 
						 | 
					@ -450,7 +457,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned const_cnt = get_constant_count(*first);
 | 
					        unsigned const_cnt = get_constant_count(*first);
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
        for(unsigned ignored_index=0; ignored_index<const_cnt; ignored_index++) {
 | 
					        for (unsigned ignored_index=0; ignored_index<const_cnt; ignored_index++) {
 | 
				
			||||||
            arg_ignoring_comparator comparator(ignored_index);
 | 
					            arg_ignoring_comparator comparator(ignored_index);
 | 
				
			||||||
            std::sort(first, after_last, comparator);
 | 
					            std::sort(first, after_last, comparator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -461,11 +468,11 @@ namespace datalog {
 | 
				
			||||||
                rule_vector::iterator prev = it;
 | 
					                rule_vector::iterator prev = it;
 | 
				
			||||||
                ++it;
 | 
					                ++it;
 | 
				
			||||||
                grp_size++;
 | 
					                grp_size++;
 | 
				
			||||||
                if(it==after_last || !comparator.eq(*prev, *it)) {
 | 
					                if (it==after_last || !comparator.eq(*prev, *it)) {
 | 
				
			||||||
                    if(grp_size>m_threshold_count) {
 | 
					                    if (grp_size>m_threshold_count) {
 | 
				
			||||||
                        merge_class(grp_begin, it);
 | 
					                        merge_class(grp_begin, it);
 | 
				
			||||||
                        //group was processed, so we remove it from the class
 | 
					                        //group was processed, so we remove it from the class
 | 
				
			||||||
                        if(it==after_last) {
 | 
					                        if (it==after_last) {
 | 
				
			||||||
                            after_last=grp_begin;
 | 
					                            after_last=grp_begin;
 | 
				
			||||||
                            it=after_last;
 | 
					                            it=after_last;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -484,9 +491,9 @@ namespace datalog {
 | 
				
			||||||
        //TODO: compress also rules with pairs (or tuples) of equal constants
 | 
					        //TODO: compress also rules with pairs (or tuples) of equal constants
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 1
 | 
					#if 1
 | 
				
			||||||
        if(const_cnt>0) {
 | 
					        if (const_cnt>0 && !source.is_output_predicate((*first)->get_decl())) {
 | 
				
			||||||
            unsigned rule_cnt = static_cast<unsigned>(after_last-first);
 | 
					            unsigned rule_cnt = static_cast<unsigned>(after_last-first);
 | 
				
			||||||
            if(rule_cnt>m_threshold_count) {
 | 
					            if (rule_cnt>m_threshold_count) {
 | 
				
			||||||
                merge_class(first, after_last);
 | 
					                merge_class(first, after_last);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -495,7 +502,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //put rules which weren't merged into result
 | 
					        //put rules which weren't merged into result
 | 
				
			||||||
        rule_vector::iterator it = first;
 | 
					        rule_vector::iterator it = first;
 | 
				
			||||||
        for(; it!=after_last; ++it) {
 | 
					        for (; it!=after_last; ++it) {
 | 
				
			||||||
            m_result_rules.push_back(*it);
 | 
					            m_result_rules.push_back(*it);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -505,7 +512,7 @@ namespace datalog {
 | 
				
			||||||
        m_modified = false;
 | 
					        m_modified = false;
 | 
				
			||||||
        unsigned init_rule_cnt = source.get_num_rules();
 | 
					        unsigned init_rule_cnt = source.get_num_rules();
 | 
				
			||||||
        SASSERT(m_rules.empty());
 | 
					        SASSERT(m_rules.empty());
 | 
				
			||||||
        for(unsigned i=0; i<init_rule_cnt; i++) {
 | 
					        for (unsigned i=0; i<init_rule_cnt; i++) {
 | 
				
			||||||
            m_rules.push_back(source.get_rule(i));
 | 
					            m_rules.push_back(source.get_rule(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -517,19 +524,20 @@ namespace datalog {
 | 
				
			||||||
        while(it!=end) {
 | 
					        while(it!=end) {
 | 
				
			||||||
            rule_vector::iterator prev = it;
 | 
					            rule_vector::iterator prev = it;
 | 
				
			||||||
            ++it;
 | 
					            ++it;
 | 
				
			||||||
            if(it==end || rough_compare(*prev, *it)!=0) {
 | 
					            if (it==end || rough_compare(*prev, *it)!=0) {
 | 
				
			||||||
                process_class(cl_begin, it);
 | 
					                process_class(source, cl_begin, it);
 | 
				
			||||||
                cl_begin = it;
 | 
					                cl_begin = it;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rule_set * result = static_cast<rule_set *>(0);
 | 
					        rule_set * result = static_cast<rule_set *>(0);
 | 
				
			||||||
        if(m_modified) {
 | 
					        if (m_modified) {
 | 
				
			||||||
            result = alloc(rule_set, m_context);
 | 
					            result = alloc(rule_set, m_context);
 | 
				
			||||||
            unsigned fin_rule_cnt = m_result_rules.size();
 | 
					            unsigned fin_rule_cnt = m_result_rules.size();
 | 
				
			||||||
            for(unsigned i=0; i<fin_rule_cnt; i++) {
 | 
					            for (unsigned i=0; i<fin_rule_cnt; i++) {
 | 
				
			||||||
                result->add_rule(m_result_rules.get(i));
 | 
					                result->add_rule(m_result_rules.get(i));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            result->inherit_predicates(source);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        reset();
 | 
					        reset();
 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,11 +63,11 @@ namespace datalog {
 | 
				
			||||||
        ast_ref_vector      m_pinned;
 | 
					        ast_ref_vector      m_pinned;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        void merge_class(rule_vector::iterator first, rule_vector::iterator after_last);
 | 
					        void merge_class(rule_vector::iterator first, rule_vector::iterator after_last);
 | 
				
			||||||
        void process_class(rule_vector::iterator first, rule_vector::iterator after_last);
 | 
					        void process_class(rule_set const& source, rule_vector::iterator first, rule_vector::iterator after_last);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void reset();
 | 
					        void reset();
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        mk_similarity_compressor(context & ctx, unsigned threshold_count);
 | 
					        mk_similarity_compressor(context & ctx);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        rule_set * operator()(rule_set const & source);
 | 
					        rule_set * operator()(rule_set const & source);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,8 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk_simple_joins::mk_simple_joins(context & ctx):
 | 
					    mk_simple_joins::mk_simple_joins(context & ctx):
 | 
				
			||||||
        plugin(1000),
 | 
					        plugin(1000),
 | 
				
			||||||
        m_context(ctx) {
 | 
					        m_context(ctx),
 | 
				
			||||||
 | 
					        rm(ctx.get_rule_manager()) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class join_planner {
 | 
					    class join_planner {
 | 
				
			||||||
| 
						 | 
					@ -89,7 +90,7 @@ namespace datalog {
 | 
				
			||||||
                    m_consumers++;
 | 
					                    m_consumers++;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if(m_stratified) {
 | 
					                if(m_stratified) {
 | 
				
			||||||
                    unsigned head_stratum = pl.get_stratum(r->get_head()->get_decl());
 | 
					                    unsigned head_stratum = pl.get_stratum(r->get_decl());
 | 
				
			||||||
                    SASSERT(head_stratum>=m_src_stratum);
 | 
					                    SASSERT(head_stratum>=m_src_stratum);
 | 
				
			||||||
                    if(head_stratum==m_src_stratum) {
 | 
					                    if(head_stratum==m_src_stratum) {
 | 
				
			||||||
                        m_stratified = false;
 | 
					                        m_stratified = false;
 | 
				
			||||||
| 
						 | 
					@ -120,6 +121,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context & m_context;
 | 
					        context & m_context;
 | 
				
			||||||
        ast_manager & m;
 | 
					        ast_manager & m;
 | 
				
			||||||
 | 
					        rule_manager & rm;
 | 
				
			||||||
        var_subst & m_var_subst;
 | 
					        var_subst & m_var_subst;
 | 
				
			||||||
        rule_set & m_rs_aux_copy; //reference to a rule_set that will allow to ask for stratum levels
 | 
					        rule_set & m_rs_aux_copy; //reference to a rule_set that will allow to ask for stratum levels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,10 +132,13 @@ namespace datalog {
 | 
				
			||||||
        ptr_hashtable<rule, ptr_hash<rule>, ptr_eq<rule> > m_modified_rules;
 | 
					        ptr_hashtable<rule, ptr_hash<rule>, ptr_eq<rule> > m_modified_rules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ast_ref_vector m_pinned;
 | 
					        ast_ref_vector m_pinned;
 | 
				
			||||||
 | 
					        mutable ptr_vector<sort> m_vars;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        join_planner(context & ctx, rule_set & rs_aux_copy)
 | 
					        join_planner(context & ctx, rule_set & rs_aux_copy)
 | 
				
			||||||
            : m_context(ctx), m(ctx.get_manager()), m_var_subst(ctx.get_var_subst()),
 | 
					            : m_context(ctx), m(ctx.get_manager()), 
 | 
				
			||||||
 | 
					              rm(ctx.get_rule_manager()),
 | 
				
			||||||
 | 
					              m_var_subst(ctx.get_var_subst()),
 | 
				
			||||||
              m_rs_aux_copy(rs_aux_copy), 
 | 
					              m_rs_aux_copy(rs_aux_copy), 
 | 
				
			||||||
              m_introduced_rules(ctx.get_rule_manager()),
 | 
					              m_introduced_rules(ctx.get_rule_manager()),
 | 
				
			||||||
              m_pinned(ctx.get_manager())
 | 
					              m_pinned(ctx.get_manager())
 | 
				
			||||||
| 
						 | 
					@ -175,9 +180,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            unsigned max_var_idx = 0;
 | 
					            unsigned max_var_idx = 0;
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var_idx_set orig_var_set;
 | 
					                var_idx_set& orig_var_set = rm.collect_vars(t1, t2);
 | 
				
			||||||
                collect_vars(m, t1, orig_var_set);
 | 
					 | 
				
			||||||
                collect_vars(m, t2, orig_var_set);
 | 
					 | 
				
			||||||
                var_idx_set::iterator ovit = orig_var_set.begin();
 | 
					                var_idx_set::iterator ovit = orig_var_set.begin();
 | 
				
			||||||
                var_idx_set::iterator ovend = orig_var_set.end();
 | 
					                var_idx_set::iterator ovend = orig_var_set.end();
 | 
				
			||||||
                for(; ovit!=ovend; ++ovit) {
 | 
					                for(; ovit!=ovend; ++ovit) {
 | 
				
			||||||
| 
						 | 
					@ -323,14 +326,13 @@ namespace datalog {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            for(unsigned i=0; i<pos_tail_size; i++) {
 | 
					            for(unsigned i=0; i<pos_tail_size; i++) {
 | 
				
			||||||
                app * t1 = r->get_tail(i);
 | 
					                app * t1 = r->get_tail(i);
 | 
				
			||||||
                var_idx_set t1_vars;
 | 
					                var_idx_set t1_vars = rm.collect_vars(t1);
 | 
				
			||||||
                collect_vars(m, t1, t1_vars);
 | 
					 | 
				
			||||||
                counter.count_vars(m, t1, -1);  //temporarily remove t1 variables from counter
 | 
					                counter.count_vars(m, t1, -1);  //temporarily remove t1 variables from counter
 | 
				
			||||||
                for(unsigned j=i+1; j<pos_tail_size; j++) {
 | 
					                for(unsigned j=i+1; j<pos_tail_size; j++) {
 | 
				
			||||||
                    app * t2 = r->get_tail(j);
 | 
					                    app * t2 = r->get_tail(j);
 | 
				
			||||||
                    counter.count_vars(m, t2, -1);  //temporarily remove t2 variables from counter
 | 
					                    counter.count_vars(m, t2, -1);  //temporarily remove t2 variables from counter
 | 
				
			||||||
                    var_idx_set scope_vars(t1_vars);
 | 
					                    var_idx_set scope_vars = rm.collect_vars(t2);
 | 
				
			||||||
                    collect_vars(m, t2, scope_vars);
 | 
					                    scope_vars |= t1_vars;
 | 
				
			||||||
                    var_idx_set non_local_vars;
 | 
					                    var_idx_set non_local_vars;
 | 
				
			||||||
                    counter.collect_positive(non_local_vars);
 | 
					                    counter.collect_positive(non_local_vars);
 | 
				
			||||||
                    counter.count_vars(m, t2, 1);  //restore t2 variables in counter
 | 
					                    counter.count_vars(m, t2, 1);  //restore t2 variables in counter
 | 
				
			||||||
| 
						 | 
					@ -383,7 +385,7 @@ namespace datalog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            rule * one_parent = inf.m_rules.back();
 | 
					            rule * one_parent = inf.m_rules.back();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            func_decl* parent_head = one_parent->get_head()->get_decl();
 | 
					            func_decl* parent_head = one_parent->get_decl();
 | 
				
			||||||
            const char * one_parent_name = parent_head->get_name().bare_str();
 | 
					            const char * one_parent_name = parent_head->get_name().bare_str();
 | 
				
			||||||
            std::string parent_name;
 | 
					            std::string parent_name;
 | 
				
			||||||
            if(inf.m_rules.size()>1) {
 | 
					            if(inf.m_rules.size()>1) {
 | 
				
			||||||
| 
						 | 
					@ -472,8 +474,7 @@ namespace datalog {
 | 
				
			||||||
            while(!added_tails.empty()) {
 | 
					            while(!added_tails.empty()) {
 | 
				
			||||||
                app * a_tail = added_tails.back();  //added tail
 | 
					                app * a_tail = added_tails.back();  //added tail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var_idx_set a_tail_vars;
 | 
					                var_idx_set a_tail_vars = rm.collect_vars(a_tail);
 | 
				
			||||||
                collect_vars(m, a_tail, a_tail_vars);
 | 
					 | 
				
			||||||
                counter.count_vars(m, a_tail, -1);  //temporarily remove a_tail variables from counter
 | 
					                counter.count_vars(m, a_tail, -1);  //temporarily remove a_tail variables from counter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for(unsigned i=0; i<len; i++) {
 | 
					                for(unsigned i=0; i<len; i++) {
 | 
				
			||||||
| 
						 | 
					@ -484,8 +485,8 @@ namespace datalog {
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    counter.count_vars(m, o_tail, -1);  //temporarily remove o_tail variables from counter
 | 
					                    counter.count_vars(m, o_tail, -1);  //temporarily remove o_tail variables from counter
 | 
				
			||||||
                    var_idx_set scope_vars(a_tail_vars);
 | 
					                    var_idx_set scope_vars = rm.collect_vars(o_tail);
 | 
				
			||||||
                    collect_vars(m, o_tail, scope_vars);
 | 
					                    scope_vars |= a_tail_vars;
 | 
				
			||||||
                    var_idx_set non_local_vars;
 | 
					                    var_idx_set non_local_vars;
 | 
				
			||||||
                    counter.collect_positive(non_local_vars);
 | 
					                    counter.collect_positive(non_local_vars);
 | 
				
			||||||
                    counter.count_vars(m, o_tail, 1);  //restore o_tail variables in counter
 | 
					                    counter.count_vars(m, o_tail, 1);  //restore o_tail variables in counter
 | 
				
			||||||
| 
						 | 
					@ -714,13 +715,14 @@ namespace datalog {
 | 
				
			||||||
                m_context.get_rule_manager().mk_rule_asserted_proof(*m_introduced_rules.back());
 | 
					                m_context.get_rule_manager().mk_rule_asserted_proof(*m_introduced_rules.back());
 | 
				
			||||||
                m_introduced_rules.pop_back();
 | 
					                m_introduced_rules.pop_back();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            result->inherit_predicates(source);
 | 
				
			||||||
            return result;
 | 
					            return result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rule_set * mk_simple_joins::operator()(rule_set const & source) {
 | 
					    rule_set * mk_simple_joins::operator()(rule_set const & source) {
 | 
				
			||||||
        rule_set rs_aux_copy(m_context);
 | 
					        rule_set rs_aux_copy(m_context);
 | 
				
			||||||
        rs_aux_copy.add_rules(source);
 | 
					        rs_aux_copy.replace_rules(source);
 | 
				
			||||||
        if(!rs_aux_copy.is_closed()) {
 | 
					        if(!rs_aux_copy.is_closed()) {
 | 
				
			||||||
            rs_aux_copy.close();
 | 
					            rs_aux_copy.close();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,8 @@ namespace datalog {
 | 
				
			||||||
       We say that a rule containing C_i's is a rule with a "big tail".
 | 
					       We say that a rule containing C_i's is a rule with a "big tail".
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    class mk_simple_joins : public rule_transformer::plugin {
 | 
					    class mk_simple_joins : public rule_transformer::plugin {
 | 
				
			||||||
        context &							m_context;
 | 
					        context & 	    m_context;
 | 
				
			||||||
 | 
					        rule_manager &      rm;
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        mk_simple_joins(context & ctx);
 | 
					        mk_simple_joins(context & ctx);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
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