/** Copyright (c) 2012-2014 Microsoft Corporation Module Name: Context.java Abstract: Author: @author Christoph Wintersteiger (cwinter) 2012-03-15 Notes: **/ package com.microsoft.z3; import static com.microsoft.z3.Constructor.of; import com.microsoft.z3.enumerations.Z3_ast_print_mode; import java.util.Map; /** * The main interaction with Z3 happens via the Context. * For applications that spawn an unbounded number of contexts, * the proper use is within a try-with-resources * scope so that the Context object gets garbage collected in * a predictable way. Contexts maintain all data-structures * related to terms and formulas that are created relative * to them. **/ public class Context implements AutoCloseable { private final long m_ctx; static final Object creation_lock = new Object(); public Context () { synchronized (creation_lock) { m_ctx = Native.mkContextRc(0); init(); } } protected Context (long m_ctx) { synchronized (creation_lock) { this.m_ctx = m_ctx; init(); } } /** * Constructor. * Remarks: * The following parameters can be set: * - proof (Boolean) Enable proof generation * - debug_ref_count (Boolean) Enable debug support for Z3_ast reference counting * - trace (Boolean) Tracing support for VCC * - trace_file_name (String) Trace out file for VCC traces * - timeout (unsigned) default timeout (in milliseconds) used for solvers * - well_sorted_check type checker * - auto_config use heuristics to automatically select solver and configure it * - model model generation for solvers, this parameter can be overwritten when creating a solver * - model_validate validate models produced by solvers * - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver * Note that in previous versions of Z3, this constructor was also used to set global and * module parameters. For this purpose we should now use {@code Global.setParameter} **/ public Context(Map settings) { synchronized (creation_lock) { long cfg = Native.mkConfig(); for (Map.Entry kv : settings.entrySet()) { Native.setParamValue(cfg, kv.getKey(), kv.getValue()); } m_ctx = Native.mkContextRc(cfg); Native.delConfig(cfg); init(); } } private void init() { setPrintMode(Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT); Native.setInternalErrorHandler(m_ctx); } /** * Creates a new symbol using an integer. * Remarks: Not all integers can be passed to this function. * The legal range of unsigned integers is 0 to 2^30-1. **/ public IntSymbol mkSymbol(int i) { return new IntSymbol(this, i); } /** * Create a symbol using a string. **/ public StringSymbol mkSymbol(String name) { return new StringSymbol(this, name); } /** * Create an array of symbols. **/ Symbol[] mkSymbols(String[] names) { if (names == null) return null; Symbol[] result = new Symbol[names.length]; for (int i = 0; i < names.length; ++i) result[i] = mkSymbol(names[i]); return result; } private BoolSort m_boolSort = null; private IntSort m_intSort = null; private RealSort m_realSort = null; private SeqSort m_stringSort = null; /** * Retrieves the Boolean sort of the context. **/ public BoolSort getBoolSort() { if (m_boolSort == null) { m_boolSort = new BoolSort(this); } return m_boolSort; } /** * Retrieves the Integer sort of the context. **/ public IntSort getIntSort() { if (m_intSort == null) { m_intSort = new IntSort(this); } return m_intSort; } /** * Retrieves the Real sort of the context. **/ public RealSort getRealSort() { if (m_realSort == null) { m_realSort = new RealSort(this); } return m_realSort; } /** * Create a new Boolean sort. **/ public BoolSort mkBoolSort() { return new BoolSort(this); } /** * Retrieves the Integer sort of the context. **/ public SeqSort getStringSort() { if (m_stringSort == null) { m_stringSort = mkStringSort(); } return m_stringSort; } /** * Create a new uninterpreted sort. **/ public UninterpretedSort mkUninterpretedSort(Symbol s) { checkContextMatch(s); return new UninterpretedSort(this, s); } /** * Create a new uninterpreted sort. **/ public UninterpretedSort mkUninterpretedSort(String str) { return mkUninterpretedSort(mkSymbol(str)); } /** * Create a new integer sort. **/ public IntSort mkIntSort() { return new IntSort(this); } /** * Create a real sort. **/ public RealSort mkRealSort() { return new RealSort(this); } /** * Create a new bit-vector sort. **/ public BitVecSort mkBitVecSort(int size) { return new BitVecSort(this, Native.mkBvSort(nCtx(), size)); } /** * Create a new array sort. **/ public ArraySort mkArraySort(Sort domain, Sort range) { checkContextMatch(domain); checkContextMatch(range); return new ArraySort(this, domain, range); } /** * Create a new string sort **/ public SeqSort mkStringSort() { return new SeqSort(this, Native.mkStringSort(nCtx())); } /** * Create a new sequence sort **/ public SeqSort mkSeqSort(Sort s) { return new SeqSort(this, Native.mkSeqSort(nCtx(), s.getNativeObject())); } /** * Create a new regular expression sort **/ public ReSort mkReSort(Sort s) { return new ReSort(this, Native.mkReSort(nCtx(), s.getNativeObject())); } /** * Create a new tuple sort. **/ public TupleSort mkTupleSort(Symbol name, Symbol[] fieldNames, Sort[] fieldSorts) { checkContextMatch(name); checkContextMatch(fieldNames); checkContextMatch(fieldSorts); return new TupleSort(this, name, fieldNames.length, fieldNames, fieldSorts); } /** * Create a new enumeration sort. **/ public EnumSort mkEnumSort(Symbol name, Symbol... enumNames) { checkContextMatch(name); checkContextMatch(enumNames); return new EnumSort(this, name, enumNames); } /** * Create a new enumeration sort. **/ public EnumSort mkEnumSort(String name, String... enumNames) { return new EnumSort(this, mkSymbol(name), mkSymbols(enumNames)); } /** * Create a new list sort. **/ public ListSort mkListSort(Symbol name, Sort elemSort) { checkContextMatch(name); checkContextMatch(elemSort); return new ListSort(this, name, elemSort); } /** * Create a new list sort. **/ public ListSort mkListSort(String name, Sort elemSort) { checkContextMatch(elemSort); return new ListSort(this, mkSymbol(name), elemSort); } /** * Create a new finite domain sort. **/ public FiniteDomainSort mkFiniteDomainSort(Symbol name, long size) { checkContextMatch(name); return new FiniteDomainSort(this, name, size); } /** * Create a new finite domain sort. **/ public FiniteDomainSort mkFiniteDomainSort(String name, long size) { return new FiniteDomainSort(this, mkSymbol(name), size); } /** * Create a datatype constructor. * @param name constructor name * @param recognizer name of recognizer function. * @param fieldNames names of the constructor fields. * @param sorts field sorts, 0 if the field sort refers to a recursive sort. * @param sortRefs reference to datatype sort that is an argument to the * constructor; if the corresponding sort reference is 0, then the value in sort_refs should be * an index referring to one of the recursive datatypes that is * declared. **/ public Constructor mkConstructor(Symbol name, Symbol recognizer, Symbol[] fieldNames, Sort[] sorts, int[] sortRefs) { return of(this, name, recognizer, fieldNames, sorts, sortRefs); } /** * Create a datatype constructor. **/ public Constructor mkConstructor(String name, String recognizer, String[] fieldNames, Sort[] sorts, int[] sortRefs) { return of(this, mkSymbol(name), mkSymbol(recognizer), mkSymbols(fieldNames), sorts, sortRefs); } /** * Create a new datatype sort. **/ public DatatypeSort mkDatatypeSort(Symbol name, Constructor[] constructors) { checkContextMatch(name); checkContextMatch(constructors); return new DatatypeSort(this, name, constructors); } /** * Create a new datatype sort. **/ public DatatypeSort mkDatatypeSort(String name, Constructor[] constructors) { checkContextMatch(constructors); return new DatatypeSort(this, mkSymbol(name), constructors); } /** * Create mutually recursive datatypes. * @param names names of datatype sorts * @param c list of constructors, one list per sort. **/ public DatatypeSort[] mkDatatypeSorts(Symbol[] names, Constructor[][] c) { checkContextMatch(names); int n = names.length; ConstructorList[] cla = new ConstructorList[n]; long[] n_constr = new long[n]; for (int i = 0; i < n; i++) { Constructor[] constructor = c[i]; checkContextMatch(constructor); cla[i] = new ConstructorList(this, constructor); n_constr[i] = cla[i].getNativeObject(); } long[] n_res = new long[n]; Native.mkDatatypes(nCtx(), n, Symbol.arrayToNative(names), n_res, n_constr); DatatypeSort[] res = new DatatypeSort[n]; for (int i = 0; i < n; i++) res[i] = new DatatypeSort(this, n_res[i]); return res; } /** * Create mutually recursive data-types. **/ public DatatypeSort[] mkDatatypeSorts(String[] names, Constructor[][] c) { return mkDatatypeSorts(mkSymbols(names), c); } /** * Update a datatype field at expression t with value v. * The function performs a record update at t. The field * that is passed in as argument is updated with value v, * the remaining fields of t are unchanged. **/ public Expr MkUpdateField(FuncDecl field, Expr t, Expr v) throws Z3Exception { return Expr.create (this, Native.datatypeUpdateField (nCtx(), field.getNativeObject(), t.getNativeObject(), v.getNativeObject())); } /** * Creates a new function declaration. **/ public FuncDecl mkFuncDecl(Symbol name, Sort[] domain, Sort range) { checkContextMatch(name); checkContextMatch(domain); checkContextMatch(range); return new FuncDecl(this, name, domain, range); } /** * Creates a new function declaration. **/ public FuncDecl mkFuncDecl(Symbol name, Sort domain, Sort range) { checkContextMatch(name); checkContextMatch(domain); checkContextMatch(range); Sort[] q = new Sort[] { domain }; return new FuncDecl(this, name, q, range); } /** * Creates a new function declaration. **/ public FuncDecl mkFuncDecl(String name, Sort[] domain, Sort range) { checkContextMatch(domain); checkContextMatch(range); return new FuncDecl(this, mkSymbol(name), domain, range); } /** * Creates a new function declaration. **/ public FuncDecl mkFuncDecl(String name, Sort domain, Sort range) { checkContextMatch(domain); checkContextMatch(range); Sort[] q = new Sort[] { domain }; return new FuncDecl(this, mkSymbol(name), q, range); } /** * Creates a fresh function declaration with a name prefixed with * {@code prefix}. * @see #mkFuncDecl(String,Sort,Sort) * @see #mkFuncDecl(String,Sort[],Sort) **/ public FuncDecl mkFreshFuncDecl(String prefix, Sort[] domain, Sort range) { checkContextMatch(domain); checkContextMatch(range); return new FuncDecl(this, prefix, domain, range); } /** * Creates a new constant function declaration. **/ public FuncDecl mkConstDecl(Symbol name, Sort range) { checkContextMatch(name); checkContextMatch(range); return new FuncDecl(this, name, null, range); } /** * Creates a new constant function declaration. **/ public FuncDecl mkConstDecl(String name, Sort range) { checkContextMatch(range); return new FuncDecl(this, mkSymbol(name), null, range); } /** * Creates a fresh constant function declaration with a name prefixed with * {@code prefix"}. * @see #mkFuncDecl(String,Sort,Sort) * @see #mkFuncDecl(String,Sort[],Sort) **/ public FuncDecl mkFreshConstDecl(String prefix, Sort range) { checkContextMatch(range); return new FuncDecl(this, prefix, null, range); } /** * Creates a new bound variable. * @param index The de-Bruijn index of the variable * @param ty The sort of the variable **/ public Expr mkBound(int index, Sort ty) { return Expr.create(this, Native.mkBound(nCtx(), index, ty.getNativeObject())); } /** * Create a quantifier pattern. **/ public Pattern mkPattern(Expr... terms) { if (terms.length == 0) throw new Z3Exception("Cannot create a pattern from zero terms"); long[] termsNative = AST.arrayToNative(terms); return new Pattern(this, Native.mkPattern(nCtx(), terms.length, termsNative)); } /** * Creates a new Constant of sort {@code range} and named * {@code name}. **/ public Expr mkConst(Symbol name, Sort range) { checkContextMatch(name); checkContextMatch(range); return Expr.create( this, Native.mkConst(nCtx(), name.getNativeObject(), range.getNativeObject())); } /** * Creates a new Constant of sort {@code range} and named * {@code name}. **/ public Expr mkConst(String name, Sort range) { return mkConst(mkSymbol(name), range); } /** * Creates a fresh Constant of sort {@code range} and a name * prefixed with {@code prefix}. **/ public Expr mkFreshConst(String prefix, Sort range) { checkContextMatch(range); return Expr.create(this, Native.mkFreshConst(nCtx(), prefix, range.getNativeObject())); } /** * Creates a fresh constant from the FuncDecl {@code f}. * @param f A decl of a 0-arity function **/ public Expr mkConst(FuncDecl f) { return mkApp(f, (Expr[]) null); } /** * Create a Boolean constant. **/ public BoolExpr mkBoolConst(Symbol name) { return (BoolExpr) mkConst(name, getBoolSort()); } /** * Create a Boolean constant. **/ public BoolExpr mkBoolConst(String name) { return (BoolExpr) mkConst(mkSymbol(name), getBoolSort()); } /** * Creates an integer constant. **/ public IntExpr mkIntConst(Symbol name) { return (IntExpr) mkConst(name, getIntSort()); } /** * Creates an integer constant. **/ public IntExpr mkIntConst(String name) { return (IntExpr) mkConst(name, getIntSort()); } /** * Creates a real constant. **/ public RealExpr mkRealConst(Symbol name) { return (RealExpr) mkConst(name, getRealSort()); } /** * Creates a real constant. **/ public RealExpr mkRealConst(String name) { return (RealExpr) mkConst(name, getRealSort()); } /** * Creates a bit-vector constant. **/ public BitVecExpr mkBVConst(Symbol name, int size) { return (BitVecExpr) mkConst(name, mkBitVecSort(size)); } /** * Creates a bit-vector constant. **/ public BitVecExpr mkBVConst(String name, int size) { return (BitVecExpr) mkConst(name, mkBitVecSort(size)); } /** * Create a new function application. **/ public Expr mkApp(FuncDecl f, Expr... args) { checkContextMatch(f); checkContextMatch(args); return Expr.create(this, f, args); } /** * The true Term. **/ public BoolExpr mkTrue() { return new BoolExpr(this, Native.mkTrue(nCtx())); } /** * The false Term. **/ public BoolExpr mkFalse() { return new BoolExpr(this, Native.mkFalse(nCtx())); } /** * Creates a Boolean value. **/ public BoolExpr mkBool(boolean value) { return value ? mkTrue() : mkFalse(); } /** * Creates the equality {@code x"/> = to every subgoal produced by evaluates to true and getConstructorDRQ() { return m_Constructor_DRQ; } public IDecRefQueue getConstructorListDRQ() { return m_ConstructorList_DRQ; } public IDecRefQueue getASTDRQ() { return m_AST_DRQ; } public IDecRefQueue getASTMapDRQ() { return m_ASTMap_DRQ; } public IDecRefQueue getASTVectorDRQ() { return m_ASTVector_DRQ; } public IDecRefQueue getApplyResultDRQ() { return m_ApplyResult_DRQ; } public IDecRefQueue getFuncEntryDRQ() { return m_FuncEntry_DRQ; } public IDecRefQueue getFuncInterpDRQ() { return m_FuncInterp_DRQ; } public IDecRefQueue getGoalDRQ() { return m_Goal_DRQ; } public IDecRefQueue getModelDRQ() { return m_Model_DRQ; } public IDecRefQueue getParamsDRQ() { return m_Params_DRQ; } public IDecRefQueue getParamDescrsDRQ() { return m_ParamDescrs_DRQ; } public IDecRefQueue getProbeDRQ() { return m_Probe_DRQ; } public IDecRefQueue getSolverDRQ() { return m_Solver_DRQ; } public IDecRefQueue getStatisticsDRQ() { return m_Statistics_DRQ; } public IDecRefQueue getTacticDRQ() { return m_Tactic_DRQ; } public IDecRefQueue getFixedpointDRQ() { return m_Fixedpoint_DRQ; } public IDecRefQueue getOptimizeDRQ() { return m_Optimize_DRQ; } /** * Disposes of the context. **/ @Override public void close() { m_AST_DRQ.forceClear(this); m_ASTMap_DRQ.forceClear(this); m_ASTVector_DRQ.forceClear(this); m_ApplyResult_DRQ.forceClear(this); m_FuncEntry_DRQ.forceClear(this); m_FuncInterp_DRQ.forceClear(this); m_Goal_DRQ.forceClear(this); m_Model_DRQ.forceClear(this); m_Params_DRQ.forceClear(this); m_Probe_DRQ.forceClear(this); m_Solver_DRQ.forceClear(this); m_Optimize_DRQ.forceClear(this); m_Statistics_DRQ.forceClear(this); m_Tactic_DRQ.forceClear(this); m_Fixedpoint_DRQ.forceClear(this); m_boolSort = null; m_intSort = null; m_realSort = null; m_stringSort = null; synchronized (creation_lock) { Native.delContext(m_ctx); } } }