mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 03:32:28 +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) | ||||
|        return self.varcache[i] | ||||
| 
 | ||||
|    # Retrieve the latest model | ||||
|    # Add formulas that are true in the model to  | ||||
|    # the current mss | ||||
| 
 | ||||
|    def update_unknown(self): | ||||
|        self.model = self.s.model() | ||||
|        new_unknown = set([]) | ||||
|  | @ -83,23 +87,29 @@ class MSSSolver: | |||
|               new_unknown.add(x) | ||||
|        self.unknown = new_unknown | ||||
|        | ||||
|    def relax_core(self, core): | ||||
|        assert(core <= self.soft_vars) | ||||
|        prev = BoolVal(True) | ||||
|        core_list = [x for x in core] | ||||
|        self.soft_vars -= core | ||||
|        # replace x0, x1, x2, .. by | ||||
|        # Or(x1, x0), Or(x2, And(x1, x0)), Or(x3, And(x2, And(x1, x0))), ... | ||||
|        for i in range(len(core_list)-1): | ||||
|            x = core_list[i] | ||||
|            y = core_list[i+1] | ||||
|            prevf = And(x, prev) | ||||
|            prev = Bool("%s" % prevf) | ||||
|            self.s.add(prev == prevf) | ||||
|            zf = Or(prev, y) | ||||
|            z = Bool("%s" % zf) | ||||
|            self.s.add(z == zf) | ||||
|            self.soft_vars.add(z) | ||||
|    # Create a name, propositional atom, | ||||
|    #  for formula 'fml' and return the name. | ||||
| 
 | ||||
|    def add_def(self, fml): | ||||
|        name = Bool("%s" % fml) | ||||
|        self.s.add(name == fml) | ||||
|        return name | ||||
| 
 | ||||
|    # replace Fs := f0, f1, f2, .. by | ||||
|    # Or(f1, f0), Or(f2, And(f1, f0)), Or(f3, And(f2, And(f1, f0))), ... | ||||
| 
 | ||||
|    def relax_core(self, Fs): | ||||
|        assert(Fs <= self.soft_vars) | ||||
|        prefix = BoolVal(True) | ||||
|        self.soft_vars -= Fs | ||||
|        Fs = [ f for f in Fs ] | ||||
|        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): | ||||
|        new_core = set([]) | ||||
|  | @ -111,6 +121,14 @@ class MSSSolver: | |||
|        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): | ||||
|        self.mss = [] | ||||
|        self.mcs = [] | ||||
|  |  | |||
|  | @ -415,6 +415,7 @@ extern "C" { | |||
|             return; | ||||
|         } | ||||
|         mk_c(c)->m().dec_ref(to_ast(a)); | ||||
| 
 | ||||
|         Z3_CATCH; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -286,8 +286,8 @@ namespace Microsoft.Z3 | |||
|             Contract.Ensures(Contract.Result<TupleSort>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(name); | ||||
|             CheckContextMatch(fieldNames); | ||||
|             CheckContextMatch(fieldSorts); | ||||
|             CheckContextMatch<Symbol>(fieldNames); | ||||
|             CheckContextMatch<Sort>(fieldSorts); | ||||
|             return new TupleSort(this, name, (uint)fieldNames.Length, fieldNames, fieldSorts); | ||||
|         } | ||||
| 
 | ||||
|  | @ -303,7 +303,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Ensures(Contract.Result<EnumSort>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(name); | ||||
|             CheckContextMatch(enumNames); | ||||
|             CheckContextMatch<Symbol>(enumNames); | ||||
|             return new EnumSort(this, name, enumNames); | ||||
|         } | ||||
| 
 | ||||
|  | @ -423,7 +423,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Ensures(Contract.Result<DatatypeSort>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(name); | ||||
|             CheckContextMatch(constructors); | ||||
|             CheckContextMatch<Constructor>(constructors); | ||||
|             return new DatatypeSort(this, name, constructors); | ||||
|         } | ||||
| 
 | ||||
|  | @ -436,7 +436,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(constructors, c => c != null)); | ||||
|             Contract.Ensures(Contract.Result<DatatypeSort>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(constructors); | ||||
|             CheckContextMatch<Constructor>(constructors); | ||||
|             return new DatatypeSort(this, MkSymbol(name), constructors); | ||||
|         } | ||||
| 
 | ||||
|  | @ -454,7 +454,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(names, name => name != null)); | ||||
|             Contract.Ensures(Contract.Result<DatatypeSort[]>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(names); | ||||
|             CheckContextMatch<Symbol>(names); | ||||
|             uint n = (uint)names.Length; | ||||
|             ConstructorList[] cla = new ConstructorList[n]; | ||||
|             IntPtr[] n_constr = new IntPtr[n]; | ||||
|  | @ -462,7 +462,7 @@ namespace Microsoft.Z3 | |||
|             { | ||||
|                 Constructor[] constructor = c[i]; | ||||
|                 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); | ||||
|                 n_constr[i] = cla[i].NativeObject; | ||||
|             } | ||||
|  | @ -520,7 +520,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Ensures(Contract.Result<FuncDecl>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(name); | ||||
|             CheckContextMatch(domain); | ||||
|             CheckContextMatch<Sort>(domain); | ||||
|             CheckContextMatch(range); | ||||
|             return new FuncDecl(this, name, domain, range); | ||||
|         } | ||||
|  | @ -551,7 +551,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(domain, d => d != null)); | ||||
|             Contract.Ensures(Contract.Result<FuncDecl>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(domain); | ||||
|             CheckContextMatch<Sort>(domain); | ||||
|             CheckContextMatch(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.Ensures(Contract.Result<FuncDecl>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(domain); | ||||
|             CheckContextMatch<Sort>(domain); | ||||
|             CheckContextMatch(range); | ||||
|             return new FuncDecl(this, prefix, domain, range); | ||||
|         } | ||||
|  | @ -811,7 +811,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Ensures(Contract.Result<Expr>() != null); | ||||
| 
 | ||||
|             CheckContextMatch(f); | ||||
|             CheckContextMatch(args); | ||||
|             CheckContextMatch<Expr>(args); | ||||
|             return Expr.Create(this, f, args); | ||||
|         } | ||||
| 
 | ||||
|  | @ -884,7 +884,7 @@ namespace Microsoft.Z3 | |||
| 
 | ||||
|             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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -970,7 +970,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -982,7 +982,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(t != null); | ||||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -995,7 +995,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -1025,7 +1025,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -1051,7 +1051,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -1064,7 +1064,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -1077,7 +1077,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -2205,7 +2205,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Ensures(Contract.Result<ArrayExpr>() != null); | ||||
| 
 | ||||
|             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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -2315,7 +2315,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(args != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -2328,7 +2328,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(args, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -2429,7 +2429,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -2593,7 +2593,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -2606,7 +2606,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(t, a => a != 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))); | ||||
|         } | ||||
|      | ||||
|  | @ -2621,7 +2621,7 @@ namespace Microsoft.Z3 | |||
|         { | ||||
|            Contract.Requires(args != null); | ||||
|            Contract.Requires(Contract.Result<BoolExpr[]>() != null); | ||||
|            CheckContextMatch(args); | ||||
|            CheckContextMatch<BoolExpr>(args); | ||||
|            return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint) args.Length, | ||||
|                                                           AST.ArrayToNative(args), k)); | ||||
|         } | ||||
|  | @ -2635,7 +2635,7 @@ namespace Microsoft.Z3 | |||
|            Contract.Requires(coeffs != null); | ||||
|            Contract.Requires(args.Length == coeffs.Length); | ||||
|            Contract.Requires(Contract.Result<BoolExpr[]>() != null); | ||||
|            CheckContextMatch(args); | ||||
|            CheckContextMatch<BoolExpr>(args); | ||||
|            return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint) args.Length, | ||||
|                                                           AST.ArrayToNative(args), | ||||
|                                                           coeffs, k)); | ||||
|  | @ -3386,7 +3386,7 @@ namespace Microsoft.Z3 | |||
| 
 | ||||
|             CheckContextMatch(t1); | ||||
|             CheckContextMatch(t2); | ||||
|             CheckContextMatch(ts); | ||||
|             CheckContextMatch<Tactic>(ts); | ||||
| 
 | ||||
|             IntPtr last = IntPtr.Zero; | ||||
|             if (ts != null && ts.Length > 0) | ||||
|  | @ -3577,7 +3577,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(t == null || Contract.ForAll(t, tactic => 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))); | ||||
|         } | ||||
| 
 | ||||
|  | @ -4810,7 +4810,7 @@ namespace Microsoft.Z3 | |||
|         } | ||||
| 
 | ||||
|         [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)); | ||||
| 
 | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(args != null); | ||||
|             Contract.Requires(Contract.ForAll(args, a => a != null)); | ||||
| 
 | ||||
|             Context.CheckContextMatch(args); | ||||
|             Context.CheckContextMatch<Expr>(args); | ||||
|             if (IsApp && args.Length != NumArgs) | ||||
|                 throw new Z3Exception("Number of arguments does not match"); | ||||
|             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.Ensures(Contract.Result<Expr>() != null); | ||||
| 
 | ||||
|             Context.CheckContextMatch(from); | ||||
|             Context.CheckContextMatch(to); | ||||
|             Context.CheckContextMatch<Expr>(from); | ||||
|             Context.CheckContextMatch<Expr>(to); | ||||
|             if (from.Length != to.Length) | ||||
|                 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))); | ||||
|  | @ -152,7 +152,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(Contract.ForAll(to, t => t != 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))); | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(constraints != null); | ||||
|             Contract.Requires(Contract.ForAll(constraints, c => c != null)); | ||||
| 
 | ||||
|             Context.CheckContextMatch(constraints); | ||||
|             Context.CheckContextMatch<BoolExpr>(constraints); | ||||
|             foreach (BoolExpr a in constraints) | ||||
|             { | ||||
|                 Native.Z3_fixedpoint_assert(Context.nCtx, NativeObject, a.NativeObject); | ||||
|  | @ -151,7 +151,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(relations != 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, | ||||
|                                    AST.ArrayLength(relations), AST.ArrayToNative(relations)); | ||||
|             switch (r) | ||||
|  |  | |||
|  | @ -339,7 +339,7 @@ namespace Microsoft.Z3 | |||
|         { | ||||
|             Contract.Requires(args == null || Contract.ForAll(args, a => a != null)); | ||||
| 
 | ||||
|             Context.CheckContextMatch(args); | ||||
|             Context.CheckContextMatch<Expr>(args); | ||||
|             return Expr.Create(Context, this, args); | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -82,7 +82,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(constraints != null); | ||||
|             Contract.Requires(Contract.ForAll(constraints, c => c != null)); | ||||
| 
 | ||||
|             Context.CheckContextMatch(constraints); | ||||
|             Context.CheckContextMatch<BoolExpr>(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 | ||||
|  |  | |||
|  | @ -172,10 +172,10 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(patterns == null || Contract.ForAll(patterns, p => p != null)); | ||||
|             Contract.Requires(noPatterns == null || Contract.ForAll(noPatterns, np => np != null)); | ||||
| 
 | ||||
|             Context.CheckContextMatch(patterns); | ||||
|             Context.CheckContextMatch(noPatterns); | ||||
|             Context.CheckContextMatch(sorts); | ||||
|             Context.CheckContextMatch(names); | ||||
|             Context.CheckContextMatch<Pattern>(patterns); | ||||
|             Context.CheckContextMatch<Expr>(noPatterns); | ||||
|             Context.CheckContextMatch<Sort>(sorts); | ||||
|             Context.CheckContextMatch<Symbol>(names); | ||||
|             Context.CheckContextMatch(body); | ||||
| 
 | ||||
|             if (sorts.Length != names.Length) | ||||
|  | @ -212,8 +212,8 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(noPatterns == null || Contract.ForAll(noPatterns, np => np != null)); | ||||
|             Contract.Requires(bound == null || Contract.ForAll(bound, n => n != null)); | ||||
| 
 | ||||
|             Context.CheckContextMatch(noPatterns); | ||||
|             Context.CheckContextMatch(patterns); | ||||
|             Context.CheckContextMatch<Expr>(noPatterns); | ||||
|             Context.CheckContextMatch<Pattern>(patterns); | ||||
|             //Context.CheckContextMatch(bound); | ||||
|             Context.CheckContextMatch(body); | ||||
| 
 | ||||
|  |  | |||
|  | @ -111,7 +111,7 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(constraints != null); | ||||
|             Contract.Requires(Contract.ForAll(constraints, c => c != null)); | ||||
| 
 | ||||
|             Context.CheckContextMatch(constraints); | ||||
|             Context.CheckContextMatch<BoolExpr>(constraints); | ||||
|             foreach (BoolExpr a in constraints) | ||||
|             { | ||||
|                 Native.Z3_solver_assert(Context.nCtx, NativeObject, a.NativeObject); | ||||
|  | @ -142,8 +142,8 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(constraints != null); | ||||
|             Contract.Requires(Contract.ForAll(constraints, c => c != null)); | ||||
|             Contract.Requires(Contract.ForAll(ps, c => c != null)); | ||||
|             Context.CheckContextMatch(constraints); | ||||
|             Context.CheckContextMatch(ps); | ||||
|             Context.CheckContextMatch<BoolExpr>(constraints); | ||||
|             Context.CheckContextMatch<BoolExpr>(ps); | ||||
|             if (constraints.Length != ps.Length) | ||||
|                 throw new Z3Exception("Argument size mismatch"); | ||||
|              | ||||
|  |  | |||
|  | @ -138,7 +138,7 @@ namespace Microsoft.Z3 | |||
|         } | ||||
| 
 | ||||
|         [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[]>().Length == a.Count()); | ||||
|  |  | |||
|  | @ -118,6 +118,8 @@ def _get_args(args): | |||
|     try: | ||||
|         if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)): | ||||
|             return args[0] | ||||
|         elif len(args) == 1 and isinstance(args[0], set): | ||||
|             return [arg for arg in args[0]] | ||||
|         else: | ||||
|             return args | ||||
|     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()) { | ||||
|         SASSERT(fid != null_family_id); | ||||
|         m.get_plugin(fid)->del(*this); | ||||
|         decl_plugin * plugin = m.get_plugin(fid); | ||||
|         if (plugin) { | ||||
|             plugin->del(*this); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1418,9 +1421,10 @@ ast_manager::~ast_manager() { | |||
|     } | ||||
|     it = m_plugins.begin(); | ||||
|     for (; it != end; ++it) { | ||||
|         if (*it) | ||||
|         if (*it)  | ||||
|             dealloc(*it); | ||||
|     } | ||||
|     m_plugins.reset(); | ||||
|     while (!m_ast_table.empty()) { | ||||
|         DEBUG_CODE(std::cout << "ast_manager LEAKED: " << m_ast_table.size() << std::endl;); | ||||
|         ptr_vector<ast> roots; | ||||
|  | @ -1430,14 +1434,22 @@ ast_manager::~ast_manager() { | |||
|         for (; it_a != end_a; ++it_a) { | ||||
|             ast* n = (*it_a); | ||||
|             switch (n->get_kind()) { | ||||
|             case AST_SORT: | ||||
|                 mark_array_ref(mark, to_sort(n)->get_info()->get_num_parameters(), to_sort(n)->get_info()->get_parameters()); | ||||
|             case AST_SORT: { | ||||
|                 sort_info* info = to_sort(n)->get_info(); | ||||
|                 if (info != 0) { | ||||
|                     mark_array_ref(mark, info->get_num_parameters(), info->get_parameters()); | ||||
|                 } | ||||
|                 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.mark(to_func_decl(n)->get_range(), true); | ||||
|                 break; | ||||
|             } | ||||
|             case AST_APP: | ||||
|                 mark.mark(to_app(n)->get_decl(), true); | ||||
|                 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_no_patterns(), to_quantifier(n)->get_no_patterns()); | ||||
|             break; | ||||
|     default: | ||||
|         break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|         if (m_debug_ref_count) { | ||||
|             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): | ||||
|     m_manager(m), | ||||
|     m_family_id(m.mk_family_id("datatype")), | ||||
|     m_asts(m) { | ||||
|     m_asts(m), | ||||
|     m_start(0) { | ||||
| } | ||||
| 
 | ||||
| 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 
 | ||||
|     //   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_iterator it  = constructors->begin(); | ||||
|     ptr_vector<func_decl>::const_iterator end = constructors->end(); | ||||
|     // step 1)
 | ||||
|     for (; it != end; ++it) { | ||||
|         func_decl * c = *it; | ||||
|     unsigned sz = constructors->size(); | ||||
|     ++m_start; | ||||
|     for (unsigned j = 0; j < sz; ++j) {         | ||||
|         func_decl * c = (*constructors)[(j + m_start) % sz]; | ||||
|         unsigned num_args = c->get_arity(); | ||||
|         unsigned i = 0; | ||||
|         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; | ||||
|     } | ||||
|     // step 2)
 | ||||
|     it  = constructors->begin(); | ||||
|     for (; it != end; ++it) { | ||||
|         func_decl * c = *it; | ||||
|     for (unsigned j = 0; j < sz; ++j) {         | ||||
|         func_decl * c = (*constructors)[(j + m_start) % sz]; | ||||
|         TRACE("datatype_util_bug", tout << "non_rec_constructor c: " << c->get_name() << "\n";); | ||||
|         unsigned num_args = c->get_arity(); | ||||
|         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> >()); | ||||
|     m_vectors.reset(); | ||||
|     m_asts.reset(); | ||||
|     ++m_start; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -176,7 +176,8 @@ class datatype_util { | |||
|     obj_map<sort, bool>                         m_is_enum; | ||||
|     ast_ref_vector                              m_asts; | ||||
|     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_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); | ||||
|     bool changed = false; | ||||
|     unsigned num_args = head->get_num_args(); | ||||
|     unsigned max      = num_args; | ||||
|     unsigned max_var_idx = 0; | ||||
|     for (unsigned i = 0; i < num_args; i++) { | ||||
|         var * v     = to_var(head->get_arg(i)); | ||||
|         if (v->get_idx() >= max) | ||||
|             max = v->get_idx() + 1; | ||||
|         var const * v = to_var(head->get_arg(i)); | ||||
|         if (v->get_idx() > max_var_idx) | ||||
|             max_var_idx = v->get_idx(); | ||||
|     } | ||||
|     TRACE("normalize_expr_bug", | ||||
|           tout << "head: " << mk_pp(head, m_manager) << "\n"; | ||||
|           tout << "applying substitution to:\n" << mk_bounded_pp(t, m_manager) << "\n";); | ||||
|     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) { | ||||
|             changed = true; | ||||
|             var * new_var = m_manager.mk_var(i, v->get_sort()); | ||||
|             CTRACE("normalize_expr_bug", v->get_idx() >= num_args, tout << mk_pp(v, m_manager) << ", num_args: " << num_args << "\n";); | ||||
|             SASSERT(v->get_idx() < max); | ||||
|             var_mapping.setx(max - v->get_idx() - 1, new_var); | ||||
|         } | ||||
|         else { | ||||
|             var_mapping.setx(max - i - 1, v); | ||||
|             var_ref new_var(m_manager.mk_var(i, v->get_sort()), m_manager); | ||||
|             var_mapping.setx(max_var_idx - v->get_idx(), new_var); | ||||
|         } | ||||
|         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) { | ||||
|         // REMARK: t may have nested quantifiers... So, I must use the std order for variable substitution.
 | ||||
|         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"; | ||||
|               for (unsigned i = 0; i < var_mapping.size(); i++) { | ||||
|                   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); | ||||
|     } | ||||
|  |  | |||
|  | @ -16,4 +16,5 @@ def_module_params('pp', | |||
|                           ('fixed_indent', BOOL, False, 'use a fixed indentation for applications'), | ||||
|                           ('single_line', BOOL, False, 'ignore line breaks when true'), | ||||
|                           ('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'))) | ||||
|  |  | |||
|  | @ -144,6 +144,9 @@ zstring zstring::replace(zstring const& src, zstring const& dst) const { | |||
|     if (length() < src.length()) { | ||||
|         return zstring(*this); | ||||
|     } | ||||
|     if (src.length() == 0) { | ||||
|         return zstring(*this); | ||||
|     } | ||||
|     bool found = false; | ||||
|     for (unsigned i = 0; i < length(); ++i) { | ||||
|         bool eq = !found && i + src.length() <= length(); | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ Notes: | |||
| #include"gparams.h" | ||||
| #include"env_params.h" | ||||
| #include"well_sorted.h" | ||||
| #include"pp_params.hpp" | ||||
| 
 | ||||
| class help_cmd : public cmd { | ||||
|     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"); | ||||
|     } | ||||
|      | ||||
|     // TODO: reimplement a new SMT2 pretty printer 
 | ||||
|     ast_smt_pp pp(ctx.m()); | ||||
|     cmd_is_declared isd(ctx); | ||||
|     pp.set_is_declared(&isd); | ||||
|     pp.set_logic(ctx.get_logic()); | ||||
|     // ctx.regular_stream() << mk_pp(pr, ctx.m()) << "\n";
 | ||||
|     pp.display_smt2(ctx.regular_stream(), pr); | ||||
|     ctx.regular_stream() << std::endl; | ||||
|     pp_params params; | ||||
|     if (params.pretty_proof()) { | ||||
|         ctx.regular_stream() << mk_pp(pr, ctx.m()) << std::endl; | ||||
|     } | ||||
|     else { | ||||
|         // TODO: reimplement a new SMT2 pretty printer 
 | ||||
|         ast_smt_pp pp(ctx.m()); | ||||
|         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()                                            \ | ||||
|  |  | |||
|  | @ -28,7 +28,6 @@ | |||
| #include"mpq.h" | ||||
| #include"expr2var.h" | ||||
| #include"pp.h" | ||||
| #include"pp_params.hpp" | ||||
| #include"iz3interp.h" | ||||
| #include"iz3checker.h" | ||||
| #include"iz3profiling.h" | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ namespace datalog { | |||
|                     } | ||||
|                     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(); | ||||
|                     bool new_info = m_facts.insert_if_not_there2(sym, Fact())->get_data().m_value.init_up(m_context, cur); | ||||
|                     if (new_info) { | ||||
|  | @ -97,7 +97,7 @@ namespace datalog { | |||
|         } | ||||
| 
 | ||||
|         void step_bottom_up() { | ||||
|             for(todo_set::iterator I = m_todo[m_todo_idx].begin(), | ||||
|             for(todo_set::iterator I = m_todo[m_todo_idx].begin(),                     | ||||
|                 E = m_todo[m_todo_idx].end(); I!=E; ++I) { | ||||
|                 ptr_vector<rule> * rules;  | ||||
|                 if (!m_body2rules.find(*I, rules)) | ||||
|  | @ -236,7 +236,7 @@ namespace datalog { | |||
|             return m_facts.get(m_rule->get_decl(idx), Fact::null_fact); | ||||
|         } | ||||
|         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))) { | ||||
|                     return 0; | ||||
|                 } | ||||
| 
 | ||||
|                 if (r->is_neg_tail(i)) { | ||||
|                     if (!engine.get_fact(r->get_decl(i)).is_reachable()) { | ||||
|                         if (!new_tail) { | ||||
|  | @ -53,11 +54,14 @@ namespace datalog { | |||
|                             } | ||||
|                             new_tail = true; | ||||
|                         } | ||||
|                     } else if (new_tail) { | ||||
|                     }  | ||||
|                     else if (new_tail) { | ||||
|                         m_new_tail.push_back(r->get_tail(i)); | ||||
|                         m_new_tail_neg.push_back(true); | ||||
|                     } | ||||
|                 } else { | ||||
|                 }  | ||||
| 
 | ||||
|                 else { | ||||
|                     SASSERT(!new_tail); | ||||
|                     if (!engine.get_fact(r->get_decl(i)).is_reachable()) { | ||||
|                         contained = false; | ||||
|  |  | |||
|  | @ -1573,7 +1573,8 @@ private: | |||
|                         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()))) { | ||||
|                     set_error("invalid pattern", children[0]); | ||||
|                     return false; | ||||
|  | @ -1581,8 +1582,11 @@ private: | |||
|                 patterns.push_back(p); | ||||
|             } | ||||
|             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()); | ||||
|                 expr * p = m_manager.mk_pattern(1, &sk_hack); | ||||
|                 app_ref sk_hack(m_manager); | ||||
|                 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()))) { | ||||
|                     set_error("invalid pattern", children[0]); | ||||
|                     return false; | ||||
|  |  | |||
|  | @ -493,14 +493,14 @@ namespace sat { | |||
|     void bceq::operator()() { | ||||
|         if (!m_solver.m_config.m_bcd) return; | ||||
|         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<unsigned> _bound_maxc(m_solver.m_config.m_max_conflicts, 1500); | ||||
| 
 | ||||
|         use_list     ul;         | ||||
|         solver       s(m_solver.m_params, m_solver.rlimit(), 0); | ||||
|         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_max_conflicts  = 1500; | ||||
|         m_use_list = &ul; | ||||
|  |  | |||
|  | @ -107,8 +107,8 @@ namespace sat { | |||
|             m_gc_increment    = p.gc_increment(); | ||||
|         } | ||||
|         m_minimize_lemmas = p.minimize_lemmas(); | ||||
|         m_minimize_core   = p.minimize_core(); | ||||
|         m_minimize_core_partial   = p.minimize_core_partial(); | ||||
|         m_core_minimize   = p.core_minimize(); | ||||
|         m_core_minimize_partial   = p.core_minimize_partial(); | ||||
|         m_optimize_model  = p.optimize_model(); | ||||
|         m_bcd             = p.bcd(); | ||||
|         m_dyn_sub_res     = p.dyn_sub_res(); | ||||
|  |  | |||
|  | @ -69,8 +69,8 @@ namespace sat { | |||
| 
 | ||||
|         bool               m_minimize_lemmas; | ||||
|         bool               m_dyn_sub_res; | ||||
|         bool               m_minimize_core; | ||||
|         bool               m_minimize_core_partial; | ||||
|         bool               m_core_minimize; | ||||
|         bool               m_core_minimize_partial; | ||||
|         bool               m_optimize_model; | ||||
|         bool               m_bcd; | ||||
| 
 | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ namespace sat { | |||
|     } | ||||
| 
 | ||||
|     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> _is_active(m_is_active, true); | ||||
|         IF_VERBOSE(3, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";); | ||||
|  | @ -69,7 +69,7 @@ namespace sat { | |||
|     } | ||||
| 
 | ||||
|     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";); | ||||
|         literal_vector& core = get_core(); | ||||
|         literal_vector& mus = m_mus; | ||||
|  | @ -96,7 +96,7 @@ namespace sat { | |||
|                 // IF_VERBOSE(0, verbose_stream() << "num literals: " << core << " " << mus << "\n";);
 | ||||
|                 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";); | ||||
|                 set_core(); | ||||
|                 return l_true; | ||||
|  | @ -172,7 +172,7 @@ namespace sat { | |||
| 
 | ||||
|     lbool mus::qx(literal_set& assignment, literal_set& support, bool has_support) { | ||||
|         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";); | ||||
|             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)'), | ||||
|                           ('minimize_lemmas', BOOL, True, 'minimize learned clauses'), | ||||
|                           ('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'), | ||||
|                           ('minimize_core', BOOL, False, 'minimize computed core'), | ||||
|                           ('minimize_core_partial', BOOL, False, 'apply partial (cheap) core minimization'), | ||||
|                           ('core.minimize', BOOL, False, 'minimize computed core'), | ||||
|                           ('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'), | ||||
|                           ('optimize_model', BOOL, False, 'enable optimization of soft constraints'), | ||||
|                           ('bcd', BOOL, False, 'enable blocked clause decomposition for equality extraction'), | ||||
|                           ('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) { | ||||
|         flet<bool> _min1(m_config.m_minimize_core, false); | ||||
|         flet<bool> _min1(m_config.m_core_minimize, false); | ||||
|         m_weight = 0; | ||||
|         m_blocker.reset(); | ||||
|         svector<lbool> values; | ||||
|  | @ -2015,7 +2015,7 @@ namespace sat { | |||
|             idx--; | ||||
|         }         | ||||
|         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_VERBOSE(1, verbose_stream() << "(sat.updating core " << m_min_core.size() << " " << m_core.size() << ")\n";); | ||||
|                 m_core.reset(); | ||||
|  |  | |||
|  | @ -403,7 +403,6 @@ namespace smt { | |||
|         // the previous levels were already inconsistent, or the inconsistency was
 | ||||
|         // triggered by an axiom or justification proof wrapper, this two kinds
 | ||||
|         // of justification are considered level zero.
 | ||||
| 
 | ||||
|         if (m_conflict_lvl <= m_ctx.get_search_level()) { | ||||
|             TRACE("conflict", tout << "problem is unsat\n";); | ||||
|             if (m_manager.proofs_enabled()) | ||||
|  |  | |||
|  | @ -18,6 +18,8 @@ Revision History: | |||
| --*/ | ||||
| #include "smt_context.h" | ||||
| #include "ast_util.h" | ||||
| #include "datatype_decl_plugin.h" | ||||
| #include "model_pp.h" | ||||
| 
 | ||||
| namespace smt { | ||||
| 
 | ||||
|  | @ -31,77 +33,112 @@ namespace smt { | |||
|         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; | ||||
|         pop_to_search_lvl(); | ||||
|         literal_vector const& lits = assigned_literals(); | ||||
|         unsigned sz = lits.size(); | ||||
|         datatype_util dt(m); | ||||
|         expr* e1, *e2;        | ||||
|         expr_ref fml(m); | ||||
|         for (unsigned i = start; i < sz; ++i) {             | ||||
|             literal lit = lits[i]; | ||||
|             if (lit == true_literal) continue; | ||||
|             expr* e = bool_var2expr(lit.var()); | ||||
|             uint_set s; | ||||
|             if (assumptions.contains(lit.var())) { | ||||
|                 s.insert(lit.var()); | ||||
|             } | ||||
|             else { | ||||
|                 b_justification js = get_justification(lit.var()); | ||||
|                 switch (js.get_kind()) { | ||||
|                 case b_justification::CLAUSE: { | ||||
|                     clause * cls      = js.get_clause(); | ||||
|                     unsigned num_lits = cls->get_num_literals(); | ||||
|                     for (unsigned j = 0; j < num_lits; ++j) { | ||||
|                         literal lit2 = cls->get_literal(j); | ||||
|                         if (lit2.var() != lit.var()) { | ||||
|                             s |= m_antecedents.find(lit2.var()); | ||||
|                         } | ||||
|         expr_ref fml(m);         | ||||
|         if (lit == true_literal) return; | ||||
|         expr* e = bool_var2expr(lit.var()); | ||||
|         uint_set s; | ||||
|         if (assumptions.contains(lit.var())) { | ||||
|             s.insert(lit.var()); | ||||
|         } | ||||
|         else { | ||||
|             b_justification js = get_justification(lit.var()); | ||||
|             switch (js.get_kind()) { | ||||
|             case b_justification::CLAUSE: { | ||||
|                 clause * cls = js.get_clause(); | ||||
|                 if (!cls) break; | ||||
|                 unsigned num_lits = cls->get_num_literals(); | ||||
|                 for (unsigned j = 0; j < num_lits; ++j) { | ||||
|                     literal lit2 = cls->get_literal(j); | ||||
|                     if (lit2.var() != lit.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; | ||||
|                 } | ||||
|                 }                 | ||||
|             }        | ||||
|             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); | ||||
|                 break; | ||||
|             } | ||||
|             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);                     | ||||
|                 } | ||||
|             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; | ||||
|             } | ||||
|             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) { | ||||
|         ast_manager& m = m_manager; | ||||
|         ptr_vector<expr> to_delete; | ||||
|  | @ -144,10 +181,15 @@ namespace smt { | |||
|         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.
 | ||||
|     // 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) { | ||||
|         TRACE("context", tout << "extract fixed consequences\n";); | ||||
|         ast_manager& m = m_manager; | ||||
|         ptr_vector<expr> to_delete; | ||||
|         expr_ref fml(m), eq(m); | ||||
|  | @ -155,8 +197,7 @@ namespace smt { | |||
|         for (; it != end; ++it) { | ||||
|             expr* k = it->m_key; | ||||
|             expr* v = it->m_value; | ||||
|             if (!m.is_bool(k) && e_internalized(k) && e_internalized(v) &&  | ||||
|                 get_enode(k)->get_root() == get_enode(v)->get_root()) { | ||||
|             if (!m.is_bool(k) && are_equal(k, v)) { | ||||
|                 literal_vector literals; | ||||
|                 m_conflict_resolution->eq2literals(get_enode(v), get_enode(k), literals); | ||||
|                 uint_set s; | ||||
|  | @ -175,9 +216,10 @@ namespace smt { | |||
|                 } | ||||
|                 eq = mk_eq_atom(k, v); | ||||
|                 internalize_formula(eq, false); | ||||
|                 literal lit(get_bool_var(eq), true); | ||||
|                 literal lit(get_bool_var(eq), false); | ||||
|                 literals.push_back(lit); | ||||
|                 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) { | ||||
|  | @ -192,6 +234,7 @@ namespace smt { | |||
|                                     expr_ref_vector& unfixed) { | ||||
| 
 | ||||
|         m_antecedents.reset(); | ||||
|         pop_to_base_lvl(); | ||||
|         lbool is_sat = check(assumptions.size(), assumptions.c_ptr()); | ||||
|         if (is_sat != l_true) { | ||||
|             return is_sat; | ||||
|  | @ -207,6 +250,7 @@ namespace smt { | |||
|         expr_ref_vector trail(m); | ||||
|         model_evaluator eval(*mdl.get()); | ||||
|         expr_ref val(m); | ||||
|         TRACE("context", model_pp(tout, *mdl);); | ||||
|         for (unsigned i = 0; i < vars.size(); ++i) { | ||||
|             eval(vars[i], val); | ||||
|             if (m.is_value(val)) { | ||||
|  | @ -233,9 +277,17 @@ namespace smt { | |||
|             obj_map<expr,expr*>::iterator it = var2val.begin(); | ||||
|             expr* e = it->m_key; | ||||
|             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; | ||||
|             if (m.is_bool(e)) { | ||||
|                 lit = literal(get_bool_var(e), m.is_true(val)); | ||||
|  | @ -244,9 +296,20 @@ namespace smt { | |||
|                 eq = mk_eq_atom(e, val); | ||||
|                 internalize_formula(eq, false); | ||||
|                 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); | ||||
|             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) { | ||||
|                 is_sat = bounded_search(); | ||||
|                 TRACE("context", tout << "search result: " << is_sat << "\n";); | ||||
|  | @ -260,33 +323,78 @@ namespace smt { | |||
|                 } | ||||
|                 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); | ||||
|                 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";); | ||||
|                 pop_to_search_lvl(); | ||||
|                 extract_fixed_consequences(num_units, var2val, _assumptions, conseq); | ||||
|                 ++num_reiterations; | ||||
|                 continue; | ||||
|             } | ||||
|             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; | ||||
| 
 | ||||
|             //
 | ||||
|             // 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; | ||||
|             if (apply_slow_pass) { | ||||
|             if (apply_slow_pass && is_sat == l_true) { | ||||
|                 num_unfixed += delete_unfixed(var2val, unfixed); | ||||
|                 // The next time we check the model is after 1.5 additional iterations.
 | ||||
|                 model_threshold *= 3; | ||||
|                 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); | ||||
|             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) { | ||||
|                 num_fixed_eqs += extract_fixed_eqs(var2val, conseq); | ||||
|                 IF_VERBOSE(1, verbose_stream() << "(get-consequences" | ||||
|  | @ -306,18 +414,72 @@ namespace smt { | |||
|                       << " unfixed-deleted: " << num_unfixed | ||||
|                       << ")\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)) { | ||||
|                 TRACE("context", tout << "Fixed value to " << mk_pp(e, m) << " was not processed\n";); | ||||
|                 expr_ref fml(m); | ||||
|                 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); | ||||
|                 conseq.push_back(fml); | ||||
|                 var2val.erase(e); | ||||
|                 SASSERT(get_assignment(lit) == l_false); | ||||
|             }         | ||||
|         } | ||||
|         end_search(); | ||||
|         DEBUG_CODE(validate_consequences(assumptions, vars, conseq, unfixed);); | ||||
|         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. | ||||
|        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 * r2 = n2->get_root(); | ||||
|         TRACE("add_diseq", tout << "assigning: #" << n1->get_owner_id() << " != #" << n2->get_owner_id() << "\n"; | ||||
|  | @ -1111,7 +1111,7 @@ namespace smt { | |||
| 
 | ||||
|         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";); | ||||
|             return; // context is inconsistent
 | ||||
|             return false; // context is inconsistent
 | ||||
|         } | ||||
| 
 | ||||
|         // Propagate disequalities to theories
 | ||||
|  | @ -1145,6 +1145,7 @@ namespace smt { | |||
|                 l1 = l1->get_next(); | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|      | ||||
|     /**
 | ||||
|  | @ -1400,7 +1401,9 @@ namespace smt { | |||
|                 } | ||||
|                 else { | ||||
|                     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()) { | ||||
|  |  | |||
|  | @ -942,7 +942,7 @@ namespace smt { | |||
|             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); | ||||
| 
 | ||||
|  | @ -1345,6 +1345,7 @@ namespace smt { | |||
|             vector<bool_var> b2v, ast_translation& tr); | ||||
| 
 | ||||
|         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); | ||||
|          | ||||
|         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); | ||||
| 
 | ||||
|         void validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars,  | ||||
|                                    expr_ref_vector const& conseq, expr_ref_vector const& unfixed); | ||||
| 
 | ||||
| 
 | ||||
|     public: | ||||
|         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";); | ||||
|         switch (k) { | ||||
|         case CLS_AUX: { | ||||
|             unsigned old_num_lits = num_lits; | ||||
|             literal_buffer simp_lits; | ||||
|             if (!simplify_aux_clause_literals(num_lits, lits, simp_lits)) | ||||
|                 return 0; // clause is equivalent to true;
 | ||||
|  |  | |||
|  | @ -64,7 +64,7 @@ namespace smt { | |||
|                     lower(v2)->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, v2);); | ||||
|                     m_stats.m_fixed_eqs++; | ||||
|  | @ -175,7 +175,7 @@ namespace smt { | |||
|         timer.stop(); | ||||
|         ok++; | ||||
|         if (ok % 100000 == 0) { | ||||
|             TRACE("propagate_cheap_eq",  | ||||
|             TRACE("arith_eq",  | ||||
|                   tout << total << " " << ok << " "  | ||||
|                   << static_cast<double>(ok)/static_cast<double>(total)  | ||||
|                   << " " << timer.get_seconds() << "\n"; | ||||
|  | @ -216,7 +216,7 @@ namespace smt { | |||
|     void theory_arith<Ext>::propagate_cheap_eq(unsigned rid) { | ||||
|         if (!propagate_eqs()) | ||||
|             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);); | ||||
|         row const & r = m_rows[rid]; | ||||
|         theory_var x; | ||||
|  | @ -258,7 +258,7 @@ namespace smt { | |||
|                 // found equality x = y
 | ||||
|                 antecedents ante(*this); | ||||
|                 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++; | ||||
|                 propagate_eq_to_core(x, y, ante); | ||||
|             } | ||||
|  | @ -299,7 +299,7 @@ namespace smt { | |||
|                             antecedents ante(*this); | ||||
|                             collect_fixed_var_justifications(r, 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 << "x  : v" << x << "\n"; | ||||
|                                   tout << "x2 : v" << x2 << "\n"; | ||||
|  | @ -343,7 +343,7 @@ namespace smt { | |||
|                     antecedents.eqs().size(), antecedents.eqs().c_ptr(), | ||||
|                     _x, _y,  | ||||
|                     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, y);); | ||||
|         ctx.assign_eq(_x, _y, eq_justification(js)); | ||||
|  |  | |||
|  | @ -97,6 +97,7 @@ namespace smt { | |||
|         virtual void pop_scope_eh(unsigned num_scopes); | ||||
|         virtual final_check_status final_check_eh(); | ||||
|         virtual void reset_eh(); | ||||
|         virtual void restart_eh() { m_util.reset(); } | ||||
|         virtual bool is_shared(theory_var v) const; | ||||
|     public: | ||||
|         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; | ||||
|     TRACE("seq", display(tout << "level: " << get_context().get_scope_level() << "\n");); | ||||
|     TRACE("seq_verbose", get_context().display(tout);); | ||||
|     if (simplify_and_solve_eqs()) { | ||||
|         ++m_stats.m_solve_eqs; | ||||
|         TRACE("seq", tout << ">>solve_eqs\n";); | ||||
|  | @ -1009,6 +1010,17 @@ bool theory_seq::is_nth(expr* e) const { | |||
|     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 { | ||||
|     rational r; | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|     zstring str; | ||||
|     if (m_util.str.is_string(s, str) && str.length() > 0) { | ||||
|  | @ -1133,7 +1149,7 @@ bool theory_seq::check_extensionality() { | |||
|                     continue; | ||||
|                 } | ||||
|                 TRACE("seq", tout << m_lhs << " = " << m_rhs << "\n";); | ||||
|                 ctx.assume_eq(n1, n2);                 | ||||
|                 ctx.assume_eq(n1, n2); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | @ -2668,6 +2684,13 @@ expr_ref theory_seq::expand(expr* e0, dependency*& eqs) { | |||
|     } | ||||
|     else if (m.is_ite(e, e1, e2, e3)) { | ||||
|         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)) { | ||||
|         case l_true: | ||||
|             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";); | ||||
|             break; | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|     else if (m_util.str.is_itos(e, e1)) { | ||||
|         rational val; | ||||
|  | @ -2902,9 +2926,13 @@ void theory_seq::add_replace_axiom(expr* r) { | |||
|     expr_ref xty = mk_concat(x, t, y); | ||||
|     expr_ref xsy = mk_concat(x, s, y); | ||||
|     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(a, xsy)); | ||||
|     add_axiom(~cnt, mk_seq_eq(r, xty)); | ||||
|     add_axiom(~s_emp, mk_seq_eq(r, a)); | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -449,10 +449,12 @@ namespace smt { | |||
|         bool is_var(expr* b); | ||||
|         bool add_solution(expr* l, expr* r, dependency* dep); | ||||
|         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_eq(expr* e, expr*& a, expr*& b) const;  | ||||
|         bool is_pre(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_last(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); | ||||
|                 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.
 | ||||
|                 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)); | ||||
|  | @ -130,6 +130,9 @@ class dt2bv_tactic : public tactic { | |||
|                 m_t.m_ext->insert(f, f_def); | ||||
|                 m_t.m_filter->insert(to_app(result)->get_decl()); | ||||
|             } | ||||
|             else { | ||||
|                 return false; | ||||
|             } | ||||
|             m_cache.insert(a, result); | ||||
|             ++m_t.m_num_translated; | ||||
|             return true; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue