mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 19:52:29 +00:00 
			
		
		
		
	Merge branch 'master' of https://github.com/Z3Prover/z3
This commit is contained in:
		
						commit
						424a8c69bd
					
				
					 38 changed files with 473 additions and 216 deletions
				
			
		|  | @ -73,6 +73,10 @@ class MSSSolver: | ||||||
|              self.varcache[i] = Not(v) |              self.varcache[i] = Not(v) | ||||||
|        return self.varcache[i] |        return self.varcache[i] | ||||||
| 
 | 
 | ||||||
|  |    # Retrieve the latest model | ||||||
|  |    # Add formulas that are true in the model to  | ||||||
|  |    # the current mss | ||||||
|  | 
 | ||||||
|    def update_unknown(self): |    def update_unknown(self): | ||||||
|        self.model = self.s.model() |        self.model = self.s.model() | ||||||
|        new_unknown = set([]) |        new_unknown = set([]) | ||||||
|  | @ -83,23 +87,29 @@ class MSSSolver: | ||||||
|               new_unknown.add(x) |               new_unknown.add(x) | ||||||
|        self.unknown = new_unknown |        self.unknown = new_unknown | ||||||
|        |        | ||||||
|    def relax_core(self, core): |    # Create a name, propositional atom, | ||||||
|        assert(core <= self.soft_vars) |    #  for formula 'fml' and return the name. | ||||||
|        prev = BoolVal(True) | 
 | ||||||
|        core_list = [x for x in core] |    def add_def(self, fml): | ||||||
|        self.soft_vars -= core |        name = Bool("%s" % fml) | ||||||
|        # replace x0, x1, x2, .. by |        self.s.add(name == fml) | ||||||
|        # Or(x1, x0), Or(x2, And(x1, x0)), Or(x3, And(x2, And(x1, x0))), ... |        return name | ||||||
|        for i in range(len(core_list)-1): | 
 | ||||||
|            x = core_list[i] |    # replace Fs := f0, f1, f2, .. by | ||||||
|            y = core_list[i+1] |    # Or(f1, f0), Or(f2, And(f1, f0)), Or(f3, And(f2, And(f1, f0))), ... | ||||||
|            prevf = And(x, prev) | 
 | ||||||
|            prev = Bool("%s" % prevf) |    def relax_core(self, Fs): | ||||||
|            self.s.add(prev == prevf) |        assert(Fs <= self.soft_vars) | ||||||
|            zf = Or(prev, y) |        prefix = BoolVal(True) | ||||||
|            z = Bool("%s" % zf) |        self.soft_vars -= Fs | ||||||
|            self.s.add(z == zf) |        Fs = [ f for f in Fs ] | ||||||
|            self.soft_vars.add(z) |        for i in range(len(Fs)-1): | ||||||
|  |            prefix = self.add_def(And(Fs[i], prefix)) | ||||||
|  |            self.soft_vars.add(self.add_def(Or(prefix, Fs[i+1]))) | ||||||
|  | 
 | ||||||
|  |    # Resolve literals from the core that  | ||||||
|  |    # are 'explained', e.g., implied by  | ||||||
|  |    # other literals. | ||||||
| 
 | 
 | ||||||
|    def resolve_core(self, core): |    def resolve_core(self, core): | ||||||
|        new_core = set([]) |        new_core = set([]) | ||||||
|  | @ -111,6 +121,14 @@ class MSSSolver: | ||||||
|        return new_core |        return new_core | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |    # Given a current satisfiable state | ||||||
|  |    # Extract an MSS, and ensure that currently  | ||||||
|  |    # encoutered cores are avoided in next iterations | ||||||
|  |    # by weakening the set of literals that are | ||||||
|  |    # examined in next iterations. | ||||||
|  |    # Strengthen the solver state by enforcing that | ||||||
|  |    # an element from the MCS is encoutered. | ||||||
|  | 
 | ||||||
|    def grow(self): |    def grow(self): | ||||||
|        self.mss = [] |        self.mss = [] | ||||||
|        self.mcs = [] |        self.mcs = [] | ||||||
|  |  | ||||||
|  | @ -415,6 +415,7 @@ extern "C" { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         mk_c(c)->m().dec_ref(to_ast(a)); |         mk_c(c)->m().dec_ref(to_ast(a)); | ||||||
|  | 
 | ||||||
|         Z3_CATCH; |         Z3_CATCH; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -286,8 +286,8 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Ensures(Contract.Result<TupleSort>() != null); |             Contract.Ensures(Contract.Result<TupleSort>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(name); |             CheckContextMatch(name); | ||||||
|             CheckContextMatch(fieldNames); |             CheckContextMatch<Symbol>(fieldNames); | ||||||
|             CheckContextMatch(fieldSorts); |             CheckContextMatch<Sort>(fieldSorts); | ||||||
|             return new TupleSort(this, name, (uint)fieldNames.Length, fieldNames, fieldSorts); |             return new TupleSort(this, name, (uint)fieldNames.Length, fieldNames, fieldSorts); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -303,7 +303,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Ensures(Contract.Result<EnumSort>() != null); |             Contract.Ensures(Contract.Result<EnumSort>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(name); |             CheckContextMatch(name); | ||||||
|             CheckContextMatch(enumNames); |             CheckContextMatch<Symbol>(enumNames); | ||||||
|             return new EnumSort(this, name, enumNames); |             return new EnumSort(this, name, enumNames); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -423,7 +423,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Ensures(Contract.Result<DatatypeSort>() != null); |             Contract.Ensures(Contract.Result<DatatypeSort>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(name); |             CheckContextMatch(name); | ||||||
|             CheckContextMatch(constructors); |             CheckContextMatch<Constructor>(constructors); | ||||||
|             return new DatatypeSort(this, name, constructors); |             return new DatatypeSort(this, name, constructors); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -436,7 +436,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(constructors, c => c != null)); |             Contract.Requires(Contract.ForAll(constructors, c => c != null)); | ||||||
|             Contract.Ensures(Contract.Result<DatatypeSort>() != null); |             Contract.Ensures(Contract.Result<DatatypeSort>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(constructors); |             CheckContextMatch<Constructor>(constructors); | ||||||
|             return new DatatypeSort(this, MkSymbol(name), constructors); |             return new DatatypeSort(this, MkSymbol(name), constructors); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -454,7 +454,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(names, name => name != null)); |             Contract.Requires(Contract.ForAll(names, name => name != null)); | ||||||
|             Contract.Ensures(Contract.Result<DatatypeSort[]>() != null); |             Contract.Ensures(Contract.Result<DatatypeSort[]>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(names); |             CheckContextMatch<Symbol>(names); | ||||||
|             uint n = (uint)names.Length; |             uint n = (uint)names.Length; | ||||||
|             ConstructorList[] cla = new ConstructorList[n]; |             ConstructorList[] cla = new ConstructorList[n]; | ||||||
|             IntPtr[] n_constr = new IntPtr[n]; |             IntPtr[] n_constr = new IntPtr[n]; | ||||||
|  | @ -462,7 +462,7 @@ namespace Microsoft.Z3 | ||||||
|             { |             { | ||||||
|                 Constructor[] constructor = c[i]; |                 Constructor[] constructor = c[i]; | ||||||
|                 Contract.Assume(Contract.ForAll(constructor, arr => arr != null), "Clousot does not support yet quantified formula on multidimensional arrays"); |                 Contract.Assume(Contract.ForAll(constructor, arr => arr != null), "Clousot does not support yet quantified formula on multidimensional arrays"); | ||||||
|                 CheckContextMatch(constructor); |                 CheckContextMatch<Constructor>(constructor); | ||||||
|                 cla[i] = new ConstructorList(this, constructor); |                 cla[i] = new ConstructorList(this, constructor); | ||||||
|                 n_constr[i] = cla[i].NativeObject; |                 n_constr[i] = cla[i].NativeObject; | ||||||
|             } |             } | ||||||
|  | @ -520,7 +520,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Ensures(Contract.Result<FuncDecl>() != null); |             Contract.Ensures(Contract.Result<FuncDecl>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(name); |             CheckContextMatch(name); | ||||||
|             CheckContextMatch(domain); |             CheckContextMatch<Sort>(domain); | ||||||
|             CheckContextMatch(range); |             CheckContextMatch(range); | ||||||
|             return new FuncDecl(this, name, domain, range); |             return new FuncDecl(this, name, domain, range); | ||||||
|         } |         } | ||||||
|  | @ -551,7 +551,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(domain, d => d != null)); |             Contract.Requires(Contract.ForAll(domain, d => d != null)); | ||||||
|             Contract.Ensures(Contract.Result<FuncDecl>() != null); |             Contract.Ensures(Contract.Result<FuncDecl>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(domain); |             CheckContextMatch<Sort>(domain); | ||||||
|             CheckContextMatch(range); |             CheckContextMatch(range); | ||||||
|             return new FuncDecl(this, MkSymbol(name), domain, range); |             return new FuncDecl(this, MkSymbol(name), domain, range); | ||||||
|         } |         } | ||||||
|  | @ -582,7 +582,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(domain, d => d != null)); |             Contract.Requires(Contract.ForAll(domain, d => d != null)); | ||||||
|             Contract.Ensures(Contract.Result<FuncDecl>() != null); |             Contract.Ensures(Contract.Result<FuncDecl>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(domain); |             CheckContextMatch<Sort>(domain); | ||||||
|             CheckContextMatch(range); |             CheckContextMatch(range); | ||||||
|             return new FuncDecl(this, prefix, domain, range); |             return new FuncDecl(this, prefix, domain, range); | ||||||
|         } |         } | ||||||
|  | @ -811,7 +811,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Ensures(Contract.Result<Expr>() != null); |             Contract.Ensures(Contract.Result<Expr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(f); |             CheckContextMatch(f); | ||||||
|             CheckContextMatch(args); |             CheckContextMatch<Expr>(args); | ||||||
|             return Expr.Create(this, f, args); |             return Expr.Create(this, f, args); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -884,7 +884,7 @@ namespace Microsoft.Z3 | ||||||
| 
 | 
 | ||||||
|             Contract.Ensures(Contract.Result<BoolExpr>() != null); |             Contract.Ensures(Contract.Result<BoolExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(args); |             CheckContextMatch<Expr>(args); | ||||||
|             return new BoolExpr(this, Native.Z3_mk_distinct(nCtx, (uint)args.Length, AST.ArrayToNative(args))); |             return new BoolExpr(this, Native.Z3_mk_distinct(nCtx, (uint)args.Length, AST.ArrayToNative(args))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -970,7 +970,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<BoolExpr>() != null); |             Contract.Ensures(Contract.Result<BoolExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<BoolExpr>(t); | ||||||
|             return new BoolExpr(this, Native.Z3_mk_and(nCtx, (uint)t.Length, AST.ArrayToNative(t))); |             return new BoolExpr(this, Native.Z3_mk_and(nCtx, (uint)t.Length, AST.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -982,7 +982,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(t != null); |             Contract.Requires(t != null); | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<BoolExpr>() != null); |             Contract.Ensures(Contract.Result<BoolExpr>() != null); | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<BoolExpr>(t); | ||||||
|             return new BoolExpr(this, Native.Z3_mk_and(nCtx, (uint)t.Count(), AST.EnumToNative(t))); |             return new BoolExpr(this, Native.Z3_mk_and(nCtx, (uint)t.Count(), AST.EnumToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -995,7 +995,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<BoolExpr>() != null); |             Contract.Ensures(Contract.Result<BoolExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<BoolExpr>(t); | ||||||
|             return new BoolExpr(this, Native.Z3_mk_or(nCtx, (uint)t.Length, AST.ArrayToNative(t))); |             return new BoolExpr(this, Native.Z3_mk_or(nCtx, (uint)t.Length, AST.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1025,7 +1025,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<ArithExpr>() != null); |             Contract.Ensures(Contract.Result<ArithExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<ArithExpr>(t); | ||||||
|             return (ArithExpr)Expr.Create(this, Native.Z3_mk_add(nCtx, (uint)t.Length, AST.ArrayToNative(t))); |             return (ArithExpr)Expr.Create(this, Native.Z3_mk_add(nCtx, (uint)t.Length, AST.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1051,7 +1051,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<ArithExpr>() != null); |             Contract.Ensures(Contract.Result<ArithExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<ArithExpr>(t); | ||||||
|             return (ArithExpr)Expr.Create(this, Native.Z3_mk_mul(nCtx, (uint)t.Length, AST.ArrayToNative(t))); |             return (ArithExpr)Expr.Create(this, Native.Z3_mk_mul(nCtx, (uint)t.Length, AST.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1064,7 +1064,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<ArithExpr>() != null); |             Contract.Ensures(Contract.Result<ArithExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<ArithExpr>(t); | ||||||
|             return (ArithExpr)Expr.Create(this, Native.Z3_mk_mul(nCtx, (uint)t.Count(), AST.EnumToNative(t))); |             return (ArithExpr)Expr.Create(this, Native.Z3_mk_mul(nCtx, (uint)t.Count(), AST.EnumToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1077,7 +1077,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<ArithExpr>() != null); |             Contract.Ensures(Contract.Result<ArithExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<ArithExpr>(t); | ||||||
|             return (ArithExpr)Expr.Create(this, Native.Z3_mk_sub(nCtx, (uint)t.Length, AST.ArrayToNative(t))); |             return (ArithExpr)Expr.Create(this, Native.Z3_mk_sub(nCtx, (uint)t.Length, AST.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2205,7 +2205,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Ensures(Contract.Result<ArrayExpr>() != null); |             Contract.Ensures(Contract.Result<ArrayExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(f); |             CheckContextMatch(f); | ||||||
|             CheckContextMatch(args); |             CheckContextMatch<ArrayExpr>(args); | ||||||
|             return (ArrayExpr)Expr.Create(this, Native.Z3_mk_map(nCtx, f.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args))); |             return (ArrayExpr)Expr.Create(this, Native.Z3_mk_map(nCtx, f.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2315,7 +2315,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(args != null); |             Contract.Requires(args != null); | ||||||
|             Contract.Requires(Contract.ForAll(args, a => a != null)); |             Contract.Requires(Contract.ForAll(args, a => a != null)); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(args); |             CheckContextMatch<ArrayExpr>(args); | ||||||
|             return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_union(nCtx, (uint)args.Length, AST.ArrayToNative(args))); |             return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_union(nCtx, (uint)args.Length, AST.ArrayToNative(args))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2328,7 +2328,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(args, a => a != null)); |             Contract.Requires(Contract.ForAll(args, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<Expr>() != null); |             Contract.Ensures(Contract.Result<Expr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(args); |             CheckContextMatch<ArrayExpr>(args); | ||||||
|             return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_intersect(nCtx, (uint)args.Length, AST.ArrayToNative(args))); |             return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_intersect(nCtx, (uint)args.Length, AST.ArrayToNative(args))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2429,7 +2429,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<SeqExpr>() != null); |             Contract.Ensures(Contract.Result<SeqExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<SeqExpr>(t); | ||||||
|             return new SeqExpr(this, Native.Z3_mk_seq_concat(nCtx, (uint)t.Length, AST.ArrayToNative(t))); |             return new SeqExpr(this, Native.Z3_mk_seq_concat(nCtx, (uint)t.Length, AST.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2593,7 +2593,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<ReExpr>() != null); |             Contract.Ensures(Contract.Result<ReExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<ReExpr>(t); | ||||||
|             return new ReExpr(this, Native.Z3_mk_re_concat(nCtx, (uint)t.Length, AST.ArrayToNative(t))); |             return new ReExpr(this, Native.Z3_mk_re_concat(nCtx, (uint)t.Length, AST.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2606,7 +2606,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(t, a => a != null)); |             Contract.Requires(Contract.ForAll(t, a => a != null)); | ||||||
|             Contract.Ensures(Contract.Result<ReExpr>() != null); |             Contract.Ensures(Contract.Result<ReExpr>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<ReExpr>(t); | ||||||
|             return new ReExpr(this, Native.Z3_mk_re_union(nCtx, (uint)t.Length, AST.ArrayToNative(t))); |             return new ReExpr(this, Native.Z3_mk_re_union(nCtx, (uint)t.Length, AST.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
|      |      | ||||||
|  | @ -2621,7 +2621,7 @@ namespace Microsoft.Z3 | ||||||
|         { |         { | ||||||
|            Contract.Requires(args != null); |            Contract.Requires(args != null); | ||||||
|            Contract.Requires(Contract.Result<BoolExpr[]>() != null); |            Contract.Requires(Contract.Result<BoolExpr[]>() != null); | ||||||
|            CheckContextMatch(args); |            CheckContextMatch<BoolExpr>(args); | ||||||
|            return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint) args.Length, |            return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint) args.Length, | ||||||
|                                                           AST.ArrayToNative(args), k)); |                                                           AST.ArrayToNative(args), k)); | ||||||
|         } |         } | ||||||
|  | @ -2635,7 +2635,7 @@ namespace Microsoft.Z3 | ||||||
|            Contract.Requires(coeffs != null); |            Contract.Requires(coeffs != null); | ||||||
|            Contract.Requires(args.Length == coeffs.Length); |            Contract.Requires(args.Length == coeffs.Length); | ||||||
|            Contract.Requires(Contract.Result<BoolExpr[]>() != null); |            Contract.Requires(Contract.Result<BoolExpr[]>() != null); | ||||||
|            CheckContextMatch(args); |            CheckContextMatch<BoolExpr>(args); | ||||||
|            return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint) args.Length, |            return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint) args.Length, | ||||||
|                                                           AST.ArrayToNative(args), |                                                           AST.ArrayToNative(args), | ||||||
|                                                           coeffs, k)); |                                                           coeffs, k)); | ||||||
|  | @ -3386,7 +3386,7 @@ namespace Microsoft.Z3 | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t1); |             CheckContextMatch(t1); | ||||||
|             CheckContextMatch(t2); |             CheckContextMatch(t2); | ||||||
|             CheckContextMatch(ts); |             CheckContextMatch<Tactic>(ts); | ||||||
| 
 | 
 | ||||||
|             IntPtr last = IntPtr.Zero; |             IntPtr last = IntPtr.Zero; | ||||||
|             if (ts != null && ts.Length > 0) |             if (ts != null && ts.Length > 0) | ||||||
|  | @ -3577,7 +3577,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(t == null || Contract.ForAll(t, tactic => tactic != null)); |             Contract.Requires(t == null || Contract.ForAll(t, tactic => tactic != null)); | ||||||
|             Contract.Ensures(Contract.Result<Tactic>() != null); |             Contract.Ensures(Contract.Result<Tactic>() != null); | ||||||
| 
 | 
 | ||||||
|             CheckContextMatch(t); |             CheckContextMatch<Tactic>(t); | ||||||
|             return new Tactic(this, Native.Z3_tactic_par_or(nCtx, Tactic.ArrayLength(t), Tactic.ArrayToNative(t))); |             return new Tactic(this, Native.Z3_tactic_par_or(nCtx, Tactic.ArrayLength(t), Tactic.ArrayToNative(t))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -4810,7 +4810,7 @@ namespace Microsoft.Z3 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Pure] |         [Pure] | ||||||
|         internal void CheckContextMatch(IEnumerable<Z3Object> arr) |         internal void CheckContextMatch<T>(IEnumerable<T> arr) where T : Z3Object | ||||||
|         { |         { | ||||||
|             Contract.Requires(arr == null || Contract.ForAll(arr, a => a != null)); |             Contract.Requires(arr == null || Contract.ForAll(arr, a => a != null)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -98,7 +98,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(args != null); |             Contract.Requires(args != null); | ||||||
|             Contract.Requires(Contract.ForAll(args, a => a != null)); |             Contract.Requires(Contract.ForAll(args, a => a != null)); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(args); |             Context.CheckContextMatch<Expr>(args); | ||||||
|             if (IsApp && args.Length != NumArgs) |             if (IsApp && args.Length != NumArgs) | ||||||
|                 throw new Z3Exception("Number of arguments does not match"); |                 throw new Z3Exception("Number of arguments does not match"); | ||||||
|             NativeObject = Native.Z3_update_term(Context.nCtx, NativeObject, (uint)args.Length, Expr.ArrayToNative(args)); |             NativeObject = Native.Z3_update_term(Context.nCtx, NativeObject, (uint)args.Length, Expr.ArrayToNative(args)); | ||||||
|  | @ -120,8 +120,8 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(to, t => t != null)); |             Contract.Requires(Contract.ForAll(to, t => t != null)); | ||||||
|             Contract.Ensures(Contract.Result<Expr>() != null); |             Contract.Ensures(Contract.Result<Expr>() != null); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(from); |             Context.CheckContextMatch<Expr>(from); | ||||||
|             Context.CheckContextMatch(to); |             Context.CheckContextMatch<Expr>(to); | ||||||
|             if (from.Length != to.Length) |             if (from.Length != to.Length) | ||||||
|                 throw new Z3Exception("Argument sizes do not match"); |                 throw new Z3Exception("Argument sizes do not match"); | ||||||
|             return Expr.Create(Context, Native.Z3_substitute(Context.nCtx, NativeObject, (uint)from.Length, Expr.ArrayToNative(from), Expr.ArrayToNative(to))); |             return Expr.Create(Context, Native.Z3_substitute(Context.nCtx, NativeObject, (uint)from.Length, Expr.ArrayToNative(from), Expr.ArrayToNative(to))); | ||||||
|  | @ -152,7 +152,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(Contract.ForAll(to, t => t != null)); |             Contract.Requires(Contract.ForAll(to, t => t != null)); | ||||||
|             Contract.Ensures(Contract.Result<Expr>() != null); |             Contract.Ensures(Contract.Result<Expr>() != null); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(to); |             Context.CheckContextMatch<Expr>(to); | ||||||
|             return Expr.Create(Context, Native.Z3_substitute_vars(Context.nCtx, NativeObject, (uint)to.Length, Expr.ArrayToNative(to))); |             return Expr.Create(Context, Native.Z3_substitute_vars(Context.nCtx, NativeObject, (uint)to.Length, Expr.ArrayToNative(to))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(constraints != null); |             Contract.Requires(constraints != null); | ||||||
|             Contract.Requires(Contract.ForAll(constraints, c => c != null)); |             Contract.Requires(Contract.ForAll(constraints, c => c != null)); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(constraints); |             Context.CheckContextMatch<BoolExpr>(constraints); | ||||||
|             foreach (BoolExpr a in constraints) |             foreach (BoolExpr a in constraints) | ||||||
|             { |             { | ||||||
|                 Native.Z3_fixedpoint_assert(Context.nCtx, NativeObject, a.NativeObject); |                 Native.Z3_fixedpoint_assert(Context.nCtx, NativeObject, a.NativeObject); | ||||||
|  | @ -151,7 +151,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(relations != null); |             Contract.Requires(relations != null); | ||||||
|             Contract.Requires(Contract.ForAll(0, relations.Length, i => relations[i] != null)); |             Contract.Requires(Contract.ForAll(0, relations.Length, i => relations[i] != null)); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(relations); |             Context.CheckContextMatch<FuncDecl>(relations); | ||||||
|             Z3_lbool r = (Z3_lbool)Native.Z3_fixedpoint_query_relations(Context.nCtx, NativeObject, |             Z3_lbool r = (Z3_lbool)Native.Z3_fixedpoint_query_relations(Context.nCtx, NativeObject, | ||||||
|                                    AST.ArrayLength(relations), AST.ArrayToNative(relations)); |                                    AST.ArrayLength(relations), AST.ArrayToNative(relations)); | ||||||
|             switch (r) |             switch (r) | ||||||
|  |  | ||||||
|  | @ -339,7 +339,7 @@ namespace Microsoft.Z3 | ||||||
|         { |         { | ||||||
|             Contract.Requires(args == null || Contract.ForAll(args, a => a != null)); |             Contract.Requires(args == null || Contract.ForAll(args, a => a != null)); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(args); |             Context.CheckContextMatch<Expr>(args); | ||||||
|             return Expr.Create(Context, this, args); |             return Expr.Create(Context, this, args); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(constraints != null); |             Contract.Requires(constraints != null); | ||||||
|             Contract.Requires(Contract.ForAll(constraints, c => c != null)); |             Contract.Requires(Contract.ForAll(constraints, c => c != null)); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(constraints); |             Context.CheckContextMatch<BoolExpr>(constraints); | ||||||
|             foreach (BoolExpr c in constraints) |             foreach (BoolExpr c in constraints) | ||||||
|             { |             { | ||||||
|                 Contract.Assert(c != null); // It was an assume, now made an assert just to be sure we do not regress |                 Contract.Assert(c != null); // It was an assume, now made an assert just to be sure we do not regress | ||||||
|  |  | ||||||
|  | @ -172,10 +172,10 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(patterns == null || Contract.ForAll(patterns, p => p != null)); |             Contract.Requires(patterns == null || Contract.ForAll(patterns, p => p != null)); | ||||||
|             Contract.Requires(noPatterns == null || Contract.ForAll(noPatterns, np => np != null)); |             Contract.Requires(noPatterns == null || Contract.ForAll(noPatterns, np => np != null)); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(patterns); |             Context.CheckContextMatch<Pattern>(patterns); | ||||||
|             Context.CheckContextMatch(noPatterns); |             Context.CheckContextMatch<Expr>(noPatterns); | ||||||
|             Context.CheckContextMatch(sorts); |             Context.CheckContextMatch<Sort>(sorts); | ||||||
|             Context.CheckContextMatch(names); |             Context.CheckContextMatch<Symbol>(names); | ||||||
|             Context.CheckContextMatch(body); |             Context.CheckContextMatch(body); | ||||||
| 
 | 
 | ||||||
|             if (sorts.Length != names.Length) |             if (sorts.Length != names.Length) | ||||||
|  | @ -212,8 +212,8 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(noPatterns == null || Contract.ForAll(noPatterns, np => np != null)); |             Contract.Requires(noPatterns == null || Contract.ForAll(noPatterns, np => np != null)); | ||||||
|             Contract.Requires(bound == null || Contract.ForAll(bound, n => n != null)); |             Contract.Requires(bound == null || Contract.ForAll(bound, n => n != null)); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(noPatterns); |             Context.CheckContextMatch<Expr>(noPatterns); | ||||||
|             Context.CheckContextMatch(patterns); |             Context.CheckContextMatch<Pattern>(patterns); | ||||||
|             //Context.CheckContextMatch(bound); |             //Context.CheckContextMatch(bound); | ||||||
|             Context.CheckContextMatch(body); |             Context.CheckContextMatch(body); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -111,7 +111,7 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(constraints != null); |             Contract.Requires(constraints != null); | ||||||
|             Contract.Requires(Contract.ForAll(constraints, c => c != null)); |             Contract.Requires(Contract.ForAll(constraints, c => c != null)); | ||||||
| 
 | 
 | ||||||
|             Context.CheckContextMatch(constraints); |             Context.CheckContextMatch<BoolExpr>(constraints); | ||||||
|             foreach (BoolExpr a in constraints) |             foreach (BoolExpr a in constraints) | ||||||
|             { |             { | ||||||
|                 Native.Z3_solver_assert(Context.nCtx, NativeObject, a.NativeObject); |                 Native.Z3_solver_assert(Context.nCtx, NativeObject, a.NativeObject); | ||||||
|  | @ -142,8 +142,8 @@ namespace Microsoft.Z3 | ||||||
|             Contract.Requires(constraints != null); |             Contract.Requires(constraints != null); | ||||||
|             Contract.Requires(Contract.ForAll(constraints, c => c != null)); |             Contract.Requires(Contract.ForAll(constraints, c => c != null)); | ||||||
|             Contract.Requires(Contract.ForAll(ps, c => c != null)); |             Contract.Requires(Contract.ForAll(ps, c => c != null)); | ||||||
|             Context.CheckContextMatch(constraints); |             Context.CheckContextMatch<BoolExpr>(constraints); | ||||||
|             Context.CheckContextMatch(ps); |             Context.CheckContextMatch<BoolExpr>(ps); | ||||||
|             if (constraints.Length != ps.Length) |             if (constraints.Length != ps.Length) | ||||||
|                 throw new Z3Exception("Argument size mismatch"); |                 throw new Z3Exception("Argument size mismatch"); | ||||||
|              |              | ||||||
|  |  | ||||||
|  | @ -138,7 +138,7 @@ namespace Microsoft.Z3 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Pure] |         [Pure] | ||||||
|         internal static IntPtr[] EnumToNative(IEnumerable<Z3Object> a) |         internal static IntPtr[] EnumToNative<T>(IEnumerable<T> a) where T : Z3Object | ||||||
|         { |         { | ||||||
|             Contract.Ensures(a == null || Contract.Result<IntPtr[]>() != null); |             Contract.Ensures(a == null || Contract.Result<IntPtr[]>() != null); | ||||||
|             Contract.Ensures(a == null || Contract.Result<IntPtr[]>().Length == a.Count()); |             Contract.Ensures(a == null || Contract.Result<IntPtr[]>().Length == a.Count()); | ||||||
|  |  | ||||||
|  | @ -118,6 +118,8 @@ def _get_args(args): | ||||||
|     try: |     try: | ||||||
|         if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)): |         if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)): | ||||||
|             return args[0] |             return args[0] | ||||||
|  |         elif len(args) == 1 and isinstance(args[0], set): | ||||||
|  |             return [arg for arg in args[0]] | ||||||
|         else: |         else: | ||||||
|             return args |             return args | ||||||
|     except:  # len is not necessarily defined when args is not a sequence (use reflection?) |     except:  # len is not necessarily defined when args is not a sequence (use reflection?) | ||||||
|  |  | ||||||
|  | @ -78,7 +78,10 @@ void parameter::del_eh(ast_manager & m, family_id fid) { | ||||||
|     } |     } | ||||||
|     else if (is_external()) { |     else if (is_external()) { | ||||||
|         SASSERT(fid != null_family_id); |         SASSERT(fid != null_family_id); | ||||||
|         m.get_plugin(fid)->del(*this); |         decl_plugin * plugin = m.get_plugin(fid); | ||||||
|  |         if (plugin) { | ||||||
|  |             plugin->del(*this); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1421,6 +1424,7 @@ ast_manager::~ast_manager() { | ||||||
|         if (*it)  |         if (*it)  | ||||||
|             dealloc(*it); |             dealloc(*it); | ||||||
|     } |     } | ||||||
|  |     m_plugins.reset(); | ||||||
|     while (!m_ast_table.empty()) { |     while (!m_ast_table.empty()) { | ||||||
|         DEBUG_CODE(std::cout << "ast_manager LEAKED: " << m_ast_table.size() << std::endl;); |         DEBUG_CODE(std::cout << "ast_manager LEAKED: " << m_ast_table.size() << std::endl;); | ||||||
|         ptr_vector<ast> roots; |         ptr_vector<ast> roots; | ||||||
|  | @ -1430,14 +1434,22 @@ ast_manager::~ast_manager() { | ||||||
|         for (; it_a != end_a; ++it_a) { |         for (; it_a != end_a; ++it_a) { | ||||||
|             ast* n = (*it_a); |             ast* n = (*it_a); | ||||||
|             switch (n->get_kind()) { |             switch (n->get_kind()) { | ||||||
|             case AST_SORT: |             case AST_SORT: { | ||||||
|                 mark_array_ref(mark, to_sort(n)->get_info()->get_num_parameters(), to_sort(n)->get_info()->get_parameters()); |                 sort_info* info = to_sort(n)->get_info(); | ||||||
|  |                 if (info != 0) { | ||||||
|  |                     mark_array_ref(mark, info->get_num_parameters(), info->get_parameters()); | ||||||
|  |                 } | ||||||
|                 break; |                 break; | ||||||
|             case AST_FUNC_DECL: |             } | ||||||
|                 mark_array_ref(mark, to_func_decl(n)->get_info()->get_num_parameters(), to_func_decl(n)->get_info()->get_parameters()); |             case AST_FUNC_DECL: { | ||||||
|  |                 func_decl_info* info = to_func_decl(n)->get_info(); | ||||||
|  |                 if (info != 0) { | ||||||
|  |                     mark_array_ref(mark, info->get_num_parameters(), info->get_parameters()); | ||||||
|  |                 } | ||||||
|                 mark_array_ref(mark, to_func_decl(n)->get_arity(), to_func_decl(n)->get_domain()); |                 mark_array_ref(mark, to_func_decl(n)->get_arity(), to_func_decl(n)->get_domain()); | ||||||
|                 mark.mark(to_func_decl(n)->get_range(), true); |                 mark.mark(to_func_decl(n)->get_range(), true); | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|             case AST_APP: |             case AST_APP: | ||||||
|                 mark.mark(to_app(n)->get_decl(), true); |                 mark.mark(to_app(n)->get_decl(), true); | ||||||
|                 mark_array_ref(mark, to_app(n)->get_num_args(), to_app(n)->get_args()); |                 mark_array_ref(mark, to_app(n)->get_num_args(), to_app(n)->get_args()); | ||||||
|  | @ -1857,8 +1869,8 @@ void ast_manager::delete_node(ast * n) { | ||||||
|             dec_array_ref(worklist, to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns()); |             dec_array_ref(worklist, to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns()); | ||||||
|             dec_array_ref(worklist, to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns()); |             dec_array_ref(worklist, to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns()); | ||||||
|             break; |             break; | ||||||
|     default: |         default: | ||||||
|         break; |             break; | ||||||
|         } |         } | ||||||
|         if (m_debug_ref_count) { |         if (m_debug_ref_count) { | ||||||
|             m_debug_free_indices.insert(n->m_id,0); |             m_debug_free_indices.insert(n->m_id,0); | ||||||
|  |  | ||||||
|  | @ -732,7 +732,8 @@ void datatype_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol | ||||||
| datatype_util::datatype_util(ast_manager & m): | datatype_util::datatype_util(ast_manager & m): | ||||||
|     m_manager(m), |     m_manager(m), | ||||||
|     m_family_id(m.mk_family_id("datatype")), |     m_family_id(m.mk_family_id("datatype")), | ||||||
|     m_asts(m) { |     m_asts(m), | ||||||
|  |     m_start(0) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| datatype_util::~datatype_util() { | datatype_util::~datatype_util() { | ||||||
|  | @ -807,11 +808,11 @@ func_decl * datatype_util::get_non_rec_constructor_core(sort * ty, ptr_vector<so | ||||||
|     // If there is no such constructor, then we select one that 
 |     // If there is no such constructor, then we select one that 
 | ||||||
|     //   2) each type T_i is not recursive or contains a constructor that does not depend on T
 |     //   2) each type T_i is not recursive or contains a constructor that does not depend on T
 | ||||||
|     ptr_vector<func_decl> const * constructors = get_datatype_constructors(ty); |     ptr_vector<func_decl> const * constructors = get_datatype_constructors(ty); | ||||||
|     ptr_vector<func_decl>::const_iterator it  = constructors->begin(); |  | ||||||
|     ptr_vector<func_decl>::const_iterator end = constructors->end(); |  | ||||||
|     // step 1)
 |     // step 1)
 | ||||||
|     for (; it != end; ++it) { |     unsigned sz = constructors->size(); | ||||||
|         func_decl * c = *it; |     ++m_start; | ||||||
|  |     for (unsigned j = 0; j < sz; ++j) {         | ||||||
|  |         func_decl * c = (*constructors)[(j + m_start) % sz]; | ||||||
|         unsigned num_args = c->get_arity(); |         unsigned num_args = c->get_arity(); | ||||||
|         unsigned i = 0; |         unsigned i = 0; | ||||||
|         for (; i < num_args; i++) { |         for (; i < num_args; i++) { | ||||||
|  | @ -823,9 +824,8 @@ func_decl * datatype_util::get_non_rec_constructor_core(sort * ty, ptr_vector<so | ||||||
|             return c; |             return c; | ||||||
|     } |     } | ||||||
|     // step 2)
 |     // step 2)
 | ||||||
|     it  = constructors->begin(); |     for (unsigned j = 0; j < sz; ++j) {         | ||||||
|     for (; it != end; ++it) { |         func_decl * c = (*constructors)[(j + m_start) % sz]; | ||||||
|         func_decl * c = *it; |  | ||||||
|         TRACE("datatype_util_bug", tout << "non_rec_constructor c: " << c->get_name() << "\n";); |         TRACE("datatype_util_bug", tout << "non_rec_constructor c: " << c->get_name() << "\n";); | ||||||
|         unsigned num_args = c->get_arity(); |         unsigned num_args = c->get_arity(); | ||||||
|         unsigned i = 0; |         unsigned i = 0; | ||||||
|  | @ -964,6 +964,7 @@ void datatype_util::reset() { | ||||||
|     std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc<ptr_vector<func_decl> >()); |     std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc<ptr_vector<func_decl> >()); | ||||||
|     m_vectors.reset(); |     m_vectors.reset(); | ||||||
|     m_asts.reset(); |     m_asts.reset(); | ||||||
|  |     ++m_start; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -176,6 +176,7 @@ class datatype_util { | ||||||
|     obj_map<sort, bool>                         m_is_enum; |     obj_map<sort, bool>                         m_is_enum; | ||||||
|     ast_ref_vector                              m_asts; |     ast_ref_vector                              m_asts; | ||||||
|     ptr_vector<ptr_vector<func_decl> >          m_vectors; |     ptr_vector<ptr_vector<func_decl> >          m_vectors; | ||||||
|  |     unsigned                                    m_start; | ||||||
| 
 | 
 | ||||||
|     func_decl * get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set); |     func_decl * get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set); | ||||||
|     func_decl * get_constructor(sort * ty, unsigned c_id); |     func_decl * get_constructor(sort * ty, unsigned c_id); | ||||||
|  |  | ||||||
|  | @ -458,28 +458,32 @@ void macro_util::normalize_expr(app * head, expr * t, expr_ref & norm_t) const { | ||||||
|     expr_ref_buffer  var_mapping(m_manager); |     expr_ref_buffer  var_mapping(m_manager); | ||||||
|     bool changed = false; |     bool changed = false; | ||||||
|     unsigned num_args = head->get_num_args(); |     unsigned num_args = head->get_num_args(); | ||||||
|     unsigned max      = num_args; |     unsigned max_var_idx = 0; | ||||||
|     for (unsigned i = 0; i < num_args; i++) { |     for (unsigned i = 0; i < num_args; i++) { | ||||||
|         var * v     = to_var(head->get_arg(i)); |         var const * v = to_var(head->get_arg(i)); | ||||||
|         if (v->get_idx() >= max) |         if (v->get_idx() > max_var_idx) | ||||||
|             max = v->get_idx() + 1; |             max_var_idx = v->get_idx(); | ||||||
|     } |     } | ||||||
|     TRACE("normalize_expr_bug", |     TRACE("normalize_expr_bug", | ||||||
|           tout << "head: " << mk_pp(head, m_manager) << "\n"; |           tout << "head: " << mk_pp(head, m_manager) << "\n"; | ||||||
|           tout << "applying substitution to:\n" << mk_bounded_pp(t, m_manager) << "\n";); |           tout << "applying substitution to:\n" << mk_bounded_pp(t, m_manager) << "\n";); | ||||||
|     for (unsigned i = 0; i < num_args; i++) { |     for (unsigned i = 0; i < num_args; i++) { | ||||||
|         var * v     = to_var(head->get_arg(i)); |         var * v = to_var(head->get_arg(i)); | ||||||
|         if (v->get_idx() != i) { |         if (v->get_idx() != i) { | ||||||
|             changed = true; |             changed = true; | ||||||
|             var * new_var = m_manager.mk_var(i, v->get_sort()); |             var_ref new_var(m_manager.mk_var(i, v->get_sort()), m_manager); | ||||||
|             CTRACE("normalize_expr_bug", v->get_idx() >= num_args, tout << mk_pp(v, m_manager) << ", num_args: " << num_args << "\n";); |             var_mapping.setx(max_var_idx - v->get_idx(), new_var); | ||||||
|             SASSERT(v->get_idx() < max); |  | ||||||
|             var_mapping.setx(max - v->get_idx() - 1, new_var); |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             var_mapping.setx(max - i - 1, v); |  | ||||||
|         } |         } | ||||||
|  |         else | ||||||
|  |             var_mapping.setx(max_var_idx - i, v); | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     for (unsigned i = num_args; i <= max_var_idx; i++) | ||||||
|  |         // CMW: Won't be used, but dictates a larger binding size, 
 | ||||||
|  |         // so that the indexes between here and in the rewriter match.
 | ||||||
|  |         // It's possible that we don't see the true max idx of all vars here.
 | ||||||
|  |         var_mapping.setx(max_var_idx - i, 0);  | ||||||
|  | 
 | ||||||
|     if (changed) { |     if (changed) { | ||||||
|         // REMARK: t may have nested quantifiers... So, I must use the std order for variable substitution.
 |         // REMARK: t may have nested quantifiers... So, I must use the std order for variable substitution.
 | ||||||
|         var_subst subst(m_manager, true);  |         var_subst subst(m_manager, true);  | ||||||
|  | @ -488,7 +492,7 @@ void macro_util::normalize_expr(app * head, expr * t, expr_ref & norm_t) const { | ||||||
|               tout << "applying substitution to:\n" << mk_ll_pp(t, m_manager) << "\nsubstitution:\n"; |               tout << "applying substitution to:\n" << mk_ll_pp(t, m_manager) << "\nsubstitution:\n"; | ||||||
|               for (unsigned i = 0; i < var_mapping.size(); i++) { |               for (unsigned i = 0; i < var_mapping.size(); i++) { | ||||||
|                   if (var_mapping[i] != 0) |                   if (var_mapping[i] != 0) | ||||||
|                     tout << "#" << i << " -> " << mk_pp(var_mapping[i], m_manager) << "\n"; |                     tout << "#" << i << " -> " << mk_ll_pp(var_mapping[i], m_manager); | ||||||
|               }); |               }); | ||||||
|         subst(t, var_mapping.size(), var_mapping.c_ptr(), norm_t); |         subst(t, var_mapping.size(), var_mapping.c_ptr(), norm_t); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -16,4 +16,5 @@ def_module_params('pp', | ||||||
|                           ('fixed_indent', BOOL, False, 'use a fixed indentation for applications'), |                           ('fixed_indent', BOOL, False, 'use a fixed indentation for applications'), | ||||||
|                           ('single_line', BOOL, False, 'ignore line breaks when true'), |                           ('single_line', BOOL, False, 'ignore line breaks when true'), | ||||||
|                           ('bounded', BOOL, False, 'ignore characters exceeding max width'), |                           ('bounded', BOOL, False, 'ignore characters exceeding max width'), | ||||||
|  |                           ('pretty_proof', BOOL, False, 'use slower, but prettier, printer for proofs'), | ||||||
|                           ('simplify_implies', BOOL, True, 'simplify nested implications for pretty printing'))) |                           ('simplify_implies', BOOL, True, 'simplify nested implications for pretty printing'))) | ||||||
|  |  | ||||||
|  | @ -144,6 +144,9 @@ zstring zstring::replace(zstring const& src, zstring const& dst) const { | ||||||
|     if (length() < src.length()) { |     if (length() < src.length()) { | ||||||
|         return zstring(*this); |         return zstring(*this); | ||||||
|     } |     } | ||||||
|  |     if (src.length() == 0) { | ||||||
|  |         return zstring(*this); | ||||||
|  |     } | ||||||
|     bool found = false; |     bool found = false; | ||||||
|     for (unsigned i = 0; i < length(); ++i) { |     for (unsigned i = 0; i < length(); ++i) { | ||||||
|         bool eq = !found && i + src.length() <= length(); |         bool eq = !found && i + src.length() <= length(); | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ Notes: | ||||||
| #include"gparams.h" | #include"gparams.h" | ||||||
| #include"env_params.h" | #include"env_params.h" | ||||||
| #include"well_sorted.h" | #include"well_sorted.h" | ||||||
|  | #include"pp_params.hpp" | ||||||
| 
 | 
 | ||||||
| class help_cmd : public cmd { | class help_cmd : public cmd { | ||||||
|     svector<symbol> m_cmds; |     svector<symbol> m_cmds; | ||||||
|  | @ -161,14 +162,19 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", { | ||||||
|         throw cmd_exception("proof is not well sorted"); |         throw cmd_exception("proof is not well sorted"); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     // TODO: reimplement a new SMT2 pretty printer 
 |     pp_params params; | ||||||
|     ast_smt_pp pp(ctx.m()); |     if (params.pretty_proof()) { | ||||||
|     cmd_is_declared isd(ctx); |         ctx.regular_stream() << mk_pp(pr, ctx.m()) << std::endl; | ||||||
|     pp.set_is_declared(&isd); |     } | ||||||
|     pp.set_logic(ctx.get_logic()); |     else { | ||||||
|     // ctx.regular_stream() << mk_pp(pr, ctx.m()) << "\n";
 |         // TODO: reimplement a new SMT2 pretty printer 
 | ||||||
|     pp.display_smt2(ctx.regular_stream(), pr); |         ast_smt_pp pp(ctx.m()); | ||||||
|     ctx.regular_stream() << std::endl; |         cmd_is_declared isd(ctx); | ||||||
|  |         pp.set_is_declared(&isd); | ||||||
|  |         pp.set_logic(ctx.get_logic()); | ||||||
|  |         pp.display_smt2(ctx.regular_stream(), pr); | ||||||
|  |         ctx.regular_stream() << std::endl; | ||||||
|  |     } | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| #define PRINT_CORE()                                            \ | #define PRINT_CORE()                                            \ | ||||||
|  |  | ||||||
|  | @ -28,7 +28,6 @@ | ||||||
| #include"mpq.h" | #include"mpq.h" | ||||||
| #include"expr2var.h" | #include"expr2var.h" | ||||||
| #include"pp.h" | #include"pp.h" | ||||||
| #include"pp_params.hpp" |  | ||||||
| #include"iz3interp.h" | #include"iz3interp.h" | ||||||
| #include"iz3checker.h" | #include"iz3checker.h" | ||||||
| #include"iz3profiling.h" | #include"iz3profiling.h" | ||||||
|  |  | ||||||
|  | @ -72,7 +72,7 @@ namespace datalog { | ||||||
|                     } |                     } | ||||||
|                     e->get_data().m_value->push_back(cur); |                     e->get_data().m_value->push_back(cur); | ||||||
|                 } |                 } | ||||||
|                 if (cur->get_uninterpreted_tail_size() == 0) { |                 if (cur->get_positive_tail_size() == 0) { | ||||||
|                     func_decl *sym = cur->get_head()->get_decl(); |                     func_decl *sym = cur->get_head()->get_decl(); | ||||||
|                     bool new_info = m_facts.insert_if_not_there2(sym, Fact())->get_data().m_value.init_up(m_context, cur); |                     bool new_info = m_facts.insert_if_not_there2(sym, Fact())->get_data().m_value.init_up(m_context, cur); | ||||||
|                     if (new_info) { |                     if (new_info) { | ||||||
|  | @ -236,7 +236,7 @@ namespace datalog { | ||||||
|             return m_facts.get(m_rule->get_decl(idx), Fact::null_fact); |             return m_facts.get(m_rule->get_decl(idx), Fact::null_fact); | ||||||
|         } |         } | ||||||
|         unsigned size() const { |         unsigned size() const { | ||||||
|             return m_rule->get_uninterpreted_tail_size(); |             return m_rule->get_positive_tail_size(); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ namespace datalog { | ||||||
|                 if (m_context.has_facts(r->get_decl(i))) { |                 if (m_context.has_facts(r->get_decl(i))) { | ||||||
|                     return 0; |                     return 0; | ||||||
|                 } |                 } | ||||||
|  | 
 | ||||||
|                 if (r->is_neg_tail(i)) { |                 if (r->is_neg_tail(i)) { | ||||||
|                     if (!engine.get_fact(r->get_decl(i)).is_reachable()) { |                     if (!engine.get_fact(r->get_decl(i)).is_reachable()) { | ||||||
|                         if (!new_tail) { |                         if (!new_tail) { | ||||||
|  | @ -53,11 +54,14 @@ namespace datalog { | ||||||
|                             } |                             } | ||||||
|                             new_tail = true; |                             new_tail = true; | ||||||
|                         } |                         } | ||||||
|                     } else if (new_tail) { |                     }  | ||||||
|  |                     else if (new_tail) { | ||||||
|                         m_new_tail.push_back(r->get_tail(i)); |                         m_new_tail.push_back(r->get_tail(i)); | ||||||
|                         m_new_tail_neg.push_back(true); |                         m_new_tail_neg.push_back(true); | ||||||
|                     } |                     } | ||||||
|                 } else { |                 }  | ||||||
|  | 
 | ||||||
|  |                 else { | ||||||
|                     SASSERT(!new_tail); |                     SASSERT(!new_tail); | ||||||
|                     if (!engine.get_fact(r->get_decl(i)).is_reachable()) { |                     if (!engine.get_fact(r->get_decl(i)).is_reachable()) { | ||||||
|                         contained = false; |                         contained = false; | ||||||
|  |  | ||||||
|  | @ -1573,7 +1573,8 @@ private: | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 expr * p = m_manager.mk_pattern(ts.size(), (app*const*)(ts.c_ptr())); |                 expr_ref p(m_manager); | ||||||
|  |                 p = m_manager.mk_pattern(ts.size(), (app*const*)(ts.c_ptr())); | ||||||
|                 if (!p || (!ignore_user_patterns() && !m_pattern_validator(num_bindings, p, children[0]->line(), children[0]->pos()))) { |                 if (!p || (!ignore_user_patterns() && !m_pattern_validator(num_bindings, p, children[0]->line(), children[0]->pos()))) { | ||||||
|                     set_error("invalid pattern", children[0]); |                     set_error("invalid pattern", children[0]); | ||||||
|                     return false; |                     return false; | ||||||
|  | @ -1581,8 +1582,11 @@ private: | ||||||
|                 patterns.push_back(p); |                 patterns.push_back(p); | ||||||
|             } |             } | ||||||
|             else if (children[0]->string() == symbol("ex_act") && ts.size() == 1) { |             else if (children[0]->string() == symbol("ex_act") && ts.size() == 1) { | ||||||
|                 app * sk_hack = m_manager.mk_app(m_sk_hack, 1, ts.c_ptr()); |                 app_ref sk_hack(m_manager); | ||||||
|                 expr * p = m_manager.mk_pattern(1, &sk_hack); |                 sk_hack = m_manager.mk_app(m_sk_hack, 1, ts.c_ptr()); | ||||||
|  |                 app * sk_hackp = sk_hack.get(); | ||||||
|  |                 expr_ref p(m_manager); | ||||||
|  |                 p = m_manager.mk_pattern(1, &sk_hackp); | ||||||
|                 if (!p || (!ignore_user_patterns() && !m_pattern_validator(num_bindings, p, children[0]->line(), children[0]->pos()))) { |                 if (!p || (!ignore_user_patterns() && !m_pattern_validator(num_bindings, p, children[0]->line(), children[0]->pos()))) { | ||||||
|                     set_error("invalid pattern", children[0]); |                     set_error("invalid pattern", children[0]); | ||||||
|                     return false; |                     return false; | ||||||
|  |  | ||||||
|  | @ -493,14 +493,14 @@ namespace sat { | ||||||
|     void bceq::operator()() { |     void bceq::operator()() { | ||||||
|         if (!m_solver.m_config.m_bcd) return; |         if (!m_solver.m_config.m_bcd) return; | ||||||
|         flet<bool> _disable_bcd(m_solver.m_config.m_bcd, false); |         flet<bool> _disable_bcd(m_solver.m_config.m_bcd, false); | ||||||
|         flet<bool> _disable_min(m_solver.m_config.m_minimize_core, false); |         flet<bool> _disable_min(m_solver.m_config.m_core_minimize, false); | ||||||
|         flet<bool> _disable_opt(m_solver.m_config.m_optimize_model, false); |         flet<bool> _disable_opt(m_solver.m_config.m_optimize_model, false); | ||||||
|         flet<unsigned> _bound_maxc(m_solver.m_config.m_max_conflicts, 1500); |         flet<unsigned> _bound_maxc(m_solver.m_config.m_max_conflicts, 1500); | ||||||
| 
 | 
 | ||||||
|         use_list     ul;         |         use_list     ul;         | ||||||
|         solver       s(m_solver.m_params, m_solver.rlimit(), 0); |         solver       s(m_solver.m_params, m_solver.rlimit(), 0); | ||||||
|         s.m_config.m_bcd            = false; |         s.m_config.m_bcd            = false; | ||||||
|         s.m_config.m_minimize_core  = false; |         s.m_config.m_core_minimize  = false; | ||||||
|         s.m_config.m_optimize_model = false; |         s.m_config.m_optimize_model = false; | ||||||
|         s.m_config.m_max_conflicts  = 1500; |         s.m_config.m_max_conflicts  = 1500; | ||||||
|         m_use_list = &ul; |         m_use_list = &ul; | ||||||
|  |  | ||||||
|  | @ -107,8 +107,8 @@ namespace sat { | ||||||
|             m_gc_increment    = p.gc_increment(); |             m_gc_increment    = p.gc_increment(); | ||||||
|         } |         } | ||||||
|         m_minimize_lemmas = p.minimize_lemmas(); |         m_minimize_lemmas = p.minimize_lemmas(); | ||||||
|         m_minimize_core   = p.minimize_core(); |         m_core_minimize   = p.core_minimize(); | ||||||
|         m_minimize_core_partial   = p.minimize_core_partial(); |         m_core_minimize_partial   = p.core_minimize_partial(); | ||||||
|         m_optimize_model  = p.optimize_model(); |         m_optimize_model  = p.optimize_model(); | ||||||
|         m_bcd             = p.bcd(); |         m_bcd             = p.bcd(); | ||||||
|         m_dyn_sub_res     = p.dyn_sub_res(); |         m_dyn_sub_res     = p.dyn_sub_res(); | ||||||
|  |  | ||||||
|  | @ -69,8 +69,8 @@ namespace sat { | ||||||
| 
 | 
 | ||||||
|         bool               m_minimize_lemmas; |         bool               m_minimize_lemmas; | ||||||
|         bool               m_dyn_sub_res; |         bool               m_dyn_sub_res; | ||||||
|         bool               m_minimize_core; |         bool               m_core_minimize; | ||||||
|         bool               m_minimize_core_partial; |         bool               m_core_minimize_partial; | ||||||
|         bool               m_optimize_model; |         bool               m_optimize_model; | ||||||
|         bool               m_bcd; |         bool               m_bcd; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -58,7 +58,7 @@ namespace sat { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     lbool mus::operator()() { |     lbool mus::operator()() { | ||||||
|         flet<bool> _disable_min(s.m_config.m_minimize_core, false); |         flet<bool> _disable_min(s.m_config.m_core_minimize, false); | ||||||
|         flet<bool> _disable_opt(s.m_config.m_optimize_model, false); |         flet<bool> _disable_opt(s.m_config.m_optimize_model, false); | ||||||
|         flet<bool> _is_active(m_is_active, true); |         flet<bool> _is_active(m_is_active, true); | ||||||
|         IF_VERBOSE(3, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";); |         IF_VERBOSE(3, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";); | ||||||
|  | @ -69,7 +69,7 @@ namespace sat { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     lbool mus::mus1() { |     lbool mus::mus1() { | ||||||
|         bool minimize_partial = s.m_config.m_minimize_core_partial; |         bool minimize_partial = s.m_config.m_core_minimize_partial; | ||||||
|         TRACE("sat", tout << "old core: " << s.get_core() << "\n";); |         TRACE("sat", tout << "old core: " << s.get_core() << "\n";); | ||||||
|         literal_vector& core = get_core(); |         literal_vector& core = get_core(); | ||||||
|         literal_vector& mus = m_mus; |         literal_vector& mus = m_mus; | ||||||
|  | @ -96,7 +96,7 @@ namespace sat { | ||||||
|                 // IF_VERBOSE(0, verbose_stream() << "num literals: " << core << " " << mus << "\n";);
 |                 // IF_VERBOSE(0, verbose_stream() << "num literals: " << core << " " << mus << "\n";);
 | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             if (s.m_config.m_minimize_core_partial && s.m_stats.m_restart - m_restart > m_max_restarts) { |             if (s.m_config.m_core_minimize_partial && s.m_stats.m_restart - m_restart > m_max_restarts) { | ||||||
|                 IF_VERBOSE(1, verbose_stream() << "(sat restart budget exceeded)\n";); |                 IF_VERBOSE(1, verbose_stream() << "(sat restart budget exceeded)\n";); | ||||||
|                 set_core(); |                 set_core(); | ||||||
|                 return l_true; |                 return l_true; | ||||||
|  | @ -172,7 +172,7 @@ namespace sat { | ||||||
| 
 | 
 | ||||||
|     lbool mus::qx(literal_set& assignment, literal_set& support, bool has_support) { |     lbool mus::qx(literal_set& assignment, literal_set& support, bool has_support) { | ||||||
|         lbool is_sat = l_true; |         lbool is_sat = l_true; | ||||||
|         if (s.m_config.m_minimize_core_partial && s.m_stats.m_restart - m_restart > m_max_restarts) { |         if (s.m_config.m_core_minimize_partial && s.m_stats.m_restart - m_restart > m_max_restarts) { | ||||||
|             IF_VERBOSE(1, verbose_stream() << "(sat restart budget exceeded)\n";); |             IF_VERBOSE(1, verbose_stream() << "(sat restart budget exceeded)\n";); | ||||||
|             return l_true; |             return l_true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -19,8 +19,8 @@ def_module_params('sat', | ||||||
|                           ('gc.k', UINT, 7, 'learned clauses that are inactive for k gc rounds are permanently deleted (only used in dyn_psm)'), |                           ('gc.k', UINT, 7, 'learned clauses that are inactive for k gc rounds are permanently deleted (only used in dyn_psm)'), | ||||||
|                           ('minimize_lemmas', BOOL, True, 'minimize learned clauses'), |                           ('minimize_lemmas', BOOL, True, 'minimize learned clauses'), | ||||||
|                           ('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'), |                           ('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'), | ||||||
|                           ('minimize_core', BOOL, False, 'minimize computed core'), |                           ('core.minimize', BOOL, False, 'minimize computed core'), | ||||||
|                           ('minimize_core_partial', BOOL, False, 'apply partial (cheap) core minimization'), |                           ('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'), | ||||||
|                           ('optimize_model', BOOL, False, 'enable optimization of soft constraints'), |                           ('optimize_model', BOOL, False, 'enable optimization of soft constraints'), | ||||||
|                           ('bcd', BOOL, False, 'enable blocked clause decomposition for equality extraction'), |                           ('bcd', BOOL, False, 'enable blocked clause decomposition for equality extraction'), | ||||||
|                           ('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'))) |                           ('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'))) | ||||||
|  |  | ||||||
|  | @ -937,7 +937,7 @@ namespace sat { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     bool solver::init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight) { |     bool solver::init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight) { | ||||||
|         flet<bool> _min1(m_config.m_minimize_core, false); |         flet<bool> _min1(m_config.m_core_minimize, false); | ||||||
|         m_weight = 0; |         m_weight = 0; | ||||||
|         m_blocker.reset(); |         m_blocker.reset(); | ||||||
|         svector<lbool> values; |         svector<lbool> values; | ||||||
|  | @ -2015,7 +2015,7 @@ namespace sat { | ||||||
|             idx--; |             idx--; | ||||||
|         }         |         }         | ||||||
|         reset_unmark(old_size); |         reset_unmark(old_size); | ||||||
|         if (m_config.m_minimize_core) { |         if (m_config.m_core_minimize) { | ||||||
|             if (m_min_core_valid && m_min_core.size() < m_core.size()) { |             if (m_min_core_valid && m_min_core.size() < m_core.size()) { | ||||||
|                 IF_VERBOSE(1, verbose_stream() << "(sat.updating core " << m_min_core.size() << " " << m_core.size() << ")\n";); |                 IF_VERBOSE(1, verbose_stream() << "(sat.updating core " << m_min_core.size() << " " << m_core.size() << ")\n";); | ||||||
|                 m_core.reset(); |                 m_core.reset(); | ||||||
|  |  | ||||||
|  | @ -403,7 +403,6 @@ namespace smt { | ||||||
|         // the previous levels were already inconsistent, or the inconsistency was
 |         // the previous levels were already inconsistent, or the inconsistency was
 | ||||||
|         // triggered by an axiom or justification proof wrapper, this two kinds
 |         // triggered by an axiom or justification proof wrapper, this two kinds
 | ||||||
|         // of justification are considered level zero.
 |         // of justification are considered level zero.
 | ||||||
| 
 |  | ||||||
|         if (m_conflict_lvl <= m_ctx.get_search_level()) { |         if (m_conflict_lvl <= m_ctx.get_search_level()) { | ||||||
|             TRACE("conflict", tout << "problem is unsat\n";); |             TRACE("conflict", tout << "problem is unsat\n";); | ||||||
|             if (m_manager.proofs_enabled()) |             if (m_manager.proofs_enabled()) | ||||||
|  |  | ||||||
|  | @ -18,6 +18,8 @@ Revision History: | ||||||
| --*/ | --*/ | ||||||
| #include "smt_context.h" | #include "smt_context.h" | ||||||
| #include "ast_util.h" | #include "ast_util.h" | ||||||
|  | #include "datatype_decl_plugin.h" | ||||||
|  | #include "model_pp.h" | ||||||
| 
 | 
 | ||||||
| namespace smt { | namespace smt { | ||||||
| 
 | 
 | ||||||
|  | @ -31,77 +33,112 @@ namespace smt { | ||||||
|         return mk_and(premises); |         return mk_and(premises); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void context::extract_fixed_consequences(unsigned start, obj_map<expr, expr*>& vars, uint_set const& assumptions, expr_ref_vector& conseq) { |     //
 | ||||||
|  |     // The literal lit is assigned at the search level, so it follows from the assumptions.
 | ||||||
|  |     // We retrieve the set of assumptions it depends on in the set 's'.
 | ||||||
|  |     // The map m_antecedents contains the association from these literals to the assumptions they depend on.
 | ||||||
|  |     // We then examine the contents of the literal lit and augment the set of consequences in one of the following cases:
 | ||||||
|  |     // - e is a propositional atom and it is one of the variables that is to be fixed.
 | ||||||
|  |     // - e is an equality between a variable and value that is to be fixed.
 | ||||||
|  |     // - e is a data-type recognizer of a variable that is to be fixed.
 | ||||||
|  |     // 
 | ||||||
|  |     void context::extract_fixed_consequences(literal lit, obj_map<expr, expr*>& vars, uint_set const& assumptions, expr_ref_vector& conseq) { | ||||||
|         ast_manager& m = m_manager; |         ast_manager& m = m_manager; | ||||||
|         pop_to_search_lvl(); |         datatype_util dt(m); | ||||||
|         literal_vector const& lits = assigned_literals(); |  | ||||||
|         unsigned sz = lits.size(); |  | ||||||
|         expr* e1, *e2;        |         expr* e1, *e2;        | ||||||
|         expr_ref fml(m);         |         expr_ref fml(m);         | ||||||
|         for (unsigned i = start; i < sz; ++i) {             |         if (lit == true_literal) return; | ||||||
|             literal lit = lits[i]; |         expr* e = bool_var2expr(lit.var()); | ||||||
|             if (lit == true_literal) continue; |         uint_set s; | ||||||
|             expr* e = bool_var2expr(lit.var()); |         if (assumptions.contains(lit.var())) { | ||||||
|             uint_set s; |             s.insert(lit.var()); | ||||||
|             if (assumptions.contains(lit.var())) { |         } | ||||||
|                 s.insert(lit.var()); |         else { | ||||||
|             } |             b_justification js = get_justification(lit.var()); | ||||||
|             else { |             switch (js.get_kind()) { | ||||||
|                 b_justification js = get_justification(lit.var()); |             case b_justification::CLAUSE: { | ||||||
|                 switch (js.get_kind()) { |                 clause * cls = js.get_clause(); | ||||||
|                 case b_justification::CLAUSE: { |                 if (!cls) break; | ||||||
|                     clause * cls      = js.get_clause(); |                 unsigned num_lits = cls->get_num_literals(); | ||||||
|                     unsigned num_lits = cls->get_num_literals(); |                 for (unsigned j = 0; j < num_lits; ++j) { | ||||||
|                     for (unsigned j = 0; j < num_lits; ++j) { |                     literal lit2 = cls->get_literal(j); | ||||||
|                         literal lit2 = cls->get_literal(j); |                     if (lit2.var() != lit.var()) { | ||||||
|                         if (lit2.var() != lit.var()) { |                         s |= m_antecedents.find(lit2.var()); | ||||||
|                             s |= m_antecedents.find(lit2.var()); |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case b_justification::BIN_CLAUSE: { |  | ||||||
|                     s |= m_antecedents.find(js.get_literal().var()); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case b_justification::AXIOM: { |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case b_justification::JUSTIFICATION: { |  | ||||||
|                     literal_vector literals; |  | ||||||
|                     m_conflict_resolution->justification2literals(js.get_justification(), literals); |  | ||||||
|                     for (unsigned j = 0; j < literals.size(); ++j) { |  | ||||||
|                         s |= m_antecedents.find(literals[j].var()); |  | ||||||
|                     } |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 } |                 } | ||||||
|  |                 break; | ||||||
|             } |             } | ||||||
|             m_antecedents.insert(lit.var(), s); |             case b_justification::BIN_CLAUSE: { | ||||||
|             TRACE("context", display_literal_verbose(tout, lit); tout << " " << s << "\n";); |                 s |= m_antecedents.find(js.get_literal().var()); | ||||||
|             bool found = false; |                 break; | ||||||
|             if (vars.contains(e)) { |  | ||||||
|                 found = true; |  | ||||||
|                 fml = lit.sign()?m.mk_not(e):e; |  | ||||||
|                 vars.erase(e); |  | ||||||
|             } |             } | ||||||
|             else if (!lit.sign() && m.is_eq(e, e1, e2)) { |             case b_justification::AXIOM: { | ||||||
|                 if (vars.contains(e2)) { |                 break; | ||||||
|                     std::swap(e1, e2); |             } | ||||||
|                 } |             case b_justification::JUSTIFICATION: { | ||||||
|                 if (vars.contains(e1) && m.is_value(e2)) { |                 literal_vector literals; | ||||||
|                     found = true; |                 m_conflict_resolution->justification2literals(js.get_justification(), literals); | ||||||
|                     fml = e; |                 for (unsigned j = 0; j < literals.size(); ++j) { | ||||||
|                     vars.erase(e1);                     |                     s |= m_antecedents.find(literals[j].var()); | ||||||
|                 } |                 } | ||||||
|  |                 break; | ||||||
|             } |             } | ||||||
|             if (found) { |  | ||||||
|                 fml = m.mk_implies(antecedent2fml(s), fml); |  | ||||||
|                 conseq.push_back(fml); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         m_antecedents.insert(lit.var(), s); | ||||||
|  |         TRACE("context", display_literal_verbose(tout, lit); tout << " " << s << "\n";); | ||||||
|  |         bool found = false; | ||||||
|  |         if (vars.contains(e)) { | ||||||
|  |             found = true; | ||||||
|  |             fml = lit.sign() ? m.mk_not(e) : e; | ||||||
|  |             vars.erase(e); | ||||||
|  |         } | ||||||
|  |         else if (!lit.sign() && m.is_eq(e, e1, e2)) { | ||||||
|  |             if (vars.contains(e2)) { | ||||||
|  |                 std::swap(e1, e2); | ||||||
|  |             } | ||||||
|  |             if (vars.contains(e1) && m.is_value(e2)) { | ||||||
|  |                 found = true; | ||||||
|  |                 fml = e; | ||||||
|  |                 vars.erase(e1); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else if (!lit.sign() && is_app(e) && dt.is_recognizer(to_app(e)->get_decl())) { | ||||||
|  |             if (vars.contains(to_app(e)->get_arg(0))) { | ||||||
|  |                 found = true; | ||||||
|  |                 fml = m.mk_eq(to_app(e)->get_arg(0), m.mk_const(dt.get_recognizer_constructor(to_app(e)->get_decl()))); | ||||||
|  |                 vars.erase(to_app(e)->get_arg(0)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (found) { | ||||||
|  |             fml = m.mk_implies(antecedent2fml(s), fml); | ||||||
|  |             conseq.push_back(fml); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void context::extract_fixed_consequences(unsigned start, obj_map<expr, expr*>& vars, uint_set const& assumptions, expr_ref_vector& conseq) { | ||||||
|  |         pop_to_search_lvl(); | ||||||
|  |         SASSERT(!inconsistent()); | ||||||
|  |         literal_vector const& lits = assigned_literals(); | ||||||
|  |         unsigned sz = lits.size(); | ||||||
|  |         for (unsigned i = start; i < sz; ++i) {             | ||||||
|  |             extract_fixed_consequences(lits[i], vars, assumptions, conseq); | ||||||
|  |         } | ||||||
|  |         SASSERT(!inconsistent()); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |     //
 | ||||||
|  |     // The assignment stack is assumed consistent.
 | ||||||
|  |     // For each Boolean variable, we check if there is a literal assigned to the 
 | ||||||
|  |     // opposite value of the reference model, and for non-Boolean variables we
 | ||||||
|  |     // check if the current state forces the variable to be distinct from the reference value.
 | ||||||
|  |     // 
 | ||||||
|  |     // For yet to be determined Boolean variables we furthermore force the phase to be opposite
 | ||||||
|  |     // to the reference value in the attempt to let the sat engine emerge with a model that
 | ||||||
|  |     // rules out as many non-fixed variables as possible.
 | ||||||
|  |     // 
 | ||||||
|  | 
 | ||||||
|     unsigned context::delete_unfixed(obj_map<expr, expr*>& var2val, expr_ref_vector& unfixed) { |     unsigned context::delete_unfixed(obj_map<expr, expr*>& var2val, expr_ref_vector& unfixed) { | ||||||
|         ast_manager& m = m_manager; |         ast_manager& m = m_manager; | ||||||
|         ptr_vector<expr> to_delete; |         ptr_vector<expr> to_delete; | ||||||
|  | @ -144,10 +181,15 @@ namespace smt { | ||||||
|         return to_delete.size(); |         return to_delete.size(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | #define are_equal(v, k) (e_internalized(k) && e_internalized(v) && get_enode(k)->get_root() == get_enode(v)->get_root()) | ||||||
|  | 
 | ||||||
|     //
 |     //
 | ||||||
|     // Extract equalities that are congruent at the search level.
 |     // Extract equalities that are congruent at the search level.
 | ||||||
|  |     // Add a clause to short-circuit the congruence justifications for
 | ||||||
|  |     // next rounds.
 | ||||||
|     // 
 |     // 
 | ||||||
|     unsigned context::extract_fixed_eqs(obj_map<expr, expr*>& var2val, expr_ref_vector& conseq) { |     unsigned context::extract_fixed_eqs(obj_map<expr, expr*>& var2val, expr_ref_vector& conseq) { | ||||||
|  |         TRACE("context", tout << "extract fixed consequences\n";); | ||||||
|         ast_manager& m = m_manager; |         ast_manager& m = m_manager; | ||||||
|         ptr_vector<expr> to_delete; |         ptr_vector<expr> to_delete; | ||||||
|         expr_ref fml(m), eq(m); |         expr_ref fml(m), eq(m); | ||||||
|  | @ -155,8 +197,7 @@ namespace smt { | ||||||
|         for (; it != end; ++it) { |         for (; it != end; ++it) { | ||||||
|             expr* k = it->m_key; |             expr* k = it->m_key; | ||||||
|             expr* v = it->m_value; |             expr* v = it->m_value; | ||||||
|             if (!m.is_bool(k) && e_internalized(k) && e_internalized(v) &&  |             if (!m.is_bool(k) && are_equal(k, v)) { | ||||||
|                 get_enode(k)->get_root() == get_enode(v)->get_root()) { |  | ||||||
|                 literal_vector literals; |                 literal_vector literals; | ||||||
|                 m_conflict_resolution->eq2literals(get_enode(v), get_enode(k), literals); |                 m_conflict_resolution->eq2literals(get_enode(v), get_enode(k), literals); | ||||||
|                 uint_set s; |                 uint_set s; | ||||||
|  | @ -175,9 +216,10 @@ namespace smt { | ||||||
|                 } |                 } | ||||||
|                 eq = mk_eq_atom(k, v); |                 eq = mk_eq_atom(k, v); | ||||||
|                 internalize_formula(eq, false); |                 internalize_formula(eq, false); | ||||||
|                 literal lit(get_bool_var(eq), true); |                 literal lit(get_bool_var(eq), false); | ||||||
|                 literals.push_back(lit); |                 literals.push_back(lit); | ||||||
|                 mk_clause(literals.size(), literals.c_ptr(), 0); |                 mk_clause(literals.size(), literals.c_ptr(), 0); | ||||||
|  |                 TRACE("context", display_literals_verbose(tout, literals.size(), literals.c_ptr());); | ||||||
|             } |             } | ||||||
|         }     |         }     | ||||||
|         for (unsigned i = 0; i < to_delete.size(); ++i) { |         for (unsigned i = 0; i < to_delete.size(); ++i) { | ||||||
|  | @ -192,6 +234,7 @@ namespace smt { | ||||||
|                                     expr_ref_vector& unfixed) { |                                     expr_ref_vector& unfixed) { | ||||||
| 
 | 
 | ||||||
|         m_antecedents.reset(); |         m_antecedents.reset(); | ||||||
|  |         pop_to_base_lvl(); | ||||||
|         lbool is_sat = check(assumptions.size(), assumptions.c_ptr()); |         lbool is_sat = check(assumptions.size(), assumptions.c_ptr()); | ||||||
|         if (is_sat != l_true) { |         if (is_sat != l_true) { | ||||||
|             return is_sat; |             return is_sat; | ||||||
|  | @ -207,6 +250,7 @@ namespace smt { | ||||||
|         expr_ref_vector trail(m); |         expr_ref_vector trail(m); | ||||||
|         model_evaluator eval(*mdl.get()); |         model_evaluator eval(*mdl.get()); | ||||||
|         expr_ref val(m); |         expr_ref val(m); | ||||||
|  |         TRACE("context", model_pp(tout, *mdl);); | ||||||
|         for (unsigned i = 0; i < vars.size(); ++i) { |         for (unsigned i = 0; i < vars.size(); ++i) { | ||||||
|             eval(vars[i], val); |             eval(vars[i], val); | ||||||
|             if (m.is_value(val)) { |             if (m.is_value(val)) { | ||||||
|  | @ -233,9 +277,17 @@ namespace smt { | ||||||
|             obj_map<expr,expr*>::iterator it = var2val.begin(); |             obj_map<expr,expr*>::iterator it = var2val.begin(); | ||||||
|             expr* e = it->m_key; |             expr* e = it->m_key; | ||||||
|             expr* val = it->m_value; |             expr* val = it->m_value; | ||||||
|             push_scope(); |  | ||||||
|             unsigned current_level = m_scope_lvl; |  | ||||||
| 
 | 
 | ||||||
|  |             TRACE("context", tout << "scope level: " << get_scope_level() << "\n";); | ||||||
|  |             SASSERT(!inconsistent()); | ||||||
|  | 
 | ||||||
|  |             //
 | ||||||
|  |             // The current variable is checked to be a backbone
 | ||||||
|  |             // We add the negation of the reference assignment to the variable.
 | ||||||
|  |             // If the variable is a Boolean, it means adding literal that has
 | ||||||
|  |             // the opposite value of the current reference model.
 | ||||||
|  |             // If the variable is a non-Boolean, it means adding a disequality.
 | ||||||
|  |             //
 | ||||||
|             literal lit; |             literal lit; | ||||||
|             if (m.is_bool(e)) { |             if (m.is_bool(e)) { | ||||||
|                 lit = literal(get_bool_var(e), m.is_true(val)); |                 lit = literal(get_bool_var(e), m.is_true(val)); | ||||||
|  | @ -244,9 +296,20 @@ namespace smt { | ||||||
|                 eq = mk_eq_atom(e, val); |                 eq = mk_eq_atom(e, val); | ||||||
|                 internalize_formula(eq, false); |                 internalize_formula(eq, false); | ||||||
|                 lit = literal(get_bool_var(eq), true); |                 lit = literal(get_bool_var(eq), true); | ||||||
|  |                 TRACE("context", tout << mk_pp(e, m) << " " << mk_pp(val, m) << "\n"; | ||||||
|  |                       display_literal_verbose(tout, lit); tout << "\n";  | ||||||
|  |                       tout << "Equal: " << are_equal(e, val) << "\n";); | ||||||
|             } |             } | ||||||
|  |             mark_as_relevant(lit); | ||||||
|  |             push_scope(); | ||||||
|             assign(lit, b_justification::mk_axiom(), true); |             assign(lit, b_justification::mk_axiom(), true); | ||||||
|             flet<bool> l(m_searching, true); |             flet<bool> l(m_searching, true); | ||||||
|  | 
 | ||||||
|  |             // 
 | ||||||
|  |             // We check if the current assignment stack can be extended to a 
 | ||||||
|  |             // satisfying assignment. bounded search may decide to restart, 
 | ||||||
|  |             // in which case it returns l_undef and clears search failure.
 | ||||||
|  |             //
 | ||||||
|             while (true) { |             while (true) { | ||||||
|                 is_sat = bounded_search(); |                 is_sat = bounded_search(); | ||||||
|                 TRACE("context", tout << "search result: " << is_sat << "\n";); |                 TRACE("context", tout << "search result: " << is_sat << "\n";); | ||||||
|  | @ -260,33 +323,78 @@ namespace smt { | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             if (get_assignment(lit) == l_true) { |             //
 | ||||||
|  |             // If the state is satisfiable with the current variable assigned to 
 | ||||||
|  |             // a different value from the reference model, it is unfixed.
 | ||||||
|  |             // 
 | ||||||
|  |             // If it is assigned above the search level we can't conclude anything
 | ||||||
|  |             // about its value. 
 | ||||||
|  |             // extract_fixed_consequences pops the assignment stack to the search level
 | ||||||
|  |             // so this sets up the state to retry finding fixed values.
 | ||||||
|  |             // 
 | ||||||
|  |             // Otherwise, the variable is fixed.
 | ||||||
|  |             // - it is either assigned at the search level to l_false, or
 | ||||||
|  |             // - the state is l_false, which means that the variable is fixed by
 | ||||||
|  |             //   the background constraints (and does not depend on assumptions).
 | ||||||
|  |             // 
 | ||||||
|  |             if (is_sat == l_true && get_assignment(lit) == l_true && is_relevant(lit)) {  | ||||||
|                 var2val.erase(e); |                 var2val.erase(e); | ||||||
|                 unfixed.push_back(e); |                 unfixed.push_back(e); | ||||||
|  |                 SASSERT(!are_equal(e, val)); | ||||||
|  |                 TRACE("context", tout << mk_pp(e, m) << " is unfixed\n"; | ||||||
|  |                       display_literal_verbose(tout, lit); tout << "\n"; | ||||||
|  |                       tout << "relevant: " << is_relevant(lit) << "\n"; | ||||||
|  |                       display(tout);); | ||||||
|             } |             } | ||||||
|             else if (get_assign_level(lit) > get_search_level()) { |             else if (is_sat == l_true && (get_assign_level(lit) > get_search_level() || !is_relevant(lit))) { | ||||||
|                 TRACE("context", tout << "Retry fixing: " << mk_pp(e, m) << "\n";); |                 TRACE("context", tout << "Retry fixing: " << mk_pp(e, m) << "\n";); | ||||||
|                 pop_to_search_lvl(); |                 extract_fixed_consequences(num_units, var2val, _assumptions, conseq); | ||||||
|                 ++num_reiterations; |                 ++num_reiterations; | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 TRACE("context", tout << "Fixed: " << mk_pp(e, m) << "\n";); |                 //
 | ||||||
|  |                 // The state can be labeled as inconsistent when the implied consequence does
 | ||||||
|  |                 // not depend on assumptions, then the conflict level sits at the search level
 | ||||||
|  |                 // which causes the conflict resolver to decide that the state is unsat.
 | ||||||
|  |                 //
 | ||||||
|  |                 if (l_false == is_sat) { | ||||||
|  |                     SASSERT(inconsistent()); | ||||||
|  |                     m_conflict = null_b_justification; | ||||||
|  |                     m_not_l = null_literal; | ||||||
|  |                 } | ||||||
|  |                 TRACE("context", tout << "Fixed: " << mk_pp(e, m) << " " << is_sat << "\n"; | ||||||
|  |                       if (is_sat == l_false) display(tout);); | ||||||
|  |                  | ||||||
|             } |             } | ||||||
|             ++num_iterations; |             ++num_iterations; | ||||||
| 
 | 
 | ||||||
|  |             //
 | ||||||
|  |             // Check the slow pass: it retrieves an updated model and checks if the
 | ||||||
|  |             // values in the updated model differ from the values in the reference
 | ||||||
|  |             // model. 
 | ||||||
|  |             // 
 | ||||||
|             bool apply_slow_pass = model_threshold <= num_iterations || num_iterations <= 2; |             bool apply_slow_pass = model_threshold <= num_iterations || num_iterations <= 2; | ||||||
|             if (apply_slow_pass) { |             if (apply_slow_pass && is_sat == l_true) { | ||||||
|                 num_unfixed += delete_unfixed(var2val, unfixed); |                 num_unfixed += delete_unfixed(var2val, unfixed); | ||||||
|                 // The next time we check the model is after 1.5 additional iterations.
 |                 // The next time we check the model is after 1.5 additional iterations.
 | ||||||
|                 model_threshold *= 3; |                 model_threshold *= 3; | ||||||
|                 model_threshold /= 2;                                 |                 model_threshold /= 2;                                 | ||||||
|             } |             } | ||||||
|             // repeat until we either have a model with negated literal or 
 |  | ||||||
|             // the literal is implied at base.
 |  | ||||||
| 
 | 
 | ||||||
|  |             //
 | ||||||
|  |             // Walk the assignment stack at level 1 for learned consequences.
 | ||||||
|  |             // The current literal should be assigned at the search level unless
 | ||||||
|  |             // the state is is_sat == l_true and the assignment to lit is l_true.
 | ||||||
|  |             // This condition is checked above.
 | ||||||
|  |             // 
 | ||||||
|             extract_fixed_consequences(num_units, var2val, _assumptions, conseq); |             extract_fixed_consequences(num_units, var2val, _assumptions, conseq); | ||||||
|             num_units = assigned_literals().size(); |             num_units = assigned_literals().size(); | ||||||
|  | 
 | ||||||
|  |             //
 | ||||||
|  |             // Fixed equalities can be extracted by walking all variables and checking
 | ||||||
|  |             // if the congruence roots are equal at the search level.
 | ||||||
|  |             // 
 | ||||||
|             if (apply_slow_pass) { |             if (apply_slow_pass) { | ||||||
|                 num_fixed_eqs += extract_fixed_eqs(var2val, conseq); |                 num_fixed_eqs += extract_fixed_eqs(var2val, conseq); | ||||||
|                 IF_VERBOSE(1, verbose_stream() << "(get-consequences" |                 IF_VERBOSE(1, verbose_stream() << "(get-consequences" | ||||||
|  | @ -306,18 +414,72 @@ namespace smt { | ||||||
|                       << " unfixed-deleted: " << num_unfixed |                       << " unfixed-deleted: " << num_unfixed | ||||||
|                       << ")\n";);         |                       << ")\n";);         | ||||||
|             } |             } | ||||||
|  |             TRACE("context", tout << "finishing " << mk_pp(e, m) << "\n";); | ||||||
|  |             SASSERT(!inconsistent()); | ||||||
|  |              | ||||||
|  |             //
 | ||||||
|  |             // This becomes unnecessary when the fixed consequence are 
 | ||||||
|  |             // completely extracted.
 | ||||||
|  |             // 
 | ||||||
|             if (var2val.contains(e)) { |             if (var2val.contains(e)) { | ||||||
|                 TRACE("context", tout << "Fixed value to " << mk_pp(e, m) << " was not processed\n";); |                 TRACE("context", tout << "Fixed value to " << mk_pp(e, m) << " was not processed\n";); | ||||||
|                 expr_ref fml(m); |                 expr_ref fml(m); | ||||||
|                 fml = m.mk_eq(e, var2val.find(e)); |                 fml = m.mk_eq(e, var2val.find(e)); | ||||||
|  |                 if (!m_antecedents.contains(lit.var())) { | ||||||
|  |                     extract_fixed_consequences(lit, var2val, _assumptions, conseq); | ||||||
|  |                 } | ||||||
|                 fml = m.mk_implies(antecedent2fml(m_antecedents[lit.var()]), fml); |                 fml = m.mk_implies(antecedent2fml(m_antecedents[lit.var()]), fml); | ||||||
|                 conseq.push_back(fml); |                 conseq.push_back(fml); | ||||||
|                 var2val.erase(e); |                 var2val.erase(e); | ||||||
|                 SASSERT(get_assignment(lit) == l_false); |  | ||||||
|             }         |             }         | ||||||
|         } |         } | ||||||
|         end_search(); |         end_search(); | ||||||
|  |         DEBUG_CODE(validate_consequences(assumptions, vars, conseq, unfixed);); | ||||||
|         return l_true; |         return l_true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     //
 | ||||||
|  |     // Validate, in a slow pass, that the current consequences are correctly 
 | ||||||
|  |     // extracted.
 | ||||||
|  |     // 
 | ||||||
|  |     void context::validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars,  | ||||||
|  |                                         expr_ref_vector const& conseq, expr_ref_vector const& unfixed) { | ||||||
|  |         ast_manager& m = m_manager; | ||||||
|  |         expr_ref tmp(m); | ||||||
|  |         SASSERT(!inconsistent()); | ||||||
|  |         for (unsigned i = 0; i < conseq.size(); ++i) { | ||||||
|  |             push();             | ||||||
|  |             for (unsigned j = 0; j < assumptions.size(); ++j) { | ||||||
|  |                 assert_expr(assumptions[j]); | ||||||
|  |             } | ||||||
|  |             TRACE("context", tout << "checking: " << mk_pp(conseq[i], m) << "\n";); | ||||||
|  |             tmp = m.mk_not(conseq[i]); | ||||||
|  |             assert_expr(tmp); | ||||||
|  |             lbool is_sat = check(); | ||||||
|  |             SASSERT(is_sat != l_true); | ||||||
|  |             pop(1); | ||||||
|  |         } | ||||||
|  |         model_ref mdl; | ||||||
|  |         for (unsigned i = 0; i < unfixed.size(); ++i) { | ||||||
|  |             push();             | ||||||
|  |             for (unsigned j = 0; j < assumptions.size(); ++j) { | ||||||
|  |                 assert_expr(assumptions[j]); | ||||||
|  |             } | ||||||
|  |             TRACE("context", tout << "checking unfixed: " << mk_pp(unfixed[i], m) << "\n";); | ||||||
|  |             lbool is_sat = check();             | ||||||
|  |             SASSERT(is_sat != l_false); | ||||||
|  |             if (is_sat == l_true) { | ||||||
|  |                 get_model(mdl); | ||||||
|  |                 mdl->eval(unfixed[i], tmp); | ||||||
|  |                 if (m.is_value(tmp)) { | ||||||
|  |                     tmp = m.mk_not(m.mk_eq(unfixed[i], tmp)); | ||||||
|  |                     assert_expr(tmp); | ||||||
|  |                     is_sat = check(); | ||||||
|  |                     SASSERT(is_sat != l_false); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             pop(1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1094,7 +1094,7 @@ namespace smt { | ||||||
|        \brief This method is invoked when a new disequality is asserted. |        \brief This method is invoked when a new disequality is asserted. | ||||||
|        The disequality is propagated to the theories. |        The disequality is propagated to the theories. | ||||||
|     */ |     */ | ||||||
|     void context::add_diseq(enode * n1, enode * n2) { |     bool context::add_diseq(enode * n1, enode * n2) { | ||||||
|         enode * r1 = n1->get_root(); |         enode * r1 = n1->get_root(); | ||||||
|         enode * r2 = n2->get_root(); |         enode * r2 = n2->get_root(); | ||||||
|         TRACE("add_diseq", tout << "assigning: #" << n1->get_owner_id() << " != #" << n2->get_owner_id() << "\n"; |         TRACE("add_diseq", tout << "assigning: #" << n1->get_owner_id() << " != #" << n2->get_owner_id() << "\n"; | ||||||
|  | @ -1111,7 +1111,7 @@ namespace smt { | ||||||
| 
 | 
 | ||||||
|         if (r1 == r2) { |         if (r1 == r2) { | ||||||
|             TRACE("add_diseq_inconsistent", tout << "add_diseq #" << n1->get_owner_id() << " #" << n2->get_owner_id() << " inconsistency, scope_lvl: " << m_scope_lvl << "\n";); |             TRACE("add_diseq_inconsistent", tout << "add_diseq #" << n1->get_owner_id() << " #" << n2->get_owner_id() << " inconsistency, scope_lvl: " << m_scope_lvl << "\n";); | ||||||
|             return; // context is inconsistent
 |             return false; // context is inconsistent
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Propagate disequalities to theories
 |         // Propagate disequalities to theories
 | ||||||
|  | @ -1145,6 +1145,7 @@ namespace smt { | ||||||
|                 l1 = l1->get_next(); |                 l1 = l1->get_next(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         return true; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -1400,7 +1401,9 @@ namespace smt { | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
|                     TRACE("add_diseq", display_eq_detail(tout, bool_var2enode(v));); |                     TRACE("add_diseq", display_eq_detail(tout, bool_var2enode(v));); | ||||||
|                     add_diseq(get_enode(lhs), get_enode(rhs)); |                     if (!add_diseq(get_enode(lhs), get_enode(rhs)) && !inconsistent()) { | ||||||
|  |                         set_conflict(b_justification(mk_justification(eq_propagation_justification(get_enode(lhs), get_enode(rhs)))), ~l);                         | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             else if (d.is_theory_atom()) { |             else if (d.is_theory_atom()) { | ||||||
|  |  | ||||||
|  | @ -942,7 +942,7 @@ namespace smt { | ||||||
|             push_eq(n1, n2, eq_justification::mk_cg(used_commutativity)); |             push_eq(n1, n2, eq_justification::mk_cg(used_commutativity)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         void add_diseq(enode * n1, enode * n2); |         bool add_diseq(enode * n1, enode * n2); | ||||||
| 
 | 
 | ||||||
|         void assign_quantifier(quantifier * q); |         void assign_quantifier(quantifier * q); | ||||||
| 
 | 
 | ||||||
|  | @ -1345,6 +1345,7 @@ namespace smt { | ||||||
|             vector<bool_var> b2v, ast_translation& tr); |             vector<bool_var> b2v, ast_translation& tr); | ||||||
| 
 | 
 | ||||||
|         u_map<uint_set> m_antecedents; |         u_map<uint_set> m_antecedents; | ||||||
|  |         void extract_fixed_consequences(literal lit, obj_map<expr, expr*>& var2val, uint_set const& assumptions, expr_ref_vector& conseq); | ||||||
|         void extract_fixed_consequences(unsigned idx, obj_map<expr, expr*>& var2val, uint_set const& assumptions, expr_ref_vector& conseq); |         void extract_fixed_consequences(unsigned idx, obj_map<expr, expr*>& var2val, uint_set const& assumptions, expr_ref_vector& conseq); | ||||||
|          |          | ||||||
|         unsigned delete_unfixed(obj_map<expr, expr*>& var2val, expr_ref_vector& unfixed); |         unsigned delete_unfixed(obj_map<expr, expr*>& var2val, expr_ref_vector& unfixed); | ||||||
|  | @ -1353,6 +1354,9 @@ namespace smt { | ||||||
| 
 | 
 | ||||||
|         expr_ref antecedent2fml(uint_set const& ante); |         expr_ref antecedent2fml(uint_set const& ante); | ||||||
| 
 | 
 | ||||||
|  |         void validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars,  | ||||||
|  |                                    expr_ref_vector const& conseq, expr_ref_vector const& unfixed); | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         context(ast_manager & m, smt_params & fp, params_ref const & p = params_ref()); |         context(ast_manager & m, smt_params & fp, params_ref const & p = params_ref()); | ||||||
|  |  | ||||||
|  | @ -1284,7 +1284,6 @@ namespace smt { | ||||||
|         TRACE("mk_clause", tout << "creating clause:\n"; display_literals(tout, num_lits, lits); tout << "\n";); |         TRACE("mk_clause", tout << "creating clause:\n"; display_literals(tout, num_lits, lits); tout << "\n";); | ||||||
|         switch (k) { |         switch (k) { | ||||||
|         case CLS_AUX: { |         case CLS_AUX: { | ||||||
|             unsigned old_num_lits = num_lits; |  | ||||||
|             literal_buffer simp_lits; |             literal_buffer simp_lits; | ||||||
|             if (!simplify_aux_clause_literals(num_lits, lits, simp_lits)) |             if (!simplify_aux_clause_literals(num_lits, lits, simp_lits)) | ||||||
|                 return 0; // clause is equivalent to true;
 |                 return 0; // clause is equivalent to true;
 | ||||||
|  |  | ||||||
|  | @ -64,7 +64,7 @@ namespace smt { | ||||||
|                     lower(v2)->push_justification(ante, numeral::zero(), proofs_enabled()); |                     lower(v2)->push_justification(ante, numeral::zero(), proofs_enabled()); | ||||||
|                     upper(v)->push_justification(ante, numeral::zero(), proofs_enabled()); |                     upper(v)->push_justification(ante, numeral::zero(), proofs_enabled()); | ||||||
| 
 | 
 | ||||||
|                     TRACE("arith_fixed_propagate_eq", tout << "propagate eq: v" << v << " = v" << v2 << "\n"; |                     TRACE("arith_eq", tout << "propagate eq: v" << v << " = v" << v2 << "\n"; | ||||||
|                           display_var(tout, v); |                           display_var(tout, v); | ||||||
|                           display_var(tout, v2);); |                           display_var(tout, v2);); | ||||||
|                     m_stats.m_fixed_eqs++; |                     m_stats.m_fixed_eqs++; | ||||||
|  | @ -175,7 +175,7 @@ namespace smt { | ||||||
|         timer.stop(); |         timer.stop(); | ||||||
|         ok++; |         ok++; | ||||||
|         if (ok % 100000 == 0) { |         if (ok % 100000 == 0) { | ||||||
|             TRACE("propagate_cheap_eq",  |             TRACE("arith_eq",  | ||||||
|                   tout << total << " " << ok << " "  |                   tout << total << " " << ok << " "  | ||||||
|                   << static_cast<double>(ok)/static_cast<double>(total)  |                   << static_cast<double>(ok)/static_cast<double>(total)  | ||||||
|                   << " " << timer.get_seconds() << "\n"; |                   << " " << timer.get_seconds() << "\n"; | ||||||
|  | @ -216,7 +216,7 @@ namespace smt { | ||||||
|     void theory_arith<Ext>::propagate_cheap_eq(unsigned rid) { |     void theory_arith<Ext>::propagate_cheap_eq(unsigned rid) { | ||||||
|         if (!propagate_eqs()) |         if (!propagate_eqs()) | ||||||
|             return; |             return; | ||||||
|         TRACE("propagate_cheap_eq", tout << "checking if row " << rid << " can propagate equality.\n"; |         TRACE("arith_eq", tout << "checking if row " << rid << " can propagate equality.\n"; | ||||||
|               display_row_info(tout, rid);); |               display_row_info(tout, rid);); | ||||||
|         row const & r = m_rows[rid]; |         row const & r = m_rows[rid]; | ||||||
|         theory_var x; |         theory_var x; | ||||||
|  | @ -258,7 +258,7 @@ namespace smt { | ||||||
|                 // found equality x = y
 |                 // found equality x = y
 | ||||||
|                 antecedents ante(*this); |                 antecedents ante(*this); | ||||||
|                 collect_fixed_var_justifications(r, ante); |                 collect_fixed_var_justifications(r, ante); | ||||||
|                 TRACE("propagate_cheap_eq", tout << "propagate eq using x-y=0 row:\n"; display_row_info(tout, r);); |                 TRACE("arith_eq", tout << "propagate eq using x-y=0 row:\n"; display_row_info(tout, r);); | ||||||
|                 m_stats.m_offset_eqs++; |                 m_stats.m_offset_eqs++; | ||||||
|                 propagate_eq_to_core(x, y, ante); |                 propagate_eq_to_core(x, y, ante); | ||||||
|             } |             } | ||||||
|  | @ -299,7 +299,7 @@ namespace smt { | ||||||
|                             antecedents ante(*this); |                             antecedents ante(*this); | ||||||
|                             collect_fixed_var_justifications(r, ante); |                             collect_fixed_var_justifications(r, ante); | ||||||
|                             collect_fixed_var_justifications(r2, ante); |                             collect_fixed_var_justifications(r2, ante); | ||||||
|                             TRACE("propagate_cheap_eq", tout << "propagate eq two rows:\n";  |                             TRACE("arith_eq", tout << "propagate eq two rows:\n";  | ||||||
|                                   tout << "swapped: " << swapped << "\n"; |                                   tout << "swapped: " << swapped << "\n"; | ||||||
|                                   tout << "x  : v" << x << "\n"; |                                   tout << "x  : v" << x << "\n"; | ||||||
|                                   tout << "x2 : v" << x2 << "\n"; |                                   tout << "x2 : v" << x2 << "\n"; | ||||||
|  | @ -343,7 +343,7 @@ namespace smt { | ||||||
|                     antecedents.eqs().size(), antecedents.eqs().c_ptr(), |                     antecedents.eqs().size(), antecedents.eqs().c_ptr(), | ||||||
|                     _x, _y,  |                     _x, _y,  | ||||||
|                     antecedents.num_params(), antecedents.params("eq-propagate"))); |                     antecedents.num_params(), antecedents.params("eq-propagate"))); | ||||||
|         TRACE("propagate_eq_to_core", tout << "detected equality: #" << _x->get_owner_id() << " = #" << _y->get_owner_id() << "\n"; |         TRACE("arith_eq", tout << "detected equality: #" << _x->get_owner_id() << " = #" << _y->get_owner_id() << "\n"; | ||||||
|               display_var(tout, x); |               display_var(tout, x); | ||||||
|               display_var(tout, y);); |               display_var(tout, y);); | ||||||
|         ctx.assign_eq(_x, _y, eq_justification(js)); |         ctx.assign_eq(_x, _y, eq_justification(js)); | ||||||
|  |  | ||||||
|  | @ -97,6 +97,7 @@ namespace smt { | ||||||
|         virtual void pop_scope_eh(unsigned num_scopes); |         virtual void pop_scope_eh(unsigned num_scopes); | ||||||
|         virtual final_check_status final_check_eh(); |         virtual final_check_status final_check_eh(); | ||||||
|         virtual void reset_eh(); |         virtual void reset_eh(); | ||||||
|  |         virtual void restart_eh() { m_util.reset(); } | ||||||
|         virtual bool is_shared(theory_var v) const; |         virtual bool is_shared(theory_var v) const; | ||||||
|     public: |     public: | ||||||
|         theory_datatype(ast_manager & m, theory_datatype_params & p); |         theory_datatype(ast_manager & m, theory_datatype_params & p); | ||||||
|  |  | ||||||
|  | @ -249,6 +249,7 @@ final_check_status theory_seq::final_check_eh() { | ||||||
|     } |     } | ||||||
|     m_new_propagation = false; |     m_new_propagation = false; | ||||||
|     TRACE("seq", display(tout << "level: " << get_context().get_scope_level() << "\n");); |     TRACE("seq", display(tout << "level: " << get_context().get_scope_level() << "\n");); | ||||||
|  |     TRACE("seq_verbose", get_context().display(tout);); | ||||||
|     if (simplify_and_solve_eqs()) { |     if (simplify_and_solve_eqs()) { | ||||||
|         ++m_stats.m_solve_eqs; |         ++m_stats.m_solve_eqs; | ||||||
|         TRACE("seq", tout << ">>solve_eqs\n";); |         TRACE("seq", tout << ">>solve_eqs\n";); | ||||||
|  | @ -1009,6 +1010,17 @@ bool theory_seq::is_nth(expr* e) const { | ||||||
|     return is_skolem(m_nth, e); |     return is_skolem(m_nth, e); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool theory_seq::is_nth(expr* e, expr*& e1, expr*& e2) const { | ||||||
|  |     if (is_nth(e)) { | ||||||
|  |         e1 = to_app(e)->get_arg(0); | ||||||
|  |         e2 = to_app(e)->get_arg(1); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool theory_seq::is_tail(expr* e, expr*& s, unsigned& idx) const { | bool theory_seq::is_tail(expr* e, expr*& s, unsigned& idx) const { | ||||||
|     rational r; |     rational r; | ||||||
|     return |     return | ||||||
|  | @ -1038,6 +1050,10 @@ expr_ref theory_seq::mk_nth(expr* s, expr* idx) { | ||||||
|     return mk_skolem(m_nth, s, idx, 0, char_sort); |     return mk_skolem(m_nth, s, idx, 0, char_sort); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | expr_ref theory_seq::mk_sk_ite(expr* c, expr* t, expr* e) { | ||||||
|  |     return mk_skolem(symbol("seq.if"), c, t, e, m.get_sort(t)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| expr_ref theory_seq::mk_last(expr* s) { | expr_ref theory_seq::mk_last(expr* s) { | ||||||
|     zstring str; |     zstring str; | ||||||
|     if (m_util.str.is_string(s, str) && str.length() > 0) { |     if (m_util.str.is_string(s, str) && str.length() > 0) { | ||||||
|  | @ -2668,6 +2684,13 @@ expr_ref theory_seq::expand(expr* e0, dependency*& eqs) { | ||||||
|     } |     } | ||||||
|     else if (m.is_ite(e, e1, e2, e3)) { |     else if (m.is_ite(e, e1, e2, e3)) { | ||||||
|         literal lit(mk_literal(e1)); |         literal lit(mk_literal(e1)); | ||||||
|  | #if 0 | ||||||
|  |         expr_ref sk_ite = mk_sk_ite(e1, e2, e3); | ||||||
|  |         add_axiom(~lit, mk_eq(e2, sk_ite, false)); | ||||||
|  |         add_axiom( lit, mk_eq(e3, sk_ite, false)); | ||||||
|  |         result = sk_ite; | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|         switch (ctx.get_assignment(lit)) { |         switch (ctx.get_assignment(lit)) { | ||||||
|         case l_true: |         case l_true: | ||||||
|             deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(lit))); |             deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(lit))); | ||||||
|  | @ -2684,6 +2707,7 @@ expr_ref theory_seq::expand(expr* e0, dependency*& eqs) { | ||||||
|                   tout << lit << "@ level: " << ctx.get_scope_level() << "\n";); |                   tout << lit << "@ level: " << ctx.get_scope_level() << "\n";); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
|     else if (m_util.str.is_itos(e, e1)) { |     else if (m_util.str.is_itos(e, e1)) { | ||||||
|         rational val; |         rational val; | ||||||
|  | @ -2902,9 +2926,13 @@ void theory_seq::add_replace_axiom(expr* r) { | ||||||
|     expr_ref xty = mk_concat(x, t, y); |     expr_ref xty = mk_concat(x, t, y); | ||||||
|     expr_ref xsy = mk_concat(x, s, y); |     expr_ref xsy = mk_concat(x, s, y); | ||||||
|     literal cnt = mk_literal(m_util.str.mk_contains(a ,s)); |     literal cnt = mk_literal(m_util.str.mk_contains(a ,s)); | ||||||
|  |     literal a_emp = mk_eq_empty(a); | ||||||
|  |     literal s_emp = mk_eq_empty(s); | ||||||
|  |     add_axiom(~a_emp, mk_seq_eq(r, a)); | ||||||
|     add_axiom(cnt,  mk_seq_eq(r, a)); |     add_axiom(cnt,  mk_seq_eq(r, a)); | ||||||
|     add_axiom(~cnt, mk_seq_eq(a, xsy)); |     add_axiom(~s_emp, mk_seq_eq(r, a)); | ||||||
|     add_axiom(~cnt, mk_seq_eq(r, xty)); |     add_axiom(~cnt, a_emp, s_emp, mk_seq_eq(a, xsy)); | ||||||
|  |     add_axiom(~cnt, a_emp, s_emp, mk_seq_eq(r, xty)); | ||||||
|     tightest_prefix(s, x); |     tightest_prefix(s, x); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -449,10 +449,12 @@ namespace smt { | ||||||
|         bool is_var(expr* b); |         bool is_var(expr* b); | ||||||
|         bool add_solution(expr* l, expr* r, dependency* dep); |         bool add_solution(expr* l, expr* r, dependency* dep); | ||||||
|         bool is_nth(expr* a) const; |         bool is_nth(expr* a) const; | ||||||
|  |         bool is_nth(expr* a, expr*& e1, expr*& e2) const; | ||||||
|         bool is_tail(expr* a, expr*& s, unsigned& idx) const; |         bool is_tail(expr* a, expr*& s, unsigned& idx) const; | ||||||
|         bool is_eq(expr* e, expr*& a, expr*& b) const;  |         bool is_eq(expr* e, expr*& a, expr*& b) const;  | ||||||
|         bool is_pre(expr* e, expr*& s, expr*& i); |         bool is_pre(expr* e, expr*& s, expr*& i); | ||||||
|         bool is_post(expr* e, expr*& s, expr*& i); |         bool is_post(expr* e, expr*& s, expr*& i); | ||||||
|  |         expr_ref mk_sk_ite(expr* c, expr* t, expr* f); | ||||||
|         expr_ref mk_nth(expr* s, expr* idx); |         expr_ref mk_nth(expr* s, expr* idx); | ||||||
|         expr_ref mk_last(expr* e); |         expr_ref mk_last(expr* e); | ||||||
|         expr_ref mk_first(expr* e); |         expr_ref mk_first(expr* e); | ||||||
|  |  | ||||||
|  | @ -112,7 +112,7 @@ class dt2bv_tactic : public tactic { | ||||||
|                 unsigned idx = m_t.m_dt.get_constructor_idx(f); |                 unsigned idx = m_t.m_dt.get_constructor_idx(f); | ||||||
|                 result = m_t.m_bv.mk_numeral(idx, bv_size); |                 result = m_t.m_bv.mk_numeral(idx, bv_size); | ||||||
|             } |             } | ||||||
|             else { |             else if (is_uninterp_const(a)) { | ||||||
|                 // create a fresh variable, add bounds constraints for it.
 |                 // create a fresh variable, add bounds constraints for it.
 | ||||||
|                 unsigned nc = m_t.m_dt.get_datatype_num_constructors(s); |                 unsigned nc = m_t.m_dt.get_datatype_num_constructors(s); | ||||||
|                 result = m.mk_fresh_const(f->get_name().str().c_str(), m_t.m_bv.mk_sort(bv_size)); |                 result = m.mk_fresh_const(f->get_name().str().c_str(), m_t.m_bv.mk_sort(bv_size)); | ||||||
|  | @ -130,6 +130,9 @@ class dt2bv_tactic : public tactic { | ||||||
|                 m_t.m_ext->insert(f, f_def); |                 m_t.m_ext->insert(f, f_def); | ||||||
|                 m_t.m_filter->insert(to_app(result)->get_decl()); |                 m_t.m_filter->insert(to_app(result)->get_decl()); | ||||||
|             } |             } | ||||||
|  |             else { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|             m_cache.insert(a, result); |             m_cache.insert(a, result); | ||||||
|             ++m_t.m_num_translated; |             ++m_t.m_num_translated; | ||||||
|             return true; |             return true; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue