00001
00002
00003
00004
00005
00006
00007
00008
00009 """Z3 is a high performance theorem prover developed at Microsoft Research. Z3 is used in many applications such as: software/hardware verification and testing, constraint solving, analysis of hybrid systems, security, biology (in silico analysis), and geometrical problems.
00010
00011 Several online tutorials for Z3Py are available at:
00012 http://rise4fun.com/Z3Py/tutorial/guide
00013
00014 Please send feedback, comments and/or corrections to leonardo@microsoft.com. Your comments are very valuable.
00015
00016 Small example:
00017
00018 >>> x = Int('x')
00019 >>> y = Int('y')
00020 >>> s = Solver()
00021 >>> s.add(x > 0)
00022 >>> s.add(x < 2)
00023 >>> s.add(y == x + 1)
00024 >>> s.check()
00025 sat
00026 >>> m = s.model()
00027 >>> m[x]
00028 1
00029 >>> m[y]
00030 2
00031
00032 Z3 exceptions:
00033
00034 >>> try:
00035 ... x = BitVec('x', 32)
00036 ... y = Bool('y')
00037 ... # the expression x + y is type incorrect
00038 ... n = x + y
00039 ... except Z3Exception as ex:
00040 ... print("failed: %s" % ex)
00041 failed: sort mismatch
00042 """
00043 from z3core import *
00044 from z3types import *
00045 from z3consts import *
00046 from z3printer import *
00047 from fractions import Fraction
00048 import sys
00049 import io
00050
00051 if sys.version < '3':
00052 def _is_int(v):
00053 return isinstance(v, int) or isinstance(v, long)
00054 else:
00055 def _is_int(v):
00056 return isinstance(v, int)
00057
00058 def enable_trace(msg):
00059 Z3_enable_trace(msg)
00060
00061 def disable_trace(msg):
00062 Z3_disable_trace(msg)
00063
00064 def get_version_string():
00065 major = ctypes.c_uint(0)
00066 minor = ctypes.c_uint(0)
00067 build = ctypes.c_uint(0)
00068 rev = ctypes.c_uint(0)
00069 Z3_get_version(major, minor, build, rev)
00070 return "%s.%s.%s" % (major.value, minor.value, build.value)
00071
00072 def get_version():
00073 major = ctypes.c_uint(0)
00074 minor = ctypes.c_uint(0)
00075 build = ctypes.c_uint(0)
00076 rev = ctypes.c_uint(0)
00077 Z3_get_version(major, minor, build, rev)
00078 return (major.value, minor.value, build.value, rev.value)
00079
00080
00081
00082 def _z3_assert(cond, msg):
00083 if not cond:
00084 raise Z3Exception(msg)
00085
00086 def open_log(fname):
00087 """Log interaction to a file. This function must be invoked immediately after init(). """
00088 Z3_open_log(fname)
00089
00090 def append_log(s):
00091 """Append user-defined string to interaction log. """
00092 Z3_append_log(s)
00093
00094 def to_symbol(s, ctx=None):
00095 """Convert an integer or string into a Z3 symbol."""
00096 if isinstance(s, int):
00097 return Z3_mk_int_symbol(_get_ctx(ctx).ref(), s)
00098 else:
00099 return Z3_mk_string_symbol(_get_ctx(ctx).ref(), s)
00100
00101 def _symbol2py(ctx, s):
00102 """Convert a Z3 symbol back into a Python object. """
00103 if Z3_get_symbol_kind(ctx.ref(), s) == Z3_INT_SYMBOL:
00104 return "k!%s" % Z3_get_symbol_int(ctx.ref(), s)
00105 else:
00106 return Z3_get_symbol_string(ctx.ref(), s)
00107
00108 _error_handler_fptr = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_uint)
00109
00110
00111
00112 def _get_args(args):
00113 try:
00114 if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)):
00115 return args[0]
00116 else:
00117 return args
00118 except:
00119 return args
00120
00121 def _Z3python_error_handler_core(c, e):
00122
00123
00124 return
00125
00126 _Z3Python_error_handler = _error_handler_fptr(_Z3python_error_handler_core)
00127
00128 def _to_param_value(val):
00129 if isinstance(val, bool):
00130 if val == True:
00131 return "true"
00132 else:
00133 return "false"
00134 else:
00135 return str(val)
00136
00137 class Context:
00138 """A Context manages all other Z3 objects, global configuration options, etc.
00139
00140 Z3Py uses a default global context. For most applications this is sufficient.
00141 An application may use multiple Z3 contexts. Objects created in one context
00142 cannot be used in another one. However, several objects may be "translated" from
00143 one context to another. It is not safe to access Z3 objects from multiple threads.
00144 The only exception is the method `interrupt()` that can be used to interrupt() a long
00145 computation.
00146 The initialization method receives global configuration options for the new context.
00147 """
00148 def __init__(self, *args, **kws):
00149 if __debug__:
00150 _z3_assert(len(args) % 2 == 0, "Argument list must have an even number of elements.")
00151 conf = Z3_mk_config()
00152 for key in kws:
00153 value = kws[key]
00154 Z3_set_param_value(conf, str(key).upper(), _to_param_value(value))
00155 prev = None
00156 for a in args:
00157 if prev == None:
00158 prev = a
00159 else:
00160 Z3_set_param_value(conf, str(prev), _to_param_value(a))
00161 prev = None
00162 self.lib = lib()
00163 self.ctx = Z3_mk_context_rc(conf)
00164 Z3_set_ast_print_mode(self.ctx, Z3_PRINT_SMTLIB2_COMPLIANT)
00165 lib().Z3_set_error_handler.restype = None
00166 lib().Z3_set_error_handler.argtypes = [ContextObj, _error_handler_fptr]
00167 lib().Z3_set_error_handler(self.ctx, _Z3Python_error_handler)
00168 Z3_del_config(conf)
00169
00170 def __del__(self):
00171 self.lib.Z3_del_context(self.ctx)
00172
00173 def ref(self):
00174 """Return a reference to the actual C pointer to the Z3 context."""
00175 return self.ctx
00176
00177 def interrupt(self):
00178 """Interrupt a solver performing a satisfiability test, a tactic processing a goal, or simplify functions.
00179
00180 This method can be invoked from a thread different from the one executing the
00181 interruptable procedure.
00182 """
00183 Z3_interrupt(self.ref())
00184
00185
00186
00187 _main_ctx = None
00188 def main_ctx():
00189 """Return a reference to the global Z3 context.
00190
00191 >>> x = Real('x')
00192 >>> x.ctx == main_ctx()
00193 True
00194 >>> c = Context()
00195 >>> c == main_ctx()
00196 False
00197 >>> x2 = Real('x', c)
00198 >>> x2.ctx == c
00199 True
00200 >>> eq(x, x2)
00201 False
00202 """
00203 global _main_ctx
00204 if _main_ctx == None:
00205 _main_ctx = Context()
00206 return _main_ctx
00207
00208 def _get_ctx(ctx):
00209 if ctx == None:
00210 return main_ctx()
00211 else:
00212 return ctx
00213
00214 def set_param(*args, **kws):
00215 """Set Z3 global (or module) parameters.
00216
00217 >>> set_param(precision=10)
00218 """
00219 if __debug__:
00220 _z3_assert(len(args) % 2 == 0, "Argument list must have an even number of elements.")
00221 new_kws = {}
00222 for k in kws:
00223 v = kws[k]
00224 if not set_pp_option(k, v):
00225 new_kws[k] = v
00226 for key in new_kws:
00227 value = new_kws[key]
00228 Z3_global_param_set(str(key).upper(), _to_param_value(value))
00229 prev = None
00230 for a in args:
00231 if prev == None:
00232 prev = a
00233 else:
00234 Z3_global_param_set(str(prev), _to_param_value(a))
00235 prev = None
00236
00237 def reset_params():
00238 """Reset all global (or module) parameters.
00239 """
00240 Z3_global_param_reset_all()
00241
00242 def set_option(*args, **kws):
00243 """Alias for 'set_param' for backward compatibility.
00244 """
00245 return set_param(*args, **kws)
00246
00247 def get_param(name):
00248 """Return the value of a Z3 global (or module) parameter
00249
00250 >>> get_param('nlsat.reorder')
00251 'true'
00252 """
00253 ptr = (ctypes.c_char_p * 1)()
00254 if Z3_global_param_get(str(name), ptr):
00255 r = z3core._to_pystr(ptr[0])
00256 return r
00257 raise Z3Exception("failed to retrieve value for '%s'" % name)
00258
00259
00260
00261
00262
00263
00264
00265
00266 class Z3PPObject:
00267 """Superclass for all Z3 objects that have support for pretty printing."""
00268 def use_pp(self):
00269 return True
00270
00271 class AstRef(Z3PPObject):
00272 """AST are Direct Acyclic Graphs (DAGs) used to represent sorts, declarations and expressions."""
00273 def __init__(self, ast, ctx=None):
00274 self.ast = ast
00275 self.ctx = _get_ctx(ctx)
00276 Z3_inc_ref(self.ctx.ref(), self.as_ast())
00277
00278 def __del__(self):
00279 Z3_dec_ref(self.ctx.ref(), self.as_ast())
00280
00281 def __str__(self):
00282 return obj_to_string(self)
00283
00284 def __repr__(self):
00285 return obj_to_string(self)
00286
00287 def sexpr(self):
00288 """Return an string representing the AST node in s-expression notation.
00289
00290 >>> x = Int('x')
00291 >>> ((x + 1)*x).sexpr()
00292 '(* (+ x 1) x)'
00293 """
00294 return Z3_ast_to_string(self.ctx_ref(), self.as_ast())
00295
00296 def as_ast(self):
00297 """Return a pointer to the corresponding C Z3_ast object."""
00298 return self.ast
00299
00300 def get_id(self):
00301 """Return unique identifier for object. It can be used for hash-tables and maps."""
00302 return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
00303
00304 def ctx_ref(self):
00305 """Return a reference to the C context where this AST node is stored."""
00306 return self.ctx.ref()
00307
00308 def eq(self, other):
00309 """Return `True` if `self` and `other` are structurally identical.
00310
00311 >>> x = Int('x')
00312 >>> n1 = x + 1
00313 >>> n2 = 1 + x
00314 >>> n1.eq(n2)
00315 False
00316 >>> n1 = simplify(n1)
00317 >>> n2 = simplify(n2)
00318 >>> n1.eq(n2)
00319 True
00320 """
00321 if __debug__:
00322 _z3_assert(is_ast(other), "Z3 AST expected")
00323 return Z3_is_eq_ast(self.ctx_ref(), self.as_ast(), other.as_ast())
00324
00325 def translate(self, target):
00326 """Translate `self` to the context `target`. That is, return a copy of `self` in the context `target`.
00327
00328 >>> c1 = Context()
00329 >>> c2 = Context()
00330 >>> x = Int('x', c1)
00331 >>> y = Int('y', c2)
00332 >>> # Nodes in different contexts can't be mixed.
00333 >>> # However, we can translate nodes from one context to another.
00334 >>> x.translate(c2) + y
00335 x + y
00336 """
00337 if __debug__:
00338 _z3_assert(isinstance(target, Context), "argument must be a Z3 context")
00339 return _to_ast_ref(Z3_translate(self.ctx.ref(), self.as_ast(), target.ref()), target)
00340
00341 def hash(self):
00342 """Return a hashcode for the `self`.
00343
00344 >>> n1 = simplify(Int('x') + 1)
00345 >>> n2 = simplify(2 + Int('x') - 1)
00346 >>> n1.hash() == n2.hash()
00347 True
00348 """
00349 return Z3_get_ast_hash(self.ctx_ref(), self.as_ast())
00350
00351 def is_ast(a):
00352 """Return `True` if `a` is an AST node.
00353
00354 >>> is_ast(10)
00355 False
00356 >>> is_ast(IntVal(10))
00357 True
00358 >>> is_ast(Int('x'))
00359 True
00360 >>> is_ast(BoolSort())
00361 True
00362 >>> is_ast(Function('f', IntSort(), IntSort()))
00363 True
00364 >>> is_ast("x")
00365 False
00366 >>> is_ast(Solver())
00367 False
00368 """
00369 return isinstance(a, AstRef)
00370
00371 def eq(a, b):
00372 """Return `True` if `a` and `b` are structurally identical AST nodes.
00373
00374 >>> x = Int('x')
00375 >>> y = Int('y')
00376 >>> eq(x, y)
00377 False
00378 >>> eq(x + 1, x + 1)
00379 True
00380 >>> eq(x + 1, 1 + x)
00381 False
00382 >>> eq(simplify(x + 1), simplify(1 + x))
00383 True
00384 """
00385 if __debug__:
00386 _z3_assert(is_ast(a) and is_ast(b), "Z3 ASTs expected")
00387 return a.eq(b)
00388
00389 def _ast_kind(ctx, a):
00390 if is_ast(a):
00391 a = a.as_ast()
00392 return Z3_get_ast_kind(ctx.ref(), a)
00393
00394 def _ctx_from_ast_arg_list(args, default_ctx=None):
00395 ctx = None
00396 for a in args:
00397 if is_ast(a) or is_probe(a):
00398 if ctx == None:
00399 ctx = a.ctx
00400 else:
00401 if __debug__:
00402 _z3_assert(ctx == a.ctx, "Context mismatch")
00403 if ctx == None:
00404 ctx = default_ctx
00405 return ctx
00406
00407 def _ctx_from_ast_args(*args):
00408 return _ctx_from_ast_arg_list(args)
00409
00410 def _to_func_decl_array(args):
00411 sz = len(args)
00412 _args = (FuncDecl * sz)()
00413 for i in range(sz):
00414 _args[i] = args[i].as_func_decl()
00415 return _args, sz
00416
00417 def _to_ast_array(args):
00418 sz = len(args)
00419 _args = (Ast * sz)()
00420 for i in range(sz):
00421 _args[i] = args[i].as_ast()
00422 return _args, sz
00423
00424 def _to_ref_array(ref, args):
00425 sz = len(args)
00426 _args = (ref * sz)()
00427 for i in range(sz):
00428 _args[i] = args[i].as_ast()
00429 return _args, sz
00430
00431 def _to_ast_ref(a, ctx):
00432 k = _ast_kind(ctx, a)
00433 if k == Z3_SORT_AST:
00434 return _to_sort_ref(a, ctx)
00435 elif k == Z3_FUNC_DECL_AST:
00436 return _to_func_decl_ref(a, ctx)
00437 else:
00438 return _to_expr_ref(a, ctx)
00439
00440
00441
00442
00443
00444
00445
00446 def _sort_kind(ctx, s):
00447 return Z3_get_sort_kind(ctx.ref(), s)
00448
00449 class SortRef(AstRef):
00450 """A Sort is essentially a type. Every Z3 expression has a sort. A sort is an AST node."""
00451 def as_ast(self):
00452 return Z3_sort_to_ast(self.ctx_ref(), self.ast)
00453
00454 def get_id(self):
00455 return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
00456
00457 def kind(self):
00458 """Return the Z3 internal kind of a sort. This method can be used to test if `self` is one of the Z3 builtin sorts.
00459
00460 >>> b = BoolSort()
00461 >>> b.kind() == Z3_BOOL_SORT
00462 True
00463 >>> b.kind() == Z3_INT_SORT
00464 False
00465 >>> A = ArraySort(IntSort(), IntSort())
00466 >>> A.kind() == Z3_ARRAY_SORT
00467 True
00468 >>> A.kind() == Z3_INT_SORT
00469 False
00470 """
00471 return _sort_kind(self.ctx, self.ast)
00472
00473 def subsort(self, other):
00474 """Return `True` if `self` is a subsort of `other`.
00475
00476 >>> IntSort().subsort(RealSort())
00477 True
00478 """
00479 return False
00480
00481 def cast(self, val):
00482 """Try to cast `val` as an element of sort `self`.
00483
00484 This method is used in Z3Py to convert Python objects such as integers,
00485 floats, longs and strings into Z3 expressions.
00486
00487 >>> x = Int('x')
00488 >>> RealSort().cast(x)
00489 ToReal(x)
00490 """
00491 if __debug__:
00492 _z3_assert(is_expr(val), "Z3 expression expected")
00493 _z3_assert(self.eq(val.sort()), "Sort mismatch")
00494 return val
00495
00496 def name(self):
00497 """Return the name (string) of sort `self`.
00498
00499 >>> BoolSort().name()
00500 'Bool'
00501 >>> ArraySort(IntSort(), IntSort()).name()
00502 'Array'
00503 """
00504 return _symbol2py(self.ctx, Z3_get_sort_name(self.ctx_ref(), self.ast))
00505
00506 def __eq__(self, other):
00507 """Return `True` if `self` and `other` are the same Z3 sort.
00508
00509 >>> p = Bool('p')
00510 >>> p.sort() == BoolSort()
00511 True
00512 >>> p.sort() == IntSort()
00513 False
00514 """
00515 if other == None:
00516 return False
00517 return Z3_is_eq_sort(self.ctx_ref(), self.ast, other.ast)
00518
00519 def __ne__(self, other):
00520 """Return `True` if `self` and `other` are not the same Z3 sort.
00521
00522 >>> p = Bool('p')
00523 >>> p.sort() != BoolSort()
00524 False
00525 >>> p.sort() != IntSort()
00526 True
00527 """
00528 return not Z3_is_eq_sort(self.ctx_ref(), self.ast, other.ast)
00529
00530 def is_sort(s):
00531 """Return `True` if `s` is a Z3 sort.
00532
00533 >>> is_sort(IntSort())
00534 True
00535 >>> is_sort(Int('x'))
00536 False
00537 >>> is_expr(Int('x'))
00538 True
00539 """
00540 return isinstance(s, SortRef)
00541
00542 def _to_sort_ref(s, ctx):
00543 if __debug__:
00544 _z3_assert(isinstance(s, Sort), "Z3 Sort expected")
00545 k = _sort_kind(ctx, s)
00546 if k == Z3_BOOL_SORT:
00547 return BoolSortRef(s, ctx)
00548 elif k == Z3_INT_SORT or k == Z3_REAL_SORT:
00549 return ArithSortRef(s, ctx)
00550 elif k == Z3_BV_SORT:
00551 return BitVecSortRef(s, ctx)
00552 elif k == Z3_ARRAY_SORT:
00553 return ArraySortRef(s, ctx)
00554 elif k == Z3_DATATYPE_SORT:
00555 return DatatypeSortRef(s, ctx)
00556 elif k == Z3_FINITE_DOMAIN_SORT:
00557 return FiniteDomainSortRef(s, ctx)
00558 elif k == Z3_FLOATING_POINT_SORT:
00559 return FPSortRef(s, ctx)
00560 elif k == Z3_ROUNDING_MODE_SORT:
00561 return FPRMSortRef(s, ctx)
00562 return SortRef(s, ctx)
00563
00564 def _sort(ctx, a):
00565 return _to_sort_ref(Z3_get_sort(ctx.ref(), a), ctx)
00566
00567 def DeclareSort(name, ctx=None):
00568 """Create a new uninterpred sort named `name`.
00569
00570 If `ctx=None`, then the new sort is declared in the global Z3Py context.
00571
00572 >>> A = DeclareSort('A')
00573 >>> a = Const('a', A)
00574 >>> b = Const('b', A)
00575 >>> a.sort() == A
00576 True
00577 >>> b.sort() == A
00578 True
00579 >>> a == b
00580 a == b
00581 """
00582 ctx = _get_ctx(ctx)
00583 return SortRef(Z3_mk_uninterpreted_sort(ctx.ref(), to_symbol(name, ctx)), ctx)
00584
00585
00586
00587
00588
00589
00590
00591 class FuncDeclRef(AstRef):
00592 """Function declaration. Every constant and function have an associated declaration.
00593
00594 The declaration assigns a name, a sort (i.e., type), and for function
00595 the sort (i.e., type) of each of its arguments. Note that, in Z3,
00596 a constant is a function with 0 arguments.
00597 """
00598 def as_ast(self):
00599 return Z3_func_decl_to_ast(self.ctx_ref(), self.ast)
00600
00601 def get_id(self):
00602 return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
00603
00604 def as_func_decl(self):
00605 return self.ast
00606
00607 def name(self):
00608 """Return the name of the function declaration `self`.
00609
00610 >>> f = Function('f', IntSort(), IntSort())
00611 >>> f.name()
00612 'f'
00613 >>> isinstance(f.name(), str)
00614 True
00615 """
00616 return _symbol2py(self.ctx, Z3_get_decl_name(self.ctx_ref(), self.ast))
00617
00618 def arity(self):
00619 """Return the number of arguments of a function declaration. If `self` is a constant, then `self.arity()` is 0.
00620
00621 >>> f = Function('f', IntSort(), RealSort(), BoolSort())
00622 >>> f.arity()
00623 2
00624 """
00625 return int(Z3_get_arity(self.ctx_ref(), self.ast))
00626
00627 def domain(self, i):
00628 """Return the sort of the argument `i` of a function declaration. This method assumes that `0 <= i < self.arity()`.
00629
00630 >>> f = Function('f', IntSort(), RealSort(), BoolSort())
00631 >>> f.domain(0)
00632 Int
00633 >>> f.domain(1)
00634 Real
00635 """
00636 if __debug__:
00637 _z3_assert(i < self.arity(), "Index out of bounds")
00638 return _to_sort_ref(Z3_get_domain(self.ctx_ref(), self.ast, i), self.ctx)
00639
00640 def range(self):
00641 """Return the sort of the range of a function declaration. For constants, this is the sort of the constant.
00642
00643 >>> f = Function('f', IntSort(), RealSort(), BoolSort())
00644 >>> f.range()
00645 Bool
00646 """
00647 return _to_sort_ref(Z3_get_range(self.ctx_ref(), self.ast), self.ctx)
00648
00649 def kind(self):
00650 """Return the internal kind of a function declaration. It can be used to identify Z3 built-in functions such as addition, multiplication, etc.
00651
00652 >>> x = Int('x')
00653 >>> d = (x + 1).decl()
00654 >>> d.kind() == Z3_OP_ADD
00655 True
00656 >>> d.kind() == Z3_OP_MUL
00657 False
00658 """
00659 return Z3_get_decl_kind(self.ctx_ref(), self.ast)
00660
00661 def __call__(self, *args):
00662 """Create a Z3 application expression using the function `self`, and the given arguments.
00663
00664 The arguments must be Z3 expressions. This method assumes that
00665 the sorts of the elements in `args` match the sorts of the
00666 domain. Limited coersion is supported. For example, if
00667 args[0] is a Python integer, and the function expects a Z3
00668 integer, then the argument is automatically converted into a
00669 Z3 integer.
00670
00671 >>> f = Function('f', IntSort(), RealSort(), BoolSort())
00672 >>> x = Int('x')
00673 >>> y = Real('y')
00674 >>> f(x, y)
00675 f(x, y)
00676 >>> f(x, x)
00677 f(x, ToReal(x))
00678 """
00679 args = _get_args(args)
00680 num = len(args)
00681 if __debug__:
00682 _z3_assert(num == self.arity(), "Incorrect number of arguments to %s" % self)
00683 _args = (Ast * num)()
00684 saved = []
00685 for i in range(num):
00686
00687
00688 tmp = self.domain(i).cast(args[i])
00689 saved.append(tmp)
00690 _args[i] = tmp.as_ast()
00691 return _to_expr_ref(Z3_mk_app(self.ctx_ref(), self.ast, len(args), _args), self.ctx)
00692
00693 def is_func_decl(a):
00694 """Return `True` if `a` is a Z3 function declaration.
00695
00696 >>> f = Function('f', IntSort(), IntSort())
00697 >>> is_func_decl(f)
00698 True
00699 >>> x = Real('x')
00700 >>> is_func_decl(x)
00701 False
00702 """
00703 return isinstance(a, FuncDeclRef)
00704
00705 def Function(name, *sig):
00706 """Create a new Z3 uninterpreted function with the given sorts.
00707
00708 >>> f = Function('f', IntSort(), IntSort())
00709 >>> f(f(0))
00710 f(f(0))
00711 """
00712 sig = _get_args(sig)
00713 if __debug__:
00714 _z3_assert(len(sig) > 0, "At least two arguments expected")
00715 arity = len(sig) - 1
00716 rng = sig[arity]
00717 if __debug__:
00718 _z3_assert(is_sort(rng), "Z3 sort expected")
00719 dom = (Sort * arity)()
00720 for i in range(arity):
00721 if __debug__:
00722 _z3_assert(is_sort(sig[i]), "Z3 sort expected")
00723 dom[i] = sig[i].ast
00724 ctx = rng.ctx
00725 return FuncDeclRef(Z3_mk_func_decl(ctx.ref(), to_symbol(name, ctx), arity, dom, rng.ast), ctx)
00726
00727 def _to_func_decl_ref(a, ctx):
00728 return FuncDeclRef(a, ctx)
00729
00730
00731
00732
00733
00734
00735
00736 class ExprRef(AstRef):
00737 """Constraints, formulas and terms are expressions in Z3.
00738
00739 Expressions are ASTs. Every expression has a sort.
00740 There are three main kinds of expressions:
00741 function applications, quantifiers and bounded variables.
00742 A constant is a function application with 0 arguments.
00743 For quantifier free problems, all expressions are
00744 function applications.
00745 """
00746 def as_ast(self):
00747 return self.ast
00748
00749 def get_id(self):
00750 return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
00751
00752 def sort(self):
00753 """Return the sort of expression `self`.
00754
00755 >>> x = Int('x')
00756 >>> (x + 1).sort()
00757 Int
00758 >>> y = Real('y')
00759 >>> (x + y).sort()
00760 Real
00761 """
00762 return _sort(self.ctx, self.as_ast())
00763
00764 def sort_kind(self):
00765 """Shorthand for `self.sort().kind()`.
00766
00767 >>> a = Array('a', IntSort(), IntSort())
00768 >>> a.sort_kind() == Z3_ARRAY_SORT
00769 True
00770 >>> a.sort_kind() == Z3_INT_SORT
00771 False
00772 """
00773 return self.sort().kind()
00774
00775 def __eq__(self, other):
00776 """Return a Z3 expression that represents the constraint `self == other`.
00777
00778 If `other` is `None`, then this method simply returns `False`.
00779
00780 >>> a = Int('a')
00781 >>> b = Int('b')
00782 >>> a == b
00783 a == b
00784 >>> a == None
00785 False
00786 """
00787 if other == None:
00788 return False
00789 a, b = _coerce_exprs(self, other)
00790 return BoolRef(Z3_mk_eq(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
00791
00792 def __ne__(self, other):
00793 """Return a Z3 expression that represents the constraint `self != other`.
00794
00795 If `other` is `None`, then this method simply returns `True`.
00796
00797 >>> a = Int('a')
00798 >>> b = Int('b')
00799 >>> a != b
00800 a != b
00801 >>> a != None
00802 True
00803 """
00804 if other == None:
00805 return True
00806 a, b = _coerce_exprs(self, other)
00807 _args, sz = _to_ast_array((a, b))
00808 return BoolRef(Z3_mk_distinct(self.ctx_ref(), 2, _args), self.ctx)
00809
00810 def decl(self):
00811 """Return the Z3 function declaration associated with a Z3 application.
00812
00813 >>> f = Function('f', IntSort(), IntSort())
00814 >>> a = Int('a')
00815 >>> t = f(a)
00816 >>> eq(t.decl(), f)
00817 True
00818 >>> (a + 1).decl()
00819 +
00820 """
00821 if __debug__:
00822 _z3_assert(is_app(self), "Z3 application expected")
00823 return FuncDeclRef(Z3_get_app_decl(self.ctx_ref(), self.as_ast()), self.ctx)
00824
00825 def num_args(self):
00826 """Return the number of arguments of a Z3 application.
00827
00828 >>> a = Int('a')
00829 >>> b = Int('b')
00830 >>> (a + b).num_args()
00831 2
00832 >>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort())
00833 >>> t = f(a, b, 0)
00834 >>> t.num_args()
00835 3
00836 """
00837 if __debug__:
00838 _z3_assert(is_app(self), "Z3 application expected")
00839 return int(Z3_get_app_num_args(self.ctx_ref(), self.as_ast()))
00840
00841 def arg(self, idx):
00842 """Return argument `idx` of the application `self`.
00843
00844 This method assumes that `self` is a function application with at least `idx+1` arguments.
00845
00846 >>> a = Int('a')
00847 >>> b = Int('b')
00848 >>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort())
00849 >>> t = f(a, b, 0)
00850 >>> t.arg(0)
00851 a
00852 >>> t.arg(1)
00853 b
00854 >>> t.arg(2)
00855 0
00856 """
00857 if __debug__:
00858 _z3_assert(is_app(self), "Z3 application expected")
00859 _z3_assert(idx < self.num_args(), "Invalid argument index")
00860 return _to_expr_ref(Z3_get_app_arg(self.ctx_ref(), self.as_ast(), idx), self.ctx)
00861
00862 def children(self):
00863 """Return a list containing the children of the given expression
00864
00865 >>> a = Int('a')
00866 >>> b = Int('b')
00867 >>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort())
00868 >>> t = f(a, b, 0)
00869 >>> t.children()
00870 [a, b, 0]
00871 """
00872 if is_app(self):
00873 return [self.arg(i) for i in range(self.num_args())]
00874 else:
00875 return []
00876
00877 def _to_expr_ref(a, ctx):
00878 if isinstance(a, Pattern):
00879 return PatternRef(a, ctx)
00880 ctx_ref = ctx.ref()
00881 k = Z3_get_ast_kind(ctx_ref, a)
00882 if k == Z3_QUANTIFIER_AST:
00883 return QuantifierRef(a, ctx)
00884 sk = Z3_get_sort_kind(ctx_ref, Z3_get_sort(ctx_ref, a))
00885 if sk == Z3_BOOL_SORT:
00886 return BoolRef(a, ctx)
00887 if sk == Z3_INT_SORT:
00888 if k == Z3_NUMERAL_AST:
00889 return IntNumRef(a, ctx)
00890 return ArithRef(a, ctx)
00891 if sk == Z3_REAL_SORT:
00892 if k == Z3_NUMERAL_AST:
00893 return RatNumRef(a, ctx)
00894 if _is_algebraic(ctx, a):
00895 return AlgebraicNumRef(a, ctx)
00896 return ArithRef(a, ctx)
00897 if sk == Z3_BV_SORT:
00898 if k == Z3_NUMERAL_AST:
00899 return BitVecNumRef(a, ctx)
00900 else:
00901 return BitVecRef(a, ctx)
00902 if sk == Z3_ARRAY_SORT:
00903 return ArrayRef(a, ctx)
00904 if sk == Z3_DATATYPE_SORT:
00905 return DatatypeRef(a, ctx)
00906 if sk == Z3_FLOATING_POINT_SORT:
00907 if k == Z3_APP_AST and _is_numeral(ctx, a):
00908 return FPNumRef(a, ctx)
00909 else:
00910 return FPRef(a, ctx)
00911 if sk == Z3_ROUNDING_MODE_SORT:
00912 return FPRMRef(a, ctx)
00913 return ExprRef(a, ctx)
00914
00915 def _coerce_expr_merge(s, a):
00916 if is_expr(a):
00917 s1 = a.sort()
00918 if s == None:
00919 return s1
00920 if s1.eq(s):
00921 return s
00922 elif s.subsort(s1):
00923 return s1
00924 elif s1.subsort(s):
00925 return s
00926 else:
00927 if __debug__:
00928 _z3_assert(s1.ctx == s.ctx, "context mismatch")
00929 _z3_assert(False, "sort mismatch")
00930 else:
00931 return s
00932
00933 def _coerce_exprs(a, b, ctx=None):
00934 if not is_expr(a) and not is_expr(b):
00935 a = _py2expr(a, ctx)
00936 b = _py2expr(b, ctx)
00937 s = None
00938 s = _coerce_expr_merge(s, a)
00939 s = _coerce_expr_merge(s, b)
00940 a = s.cast(a)
00941 b = s.cast(b)
00942 return (a, b)
00943
00944 def _reduce(f, l, a):
00945 r = a
00946 for e in l:
00947 r = f(r, e)
00948 return r
00949
00950 def _coerce_expr_list(alist, ctx=None):
00951 has_expr = False
00952 for a in alist:
00953 if is_expr(a):
00954 has_expr = True
00955 break
00956 if not has_expr:
00957 alist = [ _py2expr(a, ctx) for a in alist ]
00958 s = _reduce(_coerce_expr_merge, alist, None)
00959 return [ s.cast(a) for a in alist ]
00960
00961 def is_expr(a):
00962 """Return `True` if `a` is a Z3 expression.
00963
00964 >>> a = Int('a')
00965 >>> is_expr(a)
00966 True
00967 >>> is_expr(a + 1)
00968 True
00969 >>> is_expr(IntSort())
00970 False
00971 >>> is_expr(1)
00972 False
00973 >>> is_expr(IntVal(1))
00974 True
00975 >>> x = Int('x')
00976 >>> is_expr(ForAll(x, x >= 0))
00977 True
00978 """
00979 return isinstance(a, ExprRef)
00980
00981 def is_app(a):
00982 """Return `True` if `a` is a Z3 function application.
00983
00984 Note that, constants are function applications with 0 arguments.
00985
00986 >>> a = Int('a')
00987 >>> is_app(a)
00988 True
00989 >>> is_app(a + 1)
00990 True
00991 >>> is_app(IntSort())
00992 False
00993 >>> is_app(1)
00994 False
00995 >>> is_app(IntVal(1))
00996 True
00997 >>> x = Int('x')
00998 >>> is_app(ForAll(x, x >= 0))
00999 False
01000 """
01001 if not isinstance(a, ExprRef):
01002 return False
01003 k = _ast_kind(a.ctx, a)
01004 return k == Z3_NUMERAL_AST or k == Z3_APP_AST
01005
01006 def is_const(a):
01007 """Return `True` if `a` is Z3 constant/variable expression.
01008
01009 >>> a = Int('a')
01010 >>> is_const(a)
01011 True
01012 >>> is_const(a + 1)
01013 False
01014 >>> is_const(1)
01015 False
01016 >>> is_const(IntVal(1))
01017 True
01018 >>> x = Int('x')
01019 >>> is_const(ForAll(x, x >= 0))
01020 False
01021 """
01022 return is_app(a) and a.num_args() == 0
01023
01024 def is_var(a):
01025 """Return `True` if `a` is variable.
01026
01027 Z3 uses de-Bruijn indices for representing bound variables in
01028 quantifiers.
01029
01030 >>> x = Int('x')
01031 >>> is_var(x)
01032 False
01033 >>> is_const(x)
01034 True
01035 >>> f = Function('f', IntSort(), IntSort())
01036 >>> # Z3 replaces x with bound variables when ForAll is executed.
01037 >>> q = ForAll(x, f(x) == x)
01038 >>> b = q.body()
01039 >>> b
01040 f(Var(0)) == Var(0)
01041 >>> b.arg(1)
01042 Var(0)
01043 >>> is_var(b.arg(1))
01044 True
01045 """
01046 return is_expr(a) and _ast_kind(a.ctx, a) == Z3_VAR_AST
01047
01048 def get_var_index(a):
01049 """Return the de-Bruijn index of the Z3 bounded variable `a`.
01050
01051 >>> x = Int('x')
01052 >>> y = Int('y')
01053 >>> is_var(x)
01054 False
01055 >>> is_const(x)
01056 True
01057 >>> f = Function('f', IntSort(), IntSort(), IntSort())
01058 >>> # Z3 replaces x and y with bound variables when ForAll is executed.
01059 >>> q = ForAll([x, y], f(x, y) == x + y)
01060 >>> q.body()
01061 f(Var(1), Var(0)) == Var(1) + Var(0)
01062 >>> b = q.body()
01063 >>> b.arg(0)
01064 f(Var(1), Var(0))
01065 >>> v1 = b.arg(0).arg(0)
01066 >>> v2 = b.arg(0).arg(1)
01067 >>> v1
01068 Var(1)
01069 >>> v2
01070 Var(0)
01071 >>> get_var_index(v1)
01072 1
01073 >>> get_var_index(v2)
01074 0
01075 """
01076 if __debug__:
01077 _z3_assert(is_var(a), "Z3 bound variable expected")
01078 return int(Z3_get_index_value(a.ctx.ref(), a.as_ast()))
01079
01080 def is_app_of(a, k):
01081 """Return `True` if `a` is an application of the given kind `k`.
01082
01083 >>> x = Int('x')
01084 >>> n = x + 1
01085 >>> is_app_of(n, Z3_OP_ADD)
01086 True
01087 >>> is_app_of(n, Z3_OP_MUL)
01088 False
01089 """
01090 return is_app(a) and a.decl().kind() == k
01091
01092 def If(a, b, c, ctx=None):
01093 """Create a Z3 if-then-else expression.
01094
01095 >>> x = Int('x')
01096 >>> y = Int('y')
01097 >>> max = If(x > y, x, y)
01098 >>> max
01099 If(x > y, x, y)
01100 >>> simplify(max)
01101 If(x <= y, y, x)
01102 """
01103 if isinstance(a, Probe) or isinstance(b, Tactic) or isinstance(c, Tactic):
01104 return Cond(a, b, c, ctx)
01105 else:
01106 ctx = _get_ctx(_ctx_from_ast_arg_list([a, b, c], ctx))
01107 s = BoolSort(ctx)
01108 a = s.cast(a)
01109 b, c = _coerce_exprs(b, c, ctx)
01110 if __debug__:
01111 _z3_assert(a.ctx == b.ctx, "Context mismatch")
01112 return _to_expr_ref(Z3_mk_ite(ctx.ref(), a.as_ast(), b.as_ast(), c.as_ast()), ctx)
01113
01114 def Distinct(*args):
01115 """Create a Z3 distinct expression.
01116
01117 >>> x = Int('x')
01118 >>> y = Int('y')
01119 >>> Distinct(x, y)
01120 x != y
01121 >>> z = Int('z')
01122 >>> Distinct(x, y, z)
01123 Distinct(x, y, z)
01124 >>> simplify(Distinct(x, y, z))
01125 Distinct(x, y, z)
01126 >>> simplify(Distinct(x, y, z), blast_distinct=True)
01127 And(Not(x == y), Not(x == z), Not(y == z))
01128 """
01129 args = _get_args(args)
01130 ctx = _ctx_from_ast_arg_list(args)
01131 if __debug__:
01132 _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression")
01133 args = _coerce_expr_list(args, ctx)
01134 _args, sz = _to_ast_array(args)
01135 return BoolRef(Z3_mk_distinct(ctx.ref(), sz, _args), ctx)
01136
01137 def _mk_bin(f, a, b):
01138 args = (Ast * 2)()
01139 if __debug__:
01140 _z3_assert(a.ctx == b.ctx, "Context mismatch")
01141 args[0] = a.as_ast()
01142 args[1] = b.as_ast()
01143 return f(a.ctx.ref(), 2, args)
01144
01145 def Const(name, sort):
01146 """Create a constant of the given sort.
01147
01148 >>> Const('x', IntSort())
01149 x
01150 """
01151 if __debug__:
01152 _z3_assert(isinstance(sort, SortRef), "Z3 sort expected")
01153 ctx = sort.ctx
01154 return _to_expr_ref(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), sort.ast), ctx)
01155
01156 def Consts(names, sort):
01157 """Create a several constants of the given sort.
01158
01159 `names` is a string containing the names of all constants to be created.
01160 Blank spaces separate the names of different constants.
01161
01162 >>> x, y, z = Consts('x y z', IntSort())
01163 >>> x + y + z
01164 x + y + z
01165 """
01166 if isinstance(names, str):
01167 names = names.split(" ")
01168 return [Const(name, sort) for name in names]
01169
01170 def Var(idx, s):
01171 """Create a Z3 free variable. Free variables are used to create quantified formulas.
01172
01173 >>> Var(0, IntSort())
01174 Var(0)
01175 >>> eq(Var(0, IntSort()), Var(0, BoolSort()))
01176 False
01177 """
01178 if __debug__:
01179 _z3_assert(is_sort(s), "Z3 sort expected")
01180 return _to_expr_ref(Z3_mk_bound(s.ctx_ref(), idx, s.ast), s.ctx)
01181
01182 def RealVar(idx, ctx=None):
01183 """
01184 Create a real free variable. Free variables are used to create quantified formulas.
01185 They are also used to create polynomials.
01186
01187 >>> RealVar(0)
01188 Var(0)
01189 """
01190 return Var(idx, RealSort(ctx))
01191
01192 def RealVarVector(n, ctx=None):
01193 """
01194 Create a list of Real free variables.
01195 The variables have ids: 0, 1, ..., n-1
01196
01197 >>> x0, x1, x2, x3 = RealVarVector(4)
01198 >>> x2
01199 Var(2)
01200 """
01201 return [ RealVar(i, ctx) for i in range(n) ]
01202
01203
01204
01205
01206
01207
01208
01209 class BoolSortRef(SortRef):
01210 """Boolean sort."""
01211 def cast(self, val):
01212 """Try to cast `val` as a Boolean.
01213
01214 >>> x = BoolSort().cast(True)
01215 >>> x
01216 True
01217 >>> is_expr(x)
01218 True
01219 >>> is_expr(True)
01220 False
01221 >>> x.sort()
01222 Bool
01223 """
01224 if isinstance(val, bool):
01225 return BoolVal(val, self.ctx)
01226 if __debug__:
01227 _z3_assert(is_expr(val), "True, False or Z3 Boolean expression expected")
01228 _z3_assert(self.eq(val.sort()), "Value cannot be converted into a Z3 Boolean value")
01229 return val
01230
01231 def subsort(self, other):
01232 return isinstance(other, ArithSortRef)
01233
01234 def is_int(self):
01235 return True
01236
01237 def is_bool(self):
01238 return True
01239
01240
01241 class BoolRef(ExprRef):
01242 """All Boolean expressions are instances of this class."""
01243 def sort(self):
01244 return BoolSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
01245
01246 def is_bool(a):
01247 """Return `True` if `a` is a Z3 Boolean expression.
01248
01249 >>> p = Bool('p')
01250 >>> is_bool(p)
01251 True
01252 >>> q = Bool('q')
01253 >>> is_bool(And(p, q))
01254 True
01255 >>> x = Real('x')
01256 >>> is_bool(x)
01257 False
01258 >>> is_bool(x == 0)
01259 True
01260 """
01261 return isinstance(a, BoolRef)
01262
01263 def is_true(a):
01264 """Return `True` if `a` is the Z3 true expression.
01265
01266 >>> p = Bool('p')
01267 >>> is_true(p)
01268 False
01269 >>> is_true(simplify(p == p))
01270 True
01271 >>> x = Real('x')
01272 >>> is_true(x == 0)
01273 False
01274 >>> # True is a Python Boolean expression
01275 >>> is_true(True)
01276 False
01277 """
01278 return is_app_of(a, Z3_OP_TRUE)
01279
01280 def is_false(a):
01281 """Return `True` if `a` is the Z3 false expression.
01282
01283 >>> p = Bool('p')
01284 >>> is_false(p)
01285 False
01286 >>> is_false(False)
01287 False
01288 >>> is_false(BoolVal(False))
01289 True
01290 """
01291 return is_app_of(a, Z3_OP_FALSE)
01292
01293 def is_and(a):
01294 """Return `True` if `a` is a Z3 and expression.
01295
01296 >>> p, q = Bools('p q')
01297 >>> is_and(And(p, q))
01298 True
01299 >>> is_and(Or(p, q))
01300 False
01301 """
01302 return is_app_of(a, Z3_OP_AND)
01303
01304 def is_or(a):
01305 """Return `True` if `a` is a Z3 or expression.
01306
01307 >>> p, q = Bools('p q')
01308 >>> is_or(Or(p, q))
01309 True
01310 >>> is_or(And(p, q))
01311 False
01312 """
01313 return is_app_of(a, Z3_OP_OR)
01314
01315 def is_not(a):
01316 """Return `True` if `a` is a Z3 not expression.
01317
01318 >>> p = Bool('p')
01319 >>> is_not(p)
01320 False
01321 >>> is_not(Not(p))
01322 True
01323 """
01324 return is_app_of(a, Z3_OP_NOT)
01325
01326 def is_eq(a):
01327 """Return `True` if `a` is a Z3 equality expression.
01328
01329 >>> x, y = Ints('x y')
01330 >>> is_eq(x == y)
01331 True
01332 """
01333 return is_app_of(a, Z3_OP_EQ)
01334
01335 def is_distinct(a):
01336 """Return `True` if `a` is a Z3 distinct expression.
01337
01338 >>> x, y, z = Ints('x y z')
01339 >>> is_distinct(x == y)
01340 False
01341 >>> is_distinct(Distinct(x, y, z))
01342 True
01343 """
01344 return is_app_of(a, Z3_OP_DISTINCT)
01345
01346 def BoolSort(ctx=None):
01347 """Return the Boolean Z3 sort. If `ctx=None`, then the global context is used.
01348
01349 >>> BoolSort()
01350 Bool
01351 >>> p = Const('p', BoolSort())
01352 >>> is_bool(p)
01353 True
01354 >>> r = Function('r', IntSort(), IntSort(), BoolSort())
01355 >>> r(0, 1)
01356 r(0, 1)
01357 >>> is_bool(r(0, 1))
01358 True
01359 """
01360 ctx = _get_ctx(ctx)
01361 return BoolSortRef(Z3_mk_bool_sort(ctx.ref()), ctx)
01362
01363 def BoolVal(val, ctx=None):
01364 """Return the Boolean value `True` or `False`. If `ctx=None`, then the global context is used.
01365
01366 >>> BoolVal(True)
01367 True
01368 >>> is_true(BoolVal(True))
01369 True
01370 >>> is_true(True)
01371 False
01372 >>> is_false(BoolVal(False))
01373 True
01374 """
01375 ctx = _get_ctx(ctx)
01376 if val == False:
01377 return BoolRef(Z3_mk_false(ctx.ref()), ctx)
01378 else:
01379 return BoolRef(Z3_mk_true(ctx.ref()), ctx)
01380
01381 def Bool(name, ctx=None):
01382 """Return a Boolean constant named `name`. If `ctx=None`, then the global context is used.
01383
01384 >>> p = Bool('p')
01385 >>> q = Bool('q')
01386 >>> And(p, q)
01387 And(p, q)
01388 """
01389 ctx = _get_ctx(ctx)
01390 return BoolRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), BoolSort(ctx).ast), ctx)
01391
01392 def Bools(names, ctx=None):
01393 """Return a tuple of Boolean constants.
01394
01395 `names` is a single string containing all names separated by blank spaces.
01396 If `ctx=None`, then the global context is used.
01397
01398 >>> p, q, r = Bools('p q r')
01399 >>> And(p, Or(q, r))
01400 And(p, Or(q, r))
01401 """
01402 ctx = _get_ctx(ctx)
01403 if isinstance(names, str):
01404 names = names.split(" ")
01405 return [Bool(name, ctx) for name in names]
01406
01407 def BoolVector(prefix, sz, ctx=None):
01408 """Return a list of Boolean constants of size `sz`.
01409
01410 The constants are named using the given prefix.
01411 If `ctx=None`, then the global context is used.
01412
01413 >>> P = BoolVector('p', 3)
01414 >>> P
01415 [p__0, p__1, p__2]
01416 >>> And(P)
01417 And(p__0, p__1, p__2)
01418 """
01419 return [ Bool('%s__%s' % (prefix, i)) for i in range(sz) ]
01420
01421 def FreshBool(prefix='b', ctx=None):
01422 """Return a fresh Boolean constant in the given context using the given prefix.
01423
01424 If `ctx=None`, then the global context is used.
01425
01426 >>> b1 = FreshBool()
01427 >>> b2 = FreshBool()
01428 >>> eq(b1, b2)
01429 False
01430 """
01431 ctx = _get_ctx(ctx)
01432 return BoolRef(Z3_mk_fresh_const(ctx.ref(), prefix, BoolSort(ctx).ast), ctx)
01433
01434 def Implies(a, b, ctx=None):
01435 """Create a Z3 implies expression.
01436
01437 >>> p, q = Bools('p q')
01438 >>> Implies(p, q)
01439 Implies(p, q)
01440 >>> simplify(Implies(p, q))
01441 Or(Not(p), q)
01442 """
01443 ctx = _get_ctx(_ctx_from_ast_arg_list([a, b], ctx))
01444 s = BoolSort(ctx)
01445 a = s.cast(a)
01446 b = s.cast(b)
01447 return BoolRef(Z3_mk_implies(ctx.ref(), a.as_ast(), b.as_ast()), ctx)
01448
01449 def Xor(a, b, ctx=None):
01450 """Create a Z3 Xor expression.
01451
01452 >>> p, q = Bools('p q')
01453 >>> Xor(p, q)
01454 Xor(p, q)
01455 >>> simplify(Xor(p, q))
01456 Not(p) == q
01457 """
01458 ctx = _get_ctx(_ctx_from_ast_arg_list([a, b], ctx))
01459 s = BoolSort(ctx)
01460 a = s.cast(a)
01461 b = s.cast(b)
01462 return BoolRef(Z3_mk_xor(ctx.ref(), a.as_ast(), b.as_ast()), ctx)
01463
01464 def Not(a, ctx=None):
01465 """Create a Z3 not expression or probe.
01466
01467 >>> p = Bool('p')
01468 >>> Not(Not(p))
01469 Not(Not(p))
01470 >>> simplify(Not(Not(p)))
01471 p
01472 """
01473 ctx = _get_ctx(_ctx_from_ast_arg_list([a], ctx))
01474 if is_probe(a):
01475 # Not is also used to build probes
01476 return Probe(Z3_probe_not(ctx.ref(), a.probe), ctx)
01477 else:
01478 s = BoolSort(ctx)
01479 a = s.cast(a)
01480 return BoolRef(Z3_mk_not(ctx.ref(), a.as_ast()), ctx)
01481
01482 def _has_probe(args):
01483 """Return `True` if one of the elements of the given collection is a Z3 probe."""
01484 for arg in args:
01485 if is_probe(arg):
01486 return True
01487 return False
01488
01489 def And(*args):
01490 """Create a Z3 and-expression or and-probe.
01491
01492 >>> p, q, r = Bools('p q r')
01493 >>> And(p, q, r)
01494 And(p, q, r)
01495 >>> P = BoolVector('p', 5)
01496 >>> And(P)
01497 And(p__0, p__1, p__2, p__3, p__4)
01498 """
01499 last_arg = None
01500 if len(args) > 0:
01501 last_arg = args[len(args)-1]
01502 if isinstance(last_arg, Context):
01503 ctx = args[len(args)-1]
01504 args = args[:len(args)-1]
01505 else:
01506 ctx = main_ctx()
01507 args = _get_args(args)
01508 ctx_args = _ctx_from_ast_arg_list(args, ctx)
01509 if __debug__:
01510 _z3_assert(ctx_args == None or ctx_args == ctx, "context mismatch")
01511 _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression or probe")
01512 if _has_probe(args):
01513 return _probe_and(args, ctx)
01514 else:
01515 args = _coerce_expr_list(args, ctx)
01516 _args, sz = _to_ast_array(args)
01517 return BoolRef(Z3_mk_and(ctx.ref(), sz, _args), ctx)
01518
01519 def Or(*args):
01520 """Create a Z3 or-expression or or-probe.
01521
01522 >>> p, q, r = Bools('p q r')
01523 >>> Or(p, q, r)
01524 Or(p, q, r)
01525 >>> P = BoolVector('p', 5)
01526 >>> Or(P)
01527 Or(p__0, p__1, p__2, p__3, p__4)
01528 """
01529 last_arg = None
01530 if len(args) > 0:
01531 last_arg = args[len(args)-1]
01532 if isinstance(last_arg, Context):
01533 ctx = args[len(args)-1]
01534 args = args[:len(args)-1]
01535 else:
01536 ctx = main_ctx()
01537 args = _get_args(args)
01538 ctx_args = _ctx_from_ast_arg_list(args, ctx)
01539 if __debug__:
01540 _z3_assert(ctx_args == None or ctx_args == ctx, "context mismatch")
01541 _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression or probe")
01542 if _has_probe(args):
01543 return _probe_or(args, ctx)
01544 else:
01545 args = _coerce_expr_list(args, ctx)
01546 _args, sz = _to_ast_array(args)
01547 return BoolRef(Z3_mk_or(ctx.ref(), sz, _args), ctx)
01548
01549 #########################################
01550 #
01551 # Patterns
01552 #
01553 #########################################
01554
01555 class PatternRef(ExprRef):
01556 """Patterns are hints for quantifier instantiation.
01557
01558 See http://rise4fun.com/Z3Py/tutorial/advanced for more details.
01559 """
01560 def as_ast(self):
01561 return Z3_pattern_to_ast(self.ctx_ref(), self.ast)
01562
01563 def get_id(self):
01564 return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
01565
01566 def is_pattern(a):
01567 """Return `True` if `a` is a Z3 pattern (hint for quantifier instantiation.
01568
01569 See http://rise4fun.com/Z3Py/tutorial/advanced for more details.
01570
01571 >>> f = Function('f', IntSort(), IntSort())
01572 >>> x = Int('x')
01573 >>> q = ForAll(x, f(x) == 0, patterns = [ f(x) ])
01574 >>> q
01575 ForAll(x, f(x) == 0)
01576 >>> q.num_patterns()
01577 1
01578 >>> is_pattern(q.pattern(0))
01579 True
01580 >>> q.pattern(0)
01581 f(Var(0))
01582 """
01583 return isinstance(a, PatternRef)
01584
01585 def MultiPattern(*args):
01586 """Create a Z3 multi-pattern using the given expressions `*args`
01587
01588 See http://rise4fun.com/Z3Py/tutorial/advanced for more details.
01589
01590 >>> f = Function('f', IntSort(), IntSort())
01591 >>> g = Function('g', IntSort(), IntSort())
01592 >>> x = Int('x')
01593 >>> q = ForAll(x, f(x) != g(x), patterns = [ MultiPattern(f(x), g(x)) ])
01594 >>> q
01595 ForAll(x, f(x) != g(x))
01596 >>> q.num_patterns()
01597 1
01598 >>> is_pattern(q.pattern(0))
01599 True
01600 >>> q.pattern(0)
01601 MultiPattern(f(Var(0)), g(Var(0)))
01602 """
01603 if __debug__:
01604 _z3_assert(len(args) > 0, "At least one argument expected")
01605 _z3_assert(all([ is_expr(a) for a in args ]), "Z3 expressions expected")
01606 ctx = args[0].ctx
01607 args, sz = _to_ast_array(args)
01608 return PatternRef(Z3_mk_pattern(ctx.ref(), sz, args), ctx)
01609
01610 def _to_pattern(arg):
01611 if is_pattern(arg):
01612 return arg
01613 else:
01614 return MultiPattern(arg)
01615
01616 #########################################
01617 #
01618 # Quantifiers
01619 #
01620 #########################################
01621
01622 class QuantifierRef(BoolRef):
01623 """Universally and Existentially quantified formulas."""
01624
01625 def as_ast(self):
01626 return self.ast
01627
01628 def get_id(self):
01629 return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
01630
01631 def sort(self):
01632 """Return the Boolean sort."""
01633 return BoolSort(self.ctx)
01634
01635 def is_forall(self):
01636 """Return `True` if `self` is a universal quantifier.
01637
01638 >>> f = Function('f', IntSort(), IntSort())
01639 >>> x = Int('x')
01640 >>> q = ForAll(x, f(x) == 0)
01641 >>> q.is_forall()
01642 True
01643 >>> q = Exists(x, f(x) != 0)
01644 >>> q.is_forall()
01645 False
01646 """
01647 return Z3_is_quantifier_forall(self.ctx_ref(), self.ast)
01648
01649 def weight(self):
01650 """Return the weight annotation of `self`.
01651
01652 >>> f = Function('f', IntSort(), IntSort())
01653 >>> x = Int('x')
01654 >>> q = ForAll(x, f(x) == 0)
01655 >>> q.weight()
01656 1
01657 >>> q = ForAll(x, f(x) == 0, weight=10)
01658 >>> q.weight()
01659 10
01660 """
01661 return int(Z3_get_quantifier_weight(self.ctx_ref(), self.ast))
01662
01663 def num_patterns(self):
01664 """Return the number of patterns (i.e., quantifier instantiation hints) in `self`.
01665
01666 >>> f = Function('f', IntSort(), IntSort())
01667 >>> g = Function('g', IntSort(), IntSort())
01668 >>> x = Int('x')
01669 >>> q = ForAll(x, f(x) != g(x), patterns = [ f(x), g(x) ])
01670 >>> q.num_patterns()
01671 2
01672 """
01673 return int(Z3_get_quantifier_num_patterns(self.ctx_ref(), self.ast))
01674
01675 def pattern(self, idx):
01676 """Return a pattern (i.e., quantifier instantiation hints) in `self`.
01677
01678 >>> f = Function('f', IntSort(), IntSort())
01679 >>> g = Function('g', IntSort(), IntSort())
01680 >>> x = Int('x')
01681 >>> q = ForAll(x, f(x) != g(x), patterns = [ f(x), g(x) ])
01682 >>> q.num_patterns()
01683 2
01684 >>> q.pattern(0)
01685 f(Var(0))
01686 >>> q.pattern(1)
01687 g(Var(0))
01688 """
01689 if __debug__:
01690 _z3_assert(idx < self.num_patterns(), "Invalid pattern idx")
01691 return PatternRef(Z3_get_quantifier_pattern_ast(self.ctx_ref(), self.ast, idx), self.ctx)
01692
01693 def num_no_patterns(self):
01694 """Return the number of no-patterns."""
01695 return Z3_get_quantifier_num_no_patterns(self.ctx_ref(), self.ast)
01696
01697 def no_pattern(self, idx):
01698 """Return a no-pattern."""
01699 if __debug__:
01700 _z3_assert(idx < self.num_no_patterns(), "Invalid no-pattern idx")
01701 return _to_expr_ref(Z3_get_quantifier_no_pattern_ast(self.ctx_ref(), self.ast, idx), self.ctx)
01702
01703 def body(self):
01704 """Return the expression being quantified.
01705
01706 >>> f = Function('f', IntSort(), IntSort())
01707 >>> x = Int('x')
01708 >>> q = ForAll(x, f(x) == 0)
01709 >>> q.body()
01710 f(Var(0)) == 0
01711 """
01712 return _to_expr_ref(Z3_get_quantifier_body(self.ctx_ref(), self.ast), self.ctx)
01713
01714 def num_vars(self):
01715 """Return the number of variables bounded by this quantifier.
01716
01717 >>> f = Function('f', IntSort(), IntSort(), IntSort())
01718 >>> x = Int('x')
01719 >>> y = Int('y')
01720 >>> q = ForAll([x, y], f(x, y) >= x)
01721 >>> q.num_vars()
01722 2
01723 """
01724 return int(Z3_get_quantifier_num_bound(self.ctx_ref(), self.ast))
01725
01726 def var_name(self, idx):
01727 """Return a string representing a name used when displaying the quantifier.
01728
01729 >>> f = Function('f', IntSort(), IntSort(), IntSort())
01730 >>> x = Int('x')
01731 >>> y = Int('y')
01732 >>> q = ForAll([x, y], f(x, y) >= x)
01733 >>> q.var_name(0)
01734 'x'
01735 >>> q.var_name(1)
01736 'y'
01737 """
01738 if __debug__:
01739 _z3_assert(idx < self.num_vars(), "Invalid variable idx")
01740 return _symbol2py(self.ctx, Z3_get_quantifier_bound_name(self.ctx_ref(), self.ast, idx))
01741
01742 def var_sort(self, idx):
01743 """Return the sort of a bound variable.
01744
01745 >>> f = Function('f', IntSort(), RealSort(), IntSort())
01746 >>> x = Int('x')
01747 >>> y = Real('y')
01748 >>> q = ForAll([x, y], f(x, y) >= x)
01749 >>> q.var_sort(0)
01750 Int
01751 >>> q.var_sort(1)
01752 Real
01753 """
01754 if __debug__:
01755 _z3_assert(idx < self.num_vars(), "Invalid variable idx")
01756 return SortRef(Z3_get_quantifier_bound_sort(self.ctx_ref(), self.ast, idx), self.ctx)
01757
01758 def children(self):
01759 """Return a list containing a single element self.body()
01760
01761 >>> f = Function('f', IntSort(), IntSort())
01762 >>> x = Int('x')
01763 >>> q = ForAll(x, f(x) == 0)
01764 >>> q.children()
01765 [f(Var(0)) == 0]
01766 """
01767 return [ self.body() ]
01768
01769 def is_quantifier(a):
01770 """Return `True` if `a` is a Z3 quantifier.
01771
01772 >>> f = Function('f', IntSort(), IntSort())
01773 >>> x = Int('x')
01774 >>> q = ForAll(x, f(x) == 0)
01775 >>> is_quantifier(q)
01776 True
01777 >>> is_quantifier(f(x))
01778 False
01779 """
01780 return isinstance(a, QuantifierRef)
01781
01782 def _mk_quantifier(is_forall, vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]):
01783 if __debug__:
01784 _z3_assert(is_bool(body), "Z3 expression expected")
01785 _z3_assert(is_const(vs) or (len(vs) > 0 and all([ is_const(v) for v in vs])), "Invalid bounded variable(s)")
01786 _z3_assert(all([is_pattern(a) or is_expr(a) for a in patterns]), "Z3 patterns expected")
01787 _z3_assert(all([is_expr(p) for p in no_patterns]), "no patterns are Z3 expressions")
01788 ctx = body.ctx
01789 if is_app(vs):
01790 vs = [vs]
01791 num_vars = len(vs)
01792 _vs = (Ast * num_vars)()
01793 for i in range(num_vars):
01794 ## TODO: Check if is constant
01795 _vs[i] = vs[i].as_ast()
01796 patterns = [ _to_pattern(p) for p in patterns ]
01797 num_pats = len(patterns)
01798 _pats = (Pattern * num_pats)()
01799 for i in range(num_pats):
01800 _pats[i] = patterns[i].ast
01801 _no_pats, num_no_pats = _to_ast_array(no_patterns)
01802 qid = to_symbol(qid, ctx)
01803 skid = to_symbol(skid, ctx)
01804 return QuantifierRef(Z3_mk_quantifier_const_ex(ctx.ref(), is_forall, weight, qid, skid,
01805 num_vars, _vs,
01806 num_pats, _pats,
01807 num_no_pats, _no_pats,
01808 body.as_ast()), ctx)
01809
01810 def ForAll(vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]):
01811 """Create a Z3 forall formula.
01812
01813 The parameters `weight`, `qif`, `skid`, `patterns` and `no_patterns` are optional annotations.
01814
01815 See http://rise4fun.com/Z3Py/tutorial/advanced for more details.
01816
01817 >>> f = Function('f', IntSort(), IntSort(), IntSort())
01818 >>> x = Int('x')
01819 >>> y = Int('y')
01820 >>> ForAll([x, y], f(x, y) >= x)
01821 ForAll([x, y], f(x, y) >= x)
01822 >>> ForAll([x, y], f(x, y) >= x, patterns=[ f(x, y) ])
01823 ForAll([x, y], f(x, y) >= x)
01824 >>> ForAll([x, y], f(x, y) >= x, weight=10)
01825 ForAll([x, y], f(x, y) >= x)
01826 """
01827 return _mk_quantifier(True, vs, body, weight, qid, skid, patterns, no_patterns)
01828
01829 def Exists(vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]):
01830 """Create a Z3 exists formula.
01831
01832 The parameters `weight`, `qif`, `skid`, `patterns` and `no_patterns` are optional annotations.
01833
01834 See http://rise4fun.com/Z3Py/tutorial/advanced for more details.
01835
01836 >>> f = Function('f', IntSort(), IntSort(), IntSort())
01837 >>> x = Int('x')
01838 >>> y = Int('y')
01839 >>> q = Exists([x, y], f(x, y) >= x, skid="foo")
01840 >>> q
01841 Exists([x, y], f(x, y) >= x)
01842 >>> is_quantifier(q)
01843 True
01844 >>> r = Tactic('nnf')(q).as_expr()
01845 >>> is_quantifier(r)
01846 False
01847 """
01848 return _mk_quantifier(False, vs, body, weight, qid, skid, patterns, no_patterns)
01849
01850 #########################################
01851 #
01852 # Arithmetic
01853 #
01854 #########################################
01855
01856 class ArithSortRef(SortRef):
01857 """Real and Integer sorts."""
01858
01859 def is_real(self):
01860 """Return `True` if `self` is of the sort Real.
01861
01862 >>> x = Real('x')
01863 >>> x.is_real()
01864 True
01865 >>> (x + 1).is_real()
01866 True
01867 >>> x = Int('x')
01868 >>> x.is_real()
01869 False
01870 """
01871 return self.kind() == Z3_REAL_SORT
01872
01873 def is_int(self):
01874 """Return `True` if `self` is of the sort Integer.
01875
01876 >>> x = Int('x')
01877 >>> x.is_int()
01878 True
01879 >>> (x + 1).is_int()
01880 True
01881 >>> x = Real('x')
01882 >>> x.is_int()
01883 False
01884 """
01885 return self.kind() == Z3_INT_SORT
01886
01887 def subsort(self, other):
01888 """Return `True` if `self` is a subsort of `other`."""
01889 return self.is_int() and is_arith_sort(other) and other.is_real()
01890
01891 def cast(self, val):
01892 """Try to cast `val` as an Integer or Real.
01893
01894 >>> IntSort().cast(10)
01895 10
01896 >>> is_int(IntSort().cast(10))
01897 True
01898 >>> is_int(10)
01899 False
01900 >>> RealSort().cast(10)
01901 10
01902 >>> is_real(RealSort().cast(10))
01903 True
01904 """
01905 if is_expr(val):
01906 if __debug__:
01907 _z3_assert(self.ctx == val.ctx, "Context mismatch")
01908 val_s = val.sort()
01909 if self.eq(val_s):
01910 return val
01911 if val_s.is_int() and self.is_real():
01912 return ToReal(val)
01913 if val_s.is_bool() and self.is_int():
01914 return If(val, 1, 0)
01915 if val_s.is_bool() and self.is_real():
01916 return ToReal(If(val, 1, 0))
01917 if __debug__:
01918 _z3_assert(False, "Z3 Integer/Real expression expected" )
01919 else:
01920 if self.is_int():
01921 return IntVal(val, self.ctx)
01922 if self.is_real():
01923 return RealVal(val, self.ctx)
01924 if __debug__:
01925 _z3_assert(False, "int, long, float, string (numeral), or Z3 Integer/Real expression expected")
01926
01927 def is_arith_sort(s):
01928 """Return `True` if s is an arithmetical sort (type).
01929
01930 >>> is_arith_sort(IntSort())
01931 True
01932 >>> is_arith_sort(RealSort())
01933 True
01934 >>> is_arith_sort(BoolSort())
01935 False
01936 >>> n = Int('x') + 1
01937 >>> is_arith_sort(n.sort())
01938 True
01939 """
01940 return isinstance(s, ArithSortRef)
01941
01942 class ArithRef(ExprRef):
01943 """Integer and Real expressions."""
01944
01945 def sort(self):
01946 """Return the sort (type) of the arithmetical expression `self`.
01947
01948 >>> Int('x').sort()
01949 Int
01950 >>> (Real('x') + 1).sort()
01951 Real
01952 """
01953 return ArithSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
01954
01955 def is_int(self):
01956 """Return `True` if `self` is an integer expression.
01957
01958 >>> x = Int('x')
01959 >>> x.is_int()
01960 True
01961 >>> (x + 1).is_int()
01962 True
01963 >>> y = Real('y')
01964 >>> (x + y).is_int()
01965 False
01966 """
01967 return self.sort().is_int()
01968
01969 def is_real(self):
01970 """Return `True` if `self` is an real expression.
01971
01972 >>> x = Real('x')
01973 >>> x.is_real()
01974 True
01975 >>> (x + 1).is_real()
01976 True
01977 """
01978 return self.sort().is_real()
01979
01980 def __add__(self, other):
01981 """Create the Z3 expression `self + other`.
01982
01983 >>> x = Int('x')
01984 >>> y = Int('y')
01985 >>> x + y
01986 x + y
01987 >>> (x + y).sort()
01988 Int
01989 """
01990 a, b = _coerce_exprs(self, other)
01991 return ArithRef(_mk_bin(Z3_mk_add, a, b), self.ctx)
01992
01993 def __radd__(self, other):
01994 """Create the Z3 expression `other + self`.
01995
01996 >>> x = Int('x')
01997 >>> 10 + x
01998 10 + x
01999 """
02000 a, b = _coerce_exprs(self, other)
02001 return ArithRef(_mk_bin(Z3_mk_add, b, a), self.ctx)
02002
02003 def __mul__(self, other):
02004 """Create the Z3 expression `self * other`.
02005
02006 >>> x = Real('x')
02007 >>> y = Real('y')
02008 >>> x * y
02009 x*y
02010 >>> (x * y).sort()
02011 Real
02012 """
02013 a, b = _coerce_exprs(self, other)
02014 return ArithRef(_mk_bin(Z3_mk_mul, a, b), self.ctx)
02015
02016 def __rmul__(self, other):
02017 """Create the Z3 expression `other * self`.
02018
02019 >>> x = Real('x')
02020 >>> 10 * x
02021 10*x
02022 """
02023 a, b = _coerce_exprs(self, other)
02024 return ArithRef(_mk_bin(Z3_mk_mul, b, a), self.ctx)
02025
02026 def __sub__(self, other):
02027 """Create the Z3 expression `self - other`.
02028
02029 >>> x = Int('x')
02030 >>> y = Int('y')
02031 >>> x - y
02032 x - y
02033 >>> (x - y).sort()
02034 Int
02035 """
02036 a, b = _coerce_exprs(self, other)
02037 return ArithRef(_mk_bin(Z3_mk_sub, a, b), self.ctx)
02038
02039 def __rsub__(self, other):
02040 """Create the Z3 expression `other - self`.
02041
02042 >>> x = Int('x')
02043 >>> 10 - x
02044 10 - x
02045 """
02046 a, b = _coerce_exprs(self, other)
02047 return ArithRef(_mk_bin(Z3_mk_sub, b, a), self.ctx)
02048
02049 def __pow__(self, other):
02050 """Create the Z3 expression `self**other` (** is the power operator).
02051
02052 >>> x = Real('x')
02053 >>> x**3
02054 x**3
02055 >>> (x**3).sort()
02056 Real
02057 >>> simplify(IntVal(2)**8)
02058 256
02059 """
02060 a, b = _coerce_exprs(self, other)
02061 return ArithRef(Z3_mk_power(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
02062
02063 def __rpow__(self, other):
02064 """Create the Z3 expression `other**self` (** is the power operator).
02065
02066 >>> x = Real('x')
02067 >>> 2**x
02068 2**x
02069 >>> (2**x).sort()
02070 Real
02071 >>> simplify(2**IntVal(8))
02072 256
02073 """
02074 a, b = _coerce_exprs(self, other)
02075 return ArithRef(Z3_mk_power(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
02076
02077 def __div__(self, other):
02078 """Create the Z3 expression `other/self`.
02079
02080 >>> x = Int('x')
02081 >>> y = Int('y')
02082 >>> x/y
02083 x/y
02084 >>> (x/y).sort()
02085 Int
02086 >>> (x/y).sexpr()
02087 '(div x y)'
02088 >>> x = Real('x')
02089 >>> y = Real('y')
02090 >>> x/y
02091 x/y
02092 >>> (x/y).sort()
02093 Real
02094 >>> (x/y).sexpr()
02095 '(/ x y)'
02096 """
02097 a, b = _coerce_exprs(self, other)
02098 return ArithRef(Z3_mk_div(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
02099
02100 def __truediv__(self, other):
02101 """Create the Z3 expression `other/self`."""
02102 return self.__div__(other)
02103
02104 def __rdiv__(self, other):
02105 """Create the Z3 expression `other/self`.
02106
02107 >>> x = Int('x')
02108 >>> 10/x
02109 10/x
02110 >>> (10/x).sexpr()
02111 '(div 10 x)'
02112 >>> x = Real('x')
02113 >>> 10/x
02114 10/x
02115 >>> (10/x).sexpr()
02116 '(/ 10.0 x)'
02117 """
02118 a, b = _coerce_exprs(self, other)
02119 return ArithRef(Z3_mk_div(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
02120
02121 def __rtruediv__(self, other):
02122 """Create the Z3 expression `other/self`."""
02123 return self.__rdiv__(other)
02124
02125 def __mod__(self, other):
02126 """Create the Z3 expression `other%self`.
02127
02128 >>> x = Int('x')
02129 >>> y = Int('y')
02130 >>> x % y
02131 x%y
02132 >>> simplify(IntVal(10) % IntVal(3))
02133 1
02134 """
02135 a, b = _coerce_exprs(self, other)
02136 if __debug__:
02137 _z3_assert(a.is_int(), "Z3 integer expression expected")
02138 return ArithRef(Z3_mk_mod(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
02139
02140 def __rmod__(self, other):
02141 """Create the Z3 expression `other%self`.
02142
02143 >>> x = Int('x')
02144 >>> 10 % x
02145 10%x
02146 """
02147 a, b = _coerce_exprs(self, other)
02148 if __debug__:
02149 _z3_assert(a.is_int(), "Z3 integer expression expected")
02150 return ArithRef(Z3_mk_mod(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
02151
02152 def __neg__(self):
02153 """Return an expression representing `-self`.
02154
02155 >>> x = Int('x')
02156 >>> -x
02157 -x
02158 >>> simplify(-(-x))
02159 x
02160 """
02161 return ArithRef(Z3_mk_unary_minus(self.ctx_ref(), self.as_ast()), self.ctx)
02162
02163 def __pos__(self):
02164 """Return `self`.
02165
02166 >>> x = Int('x')
02167 >>> +x
02168 x
02169 """
02170 return self
02171
02172 def __le__(self, other):
02173 """Create the Z3 expression `other <= self`.
02174
02175 >>> x, y = Ints('x y')
02176 >>> x <= y
02177 x <= y
02178 >>> y = Real('y')
02179 >>> x <= y
02180 ToReal(x) <= y
02181 """
02182 a, b = _coerce_exprs(self, other)
02183 return BoolRef(Z3_mk_le(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
02184
02185 def __lt__(self, other):
02186 """Create the Z3 expression `other < self`.
02187
02188 >>> x, y = Ints('x y')
02189 >>> x < y
02190 x < y
02191 >>> y = Real('y')
02192 >>> x < y
02193 ToReal(x) < y
02194 """
02195 a, b = _coerce_exprs(self, other)
02196 return BoolRef(Z3_mk_lt(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
02197
02198 def __gt__(self, other):
02199 """Create the Z3 expression `other > self`.
02200
02201 >>> x, y = Ints('x y')
02202 >>> x > y
02203 x > y
02204 >>> y = Real('y')
02205 >>> x > y
02206 ToReal(x) > y
02207 """
02208 a, b = _coerce_exprs(self, other)
02209 return BoolRef(Z3_mk_gt(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
02210
02211 def __ge__(self, other):
02212 """Create the Z3 expression `other >= self`.
02213
02214 >>> x, y = Ints('x y')
02215 >>> x >= y
02216 x >= y
02217 >>> y = Real('y')
02218 >>> x >= y
02219 ToReal(x) >= y
02220 """
02221 a, b = _coerce_exprs(self, other)
02222 return BoolRef(Z3_mk_ge(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
02223
02224 def is_arith(a):
02225 """Return `True` if `a` is an arithmetical expression.
02226
02227 >>> x = Int('x')
02228 >>> is_arith(x)
02229 True
02230 >>> is_arith(x + 1)
02231 True
02232 >>> is_arith(1)
02233 False
02234 >>> is_arith(IntVal(1))
02235 True
02236 >>> y = Real('y')
02237 >>> is_arith(y)
02238 True
02239 >>> is_arith(y + 1)
02240 True
02241 """
02242 return isinstance(a, ArithRef)
02243
02244 def is_int(a):
02245 """Return `True` if `a` is an integer expression.
02246
02247 >>> x = Int('x')
02248 >>> is_int(x + 1)
02249 True
02250 >>> is_int(1)
02251 False
02252 >>> is_int(IntVal(1))
02253 True
02254 >>> y = Real('y')
02255 >>> is_int(y)
02256 False
02257 >>> is_int(y + 1)
02258 False
02259 """
02260 return is_arith(a) and a.is_int()
02261
02262 def is_real(a):
02263 """Return `True` if `a` is a real expression.
02264
02265 >>> x = Int('x')
02266 >>> is_real(x + 1)
02267 False
02268 >>> y = Real('y')
02269 >>> is_real(y)
02270 True
02271 >>> is_real(y + 1)
02272 True
02273 >>> is_real(1)
02274 False
02275 >>> is_real(RealVal(1))
02276 True
02277 """
02278 return is_arith(a) and a.is_real()
02279
02280 def _is_numeral(ctx, a):
02281 return Z3_is_numeral_ast(ctx.ref(), a)
02282
02283 def _is_algebraic(ctx, a):
02284 return Z3_is_algebraic_number(ctx.ref(), a)
02285
02286 def is_int_value(a):
02287 """Return `True` if `a` is an integer value of sort Int.
02288
02289 >>> is_int_value(IntVal(1))
02290 True
02291 >>> is_int_value(1)
02292 False
02293 >>> is_int_value(Int('x'))
02294 False
02295 >>> n = Int('x') + 1
02296 >>> n
02297 x + 1
02298 >>> n.arg(1)
02299 1
02300 >>> is_int_value(n.arg(1))
02301 True
02302 >>> is_int_value(RealVal("1/3"))
02303 False
02304 >>> is_int_value(RealVal(1))
02305 False
02306 """
02307 return is_arith(a) and a.is_int() and _is_numeral(a.ctx, a.as_ast())
02308
02309 def is_rational_value(a):
02310 """Return `True` if `a` is rational value of sort Real.
02311
02312 >>> is_rational_value(RealVal(1))
02313 True
02314 >>> is_rational_value(RealVal("3/5"))
02315 True
02316 >>> is_rational_value(IntVal(1))
02317 False
02318 >>> is_rational_value(1)
02319 False
02320 >>> n = Real('x') + 1
02321 >>> n.arg(1)
02322 1
02323 >>> is_rational_value(n.arg(1))
02324 True
02325 >>> is_rational_value(Real('x'))
02326 False
02327 """
02328 return is_arith(a) and a.is_real() and _is_numeral(a.ctx, a.as_ast())
02329
02330 def is_algebraic_value(a):
02331 """Return `True` if `a` is an algerbraic value of sort Real.
02332
02333 >>> is_algebraic_value(RealVal("3/5"))
02334 False
02335 >>> n = simplify(Sqrt(2))
02336 >>> n
02337 1.4142135623?
02338 >>> is_algebraic_value(n)
02339 True
02340 """
02341 return is_arith(a) and a.is_real() and _is_algebraic(a.ctx, a.as_ast())
02342
02343 def is_add(a):
02344 """Return `True` if `a` is an expression of the form b + c.
02345
02346 >>> x, y = Ints('x y')
02347 >>> is_add(x + y)
02348 True
02349 >>> is_add(x - y)
02350 False
02351 """
02352 return is_app_of(a, Z3_OP_ADD)
02353
02354 def is_mul(a):
02355 """Return `True` if `a` is an expression of the form b * c.
02356
02357 >>> x, y = Ints('x y')
02358 >>> is_mul(x * y)
02359 True
02360 >>> is_mul(x - y)
02361 False
02362 """
02363 return is_app_of(a, Z3_OP_MUL)
02364
02365 def is_sub(a):
02366 """Return `True` if `a` is an expression of the form b - c.
02367
02368 >>> x, y = Ints('x y')
02369 >>> is_sub(x - y)
02370 True
02371 >>> is_sub(x + y)
02372 False
02373 """
02374 return is_app_of(a, Z3_OP_SUB)
02375
02376 def is_div(a):
02377 """Return `True` if `a` is an expression of the form b / c.
02378
02379 >>> x, y = Reals('x y')
02380 >>> is_div(x / y)
02381 True
02382 >>> is_div(x + y)
02383 False
02384 >>> x, y = Ints('x y')
02385 >>> is_div(x / y)
02386 False
02387 >>> is_idiv(x / y)
02388 True
02389 """
02390 return is_app_of(a, Z3_OP_DIV)
02391
02392 def is_idiv(a):
02393 """Return `True` if `a` is an expression of the form b div c.
02394
02395 >>> x, y = Ints('x y')
02396 >>> is_idiv(x / y)
02397 True
02398 >>> is_idiv(x + y)
02399 False
02400 """
02401 return is_app_of(a, Z3_OP_IDIV)
02402
02403 def is_mod(a):
02404 """Return `True` if `a` is an expression of the form b % c.
02405
02406 >>> x, y = Ints('x y')
02407 >>> is_mod(x % y)
02408 True
02409 >>> is_mod(x + y)
02410 False
02411 """
02412 return is_app_of(a, Z3_OP_MOD)
02413
02414 def is_le(a):
02415 """Return `True` if `a` is an expression of the form b <= c.
02416
02417 >>> x, y = Ints('x y')
02418 >>> is_le(x <= y)
02419 True
02420 >>> is_le(x < y)
02421 False
02422 """
02423 return is_app_of(a, Z3_OP_LE)
02424
02425 def is_lt(a):
02426 """Return `True` if `a` is an expression of the form b < c.
02427
02428 >>> x, y = Ints('x y')
02429 >>> is_lt(x < y)
02430 True
02431 >>> is_lt(x == y)
02432 False
02433 """
02434 return is_app_of(a, Z3_OP_LT)
02435
02436 def is_ge(a):
02437 """Return `True` if `a` is an expression of the form b >= c.
02438
02439 >>> x, y = Ints('x y')
02440 >>> is_ge(x >= y)
02441 True
02442 >>> is_ge(x == y)
02443 False
02444 """
02445 return is_app_of(a, Z3_OP_GE)
02446
02447 def is_gt(a):
02448 """Return `True` if `a` is an expression of the form b > c.
02449
02450 >>> x, y = Ints('x y')
02451 >>> is_gt(x > y)
02452 True
02453 >>> is_gt(x == y)
02454 False
02455 """
02456 return is_app_of(a, Z3_OP_GT)
02457
02458 def is_is_int(a):
02459 """Return `True` if `a` is an expression of the form IsInt(b).
02460
02461 >>> x = Real('x')
02462 >>> is_is_int(IsInt(x))
02463 True
02464 >>> is_is_int(x)
02465 False
02466 """
02467 return is_app_of(a, Z3_OP_IS_INT)
02468
02469 def is_to_real(a):
02470 """Return `True` if `a` is an expression of the form ToReal(b).
02471
02472 >>> x = Int('x')
02473 >>> n = ToReal(x)
02474 >>> n
02475 ToReal(x)
02476 >>> is_to_real(n)
02477 True
02478 >>> is_to_real(x)
02479 False
02480 """
02481 return is_app_of(a, Z3_OP_TO_REAL)
02482
02483 def is_to_int(a):
02484 """Return `True` if `a` is an expression of the form ToInt(b).
02485
02486 >>> x = Real('x')
02487 >>> n = ToInt(x)
02488 >>> n
02489 ToInt(x)
02490 >>> is_to_int(n)
02491 True
02492 >>> is_to_int(x)
02493 False
02494 """
02495 return is_app_of(a, Z3_OP_TO_INT)
02496
02497 class IntNumRef(ArithRef):
02498 """Integer values."""
02499
02500 def as_long(self):
02501 """Return a Z3 integer numeral as a Python long (bignum) numeral.
02502
02503 >>> v = IntVal(1)
02504 >>> v + 1
02505 1 + 1
02506 >>> v.as_long() + 1
02507 2
02508 """
02509 if __debug__:
02510 _z3_assert(self.is_int(), "Integer value expected")
02511 return int(self.as_string())
02512
02513 def as_string(self):
02514 """Return a Z3 integer numeral as a Python string.
02515 >>> v = IntVal(100)
02516 >>> v.as_string()
02517 '100'
02518 """
02519 return Z3_get_numeral_string(self.ctx_ref(), self.as_ast())
02520
02521 class RatNumRef(ArithRef):
02522 """Rational values."""
02523
02524 def numerator(self):
02525 """ Return the numerator of a Z3 rational numeral.
02526
02527 >>> is_rational_value(RealVal("3/5"))
02528 True
02529 >>> n = RealVal("3/5")
02530 >>> n.numerator()
02531 3
02532 >>> is_rational_value(Q(3,5))
02533 True
02534 >>> Q(3,5).numerator()
02535 3
02536 """
02537 return IntNumRef(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx)
02538
02539 def denominator(self):
02540 """ Return the denominator of a Z3 rational numeral.
02541
02542 >>> is_rational_value(Q(3,5))
02543 True
02544 >>> n = Q(3,5)
02545 >>> n.denominator()
02546 5
02547 """
02548 return IntNumRef(Z3_get_denominator(self.ctx_ref(), self.as_ast()), self.ctx)
02549
02550 def numerator_as_long(self):
02551 """ Return the numerator as a Python long.
02552
02553 >>> v = RealVal(10000000000)
02554 >>> v
02555 10000000000
02556 >>> v + 1
02557 10000000000 + 1
02558 >>> v.numerator_as_long() + 1 == 10000000001
02559 True
02560 """
02561 return self.numerator().as_long()
02562
02563 def denominator_as_long(self):
02564 """ Return the denominator as a Python long.
02565
02566 >>> v = RealVal("1/3")
02567 >>> v
02568 1/3
02569 >>> v.denominator_as_long()
02570 3
02571 """
02572 return self.denominator().as_long()
02573
02574 def as_decimal(self, prec):
02575 """ Return a Z3 rational value as a string in decimal notation using at most `prec` decimal places.
02576
02577 >>> v = RealVal("1/5")
02578 >>> v.as_decimal(3)
02579 '0.2'
02580 >>> v = RealVal("1/3")
02581 >>> v.as_decimal(3)
02582 '0.333?'
02583 """
02584 return Z3_get_numeral_decimal_string(self.ctx_ref(), self.as_ast(), prec)
02585
02586 def as_string(self):
02587 """Return a Z3 rational numeral as a Python string.
02588
02589 >>> v = Q(3,6)
02590 >>> v.as_string()
02591 '1/2'
02592 """
02593 return Z3_get_numeral_string(self.ctx_ref(), self.as_ast())
02594
02595 def as_fraction(self):
02596 """Return a Z3 rational as a Python Fraction object.
02597
02598 >>> v = RealVal("1/5")
02599 >>> v.as_fraction()
02600 Fraction(1, 5)
02601 """
02602 return Fraction(self.numerator_as_long(), self.denominator_as_long())
02603
02604 class AlgebraicNumRef(ArithRef):
02605 """Algebraic irrational values."""
02606
02607 def approx(self, precision=10):
02608 """Return a Z3 rational number that approximates the algebraic number `self`.
02609 The result `r` is such that |r - self| <= 1/10^precision
02610
02611 >>> x = simplify(Sqrt(2))
02612 >>> x.approx(20)
02613 6838717160008073720548335/4835703278458516698824704
02614 >>> x.approx(5)
02615 2965821/2097152
02616 """
02617 return RatNumRef(Z3_get_algebraic_number_upper(self.ctx_ref(), self.as_ast(), precision), self.ctx)
02618 def as_decimal(self, prec):
02619 """Return a string representation of the algebraic number `self` in decimal notation using `prec` decimal places
02620
02621 >>> x = simplify(Sqrt(2))
02622 >>> x.as_decimal(10)
02623 '1.4142135623?'
02624 >>> x.as_decimal(20)
02625 '1.41421356237309504880?'
02626 """
02627 return Z3_get_numeral_decimal_string(self.ctx_ref(), self.as_ast(), prec)
02628
02629 def _py2expr(a, ctx=None):
02630 if isinstance(a, bool):
02631 return BoolVal(a, ctx)
02632 if _is_int(a):
02633 return IntVal(a, ctx)
02634 if isinstance(a, float):
02635 return RealVal(a, ctx)
02636 if __debug__:
02637 _z3_assert(False, "Python bool, int, long or float expected")
02638
02639 def IntSort(ctx=None):
02640 """Return the interger sort in the given context. If `ctx=None`, then the global context is used.
02641
02642 >>> IntSort()
02643 Int
02644 >>> x = Const('x', IntSort())
02645 >>> is_int(x)
02646 True
02647 >>> x.sort() == IntSort()
02648 True
02649 >>> x.sort() == BoolSort()
02650 False
02651 """
02652 ctx = _get_ctx(ctx)
02653 return ArithSortRef(Z3_mk_int_sort(ctx.ref()), ctx)
02654
02655 def RealSort(ctx=None):
02656 """Return the real sort in the given context. If `ctx=None`, then the global context is used.
02657
02658 >>> RealSort()
02659 Real
02660 >>> x = Const('x', RealSort())
02661 >>> is_real(x)
02662 True
02663 >>> is_int(x)
02664 False
02665 >>> x.sort() == RealSort()
02666 True
02667 """
02668 ctx = _get_ctx(ctx)
02669 return ArithSortRef(Z3_mk_real_sort(ctx.ref()), ctx)
02670
02671 def _to_int_str(val):
02672 if isinstance(val, float):
02673 return str(int(val))
02674 elif isinstance(val, bool):
02675 if val:
02676 return "1"
02677 else:
02678 return "0"
02679 elif _is_int(val):
02680 return str(val)
02681 elif isinstance(val, str):
02682 return val
02683 if __debug__:
02684 _z3_assert(False, "Python value cannot be used as a Z3 integer")
02685
02686 def IntVal(val, ctx=None):
02687 """Return a Z3 integer value. If `ctx=None`, then the global context is used.
02688
02689 >>> IntVal(1)
02690 1
02691 >>> IntVal("100")
02692 100
02693 """
02694 ctx = _get_ctx(ctx)
02695 return IntNumRef(Z3_mk_numeral(ctx.ref(), _to_int_str(val), IntSort(ctx).ast), ctx)
02696
02697 def RealVal(val, ctx=None):
02698 """Return a Z3 real value.
02699
02700 `val` may be a Python int, long, float or string representing a number in decimal or rational notation.
02701 If `ctx=None`, then the global context is used.
02702
02703 >>> RealVal(1)
02704 1
02705 >>> RealVal(1).sort()
02706 Real
02707 >>> RealVal("3/5")
02708 3/5
02709 >>> RealVal("1.5")
02710 3/2
02711 """
02712 ctx = _get_ctx(ctx)
02713 return RatNumRef(Z3_mk_numeral(ctx.ref(), str(val), RealSort(ctx).ast), ctx)
02714
02715 def RatVal(a, b, ctx=None):
02716 """Return a Z3 rational a/b.
02717
02718 If `ctx=None`, then the global context is used.
02719
02720 >>> RatVal(3,5)
02721 3/5
02722 >>> RatVal(3,5).sort()
02723 Real
02724 """
02725 if __debug__:
02726 _z3_assert(_is_int(a) or isinstance(a, str), "First argument cannot be converted into an integer")
02727 _z3_assert(_is_int(b) or isinstance(b, str), "Second argument cannot be converted into an integer")
02728 return simplify(RealVal(a, ctx)/RealVal(b, ctx))
02729
02730 def Q(a, b, ctx=None):
02731 """Return a Z3 rational a/b.
02732
02733 If `ctx=None`, then the global context is used.
02734
02735 >>> Q(3,5)
02736 3/5
02737 >>> Q(3,5).sort()
02738 Real
02739 """
02740 return simplify(RatVal(a, b))
02741
02742 def Int(name, ctx=None):
02743 """Return an integer constant named `name`. If `ctx=None`, then the global context is used.
02744
02745 >>> x = Int('x')
02746 >>> is_int(x)
02747 True
02748 >>> is_int(x + 1)
02749 True
02750 """
02751 ctx = _get_ctx(ctx)
02752 return ArithRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), IntSort(ctx).ast), ctx)
02753
02754 def Ints(names, ctx=None):
02755 """Return a tuple of Integer constants.
02756
02757 >>> x, y, z = Ints('x y z')
02758 >>> Sum(x, y, z)
02759 x + y + z
02760 """
02761 ctx = _get_ctx(ctx)
02762 if isinstance(names, str):
02763 names = names.split(" ")
02764 return [Int(name, ctx) for name in names]
02765
02766 def IntVector(prefix, sz, ctx=None):
02767 """Return a list of integer constants of size `sz`.
02768
02769 >>> X = IntVector('x', 3)
02770 >>> X
02771 [x__0, x__1, x__2]
02772 >>> Sum(X)
02773 x__0 + x__1 + x__2
02774 """
02775 return [ Int('%s__%s' % (prefix, i)) for i in range(sz) ]
02776
02777 def FreshInt(prefix='x', ctx=None):
02778 """Return a fresh integer constant in the given context using the given prefix.
02779
02780 >>> x = FreshInt()
02781 >>> y = FreshInt()
02782 >>> eq(x, y)
02783 False
02784 >>> x.sort()
02785 Int
02786 """
02787 ctx = _get_ctx(ctx)
02788 return ArithRef(Z3_mk_fresh_const(ctx.ref(), prefix, IntSort(ctx).ast), ctx)
02789
02790 def Real(name, ctx=None):
02791 """Return a real constant named `name`. If `ctx=None`, then the global context is used.
02792
02793 >>> x = Real('x')
02794 >>> is_real(x)
02795 True
02796 >>> is_real(x + 1)
02797 True
02798 """
02799 ctx = _get_ctx(ctx)
02800 return ArithRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), RealSort(ctx).ast), ctx)
02801
02802 def Reals(names, ctx=None):
02803 """Return a tuple of real constants.
02804
02805 >>> x, y, z = Reals('x y z')
02806 >>> Sum(x, y, z)
02807 x + y + z
02808 >>> Sum(x, y, z).sort()
02809 Real
02810 """
02811 ctx = _get_ctx(ctx)
02812 if isinstance(names, str):
02813 names = names.split(" ")
02814 return [Real(name, ctx) for name in names]
02815
02816 def RealVector(prefix, sz, ctx=None):
02817 """Return a list of real constants of size `sz`.
02818
02819 >>> X = RealVector('x', 3)
02820 >>> X
02821 [x__0, x__1, x__2]
02822 >>> Sum(X)
02823 x__0 + x__1 + x__2
02824 >>> Sum(X).sort()
02825 Real
02826 """
02827 return [ Real('%s__%s' % (prefix, i)) for i in range(sz) ]
02828
02829 def FreshReal(prefix='b', ctx=None):
02830 """Return a fresh real constant in the given context using the given prefix.
02831
02832 >>> x = FreshReal()
02833 >>> y = FreshReal()
02834 >>> eq(x, y)
02835 False
02836 >>> x.sort()
02837 Real
02838 """
02839 ctx = _get_ctx(ctx)
02840 return ArithRef(Z3_mk_fresh_const(ctx.ref(), prefix, RealSort(ctx).ast), ctx)
02841
02842 def ToReal(a):
02843 """ Return the Z3 expression ToReal(a).
02844
02845 >>> x = Int('x')
02846 >>> x.sort()
02847 Int
02848 >>> n = ToReal(x)
02849 >>> n
02850 ToReal(x)
02851 >>> n.sort()
02852 Real
02853 """
02854 if __debug__:
02855 _z3_assert(a.is_int(), "Z3 integer expression expected.")
02856 ctx = a.ctx
02857 return ArithRef(Z3_mk_int2real(ctx.ref(), a.as_ast()), ctx)
02858
02859 def ToInt(a):
02860 """ Return the Z3 expression ToInt(a).
02861
02862 >>> x = Real('x')
02863 >>> x.sort()
02864 Real
02865 >>> n = ToInt(x)
02866 >>> n
02867 ToInt(x)
02868 >>> n.sort()
02869 Int
02870 """
02871 if __debug__:
02872 _z3_assert(a.is_real(), "Z3 real expression expected.")
02873 ctx = a.ctx
02874 return ArithRef(Z3_mk_real2int(ctx.ref(), a.as_ast()), ctx)
02875
02876 def IsInt(a):
02877 """ Return the Z3 predicate IsInt(a).
02878
02879 >>> x = Real('x')
02880 >>> IsInt(x + "1/2")
02881 IsInt(x + 1/2)
02882 >>> solve(IsInt(x + "1/2"), x > 0, x < 1)
02883 [x = 1/2]
02884 >>> solve(IsInt(x + "1/2"), x > 0, x < 1, x != "1/2")
02885 no solution
02886 """
02887 if __debug__:
02888 _z3_assert(a.is_real(), "Z3 real expression expected.")
02889 ctx = a.ctx
02890 return BoolRef(Z3_mk_is_int(ctx.ref(), a.as_ast()), ctx)
02891
02892 def Sqrt(a, ctx=None):
02893 """ Return a Z3 expression which represents the square root of a.
02894
02895 >>> x = Real('x')
02896 >>> Sqrt(x)
02897 x**(1/2)
02898 """
02899 if not is_expr(a):
02900 ctx = _get_ctx(ctx)
02901 a = RealVal(a, ctx)
02902 return a ** "1/2"
02903
02904 def Cbrt(a, ctx=None):
02905 """ Return a Z3 expression which represents the cubic root of a.
02906
02907 >>> x = Real('x')
02908 >>> Cbrt(x)
02909 x**(1/3)
02910 """
02911 if not is_expr(a):
02912 ctx = _get_ctx(ctx)
02913 a = RealVal(a, ctx)
02914 return a ** "1/3"
02915
02916 #########################################
02917 #
02918 # Bit-Vectors
02919 #
02920 #########################################
02921
02922 class BitVecSortRef(SortRef):
02923 """Bit-vector sort."""
02924
02925 def size(self):
02926 """Return the size (number of bits) of the bit-vector sort `self`.
02927
02928 >>> b = BitVecSort(32)
02929 >>> b.size()
02930 32
02931 """
02932 return int(Z3_get_bv_sort_size(self.ctx_ref(), self.ast))
02933
02934 def subsort(self, other):
02935 return is_bv_sort(other) and self.size() < other.size()
02936
02937 def cast(self, val):
02938 """Try to cast `val` as a Bit-Vector.
02939
02940 >>> b = BitVecSort(32)
02941 >>> b.cast(10)
02942 10
02943 >>> b.cast(10).sexpr()
02944 '#x0000000a'
02945 """
02946 if is_expr(val):
02947 if __debug__:
02948 _z3_assert(self.ctx == val.ctx, "Context mismatch")
02949 # Idea: use sign_extend if sort of val is a bitvector of smaller size
02950 return val
02951 else:
02952 return BitVecVal(val, self)
02953
02954 def is_bv_sort(s):
02955 """Return True if `s` is a Z3 bit-vector sort.
02956
02957 >>> is_bv_sort(BitVecSort(32))
02958 True
02959 >>> is_bv_sort(IntSort())
02960 False
02961 """
02962 return isinstance(s, BitVecSortRef)
02963
02964 class BitVecRef(ExprRef):
02965 """Bit-vector expressions."""
02966
02967 def sort(self):
02968 """Return the sort of the bit-vector expression `self`.
02969
02970 >>> x = BitVec('x', 32)
02971 >>> x.sort()
02972 BitVec(32)
02973 >>> x.sort() == BitVecSort(32)
02974 True
02975 """
02976 return BitVecSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
02977
02978 def size(self):
02979 """Return the number of bits of the bit-vector expression `self`.
02980
02981 >>> x = BitVec('x', 32)
02982 >>> (x + 1).size()
02983 32
02984 >>> Concat(x, x).size()
02985 64
02986 """
02987 return self.sort().size()
02988
02989 def __add__(self, other):
02990 """Create the Z3 expression `self + other`.
02991
02992 >>> x = BitVec('x', 32)
02993 >>> y = BitVec('y', 32)
02994 >>> x + y
02995 x + y
02996 >>> (x + y).sort()
02997 BitVec(32)
02998 """
02999 a, b = _coerce_exprs(self, other)
03000 return BitVecRef(Z3_mk_bvadd(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03001
03002 def __radd__(self, other):
03003 """Create the Z3 expression `other + self`.
03004
03005 >>> x = BitVec('x', 32)
03006 >>> 10 + x
03007 10 + x
03008 """
03009 a, b = _coerce_exprs(self, other)
03010 return BitVecRef(Z3_mk_bvadd(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03011
03012 def __mul__(self, other):
03013 """Create the Z3 expression `self * other`.
03014
03015 >>> x = BitVec('x', 32)
03016 >>> y = BitVec('y', 32)
03017 >>> x * y
03018 x*y
03019 >>> (x * y).sort()
03020 BitVec(32)
03021 """
03022 a, b = _coerce_exprs(self, other)
03023 return BitVecRef(Z3_mk_bvmul(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03024
03025 def __rmul__(self, other):
03026 """Create the Z3 expression `other * self`.
03027
03028 >>> x = BitVec('x', 32)
03029 >>> 10 * x
03030 10*x
03031 """
03032 a, b = _coerce_exprs(self, other)
03033 return BitVecRef(Z3_mk_bvmul(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03034
03035 def __sub__(self, other):
03036 """Create the Z3 expression `self - other`.
03037
03038 >>> x = BitVec('x', 32)
03039 >>> y = BitVec('y', 32)
03040 >>> x - y
03041 x - y
03042 >>> (x - y).sort()
03043 BitVec(32)
03044 """
03045 a, b = _coerce_exprs(self, other)
03046 return BitVecRef(Z3_mk_bvsub(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03047
03048 def __rsub__(self, other):
03049 """Create the Z3 expression `other - self`.
03050
03051 >>> x = BitVec('x', 32)
03052 >>> 10 - x
03053 10 - x
03054 """
03055 a, b = _coerce_exprs(self, other)
03056 return BitVecRef(Z3_mk_bvsub(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03057
03058 def __or__(self, other):
03059 """Create the Z3 expression bitwise-or `self | other`.
03060
03061 >>> x = BitVec('x', 32)
03062 >>> y = BitVec('y', 32)
03063 >>> x | y
03064 x | y
03065 >>> (x | y).sort()
03066 BitVec(32)
03067 """
03068 a, b = _coerce_exprs(self, other)
03069 return BitVecRef(Z3_mk_bvor(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03070
03071 def __ror__(self, other):
03072 """Create the Z3 expression bitwise-or `other | self`.
03073
03074 >>> x = BitVec('x', 32)
03075 >>> 10 | x
03076 10 | x
03077 """
03078 a, b = _coerce_exprs(self, other)
03079 return BitVecRef(Z3_mk_bvor(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03080
03081 def __and__(self, other):
03082 """Create the Z3 expression bitwise-and `self & other`.
03083
03084 >>> x = BitVec('x', 32)
03085 >>> y = BitVec('y', 32)
03086 >>> x & y
03087 x & y
03088 >>> (x & y).sort()
03089 BitVec(32)
03090 """
03091 a, b = _coerce_exprs(self, other)
03092 return BitVecRef(Z3_mk_bvand(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03093
03094 def __rand__(self, other):
03095 """Create the Z3 expression bitwise-or `other & self`.
03096
03097 >>> x = BitVec('x', 32)
03098 >>> 10 & x
03099 10 & x
03100 """
03101 a, b = _coerce_exprs(self, other)
03102 return BitVecRef(Z3_mk_bvand(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03103
03104 def __xor__(self, other):
03105 """Create the Z3 expression bitwise-xor `self ^ other`.
03106
03107 >>> x = BitVec('x', 32)
03108 >>> y = BitVec('y', 32)
03109 >>> x ^ y
03110 x ^ y
03111 >>> (x ^ y).sort()
03112 BitVec(32)
03113 """
03114 a, b = _coerce_exprs(self, other)
03115 return BitVecRef(Z3_mk_bvxor(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03116
03117 def __rxor__(self, other):
03118 """Create the Z3 expression bitwise-xor `other ^ self`.
03119
03120 >>> x = BitVec('x', 32)
03121 >>> 10 ^ x
03122 10 ^ x
03123 """
03124 a, b = _coerce_exprs(self, other)
03125 return BitVecRef(Z3_mk_bvxor(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03126
03127 def __pos__(self):
03128 """Return `self`.
03129
03130 >>> x = BitVec('x', 32)
03131 >>> +x
03132 x
03133 """
03134 return self
03135
03136 def __neg__(self):
03137 """Return an expression representing `-self`.
03138
03139 >>> x = BitVec('x', 32)
03140 >>> -x
03141 -x
03142 >>> simplify(-(-x))
03143 x
03144 """
03145 return BitVecRef(Z3_mk_bvneg(self.ctx_ref(), self.as_ast()), self.ctx)
03146
03147 def __invert__(self):
03148 """Create the Z3 expression bitwise-not `~self`.
03149
03150 >>> x = BitVec('x', 32)
03151 >>> ~x
03152 ~x
03153 >>> simplify(~(~x))
03154 x
03155 """
03156 return BitVecRef(Z3_mk_bvnot(self.ctx_ref(), self.as_ast()), self.ctx)
03157
03158 def __div__(self, other):
03159 """Create the Z3 expression (signed) division `self / other`.
03160
03161 Use the function UDiv() for unsigned division.
03162
03163 >>> x = BitVec('x', 32)
03164 >>> y = BitVec('y', 32)
03165 >>> x / y
03166 x/y
03167 >>> (x / y).sort()
03168 BitVec(32)
03169 >>> (x / y).sexpr()
03170 '(bvsdiv x y)'
03171 >>> UDiv(x, y).sexpr()
03172 '(bvudiv x y)'
03173 """
03174 a, b = _coerce_exprs(self, other)
03175 return BitVecRef(Z3_mk_bvsdiv(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03176
03177 def __truediv__(self, other):
03178 """Create the Z3 expression (signed) division `self / other`."""
03179 return self.__div__(other)
03180
03181 def __rdiv__(self, other):
03182 """Create the Z3 expression (signed) division `other / self`.
03183
03184 Use the function UDiv() for unsigned division.
03185
03186 >>> x = BitVec('x', 32)
03187 >>> 10 / x
03188 10/x
03189 >>> (10 / x).sexpr()
03190 '(bvsdiv #x0000000a x)'
03191 >>> UDiv(10, x).sexpr()
03192 '(bvudiv #x0000000a x)'
03193 """
03194 a, b = _coerce_exprs(self, other)
03195 return BitVecRef(Z3_mk_bvsdiv(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03196
03197 def __rtruediv__(self, other):
03198 """Create the Z3 expression (signed) division `other / self`."""
03199 return self.__rdiv__(other)
03200
03201 def __mod__(self, other):
03202 """Create the Z3 expression (signed) mod `self % other`.
03203
03204 Use the function URem() for unsigned remainder, and SRem() for signed remainder.
03205
03206 >>> x = BitVec('x', 32)
03207 >>> y = BitVec('y', 32)
03208 >>> x % y
03209 x%y
03210 >>> (x % y).sort()
03211 BitVec(32)
03212 >>> (x % y).sexpr()
03213 '(bvsmod x y)'
03214 >>> URem(x, y).sexpr()
03215 '(bvurem x y)'
03216 >>> SRem(x, y).sexpr()
03217 '(bvsrem x y)'
03218 """
03219 a, b = _coerce_exprs(self, other)
03220 return BitVecRef(Z3_mk_bvsmod(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03221
03222 def __rmod__(self, other):
03223 """Create the Z3 expression (signed) mod `other % self`.
03224
03225 Use the function URem() for unsigned remainder, and SRem() for signed remainder.
03226
03227 >>> x = BitVec('x', 32)
03228 >>> 10 % x
03229 10%x
03230 >>> (10 % x).sexpr()
03231 '(bvsmod #x0000000a x)'
03232 >>> URem(10, x).sexpr()
03233 '(bvurem #x0000000a x)'
03234 >>> SRem(10, x).sexpr()
03235 '(bvsrem #x0000000a x)'
03236 """
03237 a, b = _coerce_exprs(self, other)
03238 return BitVecRef(Z3_mk_bvsmod(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03239
03240 def __le__(self, other):
03241 """Create the Z3 expression (signed) `other <= self`.
03242
03243 Use the function ULE() for unsigned less than or equal to.
03244
03245 >>> x, y = BitVecs('x y', 32)
03246 >>> x <= y
03247 x <= y
03248 >>> (x <= y).sexpr()
03249 '(bvsle x y)'
03250 >>> ULE(x, y).sexpr()
03251 '(bvule x y)'
03252 """
03253 a, b = _coerce_exprs(self, other)
03254 return BoolRef(Z3_mk_bvsle(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03255
03256 def __lt__(self, other):
03257 """Create the Z3 expression (signed) `other < self`.
03258
03259 Use the function ULT() for unsigned less than.
03260
03261 >>> x, y = BitVecs('x y', 32)
03262 >>> x < y
03263 x < y
03264 >>> (x < y).sexpr()
03265 '(bvslt x y)'
03266 >>> ULT(x, y).sexpr()
03267 '(bvult x y)'
03268 """
03269 a, b = _coerce_exprs(self, other)
03270 return BoolRef(Z3_mk_bvslt(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03271
03272 def __gt__(self, other):
03273 """Create the Z3 expression (signed) `other > self`.
03274
03275 Use the function UGT() for unsigned greater than.
03276
03277 >>> x, y = BitVecs('x y', 32)
03278 >>> x > y
03279 x > y
03280 >>> (x > y).sexpr()
03281 '(bvsgt x y)'
03282 >>> UGT(x, y).sexpr()
03283 '(bvugt x y)'
03284 """
03285 a, b = _coerce_exprs(self, other)
03286 return BoolRef(Z3_mk_bvsgt(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03287
03288 def __ge__(self, other):
03289 """Create the Z3 expression (signed) `other >= self`.
03290
03291 Use the function UGE() for unsigned greater than or equal to.
03292
03293 >>> x, y = BitVecs('x y', 32)
03294 >>> x >= y
03295 x >= y
03296 >>> (x >= y).sexpr()
03297 '(bvsge x y)'
03298 >>> UGE(x, y).sexpr()
03299 '(bvuge x y)'
03300 """
03301 a, b = _coerce_exprs(self, other)
03302 return BoolRef(Z3_mk_bvsge(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03303
03304 def __rshift__(self, other):
03305 """Create the Z3 expression (arithmetical) right shift `self >> other`
03306
03307 Use the function LShR() for the right logical shift
03308
03309 >>> x, y = BitVecs('x y', 32)
03310 >>> x >> y
03311 x >> y
03312 >>> (x >> y).sexpr()
03313 '(bvashr x y)'
03314 >>> LShR(x, y).sexpr()
03315 '(bvlshr x y)'
03316 >>> BitVecVal(4, 3)
03317 4
03318 >>> BitVecVal(4, 3).as_signed_long()
03319 -4
03320 >>> simplify(BitVecVal(4, 3) >> 1).as_signed_long()
03321 -2
03322 >>> simplify(BitVecVal(4, 3) >> 1)
03323 6
03324 >>> simplify(LShR(BitVecVal(4, 3), 1))
03325 2
03326 >>> simplify(BitVecVal(2, 3) >> 1)
03327 1
03328 >>> simplify(LShR(BitVecVal(2, 3), 1))
03329 1
03330 """
03331 a, b = _coerce_exprs(self, other)
03332 return BitVecRef(Z3_mk_bvashr(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03333
03334 def __lshift__(self, other):
03335 """Create the Z3 expression left shift `self << other`
03336
03337 >>> x, y = BitVecs('x y', 32)
03338 >>> x << y
03339 x << y
03340 >>> (x << y).sexpr()
03341 '(bvshl x y)'
03342 >>> simplify(BitVecVal(2, 3) << 1)
03343 4
03344 """
03345 a, b = _coerce_exprs(self, other)
03346 return BitVecRef(Z3_mk_bvshl(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
03347
03348 def __rrshift__(self, other):
03349 """Create the Z3 expression (arithmetical) right shift `other` >> `self`.
03350
03351 Use the function LShR() for the right logical shift
03352
03353 >>> x = BitVec('x', 32)
03354 >>> 10 >> x
03355 10 >> x
03356 >>> (10 >> x).sexpr()
03357 '(bvashr #x0000000a x)'
03358 """
03359 a, b = _coerce_exprs(self, other)
03360 return BitVecRef(Z3_mk_bvashr(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03361
03362 def __rlshift__(self, other):
03363 """Create the Z3 expression left shift `other << self`.
03364
03365 Use the function LShR() for the right logical shift
03366
03367 >>> x = BitVec('x', 32)
03368 >>> 10 << x
03369 10 << x
03370 >>> (10 << x).sexpr()
03371 '(bvshl #x0000000a x)'
03372 """
03373 a, b = _coerce_exprs(self, other)
03374 return BitVecRef(Z3_mk_bvshl(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx)
03375
03376 class BitVecNumRef(BitVecRef):
03377 """Bit-vector values."""
03378
03379 def as_long(self):
03380 """Return a Z3 bit-vector numeral as a Python long (bignum) numeral.
03381
03382 >>> v = BitVecVal(0xbadc0de, 32)
03383 >>> v
03384 195936478
03385 >>> print("0x%.8x" % v.as_long())
03386 0x0badc0de
03387 """
03388 return int(self.as_string())
03389
03390 def as_signed_long(self):
03391 """Return a Z3 bit-vector numeral as a Python long (bignum) numeral. The most significant bit is assumed to be the sign.
03392
03393 >>> BitVecVal(4, 3).as_signed_long()
03394 -4
03395 >>> BitVecVal(7, 3).as_signed_long()
03396 -1
03397 >>> BitVecVal(3, 3).as_signed_long()
03398 3
03399 >>> BitVecVal(2**32 - 1, 32).as_signed_long()
03400 -1
03401 >>> BitVecVal(2**64 - 1, 64).as_signed_long()
03402 -1
03403 """
03404 sz = self.size()
03405 val = self.as_long()
03406 if val >= 2**(sz - 1):
03407 val = val - 2**sz
03408 if val < -2**(sz - 1):
03409 val = val + 2**sz
03410 return int(val)
03411
03412 def as_string(self):
03413 return Z3_get_numeral_string(self.ctx_ref(), self.as_ast())
03414
03415 def is_bv(a):
03416 """Return `True` if `a` is a Z3 bit-vector expression.
03417
03418 >>> b = BitVec('b', 32)
03419 >>> is_bv(b)
03420 True
03421 >>> is_bv(b + 10)
03422 True
03423 >>> is_bv(Int('x'))
03424 False
03425 """
03426 return isinstance(a, BitVecRef)
03427
03428 def is_bv_value(a):
03429 """Return `True` if `a` is a Z3 bit-vector numeral value.
03430
03431 >>> b = BitVec('b', 32)
03432 >>> is_bv_value(b)
03433 False
03434 >>> b = BitVecVal(10, 32)
03435 >>> b
03436 10
03437 >>> is_bv_value(b)
03438 True
03439 """
03440 return is_bv(a) and _is_numeral(a.ctx, a.as_ast())
03441
03442 def BV2Int(a):
03443 """Return the Z3 expression BV2Int(a).
03444
03445 >>> b = BitVec('b', 3)
03446 >>> BV2Int(b).sort()
03447 Int
03448 >>> x = Int('x')
03449 >>> x > BV2Int(b)
03450 x > BV2Int(b)
03451 >>> solve(x > BV2Int(b), b == 1, x < 3)
03452 [b = 1, x = 2]
03453 """
03454 if __debug__:
03455 _z3_assert(is_bv(a), "Z3 bit-vector expression expected")
03456 ctx = a.ctx
03457 ## investigate problem with bv2int
03458 return ArithRef(Z3_mk_bv2int(ctx.ref(), a.as_ast(), 0), ctx)
03459
03460 def BitVecSort(sz, ctx=None):
03461 """Return a Z3 bit-vector sort of the given size. If `ctx=None`, then the global context is used.
03462
03463 >>> Byte = BitVecSort(8)
03464 >>> Word = BitVecSort(16)
03465 >>> Byte
03466 BitVec(8)
03467 >>> x = Const('x', Byte)
03468 >>> eq(x, BitVec('x', 8))
03469 True
03470 """
03471 ctx = _get_ctx(ctx)
03472 return BitVecSortRef(Z3_mk_bv_sort(ctx.ref(), sz), ctx)
03473
03474 def BitVecVal(val, bv, ctx=None):
03475 """Return a bit-vector value with the given number of bits. If `ctx=None`, then the global context is used.
03476
03477 >>> v = BitVecVal(10, 32)
03478 >>> v
03479 10
03480 >>> print("0x%.8x" % v.as_long())
03481 0x0000000a
03482 """
03483 if is_bv_sort(bv):
03484 ctx = bv.ctx
03485 return BitVecNumRef(Z3_mk_numeral(ctx.ref(), _to_int_str(val), bv.ast), ctx)
03486 else:
03487 ctx = _get_ctx(ctx)
03488 return BitVecNumRef(Z3_mk_numeral(ctx.ref(), _to_int_str(val), BitVecSort(bv, ctx).ast), ctx)
03489
03490 def BitVec(name, bv, ctx=None):
03491 """Return a bit-vector constant named `name`. `bv` may be the number of bits of a bit-vector sort.
03492 If `ctx=None`, then the global context is used.
03493
03494 >>> x = BitVec('x', 16)
03495 >>> is_bv(x)
03496 True
03497 >>> x.size()
03498 16
03499 >>> x.sort()
03500 BitVec(16)
03501 >>> word = BitVecSort(16)
03502 >>> x2 = BitVec('x', word)
03503 >>> eq(x, x2)
03504 True
03505 """
03506 if isinstance(bv, BitVecSortRef):
03507 ctx = bv.ctx
03508 else:
03509 ctx = _get_ctx(ctx)
03510 bv = BitVecSort(bv, ctx)
03511 return BitVecRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), bv.ast), ctx)
03512
03513 def BitVecs(names, bv, ctx=None):
03514 """Return a tuple of bit-vector constants of size bv.
03515
03516 >>> x, y, z = BitVecs('x y z', 16)
03517 >>> x.size()
03518 16
03519 >>> x.sort()
03520 BitVec(16)
03521 >>> Sum(x, y, z)
03522 0 + x + y + z
03523 >>> Product(x, y, z)
03524 1*x*y*z
03525 >>> simplify(Product(x, y, z))
03526 x*y*z
03527 """
03528 ctx = _get_ctx(ctx)
03529 if isinstance(names, str):
03530 names = names.split(" ")
03531 return [BitVec(name, bv, ctx) for name in names]
03532
03533 def Concat(*args):
03534 """Create a Z3 bit-vector concatenation expression.
03535
03536 >>> v = BitVecVal(1, 4)
03537 >>> Concat(v, v+1, v)
03538 Concat(Concat(1, 1 + 1), 1)
03539 >>> simplify(Concat(v, v+1, v))
03540 289
03541 >>> print("%.3x" % simplify(Concat(v, v+1, v)).as_long())
03542 121
03543 """
03544 args = _get_args(args)
03545 if __debug__:
03546 _z3_assert(all([is_bv(a) for a in args]), "All arguments must be Z3 bit-vector expressions.")
03547 _z3_assert(len(args) >= 2, "At least two arguments expected.")
03548 ctx = args[0].ctx
03549 r = args[0]
03550 for i in range(len(args) - 1):
03551 r = BitVecRef(Z3_mk_concat(ctx.ref(), r.as_ast(), args[i+1].as_ast()), ctx)
03552 return r
03553
03554 def Extract(high, low, a):
03555 """Create a Z3 bit-vector extraction expression.
03556
03557 >>> x = BitVec('x', 8)
03558 >>> Extract(6, 2, x)
03559 Extract(6, 2, x)
03560 >>> Extract(6, 2, x).sort()
03561 BitVec(5)
03562 """
03563 if __debug__:
03564 _z3_assert(low <= high, "First argument must be greater than or equal to second argument")
03565 _z3_assert(isinstance(high, int) and high >= 0 and isinstance(low, int) and low >= 0, "First and second arguments must be non negative integers")
03566 _z3_assert(is_bv(a), "Third argument must be a Z3 Bitvector expression")
03567 return BitVecRef(Z3_mk_extract(a.ctx_ref(), high, low, a.as_ast()), a.ctx)
03568
03569 def _check_bv_args(a, b):
03570 if __debug__:
03571 _z3_assert(is_bv(a) or is_bv(b), "At least one of the arguments must be a Z3 bit-vector expression")
03572
03573 def ULE(a, b):
03574 """Create the Z3 expression (unsigned) `other <= self`.
03575
03576 Use the operator <= for signed less than or equal to.
03577
03578 >>> x, y = BitVecs('x y', 32)
03579 >>> ULE(x, y)
03580 ULE(x, y)
03581 >>> (x <= y).sexpr()
03582 '(bvsle x y)'
03583 >>> ULE(x, y).sexpr()
03584 '(bvule x y)'
03585 """
03586 _check_bv_args(a, b)
03587 a, b = _coerce_exprs(a, b)
03588 return BoolRef(Z3_mk_bvule(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03589
03590 def ULT(a, b):
03591 """Create the Z3 expression (unsigned) `other < self`.
03592
03593 Use the operator < for signed less than.
03594
03595 >>> x, y = BitVecs('x y', 32)
03596 >>> ULT(x, y)
03597 ULT(x, y)
03598 >>> (x < y).sexpr()
03599 '(bvslt x y)'
03600 >>> ULT(x, y).sexpr()
03601 '(bvult x y)'
03602 """
03603 _check_bv_args(a, b)
03604 a, b = _coerce_exprs(a, b)
03605 return BoolRef(Z3_mk_bvult(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03606
03607 def UGE(a, b):
03608 """Create the Z3 expression (unsigned) `other >= self`.
03609
03610 Use the operator >= for signed greater than or equal to.
03611
03612 >>> x, y = BitVecs('x y', 32)
03613 >>> UGE(x, y)
03614 UGE(x, y)
03615 >>> (x >= y).sexpr()
03616 '(bvsge x y)'
03617 >>> UGE(x, y).sexpr()
03618 '(bvuge x y)'
03619 """
03620 _check_bv_args(a, b)
03621 a, b = _coerce_exprs(a, b)
03622 return BoolRef(Z3_mk_bvuge(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03623
03624 def UGT(a, b):
03625 """Create the Z3 expression (unsigned) `other > self`.
03626
03627 Use the operator > for signed greater than.
03628
03629 >>> x, y = BitVecs('x y', 32)
03630 >>> UGT(x, y)
03631 UGT(x, y)
03632 >>> (x > y).sexpr()
03633 '(bvsgt x y)'
03634 >>> UGT(x, y).sexpr()
03635 '(bvugt x y)'
03636 """
03637 _check_bv_args(a, b)
03638 a, b = _coerce_exprs(a, b)
03639 return BoolRef(Z3_mk_bvugt(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03640
03641 def UDiv(a, b):
03642 """Create the Z3 expression (unsigned) division `self / other`.
03643
03644 Use the operator / for signed division.
03645
03646 >>> x = BitVec('x', 32)
03647 >>> y = BitVec('y', 32)
03648 >>> UDiv(x, y)
03649 UDiv(x, y)
03650 >>> UDiv(x, y).sort()
03651 BitVec(32)
03652 >>> (x / y).sexpr()
03653 '(bvsdiv x y)'
03654 >>> UDiv(x, y).sexpr()
03655 '(bvudiv x y)'
03656 """
03657 _check_bv_args(a, b)
03658 a, b = _coerce_exprs(a, b)
03659 return BitVecRef(Z3_mk_bvudiv(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03660
03661 def URem(a, b):
03662 """Create the Z3 expression (unsigned) remainder `self % other`.
03663
03664 Use the operator % for signed modulus, and SRem() for signed remainder.
03665
03666 >>> x = BitVec('x', 32)
03667 >>> y = BitVec('y', 32)
03668 >>> URem(x, y)
03669 URem(x, y)
03670 >>> URem(x, y).sort()
03671 BitVec(32)
03672 >>> (x % y).sexpr()
03673 '(bvsmod x y)'
03674 >>> URem(x, y).sexpr()
03675 '(bvurem x y)'
03676 """
03677 _check_bv_args(a, b)
03678 a, b = _coerce_exprs(a, b)
03679 return BitVecRef(Z3_mk_bvurem(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03680
03681 def SRem(a, b):
03682 """Create the Z3 expression signed remainder.
03683
03684 Use the operator % for signed modulus, and URem() for unsigned remainder.
03685
03686 >>> x = BitVec('x', 32)
03687 >>> y = BitVec('y', 32)
03688 >>> SRem(x, y)
03689 SRem(x, y)
03690 >>> SRem(x, y).sort()
03691 BitVec(32)
03692 >>> (x % y).sexpr()
03693 '(bvsmod x y)'
03694 >>> SRem(x, y).sexpr()
03695 '(bvsrem x y)'
03696 """
03697 _check_bv_args(a, b)
03698 a, b = _coerce_exprs(a, b)
03699 return BitVecRef(Z3_mk_bvsrem(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03700
03701 def LShR(a, b):
03702 """Create the Z3 expression logical right shift.
03703
03704 Use the operator >> for the arithmetical right shift.
03705
03706 >>> x, y = BitVecs('x y', 32)
03707 >>> LShR(x, y)
03708 LShR(x, y)
03709 >>> (x >> y).sexpr()
03710 '(bvashr x y)'
03711 >>> LShR(x, y).sexpr()
03712 '(bvlshr x y)'
03713 >>> BitVecVal(4, 3)
03714 4
03715 >>> BitVecVal(4, 3).as_signed_long()
03716 -4
03717 >>> simplify(BitVecVal(4, 3) >> 1).as_signed_long()
03718 -2
03719 >>> simplify(BitVecVal(4, 3) >> 1)
03720 6
03721 >>> simplify(LShR(BitVecVal(4, 3), 1))
03722 2
03723 >>> simplify(BitVecVal(2, 3) >> 1)
03724 1
03725 >>> simplify(LShR(BitVecVal(2, 3), 1))
03726 1
03727 """
03728 _check_bv_args(a, b)
03729 a, b = _coerce_exprs(a, b)
03730 return BitVecRef(Z3_mk_bvlshr(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03731
03732 def RotateLeft(a, b):
03733 """Return an expression representing `a` rotated to the left `b` times.
03734
03735 >>> a, b = BitVecs('a b', 16)
03736 >>> RotateLeft(a, b)
03737 RotateLeft(a, b)
03738 >>> simplify(RotateLeft(a, 0))
03739 a
03740 >>> simplify(RotateLeft(a, 16))
03741 a
03742 """
03743 _check_bv_args(a, b)
03744 a, b = _coerce_exprs(a, b)
03745 return BitVecRef(Z3_mk_ext_rotate_left(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03746
03747 def RotateRight(a, b):
03748 """Return an expression representing `a` rotated to the right `b` times.
03749
03750 >>> a, b = BitVecs('a b', 16)
03751 >>> RotateRight(a, b)
03752 RotateRight(a, b)
03753 >>> simplify(RotateRight(a, 0))
03754 a
03755 >>> simplify(RotateRight(a, 16))
03756 a
03757 """
03758 _check_bv_args(a, b)
03759 a, b = _coerce_exprs(a, b)
03760 return BitVecRef(Z3_mk_ext_rotate_right(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
03761
03762 def SignExt(n, a):
03763 """Return a bit-vector expression with `n` extra sign-bits.
03764
03765 >>> x = BitVec('x', 16)
03766 >>> n = SignExt(8, x)
03767 >>> n.size()
03768 24
03769 >>> n
03770 SignExt(8, x)
03771 >>> n.sort()
03772 BitVec(24)
03773 >>> v0 = BitVecVal(2, 2)
03774 >>> v0
03775 2
03776 >>> v0.size()
03777 2
03778 >>> v = simplify(SignExt(6, v0))
03779 >>> v
03780 254
03781 >>> v.size()
03782 8
03783 >>> print("%.x" % v.as_long())
03784 fe
03785 """
03786 if __debug__:
03787 _z3_assert(isinstance(n, int), "First argument must be an integer")
03788 _z3_assert(is_bv(a), "Second argument must be a Z3 Bitvector expression")
03789 return BitVecRef(Z3_mk_sign_ext(a.ctx_ref(), n, a.as_ast()), a.ctx)
03790
03791 def ZeroExt(n, a):
03792 """Return a bit-vector expression with `n` extra zero-bits.
03793
03794 >>> x = BitVec('x', 16)
03795 >>> n = ZeroExt(8, x)
03796 >>> n.size()
03797 24
03798 >>> n
03799 ZeroExt(8, x)
03800 >>> n.sort()
03801 BitVec(24)
03802 >>> v0 = BitVecVal(2, 2)
03803 >>> v0
03804 2
03805 >>> v0.size()
03806 2
03807 >>> v = simplify(ZeroExt(6, v0))
03808 >>> v
03809 2
03810 >>> v.size()
03811 8
03812 """
03813 if __debug__:
03814 _z3_assert(isinstance(n, int), "First argument must be an integer")
03815 _z3_assert(is_bv(a), "Second argument must be a Z3 Bitvector expression")
03816 return BitVecRef(Z3_mk_zero_ext(a.ctx_ref(), n, a.as_ast()), a.ctx)
03817
03818 def RepeatBitVec(n, a):
03819 """Return an expression representing `n` copies of `a`.
03820
03821 >>> x = BitVec('x', 8)
03822 >>> n = RepeatBitVec(4, x)
03823 >>> n
03824 RepeatBitVec(4, x)
03825 >>> n.size()
03826 32
03827 >>> v0 = BitVecVal(10, 4)
03828 >>> print("%.x" % v0.as_long())
03829 a
03830 >>> v = simplify(RepeatBitVec(4, v0))
03831 >>> v.size()
03832 16
03833 >>> print("%.x" % v.as_long())
03834 aaaa
03835 """
03836 if __debug__:
03837 _z3_assert(isinstance(n, int), "First argument must be an integer")
03838 _z3_assert(is_bv(a), "Second argument must be a Z3 Bitvector expression")
03839 return BitVecRef(Z3_mk_repeat(a.ctx_ref(), n, a.as_ast()), a.ctx)
03840
03841 def BVRedAnd(a):
03842 """Return the reduction-and expression of `a`."""
03843 if __debug__:
03844 _z3_assert(is_bv(a), "First argument must be a Z3 Bitvector expression")
03845 return BitVecRef(Z3_mk_bvredand(a.ctx_ref(), a.as_ast()), a.ctx)
03846
03847 def BVRedOr(a):
03848 """Return the reduction-or expression of `a`."""
03849 if __debug__:
03850 _z3_assert(is_bv(a), "First argument must be a Z3 Bitvector expression")
03851 return BitVecRef(Z3_mk_bvredor(a.ctx_ref(), a.as_ast()), a.ctx)
03852
03853 #########################################
03854 #
03855 # Arrays
03856 #
03857 #########################################
03858
03859 class ArraySortRef(SortRef):
03860 """Array sorts."""
03861
03862 def domain(self):
03863 """Return the domain of the array sort `self`.
03864
03865 >>> A = ArraySort(IntSort(), BoolSort())
03866 >>> A.domain()
03867 Int
03868 """
03869 return _to_sort_ref(Z3_get_array_sort_domain(self.ctx_ref(), self.ast), self.ctx)
03870
03871 def range(self):
03872 """Return the range of the array sort `self`.
03873
03874 >>> A = ArraySort(IntSort(), BoolSort())
03875 >>> A.range()
03876 Bool
03877 """
03878 return _to_sort_ref(Z3_get_array_sort_range(self.ctx_ref(), self.ast), self.ctx)
03879
03880 class ArrayRef(ExprRef):
03881 """Array expressions. """
03882
03883 def sort(self):
03884 """Return the array sort of the array expression `self`.
03885
03886 >>> a = Array('a', IntSort(), BoolSort())
03887 >>> a.sort()
03888 Array(Int, Bool)
03889 """
03890 return ArraySortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
03891
03892 def domain(self):
03893 """Shorthand for `self.sort().domain()`.
03894
03895 >>> a = Array('a', IntSort(), BoolSort())
03896 >>> a.domain()
03897 Int
03898 """
03899 return self.sort().domain()
03900
03901 def range(self):
03902 """Shorthand for `self.sort().range()`.
03903
03904 >>> a = Array('a', IntSort(), BoolSort())
03905 >>> a.range()
03906 Bool
03907 """
03908 return self.sort().range()
03909
03910 def __getitem__(self, arg):
03911 """Return the Z3 expression `self[arg]`.
03912
03913 >>> a = Array('a', IntSort(), BoolSort())
03914 >>> i = Int('i')
03915 >>> a[i]
03916 a[i]
03917 >>> a[i].sexpr()
03918 '(select a i)'
03919 """
03920 arg = self.domain().cast(arg)
03921 return _to_expr_ref(Z3_mk_select(self.ctx_ref(), self.as_ast(), arg.as_ast()), self.ctx)
03922
03923 def mk_default(self):
03924 return _to_expr_ref(Z3_mk_array_default(self.ctx_ref(), self.as_ast()), self.ctx)
03925
03926
03927 def is_array(a):
03928 """Return `True` if `a` is a Z3 array expression.
03929
03930 >>> a = Array('a', IntSort(), IntSort())
03931 >>> is_array(a)
03932 True
03933 >>> is_array(Store(a, 0, 1))
03934 True
03935 >>> is_array(a[0])
03936 False
03937 """
03938 return isinstance(a, ArrayRef)
03939
03940 def is_const_array(a):
03941 """Return `True` if `a` is a Z3 constant array.
03942
03943 >>> a = K(IntSort(), 10)
03944 >>> is_const_array(a)
03945 True
03946 >>> a = Array('a', IntSort(), IntSort())
03947 >>> is_const_array(a)
03948 False
03949 """
03950 return is_app_of(a, Z3_OP_CONST_ARRAY)
03951
03952 def is_K(a):
03953 """Return `True` if `a` is a Z3 constant array.
03954
03955 >>> a = K(IntSort(), 10)
03956 >>> is_K(a)
03957 True
03958 >>> a = Array('a', IntSort(), IntSort())
03959 >>> is_K(a)
03960 False
03961 """
03962 return is_app_of(a, Z3_OP_CONST_ARRAY)
03963
03964 def is_map(a):
03965 """Return `True` if `a` is a Z3 map array expression.
03966
03967 >>> f = Function('f', IntSort(), IntSort())
03968 >>> b = Array('b', IntSort(), IntSort())
03969 >>> a = Map(f, b)
03970 >>> a
03971 Map(f, b)
03972 >>> is_map(a)
03973 True
03974 >>> is_map(b)
03975 False
03976 """
03977 return is_app_of(a, Z3_OP_ARRAY_MAP)
03978
03979 def is_default(a):
03980 """Return `True` if `a` is a Z3 default array expression.
03981 >>> d = Default(K(IntSort(), 10))
03982 >>> is_default(d)
03983 True
03984 """
03985 return is_app_of(a, Z3_OP_ARRAY_DEFAULT)
03986
03987 def get_map_func(a):
03988 """Return the function declaration associated with a Z3 map array expression.
03989
03990 >>> f = Function('f', IntSort(), IntSort())
03991 >>> b = Array('b', IntSort(), IntSort())
03992 >>> a = Map(f, b)
03993 >>> eq(f, get_map_func(a))
03994 True
03995 >>> get_map_func(a)
03996 f
03997 >>> get_map_func(a)(0)
03998 f(0)
03999 """
04000 if __debug__:
04001 _z3_assert(is_map(a), "Z3 array map expression expected.")
04002 return FuncDeclRef(Z3_to_func_decl(a.ctx_ref(), Z3_get_decl_ast_parameter(a.ctx_ref(), a.decl().ast, 0)), a.ctx)
04003
04004 def ArraySort(d, r):
04005 """Return the Z3 array sort with the given domain and range sorts.
04006
04007 >>> A = ArraySort(IntSort(), BoolSort())
04008 >>> A
04009 Array(Int, Bool)
04010 >>> A.domain()
04011 Int
04012 >>> A.range()
04013 Bool
04014 >>> AA = ArraySort(IntSort(), A)
04015 >>> AA
04016 Array(Int, Array(Int, Bool))
04017 """
04018 if __debug__:
04019 _z3_assert(is_sort(d), "Z3 sort expected")
04020 _z3_assert(is_sort(r), "Z3 sort expected")
04021 _z3_assert(d.ctx == r.ctx, "Context mismatch")
04022 ctx = d.ctx
04023 return ArraySortRef(Z3_mk_array_sort(ctx.ref(), d.ast, r.ast), ctx)
04024
04025 def Array(name, dom, rng):
04026 """Return an array constant named `name` with the given domain and range sorts.
04027
04028 >>> a = Array('a', IntSort(), IntSort())
04029 >>> a.sort()
04030 Array(Int, Int)
04031 >>> a[0]
04032 a[0]
04033 """
04034 s = ArraySort(dom, rng)
04035 ctx = s.ctx
04036 return ArrayRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), s.ast), ctx)
04037
04038 def Update(a, i, v):
04039 """Return a Z3 store array expression.
04040
04041 >>> a = Array('a', IntSort(), IntSort())
04042 >>> i, v = Ints('i v')
04043 >>> s = Update(a, i, v)
04044 >>> s.sort()
04045 Array(Int, Int)
04046 >>> prove(s[i] == v)
04047 proved
04048 >>> j = Int('j')
04049 >>> prove(Implies(i != j, s[j] == a[j]))
04050 proved
04051 """
04052 if __debug__:
04053 _z3_assert(is_array(a), "First argument must be a Z3 array expression")
04054 i = a.domain().cast(i)
04055 v = a.range().cast(v)
04056 ctx = a.ctx
04057 return _to_expr_ref(Z3_mk_store(ctx.ref(), a.as_ast(), i.as_ast(), v.as_ast()), ctx)
04058
04059 def Default(a):
04060 """ Return a default value for array expression.
04061 >>> b = K(IntSort(), 1)
04062 >>> prove(Default(b) == 1)
04063 proved
04064 """
04065 if __debug__:
04066 _z3_assert(is_array(a), "First argument must be a Z3 array expression")
04067 return a.mk_default()
04068
04069
04070 def Store(a, i, v):
04071 """Return a Z3 store array expression.
04072
04073 >>> a = Array('a', IntSort(), IntSort())
04074 >>> i, v = Ints('i v')
04075 >>> s = Store(a, i, v)
04076 >>> s.sort()
04077 Array(Int, Int)
04078 >>> prove(s[i] == v)
04079 proved
04080 >>> j = Int('j')
04081 >>> prove(Implies(i != j, s[j] == a[j]))
04082 proved
04083 """
04084 return Update(a, i, v)
04085
04086 def Select(a, i):
04087 """Return a Z3 select array expression.
04088
04089 >>> a = Array('a', IntSort(), IntSort())
04090 >>> i = Int('i')
04091 >>> Select(a, i)
04092 a[i]
04093 >>> eq(Select(a, i), a[i])
04094 True
04095 """
04096 if __debug__:
04097 _z3_assert(is_array(a), "First argument must be a Z3 array expression")
04098 return a[i]
04099
04100 def Map(f, *args):
04101 """Return a Z3 map array expression.
04102
04103 >>> f = Function('f', IntSort(), IntSort(), IntSort())
04104 >>> a1 = Array('a1', IntSort(), IntSort())
04105 >>> a2 = Array('a2', IntSort(), IntSort())
04106 >>> b = Map(f, a1, a2)
04107 >>> b
04108 Map(f, a1, a2)
04109 >>> prove(b[0] == f(a1[0], a2[0]))
04110 proved
04111 """
04112 args = _get_args(args)
04113 if __debug__:
04114 _z3_assert(len(args) > 0, "At least one Z3 array expression expected")
04115 _z3_assert(is_func_decl(f), "First argument must be a Z3 function declaration")
04116 _z3_assert(all([is_array(a) for a in args]), "Z3 array expected expected")
04117 _z3_assert(len(args) == f.arity(), "Number of arguments mismatch")
04118 _args, sz = _to_ast_array(args)
04119 ctx = f.ctx
04120 return ArrayRef(Z3_mk_map(ctx.ref(), f.ast, sz, _args), ctx)
04121
04122 def K(dom, v):
04123 """Return a Z3 constant array expression.
04124
04125 >>> a = K(IntSort(), 10)
04126 >>> a
04127 K(Int, 10)
04128 >>> a.sort()
04129 Array(Int, Int)
04130 >>> i = Int('i')
04131 >>> a[i]
04132 K(Int, 10)[i]
04133 >>> simplify(a[i])
04134 10
04135 """
04136 if __debug__:
04137 _z3_assert(is_sort(dom), "Z3 sort expected")
04138 ctx = dom.ctx
04139 if not is_expr(v):
04140 v = _py2expr(v, ctx)
04141 return ArrayRef(Z3_mk_const_array(ctx.ref(), dom.ast, v.as_ast()), ctx)
04142
04143 def is_select(a):
04144 """Return `True` if `a` is a Z3 array select application.
04145
04146 >>> a = Array('a', IntSort(), IntSort())
04147 >>> is_select(a)
04148 False
04149 >>> i = Int('i')
04150 >>> is_select(a[i])
04151 True
04152 """
04153 return is_app_of(a, Z3_OP_SELECT)
04154
04155 def is_store(a):
04156 """Return `True` if `a` is a Z3 array store application.
04157
04158 >>> a = Array('a', IntSort(), IntSort())
04159 >>> is_store(a)
04160 False
04161 >>> is_store(Store(a, 0, 1))
04162 True
04163 """
04164 return is_app_of(a, Z3_OP_STORE)
04165
04166 #########################################
04167 #
04168 # Datatypes
04169 #
04170 #########################################
04171
04172 def _valid_accessor(acc):
04173 """Return `True` if acc is pair of the form (String, Datatype or Sort). """
04174 return isinstance(acc, tuple) and len(acc) == 2 and isinstance(acc[0], str) and (isinstance(acc[1], Datatype) or is_sort(acc[1]))
04175
04176 class Datatype:
04177 """Helper class for declaring Z3 datatypes.
04178
04179 >>> List = Datatype('List')
04180 >>> List.declare('cons', ('car', IntSort()), ('cdr', List))
04181 >>> List.declare('nil')
04182 >>> List = List.create()
04183 >>>
04184 >>> List.nil
04185 nil
04186 >>> List.cons(10, List.nil)
04187 cons(10, nil)
04188 >>> List.cons(10, List.nil).sort()
04189 List
04190 >>> cons = List.cons
04191 >>> nil = List.nil
04192 >>> car = List.car
04193 >>> cdr = List.cdr
04194 >>> n = cons(1, cons(0, nil))
04195 >>> n
04196 cons(1, cons(0, nil))
04197 >>> simplify(cdr(n))
04198 cons(0, nil)
04199 >>> simplify(car(n))
04200 1
04201 """
04202 def __init__(self, name, ctx=None):
04203 self.ctx = _get_ctx(ctx)
04204 self.name = name
04205 self.constructors = []
04206
04207 def declare_core(self, name, rec_name, *args):
04208 if __debug__:
04209 _z3_assert(isinstance(name, str), "String expected")
04210 _z3_assert(isinstance(rec_name, str), "String expected")
04211 _z3_assert(all([_valid_accessor(a) for a in args]), "Valid list of accessors expected. An accessor is a pair of the form (String, Datatype|Sort)")
04212 self.constructors.append((name, rec_name, args))
04213
04214 def declare(self, name, *args):
04215 """Declare constructor named `name` with the given accessors `args`.
04216 Each accessor is a pair `(name, sort)`, where `name` is a string and `sort` a Z3 sort or a reference to the datatypes being declared.
04217
04218 In the followin example `List.declare('cons', ('car', IntSort()), ('cdr', List))`
04219 declares the constructor named `cons` that builds a new List using an integer and a List.
04220 It also declares the accessors `car` and `cdr`. The accessor `car` extracts the integer of a `cons` cell,
04221 and `cdr` the list of a `cons` cell. After all constructors were declared, we use the method create() to create
04222 the actual datatype in Z3.
04223
04224 >>> List = Datatype('List')
04225 >>> List.declare('cons', ('car', IntSort()), ('cdr', List))
04226 >>> List.declare('nil')
04227 >>> List = List.create()
04228 """
04229 if __debug__:
04230 _z3_assert(isinstance(name, str), "String expected")
04231 _z3_assert(name != "", "Constructor name cannot be empty")
04232 return self.declare_core(name, "is_" + name, *args)
04233
04234 def __repr__(self):
04235 return "Datatype(%s, %s)" % (self.name, self.constructors)
04236
04237 def create(self):
04238 """Create a Z3 datatype based on the constructors declared using the mehtod `declare()`.
04239
04240 The function `CreateDatatypes()` must be used to define mutually recursive datatypes.
04241
04242 >>> List = Datatype('List')
04243 >>> List.declare('cons', ('car', IntSort()), ('cdr', List))
04244 >>> List.declare('nil')
04245 >>> List = List.create()
04246 >>> List.nil
04247 nil
04248 >>> List.cons(10, List.nil)
04249 cons(10, nil)
04250 """
04251 return CreateDatatypes([self])[0]
04252
04253 class ScopedConstructor:
04254 """Auxiliary object used to create Z3 datatypes."""
04255 def __init__(self, c, ctx):
04256 self.c = c
04257 self.ctx = ctx
04258 def __del__(self):
04259 Z3_del_constructor(self.ctx.ref(), self.c)
04260
04261 class ScopedConstructorList:
04262 """Auxiliary object used to create Z3 datatypes."""
04263 def __init__(self, c, ctx):
04264 self.c = c
04265 self.ctx = ctx
04266 def __del__(self):
04267 Z3_del_constructor_list(self.ctx.ref(), self.c)
04268
04269 def CreateDatatypes(*ds):
04270 """Create mutually recursive Z3 datatypes using 1 or more Datatype helper objects.
04271
04272 In the following example we define a Tree-List using two mutually recursive datatypes.
04273
04274 >>> TreeList = Datatype('TreeList')
04275 >>> Tree = Datatype('Tree')
04276 >>>
04277 >>> Tree.declare('leaf', ('val', IntSort()))
04278 >>>
04279 >>> Tree.declare('node', ('children', TreeList))
04280 >>> TreeList.declare('nil')
04281 >>> TreeList.declare('cons', ('car', Tree), ('cdr', TreeList))
04282 >>> Tree, TreeList = CreateDatatypes(Tree, TreeList)
04283 >>> Tree.val(Tree.leaf(10))
04284 val(leaf(10))
04285 >>> simplify(Tree.val(Tree.leaf(10)))
04286 10
04287 >>> n1 = Tree.node(TreeList.cons(Tree.leaf(10), TreeList.cons(Tree.leaf(20), TreeList.nil)))
04288 >>> n1
04289 node(cons(leaf(10), cons(leaf(20), nil)))
04290 >>> n2 = Tree.node(TreeList.cons(n1, TreeList.nil))
04291 >>> simplify(n2 == n1)
04292 False
04293 >>> simplify(TreeList.car(Tree.children(n2)) == n1)
04294 True
04295 """
04296 ds = _get_args(ds)
04297 if __debug__:
04298 _z3_assert(len(ds) > 0, "At least one Datatype must be specified")
04299 _z3_assert(all([isinstance(d, Datatype) for d in ds]), "Arguments must be Datatypes")
04300 _z3_assert(all([d.ctx == ds[0].ctx for d in ds]), "Context mismatch")
04301 _z3_assert(all([d.constructors != [] for d in ds]), "Non-empty Datatypes expected")
04302 ctx = ds[0].ctx
04303 num = len(ds)
04304 names = (Symbol * num)()
04305 out = (Sort * num)()
04306 clists = (ConstructorList * num)()
04307 to_delete = []
04308 for i in range(num):
04309 d = ds[i]
04310 names[i] = to_symbol(d.name, ctx)
04311 num_cs = len(d.constructors)
04312 cs = (Constructor * num_cs)()
04313 for j in range(num_cs):
04314 c = d.constructors[j]
04315 cname = to_symbol(c[0], ctx)
04316 rname = to_symbol(c[1], ctx)
04317 fs = c[2]
04318 num_fs = len(fs)
04319 fnames = (Symbol * num_fs)()
04320 sorts = (Sort * num_fs)()
04321 refs = (ctypes.c_uint * num_fs)()
04322 for k in range(num_fs):
04323 fname = fs[k][0]
04324 ftype = fs[k][1]
04325 fnames[k] = to_symbol(fname, ctx)
04326 if isinstance(ftype, Datatype):
04327 if __debug__:
04328 _z3_assert(ds.count(ftype) == 1, "One and only one occurrence of each datatype is expected")
04329 sorts[k] = None
04330 refs[k] = ds.index(ftype)
04331 else:
04332 if __debug__:
04333 _z3_assert(is_sort(ftype), "Z3 sort expected")
04334 sorts[k] = ftype.ast
04335 refs[k] = 0
04336 cs[j] = Z3_mk_constructor(ctx.ref(), cname, rname, num_fs, fnames, sorts, refs)
04337 to_delete.append(ScopedConstructor(cs[j], ctx))
04338 clists[i] = Z3_mk_constructor_list(ctx.ref(), num_cs, cs)
04339 to_delete.append(ScopedConstructorList(clists[i], ctx))
04340 Z3_mk_datatypes(ctx.ref(), num, names, out, clists)
04341 result = []
04342 ## Create a field for every constructor, recognizer and accessor
04343 for i in range(num):
04344 dref = DatatypeSortRef(out[i], ctx)
04345 num_cs = dref.num_constructors()
04346 for j in range(num_cs):
04347 cref = dref.constructor(j)
04348 cref_name = cref.name()
04349 cref_arity = cref.arity()
04350 if cref.arity() == 0:
04351 cref = cref()
04352 setattr(dref, cref_name, cref)
04353 rref = dref.recognizer(j)
04354 setattr(dref, rref.name(), rref)
04355 for k in range(cref_arity):
04356 aref = dref.accessor(j, k)
04357 setattr(dref, aref.name(), aref)
04358 result.append(dref)
04359 return tuple(result)
04360
04361 class DatatypeSortRef(SortRef):
04362 """Datatype sorts."""
04363 def num_constructors(self):
04364 """Return the number of constructors in the given Z3 datatype.
04365
04366 >>> List = Datatype('List')
04367 >>> List.declare('cons', ('car', IntSort()), ('cdr', List))
04368 >>> List.declare('nil')
04369 >>> List = List.create()
04370 >>>
04371 >>> List.num_constructors()
04372 2
04373 """
04374 return int(Z3_get_datatype_sort_num_constructors(self.ctx_ref(), self.ast))
04375
04376 def constructor(self, idx):
04377 """Return a constructor of the datatype `self`.
04378
04379 >>> List = Datatype('List')
04380 >>> List.declare('cons', ('car', IntSort()), ('cdr', List))
04381 >>> List.declare('nil')
04382 >>> List = List.create()
04383 >>>
04384 >>> List.num_constructors()
04385 2
04386 >>> List.constructor(0)
04387 cons
04388 >>> List.constructor(1)
04389 nil
04390 """
04391 if __debug__:
04392 _z3_assert(idx < self.num_constructors(), "Invalid constructor index")
04393 return FuncDeclRef(Z3_get_datatype_sort_constructor(self.ctx_ref(), self.ast, idx), self.ctx)
04394
04395 def recognizer(self, idx):
04396 """In Z3, each constructor has an associated recognizer predicate.
04397
04398 If the constructor is named `name`, then the recognizer `is_name`.
04399
04400 >>> List = Datatype('List')
04401 >>> List.declare('cons', ('car', IntSort()), ('cdr', List))
04402 >>> List.declare('nil')
04403 >>> List = List.create()
04404 >>>
04405 >>> List.num_constructors()
04406 2
04407 >>> List.recognizer(0)
04408 is_cons
04409 >>> List.recognizer(1)
04410 is_nil
04411 >>> simplify(List.is_nil(List.cons(10, List.nil)))
04412 False
04413 >>> simplify(List.is_cons(List.cons(10, List.nil)))
04414 True
04415 >>> l = Const('l', List)
04416 >>> simplify(List.is_cons(l))
04417 is_cons(l)
04418 """
04419 if __debug__:
04420 _z3_assert(idx < self.num_constructors(), "Invalid recognizer index")
04421 return FuncDeclRef(Z3_get_datatype_sort_recognizer(self.ctx_ref(), self.ast, idx), self.ctx)
04422
04423 def accessor(self, i, j):
04424 """In Z3, each constructor has 0 or more accessor. The number of accessors is equal to the arity of the constructor.
04425
04426 >>> List = Datatype('List')
04427 >>> List.declare('cons', ('car', IntSort()), ('cdr', List))
04428 >>> List.declare('nil')
04429 >>> List = List.create()
04430 >>> List.num_constructors()
04431 2
04432 >>> List.constructor(0)
04433 cons
04434 >>> num_accs = List.constructor(0).arity()
04435 >>> num_accs
04436 2
04437 >>> List.accessor(0, 0)
04438 car
04439 >>> List.accessor(0, 1)
04440 cdr
04441 >>> List.constructor(1)
04442 nil
04443 >>> num_accs = List.constructor(1).arity()
04444 >>> num_accs
04445 0
04446 """
04447 if __debug__:
04448 _z3_assert(i < self.num_constructors(), "Invalid constructor index")
04449 _z3_assert(j < self.constructor(i).arity(), "Invalid accessor index")
04450 return FuncDeclRef(Z3_get_datatype_sort_constructor_accessor(self.ctx_ref(), self.ast, i, j), self.ctx)
04451
04452 class DatatypeRef(ExprRef):
04453 """Datatype expressions."""
04454 def sort(self):
04455 """Return the datatype sort of the datatype expression `self`."""
04456 return DatatypeSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
04457
04458 def EnumSort(name, values, ctx=None):
04459 """Return a new enumeration sort named `name` containing the given values.
04460
04461 The result is a pair (sort, list of constants).
04462 Example:
04463 >>> Color, (red, green, blue) = EnumSort('Color', ['red', 'green', 'blue'])
04464 """
04465 if __debug__:
04466 _z3_assert(isinstance(name, str), "Name must be a string")
04467 _z3_assert(all([isinstance(v, str) for v in values]), "Eumeration sort values must be strings")
04468 _z3_assert(len(values) > 0, "At least one value expected")
04469 ctx = _get_ctx(ctx)
04470 num = len(values)
04471 _val_names = (Symbol * num)()
04472 for i in range(num):
04473 _val_names[i] = to_symbol(values[i])
04474 _values = (FuncDecl * num)()
04475 _testers = (FuncDecl * num)()
04476 name = to_symbol(name)
04477 S = DatatypeSortRef(Z3_mk_enumeration_sort(ctx.ref(), name, num, _val_names, _values, _testers), ctx)
04478 V = []
04479 for i in range(num):
04480 V.append(FuncDeclRef(_values[i], ctx))
04481 V = [a() for a in V]
04482 return S, V
04483
04484 #########################################
04485 #
04486 # Parameter Sets
04487 #
04488 #########################################
04489
04490 class ParamsRef:
04491 """Set of parameters used to configure Solvers, Tactics and Simplifiers in Z3.
04492
04493 Consider using the function `args2params` to create instances of this object.
04494 """
04495 def __init__(self, ctx=None):
04496 self.ctx = _get_ctx(ctx)
04497 self.params = Z3_mk_params(self.ctx.ref())
04498 Z3_params_inc_ref(self.ctx.ref(), self.params)
04499
04500 def __del__(self):
04501 Z3_params_dec_ref(self.ctx.ref(), self.params)
04502
04503 def set(self, name, val):
04504 """Set parameter name with value val."""
04505 if __debug__:
04506 _z3_assert(isinstance(name, str), "parameter name must be a string")
04507 name_sym = to_symbol(name, self.ctx)
04508 if isinstance(val, bool):
04509 Z3_params_set_bool(self.ctx.ref(), self.params, name_sym, val)
04510 elif isinstance(val, int):
04511 Z3_params_set_uint(self.ctx.ref(), self.params, name_sym, val)
04512 elif isinstance(val, float):
04513 Z3_params_set_double(self.ctx.ref(), self.params, name_sym, val)
04514 elif isinstance(val, str):
04515 Z3_params_set_symbol(self.ctx.ref(), self.params, name_sym, to_symbol(val, self.ctx))
04516 else:
04517 if __debug__:
04518 _z3_assert(False, "invalid parameter value")
04519
04520 def __repr__(self):
04521 return Z3_params_to_string(self.ctx.ref(), self.params)
04522
04523 def validate(self, ds):
04524 _z3_assert(isinstance(ds, ParamDescrsRef), "parameter description set expected")
04525 Z3_params_validate(self.ctx.ref(), self.params, ds.descr)
04526
04527 def args2params(arguments, keywords, ctx=None):
04528 """Convert python arguments into a Z3_params object.
04529 A ':' is added to the keywords, and '_' is replaced with '-'
04530
04531 >>> args2params(['model', True, 'relevancy', 2], {'elim_and' : True})
04532 (params model true relevancy 2 elim_and true)
04533 """
04534 if __debug__:
04535 _z3_assert(len(arguments) % 2 == 0, "Argument list must have an even number of elements.")
04536 prev = None
04537 r = ParamsRef(ctx)
04538 for a in arguments:
04539 if prev == None:
04540 prev = a
04541 else:
04542 r.set(prev, a)
04543 prev = None
04544 for k in keywords:
04545 v = keywords[k]
04546 r.set(k, v)
04547 return r
04548
04549 class ParamDescrsRef:
04550 """Set of parameter descriptions for Solvers, Tactics and Simplifiers in Z3.
04551 """
04552 def __init__(self, descr, ctx=None):
04553 _z3_assert(isinstance(descr, ParamDescrs), "parameter description object expected")
04554 self.ctx = _get_ctx(ctx)
04555 self.descr = descr
04556 Z3_param_descrs_inc_ref(self.ctx.ref(), self.descr)
04557
04558 def __del__(self):
04559 Z3_param_descrs_dec_ref(self.ctx.ref(), self.descr)
04560
04561 def size(self):
04562 """Return the size of in the parameter description `self`.
04563 """
04564 return int(Z3_param_descrs_size(self.ctx.ref(), self.descr))
04565
04566 def __len__(self):
04567 """Return the size of in the parameter description `self`.
04568 """
04569 return self.size()
04570
04571 def get_name(self, i):
04572 """Return the i-th parameter name in the parameter description `self`.
04573 """
04574 return _symbol2py(self.ctx, Z3_param_descrs_get_name(self.ctx.ref(), self.descr, i))
04575
04576 def get_kind(self, n):
04577 """Return the kind of the parameter named `n`.
04578 """
04579 return Z3_param_descrs_get_kind(self.ctx.ref(), self.descr, to_symbol(n, self.ctx))
04580
04581 def __getitem__(self, arg):
04582 if _is_int(arg):
04583 return self.get_name(arg)
04584 else:
04585 return self.get_kind(arg)
04586
04587 def __repr__(self):
04588 return Z3_param_descrs_to_string(self.ctx.ref(), self.descr)
04589
04590 #########################################
04591 #
04592 # Goals
04593 #
04594 #########################################
04595
04596 class Goal(Z3PPObject):
04597 """Goal is a collection of constraints we want to find a solution or show to be unsatisfiable (infeasible).
04598
04599 Goals are processed using Tactics. A Tactic transforms a goal into a set of subgoals.
04600 A goal has a solution if one of its subgoals has a solution.
04601 A goal is unsatisfiable if all subgoals are unsatisfiable.
04602 """
04603
04604 def __init__(self, models=True, unsat_cores=False, proofs=False, ctx=None, goal=None):
04605 if __debug__:
04606 _z3_assert(goal == None or ctx != None, "If goal is different from None, then ctx must be also different from None")
04607 self.ctx = _get_ctx(ctx)
04608 self.goal = goal
04609 if self.goal == None:
04610 self.goal = Z3_mk_goal(self.ctx.ref(), models, unsat_cores, proofs)
04611 Z3_goal_inc_ref(self.ctx.ref(), self.goal)
04612
04613 def __del__(self):
04614 if self.goal != None:
04615 Z3_goal_dec_ref(self.ctx.ref(), self.goal)
04616
04617 def depth(self):
04618 """Return the depth of the goal `self`. The depth corresponds to the number of tactics applied to `self`.
04619
04620 >>> x, y = Ints('x y')
04621 >>> g = Goal()
04622 >>> g.add(x == 0, y >= x + 1)
04623 >>> g.depth()
04624 0
04625 >>> r = Then('simplify', 'solve-eqs')(g)
04626 >>>
04627 >>> len(r)
04628 1
04629 >>> r[0].depth()
04630 2
04631 """
04632 return int(Z3_goal_depth(self.ctx.ref(), self.goal))
04633
04634 def inconsistent(self):
04635 """Return `True` if `self` contains the `False` constraints.
04636
04637 >>> x, y = Ints('x y')
04638 >>> g = Goal()
04639 >>> g.inconsistent()
04640 False
04641 >>> g.add(x == 0, x == 1)
04642 >>> g
04643 [x == 0, x == 1]
04644 >>> g.inconsistent()
04645 False
04646 >>> g2 = Tactic('propagate-values')(g)[0]
04647 >>> g2.inconsistent()
04648 True
04649 """
04650 return Z3_goal_inconsistent(self.ctx.ref(), self.goal)
04651
04652 def prec(self):
04653 """Return the precision (under-approximation, over-approximation, or precise) of the goal `self`.
04654
04655 >>> g = Goal()
04656 >>> g.prec() == Z3_GOAL_PRECISE
04657 True
04658 >>> x, y = Ints('x y')
04659 >>> g.add(x == y + 1)
04660 >>> g.prec() == Z3_GOAL_PRECISE
04661 True
04662 >>> t = With(Tactic('add-bounds'), add_bound_lower=0, add_bound_upper=10)
04663 >>> g2 = t(g)[0]
04664 >>> g2
04665 [x == y + 1, x <= 10, x >= 0, y <= 10, y >= 0]
04666 >>> g2.prec() == Z3_GOAL_PRECISE
04667 False
04668 >>> g2.prec() == Z3_GOAL_UNDER
04669 True
04670 """
04671 return Z3_goal_precision(self.ctx.ref(), self.goal)
04672
04673 def precision(self):
04674 """Alias for `prec()`.
04675
04676 >>> g = Goal()
04677 >>> g.precision() == Z3_GOAL_PRECISE
04678 True
04679 """
04680 return self.prec()
04681
04682 def size(self):
04683 """Return the number of constraints in the goal `self`.
04684
04685 >>> g = Goal()
04686 >>> g.size()
04687 0
04688 >>> x, y = Ints('x y')
04689 >>> g.add(x == 0, y > x)
04690 >>> g.size()
04691 2
04692 """
04693 return int(Z3_goal_size(self.ctx.ref(), self.goal))
04694
04695 def __len__(self):
04696 """Return the number of constraints in the goal `self`.
04697
04698 >>> g = Goal()
04699 >>> len(g)
04700 0
04701 >>> x, y = Ints('x y')
04702 >>> g.add(x == 0, y > x)
04703 >>> len(g)
04704 2
04705 """
04706 return self.size()
04707
04708 def get(self, i):
04709 """Return a constraint in the goal `self`.
04710
04711 >>> g = Goal()
04712 >>> x, y = Ints('x y')
04713 >>> g.add(x == 0, y > x)
04714 >>> g.get(0)
04715 x == 0
04716 >>> g.get(1)
04717 y > x
04718 """
04719 return _to_expr_ref(Z3_goal_formula(self.ctx.ref(), self.goal, i), self.ctx)
04720
04721 def __getitem__(self, arg):
04722 """Return a constraint in the goal `self`.
04723
04724 >>> g = Goal()
04725 >>> x, y = Ints('x y')
04726 >>> g.add(x == 0, y > x)
04727 >>> g[0]
04728 x == 0
04729 >>> g[1]
04730 y > x
04731 """
04732 if arg >= len(self):
04733 raise IndexError
04734 return self.get(arg)
04735
04736 def assert_exprs(self, *args):
04737 """Assert constraints into the goal.
04738
04739 >>> x = Int('x')
04740 >>> g = Goal()
04741 >>> g.assert_exprs(x > 0, x < 2)
04742 >>> g
04743 [x > 0, x < 2]
04744 """
04745 args = _get_args(args)
04746 s = BoolSort(self.ctx)
04747 for arg in args:
04748 arg = s.cast(arg)
04749 Z3_goal_assert(self.ctx.ref(), self.goal, arg.as_ast())
04750
04751 def append(self, *args):
04752 """Add constraints.
04753
04754 >>> x = Int('x')
04755 >>> g = Goal()
04756 >>> g.append(x > 0, x < 2)
04757 >>> g
04758 [x > 0, x < 2]
04759 """
04760 self.assert_exprs(*args)
04761
04762 def insert(self, *args):
04763 """Add constraints.
04764
04765 >>> x = Int('x')
04766 >>> g = Goal()
04767 >>> g.insert(x > 0, x < 2)
04768 >>> g
04769 [x > 0, x < 2]
04770 """
04771 self.assert_exprs(*args)
04772
04773 def add(self, *args):
04774 """Add constraints.
04775
04776 >>> x = Int('x')
04777 >>> g = Goal()
04778 >>> g.add(x > 0, x < 2)
04779 >>> g
04780 [x > 0, x < 2]
04781 """
04782 self.assert_exprs(*args)
04783
04784 def __repr__(self):
04785 return obj_to_string(self)
04786
04787 def sexpr(self):
04788 """Return a textual representation of the s-expression representing the goal."""
04789 return Z3_goal_to_string(self.ctx.ref(), self.goal)
04790
04791 def translate(self, target):
04792 """Copy goal `self` to context `target`.
04793
04794 >>> x = Int('x')
04795 >>> g = Goal()
04796 >>> g.add(x > 10)
04797 >>> g
04798 [x > 10]
04799 >>> c2 = Context()
04800 >>> g2 = g.translate(c2)
04801 >>> g2
04802 [x > 10]
04803 >>> g.ctx == main_ctx()
04804 True
04805 >>> g2.ctx == c2
04806 True
04807 >>> g2.ctx == main_ctx()
04808 False
04809 """
04810 if __debug__:
04811 _z3_assert(isinstance(target, Context), "target must be a context")
04812 return Goal(goal=Z3_goal_translate(self.ctx.ref(), self.goal, target.ref()), ctx=target)
04813
04814 def simplify(self, *arguments, **keywords):
04815 """Return a new simplified goal.
04816
04817 This method is essentially invoking the simplify tactic.
04818
04819 >>> g = Goal()
04820 >>> x = Int('x')
04821 >>> g.add(x + 1 >= 2)
04822 >>> g
04823 [x + 1 >= 2]
04824 >>> g2 = g.simplify()
04825 >>> g2
04826 [x >= 1]
04827 >>>
04828 >>> g
04829 [x + 1 >= 2]
04830 """
04831 t = Tactic('simplify')
04832 return t.apply(self, *arguments, **keywords)[0]
04833
04834 def as_expr(self):
04835 """Return goal `self` as a single Z3 expression.
04836
04837 >>> x = Int('x')
04838 >>> g = Goal()
04839 >>> g.as_expr()
04840 True
04841 >>> g.add(x > 1)
04842 >>> g.as_expr()
04843 x > 1
04844 >>> g.add(x < 10)
04845 >>> g.as_expr()
04846 And(x > 1, x < 10)
04847 """
04848 sz = len(self)
04849 if sz == 0:
04850 return BoolVal(True, self.ctx)
04851 elif sz == 1:
04852 return self.get(0)
04853 else:
04854 return And([ self.get(i) for i in range(len(self)) ])
04855
04856 #########################################
04857 #
04858 # AST Vector
04859 #
04860 #########################################
04861 class AstVector(Z3PPObject):
04862 """A collection (vector) of ASTs."""
04863
04864 def __init__(self, v=None, ctx=None):
04865 self.vector = None
04866 if v == None:
04867 self.ctx = _get_ctx(ctx)
04868 self.vector = Z3_mk_ast_vector(self.ctx.ref())
04869 else:
04870 self.vector = v
04871 assert ctx != None
04872 self.ctx = ctx
04873 Z3_ast_vector_inc_ref(self.ctx.ref(), self.vector)
04874
04875 def __del__(self):
04876 if self.vector != None:
04877 Z3_ast_vector_dec_ref(self.ctx.ref(), self.vector)
04878
04879 def __len__(self):
04880 """Return the size of the vector `self`.
04881
04882 >>> A = AstVector()
04883 >>> len(A)
04884 0
04885 >>> A.push(Int('x'))
04886 >>> A.push(Int('x'))
04887 >>> len(A)
04888 2
04889 """
04890 return int(Z3_ast_vector_size(self.ctx.ref(), self.vector))
04891
04892 def __getitem__(self, i):
04893 """Return the AST at position `i`.
04894
04895 >>> A = AstVector()
04896 >>> A.push(Int('x') + 1)
04897 >>> A.push(Int('y'))
04898 >>> A[0]
04899 x + 1
04900 >>> A[1]
04901 y
04902 """
04903 if i >= self.__len__():
04904 raise IndexError
04905 return _to_ast_ref(Z3_ast_vector_get(self.ctx.ref(), self.vector, i), self.ctx)
04906
04907 def __setitem__(self, i, v):
04908 """Update AST at position `i`.
04909
04910 >>> A = AstVector()
04911 >>> A.push(Int('x') + 1)
04912 >>> A.push(Int('y'))
04913 >>> A[0]
04914 x + 1
04915 >>> A[0] = Int('x')
04916 >>> A[0]
04917 x
04918 """
04919 if i >= self.__len__():
04920 raise IndexError
04921 Z3_ast_vector_set(self.ctx.ref(), self.vector, i, v.as_ast())
04922
04923 def push(self, v):
04924 """Add `v` in the end of the vector.
04925
04926 >>> A = AstVector()
04927 >>> len(A)
04928 0
04929 >>> A.push(Int('x'))
04930 >>> len(A)
04931 1
04932 """
04933 Z3_ast_vector_push(self.ctx.ref(), self.vector, v.as_ast())
04934
04935 def resize(self, sz):
04936 """Resize the vector to `sz` elements.
04937
04938 >>> A = AstVector()
04939 >>> A.resize(10)
04940 >>> len(A)
04941 10
04942 >>> for i in range(10): A[i] = Int('x')
04943 >>> A[5]
04944 x
04945 """
04946 Z3_ast_vector_resize(self.ctx.ref(), self.vector, sz)
04947
04948 def __contains__(self, item):
04949 """Return `True` if the vector contains `item`.
04950
04951 >>> x = Int('x')
04952 >>> A = AstVector()
04953 >>> x in A
04954 False
04955 >>> A.push(x)
04956 >>> x in A
04957 True
04958 >>> (x+1) in A
04959 False
04960 >>> A.push(x+1)
04961 >>> (x+1) in A
04962 True
04963 >>> A
04964 [x, x + 1]
04965 """
04966 for elem in self:
04967 if elem.eq(item):
04968 return True
04969 return False
04970
04971 def translate(self, other_ctx):
04972 """Copy vector `self` to context `other_ctx`.
04973
04974 >>> x = Int('x')
04975 >>> A = AstVector()
04976 >>> A.push(x)
04977 >>> c2 = Context()
04978 >>> B = A.translate(c2)
04979 >>> B
04980 [x]
04981 """
04982 return AstVector(Z3_ast_vector_translate(self.ctx.ref(), self.vector, other_ctx.ref()), other_ctx)
04983
04984 def __repr__(self):
04985 return obj_to_string(self)
04986
04987 def sexpr(self):
04988 """Return a textual representation of the s-expression representing the vector."""
04989 return Z3_ast_vector_to_string(self.ctx.ref(), self.vector)
04990
04991 #########################################
04992 #
04993 # AST Map
04994 #
04995 #########################################
04996 class AstMap:
04997 """A mapping from ASTs to ASTs."""
04998
04999 def __init__(self, m=None, ctx=None):
05000 self.map = None
05001 if m == None:
05002 self.ctx = _get_ctx(ctx)
05003 self.map = Z3_mk_ast_map(self.ctx.ref())
05004 else:
05005 self.map = m
05006 assert ctx != None
05007 self.ctx = ctx
05008 Z3_ast_map_inc_ref(self.ctx.ref(), self.map)
05009
05010 def __del__(self):
05011 if self.map != None:
05012 Z3_ast_map_dec_ref(self.ctx.ref(), self.map)
05013
05014 def __len__(self):
05015 """Return the size of the map.
05016
05017 >>> M = AstMap()
05018 >>> len(M)
05019 0
05020 >>> x = Int('x')
05021 >>> M[x] = IntVal(1)
05022 >>> len(M)
05023 1
05024 """
05025 return int(Z3_ast_map_size(self.ctx.ref(), self.map))
05026
05027 def __contains__(self, key):
05028 """Return `True` if the map contains key `key`.
05029
05030 >>> M = AstMap()
05031 >>> x = Int('x')
05032 >>> M[x] = x + 1
05033 >>> x in M
05034 True
05035 >>> x+1 in M
05036 False
05037 """
05038 return Z3_ast_map_contains(self.ctx.ref(), self.map, key.as_ast())
05039
05040 def __getitem__(self, key):
05041 """Retrieve the value associated with key `key`.
05042
05043 >>> M = AstMap()
05044 >>> x = Int('x')
05045 >>> M[x] = x + 1
05046 >>> M[x]
05047 x + 1
05048 """
05049 return _to_ast_ref(Z3_ast_map_find(self.ctx.ref(), self.map, key.as_ast()), self.ctx)
05050
05051 def __setitem__(self, k, v):
05052 """Add/Update key `k` with value `v`.
05053
05054 >>> M = AstMap()
05055 >>> x = Int('x')
05056 >>> M[x] = x + 1
05057 >>> len(M)
05058 1
05059 >>> M[x]
05060 x + 1
05061 >>> M[x] = IntVal(1)
05062 >>> M[x]
05063 1
05064 """
05065 Z3_ast_map_insert(self.ctx.ref(), self.map, k.as_ast(), v.as_ast())
05066
05067 def __repr__(self):
05068 return Z3_ast_map_to_string(self.ctx.ref(), self.map)
05069
05070 def erase(self, k):
05071 """Remove the entry associated with key `k`.
05072
05073 >>> M = AstMap()
05074 >>> x = Int('x')
05075 >>> M[x] = x + 1
05076 >>> len(M)
05077 1
05078 >>> M.erase(x)
05079 >>> len(M)
05080 0
05081 """
05082 Z3_ast_map_erase(self.ctx.ref(), self.map, k.as_ast())
05083
05084 def reset(self):
05085 """Remove all entries from the map.
05086
05087 >>> M = AstMap()
05088 >>> x = Int('x')
05089 >>> M[x] = x + 1
05090 >>> M[x+x] = IntVal(1)
05091 >>> len(M)
05092 2
05093 >>> M.reset()
05094 >>> len(M)
05095 0
05096 """
05097 Z3_ast_map_reset(self.ctx.ref(), self.map)
05098
05099 def keys(self):
05100 """Return an AstVector containing all keys in the map.
05101
05102 >>> M = AstMap()
05103 >>> x = Int('x')
05104 >>> M[x] = x + 1
05105 >>> M[x+x] = IntVal(1)
05106 >>> M.keys()
05107 [x, x + x]
05108 """
05109 return AstVector(Z3_ast_map_keys(self.ctx.ref(), self.map), self.ctx)
05110
05111 #########################################
05112 #
05113 # Model
05114 #
05115 #########################################
05116
05117 class FuncEntry:
05118 """Store the value of the interpretation of a function in a particular point."""
05119
05120 def __init__(self, entry, ctx):
05121 self.entry = entry
05122 self.ctx = ctx
05123 Z3_func_entry_inc_ref(self.ctx.ref(), self.entry)
05124
05125 def __del__(self):
05126 Z3_func_entry_dec_ref(self.ctx.ref(), self.entry)
05127
05128 def num_args(self):
05129 """Return the number of arguments in the given entry.
05130
05131 >>> f = Function('f', IntSort(), IntSort(), IntSort())
05132 >>> s = Solver()
05133 >>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10)
05134 >>> s.check()
05135 sat
05136 >>> m = s.model()
05137 >>> f_i = m[f]
05138 >>> f_i.num_entries()
05139 3
05140 >>> e = f_i.entry(0)
05141 >>> e.num_args()
05142 2
05143 """
05144 return int(Z3_func_entry_get_num_args(self.ctx.ref(), self.entry))
05145
05146 def arg_value(self, idx):
05147 """Return the value of argument `idx`.
05148
05149 >>> f = Function('f', IntSort(), IntSort(), IntSort())
05150 >>> s = Solver()
05151 >>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10)
05152 >>> s.check()
05153 sat
05154 >>> m = s.model()
05155 >>> f_i = m[f]
05156 >>> f_i.num_entries()
05157 3
05158 >>> e = f_i.entry(0)
05159 >>> e
05160 [0, 1, 10]
05161 >>> e.num_args()
05162 2
05163 >>> e.arg_value(0)
05164 0
05165 >>> e.arg_value(1)
05166 1
05167 >>> try:
05168 ... e.arg_value(2)
05169 ... except IndexError:
05170 ... print("index error")
05171 index error
05172 """
05173 if idx >= self.num_args():
05174 raise IndexError
05175 return _to_expr_ref(Z3_func_entry_get_arg(self.ctx.ref(), self.entry, idx), self.ctx)
05176
05177 def value(self):
05178 """Return the value of the function at point `self`.
05179
05180 >>> f = Function('f', IntSort(), IntSort(), IntSort())
05181 >>> s = Solver()
05182 >>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10)
05183 >>> s.check()
05184 sat
05185 >>> m = s.model()
05186 >>> f_i = m[f]
05187 >>> f_i.num_entries()
05188 3
05189 >>> e = f_i.entry(0)
05190 >>> e
05191 [0, 1, 10]
05192 >>> e.num_args()
05193 2
05194 >>> e.value()
05195 10
05196 """
05197 return _to_expr_ref(Z3_func_entry_get_value(self.ctx.ref(), self.entry), self.ctx)
05198
05199 def as_list(self):
05200 """Return entry `self` as a Python list.
05201 >>> f = Function('f', IntSort(), IntSort(), IntSort())
05202 >>> s = Solver()
05203 >>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10)
05204 >>> s.check()
05205 sat
05206 >>> m = s.model()
05207 >>> f_i = m[f]
05208 >>> f_i.num_entries()
05209 3
05210 >>> e = f_i.entry(0)
05211 >>> e.as_list()
05212 [0, 1, 10]
05213 """
05214 args = [ self.arg_value(i) for i in range(self.num_args())]
05215 args.append(self.value())
05216 return args
05217
05218 def __repr__(self):
05219 return repr(self.as_list())
05220
05221 class FuncInterp(Z3PPObject):
05222 """Stores the interpretation of a function in a Z3 model."""
05223
05224 def __init__(self, f, ctx):
05225 self.f = f
05226 self.ctx = ctx
05227 if self.f != None:
05228 Z3_func_interp_inc_ref(self.ctx.ref(), self.f)
05229
05230 def __del__(self):
05231 if self.f != None:
05232 Z3_func_interp_dec_ref(self.ctx.ref(), self.f)
05233
05234 def else_value(self):
05235 """
05236 Return the `else` value for a function interpretation.
05237 Return None if Z3 did not specify the `else` value for
05238 this object.
05239
05240 >>> f = Function('f', IntSort(), IntSort())
05241 >>> s = Solver()
05242 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
05243 >>> s.check()
05244 sat
05245 >>> m = s.model()
05246 >>> m[f]
05247 [0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
05248 >>> m[f].else_value()
05249 1
05250 """
05251 r = Z3_func_interp_get_else(self.ctx.ref(), self.f)
05252 if r:
05253 return _to_expr_ref(r, self.ctx)
05254 else:
05255 return None
05256
05257 def num_entries(self):
05258 """Return the number of entries/points in the function interpretation `self`.
05259
05260 >>> f = Function('f', IntSort(), IntSort())
05261 >>> s = Solver()
05262 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
05263 >>> s.check()
05264 sat
05265 >>> m = s.model()
05266 >>> m[f]
05267 [0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
05268 >>> m[f].num_entries()
05269 3
05270 """
05271 return int(Z3_func_interp_get_num_entries(self.ctx.ref(), self.f))
05272
05273 def arity(self):
05274 """Return the number of arguments for each entry in the function interpretation `self`.
05275
05276 >>> f = Function('f', IntSort(), IntSort())
05277 >>> s = Solver()
05278 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
05279 >>> s.check()
05280 sat
05281 >>> m = s.model()
05282 >>> m[f].arity()
05283 1
05284 """
05285 return int(Z3_func_interp_get_arity(self.ctx.ref(), self.f))
05286
05287 def entry(self, idx):
05288 """Return an entry at position `idx < self.num_entries()` in the function interpretation `self`.
05289
05290 >>> f = Function('f', IntSort(), IntSort())
05291 >>> s = Solver()
05292 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
05293 >>> s.check()
05294 sat
05295 >>> m = s.model()
05296 >>> m[f]
05297 [0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
05298 >>> m[f].num_entries()
05299 3
05300 >>> m[f].entry(0)
05301 [0, 1]
05302 >>> m[f].entry(1)
05303 [1, 1]
05304 >>> m[f].entry(2)
05305 [2, 0]
05306 """
05307 if idx >= self.num_entries():
05308 raise IndexError
05309 return FuncEntry(Z3_func_interp_get_entry(self.ctx.ref(), self.f, idx), self.ctx)
05310
05311 def as_list(self):
05312 """Return the function interpretation as a Python list.
05313 >>> f = Function('f', IntSort(), IntSort())
05314 >>> s = Solver()
05315 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
05316 >>> s.check()
05317 sat
05318 >>> m = s.model()
05319 >>> m[f]
05320 [0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
05321 >>> m[f].as_list()
05322 [[0, 1], [1, 1], [2, 0], 1]
05323 """
05324 r = [ self.entry(i).as_list() for i in range(self.num_entries())]
05325 r.append(self.else_value())
05326 return r
05327
05328 def __repr__(self):
05329 return obj_to_string(self)
05330
05331 class ModelRef(Z3PPObject):
05332 """Model/Solution of a satisfiability problem (aka system of constraints)."""
05333
05334 def __init__(self, m, ctx):
05335 assert ctx != None
05336 self.model = m
05337 self.ctx = ctx
05338 Z3_model_inc_ref(self.ctx.ref(), self.model)
05339
05340 def __del__(self):
05341 Z3_model_dec_ref(self.ctx.ref(), self.model)
05342
05343 def __repr__(self):
05344 return obj_to_string(self)
05345
05346 def sexpr(self):
05347 """Return a textual representation of the s-expression representing the model."""
05348 return Z3_model_to_string(self.ctx.ref(), self.model)
05349
05350 def eval(self, t, model_completion=False):
05351 """Evaluate the expression `t` in the model `self`. If `model_completion` is enabled, then a default interpretation is automatically added for symbols that do not have an interpretation in the model `self`.
05352
05353 >>> x = Int('x')
05354 >>> s = Solver()
05355 >>> s.add(x > 0, x < 2)
05356 >>> s.check()
05357 sat
05358 >>> m = s.model()
05359 >>> m.eval(x + 1)
05360 2
05361 >>> m.eval(x == 1)
05362 True
05363 >>> y = Int('y')
05364 >>> m.eval(y + x)
05365 1 + y
05366 >>> m.eval(y)
05367 y
05368 >>> m.eval(y, model_completion=True)
05369 0
05370 >>>
05371 >>> m.eval(y + x)
05372 1
05373 """
05374 r = (Ast * 1)()
05375 if Z3_model_eval(self.ctx.ref(), self.model, t.as_ast(), model_completion, r):
05376 return _to_expr_ref(r[0], self.ctx)
05377 raise Z3Exception("failed to evaluate expression in the model")
05378
05379 def evaluate(self, t, model_completion=False):
05380 """Alias for `eval`.
05381
05382 >>> x = Int('x')
05383 >>> s = Solver()
05384 >>> s.add(x > 0, x < 2)
05385 >>> s.check()
05386 sat
05387 >>> m = s.model()
05388 >>> m.evaluate(x + 1)
05389 2
05390 >>> m.evaluate(x == 1)
05391 True
05392 >>> y = Int('y')
05393 >>> m.evaluate(y + x)
05394 1 + y
05395 >>> m.evaluate(y)
05396 y
05397 >>> m.evaluate(y, model_completion=True)
05398 0
05399 >>>
05400 >>> m.evaluate(y + x)
05401 1
05402 """
05403 return self.eval(t, model_completion)
05404
05405 def __len__(self):
05406 """Return the number of constant and function declarations in the model `self`.
05407
05408 >>> f = Function('f', IntSort(), IntSort())
05409 >>> x = Int('x')
05410 >>> s = Solver()
05411 >>> s.add(x > 0, f(x) != x)
05412 >>> s.check()
05413 sat
05414 >>> m = s.model()
05415 >>> len(m)
05416 2
05417 """
05418 return int(Z3_model_get_num_consts(self.ctx.ref(), self.model)) + int(Z3_model_get_num_funcs(self.ctx.ref(), self.model))
05419
05420 def get_interp(self, decl):
05421 """Return the interpretation for a given declaration or constant.
05422
05423 >>> f = Function('f', IntSort(), IntSort())
05424 >>> x = Int('x')
05425 >>> s = Solver()
05426 >>> s.add(x > 0, x < 2, f(x) == 0)
05427 >>> s.check()
05428 sat
05429 >>> m = s.model()
05430 >>> m[x]
05431 1
05432 >>> m[f]
05433 [1 -> 0, else -> 0]
05434 """
05435 if __debug__:
05436 _z3_assert(isinstance(decl, FuncDeclRef) or is_const(decl), "Z3 declaration expected")
05437 if is_const(decl):
05438 decl = decl.decl()
05439 try:
05440 if decl.arity() == 0:
05441 r = _to_expr_ref(Z3_model_get_const_interp(self.ctx.ref(), self.model, decl.ast), self.ctx)
05442 if is_as_array(r):
05443 return self.get_interp(get_as_array_func(r))
05444 else:
05445 return r
05446 else:
05447 return FuncInterp(Z3_model_get_func_interp(self.ctx.ref(), self.model, decl.ast), self.ctx)
05448 except Z3Exception:
05449 return None
05450
05451 def num_sorts(self):
05452 """Return the number of unintepreted sorts that contain an interpretation in the model `self`.
05453
05454 >>> A = DeclareSort('A')
05455 >>> a, b = Consts('a b', A)
05456 >>> s = Solver()
05457 >>> s.add(a != b)
05458 >>> s.check()
05459 sat
05460 >>> m = s.model()
05461 >>> m.num_sorts()
05462 1
05463 """
05464 return int(Z3_model_get_num_sorts(self.ctx.ref(), self.model))
05465
05466 def get_sort(self, idx):
05467 """Return the unintepreted sort at position `idx` < self.num_sorts().
05468
05469 >>> A = DeclareSort('A')
05470 >>> B = DeclareSort('B')
05471 >>> a1, a2 = Consts('a1 a2', A)
05472 >>> b1, b2 = Consts('b1 b2', B)
05473 >>> s = Solver()
05474 >>> s.add(a1 != a2, b1 != b2)
05475 >>> s.check()
05476 sat
05477 >>> m = s.model()
05478 >>> m.num_sorts()
05479 2
05480 >>> m.get_sort(0)
05481 A
05482 >>> m.get_sort(1)
05483 B
05484 """
05485 if idx >= self.num_sorts():
05486 raise IndexError
05487 return _to_sort_ref(Z3_model_get_sort(self.ctx.ref(), self.model, idx), self.ctx)
05488
05489 def sorts(self):
05490 """Return all uninterpreted sorts that have an interpretation in the model `self`.
05491
05492 >>> A = DeclareSort('A')
05493 >>> B = DeclareSort('B')
05494 >>> a1, a2 = Consts('a1 a2', A)
05495 >>> b1, b2 = Consts('b1 b2', B)
05496 >>> s = Solver()
05497 >>> s.add(a1 != a2, b1 != b2)
05498 >>> s.check()
05499 sat
05500 >>> m = s.model()
05501 >>> m.sorts()
05502 [A, B]
05503 """
05504 return [ self.get_sort(i) for i in range(self.num_sorts()) ]
05505
05506 def get_universe(self, s):
05507 """Return the intepretation for the uninterpreted sort `s` in the model `self`.
05508
05509 >>> A = DeclareSort('A')
05510 >>> a, b = Consts('a b', A)
05511 >>> s = Solver()
05512 >>> s.add(a != b)
05513 >>> s.check()
05514 sat
05515 >>> m = s.model()
05516 >>> m.get_universe(A)
05517 [A!val!0, A!val!1]
05518 """
05519 if __debug__:
05520 _z3_assert(isinstance(s, SortRef), "Z3 sort expected")
05521 try:
05522 return AstVector(Z3_model_get_sort_universe(self.ctx.ref(), self.model, s.ast), self.ctx)
05523 except Z3Exception:
05524 return None
05525
05526 def __getitem__(self, idx):
05527 """If `idx` is an integer, then the declaration at position `idx` in the model `self` is returned. If `idx` is a declaration, then the actual interpreation is returned.
05528
05529 The elements can be retrieved using position or the actual declaration.
05530
05531 >>> f = Function('f', IntSort(), IntSort())
05532 >>> x = Int('x')
05533 >>> s = Solver()
05534 >>> s.add(x > 0, x < 2, f(x) == 0)
05535 >>> s.check()
05536 sat
05537 >>> m = s.model()
05538 >>> len(m)
05539 2
05540 >>> m[0]
05541 x
05542 >>> m[1]
05543 f
05544 >>> m[x]
05545 1
05546 >>> m[f]
05547 [1 -> 0, else -> 0]
05548 >>> for d in m: print("%s -> %s" % (d, m[d]))
05549 x -> 1
05550 f -> [1 -> 0, else -> 0]
05551 """
05552 if isinstance(idx, int):
05553 if idx >= len(self):
05554 raise IndexError
05555 num_consts = Z3_model_get_num_consts(self.ctx.ref(), self.model)
05556 if (idx < num_consts):
05557 return FuncDeclRef(Z3_model_get_const_decl(self.ctx.ref(), self.model, idx), self.ctx)
05558 else:
05559 return FuncDeclRef(Z3_model_get_func_decl(self.ctx.ref(), self.model, idx - num_consts), self.ctx)
05560 if isinstance(idx, FuncDeclRef):
05561 return self.get_interp(idx)
05562 if is_const(idx):
05563 return self.get_interp(idx.decl())
05564 if isinstance(idx, SortRef):
05565 return self.get_universe(idx)
05566 if __debug__:
05567 _z3_assert(False, "Integer, Z3 declaration, or Z3 constant expected")
05568 return None
05569
05570 def decls(self):
05571 """Return a list with all symbols that have an interpreation in the model `self`.
05572 >>> f = Function('f', IntSort(), IntSort())
05573 >>> x = Int('x')
05574 >>> s = Solver()
05575 >>> s.add(x > 0, x < 2, f(x) == 0)
05576 >>> s.check()
05577 sat
05578 >>> m = s.model()
05579 >>> m.decls()
05580 [x, f]
05581 """
05582 r = []
05583 for i in range(Z3_model_get_num_consts(self.ctx.ref(), self.model)):
05584 r.append(FuncDeclRef(Z3_model_get_const_decl(self.ctx.ref(), self.model, i), self.ctx))
05585 for i in range(Z3_model_get_num_funcs(self.ctx.ref(), self.model)):
05586 r.append(FuncDeclRef(Z3_model_get_func_decl(self.ctx.ref(), self.model, i), self.ctx))
05587 return r
05588
05589 def is_as_array(n):
05590 """Return true if n is a Z3 expression of the form (_ as-array f)."""
05591 return isinstance(n, ExprRef) and Z3_is_as_array(n.ctx.ref(), n.as_ast())
05592
05593 def get_as_array_func(n):
05594 """Return the function declaration f associated with a Z3 expression of the form (_ as-array f)."""
05595 if __debug__:
05596 _z3_assert(is_as_array(n), "as-array Z3 expression expected.")
05597 return FuncDeclRef(Z3_get_as_array_func_decl(n.ctx.ref(), n.as_ast()), n.ctx)
05598
05599 #########################################
05600 #
05601 # Statistics
05602 #
05603 #########################################
05604 class Statistics:
05605 """Statistics for `Solver.check()`."""
05606
05607 def __init__(self, stats, ctx):
05608 self.stats = stats
05609 self.ctx = ctx
05610 Z3_stats_inc_ref(self.ctx.ref(), self.stats)
05611
05612 def __del__(self):
05613 Z3_stats_dec_ref(self.ctx.ref(), self.stats)
05614
05615 def __repr__(self):
05616 if in_html_mode():
05617 out = io.StringIO()
05618 even = True
05619 out.write(u('<table border="1" cellpadding="2" cellspacing="0">'))
05620 for k, v in self:
05621 if even:
05622 out.write(u('<tr style="background-color:#CFCFCF">'))
05623 even = False
05624 else:
05625 out.write(u('<tr>'))
05626 even = True
05627 out.write(u('<td>%s</td><td>%s</td></tr>' % (k, v)))
05628 out.write(u('</table>'))
05629 return out.getvalue()
05630 else:
05631 return Z3_stats_to_string(self.ctx.ref(), self.stats)
05632
05633 def __len__(self):
05634 """Return the number of statistical counters.
05635
05636 >>> x = Int('x')
05637 >>> s = Then('simplify', 'nlsat').solver()
05638 >>> s.add(x > 0)
05639 >>> s.check()
05640 sat
05641 >>> st = s.statistics()
05642 >>> len(st)
05643 6
05644 """
05645 return int(Z3_stats_size(self.ctx.ref(), self.stats))
05646
05647 def __getitem__(self, idx):
05648 """Return the value of statistical counter at position `idx`. The result is a pair (key, value).
05649
05650 >>> x = Int('x')
05651 >>> s = Then('simplify', 'nlsat').solver()
05652 >>> s.add(x > 0)
05653 >>> s.check()
05654 sat
05655 >>> st = s.statistics()
05656 >>> len(st)
05657 6
05658 >>> st[0]
05659 ('nlsat propagations', 2)
05660 >>> st[1]
05661 ('nlsat stages', 2)
05662 """
05663 if idx >= len(self):
05664 raise IndexError
05665 if Z3_stats_is_uint(self.ctx.ref(), self.stats, idx):
05666 val = int(Z3_stats_get_uint_value(self.ctx.ref(), self.stats, idx))
05667 else:
05668 val = Z3_stats_get_double_value(self.ctx.ref(), self.stats, idx)
05669 return (Z3_stats_get_key(self.ctx.ref(), self.stats, idx), val)
05670
05671 def keys(self):
05672 """Return the list of statistical counters.
05673
05674 >>> x = Int('x')
05675 >>> s = Then('simplify', 'nlsat').solver()
05676 >>> s.add(x > 0)
05677 >>> s.check()
05678 sat
05679 >>> st = s.statistics()
05680 >>> st.keys()
05681 ['nlsat propagations', 'nlsat stages', 'rlimit count', 'max memory', 'memory', 'num allocs']
05682 """
05683 return [Z3_stats_get_key(self.ctx.ref(), self.stats, idx) for idx in range(len(self))]
05684
05685 def get_key_value(self, key):
05686 """Return the value of a particular statistical counter.
05687
05688 >>> x = Int('x')
05689 >>> s = Then('simplify', 'nlsat').solver()
05690 >>> s.add(x > 0)
05691 >>> s.check()
05692 sat
05693 >>> st = s.statistics()
05694 >>> st.get_key_value('nlsat propagations')
05695 2
05696 """
05697 for idx in range(len(self)):
05698 if key == Z3_stats_get_key(self.ctx.ref(), self.stats, idx):
05699 if Z3_stats_is_uint(self.ctx.ref(), self.stats, idx):
05700 return int(Z3_stats_get_uint_value(self.ctx.ref(), self.stats, idx))
05701 else:
05702 return Z3_stats_get_double_value(self.ctx.ref(), self.stats, idx)
05703 raise Z3Exception("unknown key")
05704
05705 def __getattr__(self, name):
05706 """Access the value of statistical using attributes.
05707
05708 Remark: to access a counter containing blank spaces (e.g., 'nlsat propagations'),
05709 we should use '_' (e.g., 'nlsat_propagations').
05710
05711 >>> x = Int('x')
05712 >>> s = Then('simplify', 'nlsat').solver()
05713 >>> s.add(x > 0)
05714 >>> s.check()
05715 sat
05716 >>> st = s.statistics()
05717 >>> st.keys()
05718 ['nlsat propagations', 'nlsat stages', 'rlimit count', 'max memory', 'memory', 'num allocs']
05719 >>> st.nlsat_propagations
05720 2
05721 >>> st.nlsat_stages
05722 2
05723 """
05724 key = name.replace('_', ' ')
05725 try:
05726 return self.get_key_value(key)
05727 except Z3Exception:
05728 raise AttributeError
05729
05730 #########################################
05731 #
05732 # Solver
05733 #
05734 #########################################
05735 class CheckSatResult:
05736 """Represents the result of a satisfiability check: sat, unsat, unknown.
05737
05738 >>> s = Solver()
05739 >>> s.check()
05740 sat
05741 >>> r = s.check()
05742 >>> isinstance(r, CheckSatResult)
05743 True
05744 """
05745
05746 def __init__(self, r):
05747 self.r = r
05748
05749 def __eq__(self, other):
05750 return isinstance(other, CheckSatResult) and self.r == other.r
05751
05752 def __ne__(self, other):
05753 return not self.__eq__(other)
05754
05755 def __repr__(self):
05756 if in_html_mode():
05757 if self.r == Z3_L_TRUE:
05758 return "<b>sat</b>"
05759 elif self.r == Z3_L_FALSE:
05760 return "<b>unsat</b>"
05761 else:
05762 return "<b>unknown</b>"
05763 else:
05764 if self.r == Z3_L_TRUE:
05765 return "sat"
05766 elif self.r == Z3_L_FALSE:
05767 return "unsat"
05768 else:
05769 return "unknown"
05770
05771 sat = CheckSatResult(Z3_L_TRUE)
05772 unsat = CheckSatResult(Z3_L_FALSE)
05773 unknown = CheckSatResult(Z3_L_UNDEF)
05774
05775 class Solver(Z3PPObject):
05776 """Solver API provides methods for implementing the main SMT 2.0 commands: push, pop, check, get-model, etc."""
05777
05778 def __init__(self, solver=None, ctx=None):
05779 assert solver == None or ctx != None
05780 self.ctx = _get_ctx(ctx)
05781 self.solver = None
05782 if solver == None:
05783 self.solver = Z3_mk_solver(self.ctx.ref())
05784 else:
05785 self.solver = solver
05786 Z3_solver_inc_ref(self.ctx.ref(), self.solver)
05787
05788 def __del__(self):
05789 if self.solver != None:
05790 Z3_solver_dec_ref(self.ctx.ref(), self.solver)
05791
05792 def set(self, *args, **keys):
05793 """Set a configuration option. The method `help()` return a string containing all available options.
05794
05795 >>> s = Solver()
05796 >>>
05797 >>> s.set(mbqi=True)
05798 >>> s.set('MBQI', True)
05799 >>> s.set(':mbqi', True)
05800 """
05801 p = args2params(args, keys, self.ctx)
05802 Z3_solver_set_params(self.ctx.ref(), self.solver, p.params)
05803
05804 def push(self):
05805 """Create a backtracking point.
05806
05807 >>> x = Int('x')
05808 >>> s = Solver()
05809 >>> s.add(x > 0)
05810 >>> s
05811 [x > 0]
05812 >>> s.push()
05813 >>> s.add(x < 1)
05814 >>> s
05815 [x > 0, x < 1]
05816 >>> s.check()
05817 unsat
05818 >>> s.pop()
05819 >>> s.check()
05820 sat
05821 >>> s
05822 [x > 0]
05823 """
05824 Z3_solver_push(self.ctx.ref(), self.solver)
05825
05826 def pop(self, num=1):
05827 """Backtrack \c num backtracking points.
05828
05829 >>> x = Int('x')
05830 >>> s = Solver()
05831 >>> s.add(x > 0)
05832 >>> s
05833 [x > 0]
05834 >>> s.push()
05835 >>> s.add(x < 1)
05836 >>> s
05837 [x > 0, x < 1]
05838 >>> s.check()
05839 unsat
05840 >>> s.pop()
05841 >>> s.check()
05842 sat
05843 >>> s
05844 [x > 0]
05845 """
05846 Z3_solver_pop(self.ctx.ref(), self.solver, num)
05847
05848 def reset(self):
05849 """Remove all asserted constraints and backtracking points created using `push()`.
05850
05851 >>> x = Int('x')
05852 >>> s = Solver()
05853 >>> s.add(x > 0)
05854 >>> s
05855 [x > 0]
05856 >>> s.reset()
05857 >>> s
05858 []
05859 """
05860 Z3_solver_reset(self.ctx.ref(), self.solver)
05861
05862 def assert_exprs(self, *args):
05863 """Assert constraints into the solver.
05864
05865 >>> x = Int('x')
05866 >>> s = Solver()
05867 >>> s.assert_exprs(x > 0, x < 2)
05868 >>> s
05869 [x > 0, x < 2]
05870 """
05871 args = _get_args(args)
05872 s = BoolSort(self.ctx)
05873 for arg in args:
05874 if isinstance(arg, Goal) or isinstance(arg, AstVector):
05875 for f in arg:
05876 Z3_solver_assert(self.ctx.ref(), self.solver, f.as_ast())
05877 else:
05878 arg = s.cast(arg)
05879 Z3_solver_assert(self.ctx.ref(), self.solver, arg.as_ast())
05880
05881 def add(self, *args):
05882 """Assert constraints into the solver.
05883
05884 >>> x = Int('x')
05885 >>> s = Solver()
05886 >>> s.add(x > 0, x < 2)
05887 >>> s
05888 [x > 0, x < 2]
05889 """
05890 self.assert_exprs(*args)
05891
05892 def append(self, *args):
05893 """Assert constraints into the solver.
05894
05895 >>> x = Int('x')
05896 >>> s = Solver()
05897 >>> s.append(x > 0, x < 2)
05898 >>> s
05899 [x > 0, x < 2]
05900 """
05901 self.assert_exprs(*args)
05902
05903 def insert(self, *args):
05904 """Assert constraints into the solver.
05905
05906 >>> x = Int('x')
05907 >>> s = Solver()
05908 >>> s.insert(x > 0, x < 2)
05909 >>> s
05910 [x > 0, x < 2]
05911 """
05912 self.assert_exprs(*args)
05913
05914 def assert_and_track(self, a, p):
05915 """Assert constraint `a` and track it in the unsat core using the Boolean constant `p`.
05916
05917 If `p` is a string, it will be automatically converted into a Boolean constant.
05918
05919 >>> x = Int('x')
05920 >>> p3 = Bool('p3')
05921 >>> s = Solver()
05922 >>> s.set(unsat_core=True)
05923 >>> s.assert_and_track(x > 0, 'p1')
05924 >>> s.assert_and_track(x != 1, 'p2')
05925 >>> s.assert_and_track(x < 0, p3)
05926 >>> print(s.check())
05927 unsat
05928 >>> c = s.unsat_core()
05929 >>> len(c)
05930 2
05931 >>> Bool('p1') in c
05932 True
05933 >>> Bool('p2') in c
05934 False
05935 >>> p3 in c
05936 True
05937 """
05938 if isinstance(p, str):
05939 p = Bool(p, self.ctx)
05940 _z3_assert(isinstance(a, BoolRef), "Boolean expression expected")
05941 _z3_assert(isinstance(p, BoolRef) and is_const(p), "Boolean expression expected")
05942 Z3_solver_assert_and_track(self.ctx.ref(), self.solver, a.as_ast(), p.as_ast())
05943
05944 def check(self, *assumptions):
05945 """Check whether the assertions in the given solver plus the optional assumptions are consistent or not.
05946
05947 >>> x = Int('x')
05948 >>> s = Solver()
05949 >>> s.check()
05950 sat
05951 >>> s.add(x > 0, x < 2)
05952 >>> s.check()
05953 sat
05954 >>> s.model()
05955 [x = 1]
05956 >>> s.add(x < 1)
05957 >>> s.check()
05958 unsat
05959 >>> s.reset()
05960 >>> s.add(2**x == 4)
05961 >>> s.check()
05962 unknown
05963 """
05964 assumptions = _get_args(assumptions)
05965 num = len(assumptions)
05966 _assumptions = (Ast * num)()
05967 for i in range(num):
05968 _assumptions[i] = assumptions[i].as_ast()
05969 r = Z3_solver_check_assumptions(self.ctx.ref(), self.solver, num, _assumptions)
05970 return CheckSatResult(r)
05971
05972 def model(self):
05973 """Return a model for the last `check()`.
05974
05975 This function raises an exception if
05976 a model is not available (e.g., last `check()` returned unsat).
05977
05978 >>> s = Solver()
05979 >>> a = Int('a')
05980 >>> s.add(a + 2 == 0)
05981 >>> s.check()
05982 sat
05983 >>> s.model()
05984 [a = -2]
05985 """
05986 try:
05987 return ModelRef(Z3_solver_get_model(self.ctx.ref(), self.solver), self.ctx)
05988 except Z3Exception:
05989 raise Z3Exception("model is not available")
05990
05991 def unsat_core(self):
05992 """Return a subset (as an AST vector) of the assumptions provided to the last check().
05993
05994 These are the assumptions Z3 used in the unsatisfiability proof.
05995 Assumptions are available in Z3. They are used to extract unsatisfiable cores.
05996 They may be also used to "retract" assumptions. Note that, assumptions are not really
05997 "soft constraints", but they can be used to implement them.
05998
05999 >>> p1, p2, p3 = Bools('p1 p2 p3')
06000 >>> x, y = Ints('x y')
06001 >>> s = Solver()
06002 >>> s.add(Implies(p1, x > 0))
06003 >>> s.add(Implies(p2, y > x))
06004 >>> s.add(Implies(p2, y < 1))
06005 >>> s.add(Implies(p3, y > -3))
06006 >>> s.check(p1, p2, p3)
06007 unsat
06008 >>> core = s.unsat_core()
06009 >>> len(core)
06010 2
06011 >>> p1 in core
06012 True
06013 >>> p2 in core
06014 True
06015 >>> p3 in core
06016 False
06017 >>>
06018 >>> s.check(p1, p3)
06019 sat
06020 """
06021 return AstVector(Z3_solver_get_unsat_core(self.ctx.ref(), self.solver), self.ctx)
06022
06023 def proof(self):
06024 """Return a proof for the last `check()`. Proof construction must be enabled."""
06025 return _to_expr_ref(Z3_solver_get_proof(self.ctx.ref(), self.solver), self.ctx)
06026
06027 def assertions(self):
06028 """Return an AST vector containing all added constraints.
06029
06030 >>> s = Solver()
06031 >>> s.assertions()
06032 []
06033 >>> a = Int('a')
06034 >>> s.add(a > 0)
06035 >>> s.add(a < 10)
06036 >>> s.assertions()
06037 [a > 0, a < 10]
06038 """
06039 return AstVector(Z3_solver_get_assertions(self.ctx.ref(), self.solver), self.ctx)
06040
06041 def statistics(self):
06042 """Return statistics for the last `check()`.
06043
06044 >>> s = SimpleSolver()
06045 >>> x = Int('x')
06046 >>> s.add(x > 0)
06047 >>> s.check()
06048 sat
06049 >>> st = s.statistics()
06050 >>> st.get_key_value('final checks')
06051 1
06052 >>> len(st) > 0
06053 True
06054 >>> st[0] != 0
06055 True
06056 """
06057 return Statistics(Z3_solver_get_statistics(self.ctx.ref(), self.solver), self.ctx)
06058
06059 def reason_unknown(self):
06060 """Return a string describing why the last `check()` returned `unknown`.
06061
06062 >>> x = Int('x')
06063 >>> s = SimpleSolver()
06064 >>> s.add(2**x == 4)
06065 >>> s.check()
06066 unknown
06067 >>> s.reason_unknown()
06068 '(incomplete (theory arithmetic))'
06069 """
06070 return Z3_solver_get_reason_unknown(self.ctx.ref(), self.solver)
06071
06072 def help(self):
06073 """Display a string describing all available options."""
06074 print(Z3_solver_get_help(self.ctx.ref(), self.solver))
06075
06076 def param_descrs(self):
06077 """Return the parameter description set."""
06078 return ParamDescrsRef(Z3_solver_get_param_descrs(self.ctx.ref(), self.solver), self.ctx)
06079
06080 def __repr__(self):
06081 """Return a formatted string with all added constraints."""
06082 return obj_to_string(self)
06083
06084 def sexpr(self):
06085 """Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format.
06086
06087 >>> x = Int('x')
06088 >>> s = Solver()
06089 >>> s.add(x > 0)
06090 >>> s.add(x < 2)
06091 >>> r = s.sexpr()
06092 """
06093 return Z3_solver_to_string(self.ctx.ref(), self.solver)
06094
06095 def to_smt2(self):
06096 """return SMTLIB2 formatted benchmark for solver's assertions"""
06097 es = self.assertions()
06098 sz = len(es)
06099 sz1 = sz
06100 if sz1 > 0:
06101 sz1 -= 1
06102 v = (Ast * sz1)()
06103 for i in range(sz1):
06104 v[i] = es[i].as_ast()
06105 if sz > 0:
06106 e = es[sz1].as_ast()
06107 else:
06108 e = BoolVal(True, self.ctx).as_ast()
06109 return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e)
06110
06111 def SolverFor(logic, ctx=None):
06112 """Create a solver customized for the given logic.
06113
06114 The parameter `logic` is a string. It should be contains
06115 the name of a SMT-LIB logic.
06116 See http://www.smtlib.org/ for the name of all available logics.
06117
06118 >>> s = SolverFor("QF_LIA")
06119 >>> x = Int('x')
06120 >>> s.add(x > 0)
06121 >>> s.add(x < 2)
06122 >>> s.check()
06123 sat
06124 >>> s.model()
06125 [x = 1]
06126 """
06127 ctx = _get_ctx(ctx)
06128 logic = to_symbol(logic)
06129 return Solver(Z3_mk_solver_for_logic(ctx.ref(), logic), ctx)
06130
06131 def SimpleSolver(ctx=None):
06132 """Return a simple general purpose solver with limited amount of preprocessing.
06133
06134 >>> s = SimpleSolver()
06135 >>> x = Int('x')
06136 >>> s.add(x > 0)
06137 >>> s.check()
06138 sat
06139 """
06140 ctx = _get_ctx(ctx)
06141 return Solver(Z3_mk_simple_solver(ctx.ref()), ctx)
06142
06143
06144
06145
06146
06147
06148
06149 class Fixedpoint(Z3PPObject):
06150 """Fixedpoint API provides methods for solving with recursive predicates"""
06151
06152 def __init__(self, fixedpoint=None, ctx=None):
06153 assert fixedpoint == None or ctx != None
06154 self.ctx = _get_ctx(ctx)
06155 self.fixedpoint = None
06156 if fixedpoint == None:
06157 self.fixedpoint = Z3_mk_fixedpoint(self.ctx.ref())
06158 else:
06159 self.fixedpoint = fixedpoint
06160 Z3_fixedpoint_inc_ref(self.ctx.ref(), self.fixedpoint)
06161 self.vars = []
06162
06163 def __del__(self):
06164 if self.fixedpoint != None:
06165 Z3_fixedpoint_dec_ref(self.ctx.ref(), self.fixedpoint)
06166
06167 def set(self, *args, **keys):
06168 """Set a configuration option. The method `help()` return a string containing all available options.
06169 """
06170 p = args2params(args, keys, self.ctx)
06171 Z3_fixedpoint_set_params(self.ctx.ref(), self.fixedpoint, p.params)
06172
06173 def help(self):
06174 """Display a string describing all available options."""
06175 print(Z3_fixedpoint_get_help(self.ctx.ref(), self.fixedpoint))
06176
06177 def param_descrs(self):
06178 """Return the parameter description set."""
06179 return ParamDescrsRef(Z3_fixedpoint_get_param_descrs(self.ctx.ref(), self.fixedpoint), self.ctx)
06180
06181 def assert_exprs(self, *args):
06182 """Assert constraints as background axioms for the fixedpoint solver."""
06183 args = _get_args(args)
06184 s = BoolSort(self.ctx)
06185 for arg in args:
06186 if isinstance(arg, Goal) or isinstance(arg, AstVector):
06187 for f in arg:
06188 f = self.abstract(f)
06189 Z3_fixedpoint_assert(self.ctx.ref(), self.fixedpoint, f.as_ast())
06190 else:
06191 arg = s.cast(arg)
06192 arg = self.abstract(arg)
06193 Z3_fixedpoint_assert(self.ctx.ref(), self.fixedpoint, arg.as_ast())
06194
06195 def add(self, *args):
06196 """Assert constraints as background axioms for the fixedpoint solver. Alias for assert_expr."""
06197 self.assert_exprs(*args)
06198
06199 def append(self, *args):
06200 """Assert constraints as background axioms for the fixedpoint solver. Alias for assert_expr."""
06201 self.assert_exprs(*args)
06202
06203 def insert(self, *args):
06204 """Assert constraints as background axioms for the fixedpoint solver. Alias for assert_expr."""
06205 self.assert_exprs(*args)
06206
06207 def add_rule(self, head, body = None, name = None):
06208 """Assert rules defining recursive predicates to the fixedpoint solver.
06209 >>> a = Bool('a')
06210 >>> b = Bool('b')
06211 >>> s = Fixedpoint()
06212 >>> s.register_relation(a.decl())
06213 >>> s.register_relation(b.decl())
06214 >>> s.fact(a)
06215 >>> s.rule(b, a)
06216 >>> s.query(b)
06217 sat
06218 """
06219 if name == None:
06220 name = ""
06221 name = to_symbol(name, self.ctx)
06222 if body == None:
06223 head = self.abstract(head)
06224 Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, head.as_ast(), name)
06225 else:
06226 body = _get_args(body)
06227 f = self.abstract(Implies(And(body, self.ctx),head))
06228 Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name)
06229
06230 def rule(self, head, body = None, name = None):
06231 """Assert rules defining recursive predicates to the fixedpoint solver. Alias for add_rule."""
06232 self.add_rule(head, body, name)
06233
06234 def fact(self, head, name = None):
06235 """Assert facts defining recursive predicates to the fixedpoint solver. Alias for add_rule."""
06236 self.add_rule(head, None, name)
06237
06238 def query(self, *query):
06239 """Query the fixedpoint engine whether formula is derivable.
06240 You can also pass an tuple or list of recursive predicates.
06241 """
06242 query = _get_args(query)
06243 sz = len(query)
06244 if sz >= 1 and isinstance(query[0], FuncDeclRef):
06245 _decls = (FuncDecl * sz)()
06246 i = 0
06247 for q in query:
06248 _decls[i] = q.ast
06249 i = i + 1
06250 r = Z3_fixedpoint_query_relations(self.ctx.ref(), self.fixedpoint, sz, _decls)
06251 else:
06252 if sz == 1:
06253 query = query[0]
06254 else:
06255 query = And(query, self.ctx)
06256 query = self.abstract(query, False)
06257 r = Z3_fixedpoint_query(self.ctx.ref(), self.fixedpoint, query.as_ast())
06258 return CheckSatResult(r)
06259
06260 def push(self):
06261 """create a backtracking point for added rules, facts and assertions"""
06262 Z3_fixedpoint_push(self.ctx.ref(), self.fixedpoint)
06263
06264 def pop(self):
06265 """restore to previously created backtracking point"""
06266 Z3_fixedpoint_pop(self.ctx.ref(), self.fixedpoint)
06267
06268 def update_rule(self, head, body, name):
06269 """update rule"""
06270 if name == None:
06271 name = ""
06272 name = to_symbol(name, self.ctx)
06273 body = _get_args(body)
06274 f = self.abstract(Implies(And(body, self.ctx),head))
06275 Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name)
06276
06277 def get_answer(self):
06278 """Retrieve answer from last query call."""
06279 r = Z3_fixedpoint_get_answer(self.ctx.ref(), self.fixedpoint)
06280 return _to_expr_ref(r, self.ctx)
06281
06282 def get_num_levels(self, predicate):
06283 """Retrieve number of levels used for predicate in PDR engine"""
06284 return Z3_fixedpoint_get_num_levels(self.ctx.ref(), self.fixedpoint, predicate.ast)
06285
06286 def get_cover_delta(self, level, predicate):
06287 """Retrieve properties known about predicate for the level'th unfolding. -1 is treated as the limit (infinity)"""
06288 r = Z3_fixedpoint_get_cover_delta(self.ctx.ref(), self.fixedpoint, level, predicate.ast)
06289 return _to_expr_ref(r, self.ctx)
06290
06291 def add_cover(self, level, predicate, property):
06292 """Add property to predicate for the level'th unfolding. -1 is treated as infinity (infinity)"""
06293 Z3_fixedpoint_add_cover(self.ctx.ref(), self.fixedpoint, level, predicate.ast, property.ast)
06294
06295 def register_relation(self, *relations):
06296 """Register relation as recursive"""
06297 relations = _get_args(relations)
06298 for f in relations:
06299 Z3_fixedpoint_register_relation(self.ctx.ref(), self.fixedpoint, f.ast)
06300
06301 def set_predicate_representation(self, f, *representations):
06302 """Control how relation is represented"""
06303 representations = _get_args(representations)
06304 representations = [to_symbol(s) for s in representations]
06305 sz = len(representations)
06306 args = (Symbol * sz)()
06307 for i in range(sz):
06308 args[i] = representations[i]
06309 Z3_fixedpoint_set_predicate_representation(self.ctx.ref(), self.fixedpoint, f.ast, sz, args)
06310
06311 def parse_string(self, s):
06312 """Parse rules and queries from a string"""
06313 return AstVector(Z3_fixedpoint_from_string(self.ctx.ref(), self.fixedpoint, s), self.ctx)
06314
06315 def parse_file(self, f):
06316 """Parse rules and queries from a file"""
06317 return AstVector(Z3_fixedpoint_from_file(self.ctx.ref(), self.fixedpoint, f), self.ctx)
06318
06319 def get_rules(self):
06320 """retrieve rules that have been added to fixedpoint context"""
06321 return AstVector(Z3_fixedpoint_get_rules(self.ctx.ref(), self.fixedpoint), self.ctx)
06322
06323 def get_assertions(self):
06324 """retrieve assertions that have been added to fixedpoint context"""
06325 return AstVector(Z3_fixedpoint_get_assertions(self.ctx.ref(), self.fixedpoint), self.ctx)
06326
06327 def __repr__(self):
06328 """Return a formatted string with all added rules and constraints."""
06329 return self.sexpr()
06330
06331 def sexpr(self):
06332 """Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format.
06333 """
06334 return Z3_fixedpoint_to_string(self.ctx.ref(), self.fixedpoint, 0, (Ast * 0)())
06335
06336 def to_string(self, queries):
06337 """Return a formatted string (in Lisp-like format) with all added constraints.
06338 We say the string is in s-expression format.
06339 Include also queries.
06340 """
06341 args, len = _to_ast_array(queries)
06342 return Z3_fixedpoint_to_string(self.ctx.ref(), self.fixedpoint, len, args)
06343
06344 def statistics(self):
06345 """Return statistics for the last `query()`.
06346 """
06347 return Statistics(Z3_fixedpoint_get_statistics(self.ctx.ref(), self.fixedpoint), self.ctx)
06348
06349 def reason_unknown(self):
06350 """Return a string describing why the last `query()` returned `unknown`.
06351 """
06352 return Z3_fixedpoint_get_reason_unknown(self.ctx.ref(), self.fixedpoint)
06353
06354 def declare_var(self, *vars):
06355 """Add variable or several variables.
06356 The added variable or variables will be bound in the rules
06357 and queries
06358 """
06359 vars = _get_args(vars)
06360 for v in vars:
06361 self.vars += [v]
06362
06363 def abstract(self, fml, is_forall=True):
06364 if self.vars == []:
06365 return fml
06366 if is_forall:
06367 return ForAll(self.vars, fml)
06368 else:
06369 return Exists(self.vars, fml)
06370
06371
06372
06373
06374
06375
06376
06377
06378 class FiniteDomainSortRef(SortRef):
06379 """Finite domain sort."""
06380
06381 def size(self):
06382 """Return the size of the finite domain sort"""
06383 r = (ctype.c_ulonglong * 1)()
06384 if Z3_get_finite_domain_sort_size(self.ctx_ref(), self.ast(), r):
06385 return r[0]
06386 else:
06387 raise Z3Exception("Failed to retrieve finite domain sort size")
06388
06389 def FiniteDomainSort(name, sz, ctx=None):
06390 """Create a named finite domain sort of a given size sz"""
06391 ctx = _get_ctx(ctx)
06392 return FiniteDomainSortRef(Z3_mk_finite_domain_sort(ctx.ref(), name, sz), ctx)
06393
06394
06395
06396
06397
06398
06399
06400 class OptimizeObjective:
06401 def __init__(self, opt, value, is_max):
06402 self._opt = opt
06403 self._value = value
06404 self._is_max = is_max
06405
06406 def lower(self):
06407 opt = self._opt
06408 return _to_expr_ref(Z3_optimize_get_lower(opt.ctx.ref(), opt.optimize, self._value), opt.ctx)
06409
06410 def upper(self):
06411 opt = self._opt
06412 return _to_expr_ref(Z3_optimize_get_upper(opt.ctx.ref(), opt.optimize, self._value), opt.ctx)
06413
06414 def value(self):
06415 if self._is_max:
06416 return self.upper()
06417 else:
06418 return self.lower()
06419
06420 class Optimize(Z3PPObject):
06421 """Optimize API provides methods for solving using objective functions and weighted soft constraints"""
06422
06423 def __init__(self, ctx=None):
06424 self.ctx = _get_ctx(ctx)
06425 self.optimize = Z3_mk_optimize(self.ctx.ref())
06426 Z3_optimize_inc_ref(self.ctx.ref(), self.optimize)
06427
06428 def __del__(self):
06429 if self.optimize != None:
06430 Z3_optimize_dec_ref(self.ctx.ref(), self.optimize)
06431
06432 def set(self, *args, **keys):
06433 """Set a configuration option. The method `help()` return a string containing all available options.
06434 """
06435 p = args2params(args, keys, self.ctx)
06436 Z3_optimize_set_params(self.ctx.ref(), self.optimize, p.params)
06437
06438 def help(self):
06439 """Display a string describing all available options."""
06440 print(Z3_optimize_get_help(self.ctx.ref(), self.optimize))
06441
06442 def param_descrs(self):
06443 """Return the parameter description set."""
06444 return ParamDescrsRef(Z3_optimize_get_param_descrs(self.ctx.ref(), self.optimize), self.ctx)
06445
06446 def assert_exprs(self, *args):
06447 """Assert constraints as background axioms for the optimize solver."""
06448 args = _get_args(args)
06449 for arg in args:
06450 if isinstance(arg, Goal) or isinstance(arg, AstVector):
06451 for f in arg:
06452 Z3_optimize_assert(self.ctx.ref(), self.optimize, f.as_ast())
06453 else:
06454 Z3_optimize_assert(self.ctx.ref(), self.optimize, arg.as_ast())
06455
06456 def add(self, *args):
06457 """Assert constraints as background axioms for the optimize solver. Alias for assert_expr."""
06458 self.assert_exprs(*args)
06459
06460 def add_soft(self, arg, weight = "1", id = None):
06461 """Add soft constraint with optional weight and optional identifier.
06462 If no weight is supplied, then the penalty for violating the soft constraint
06463 is 1.
06464 Soft constraints are grouped by identifiers. Soft constraints that are
06465 added without identifiers are grouped by default.
06466 """
06467 if _is_int(weight):
06468 weight = "%d" % weight
06469 if not isinstance(weight, str):
06470 raise Z3Exception("weight should be a string or an integer")
06471 if id == None:
06472 id = ""
06473 id = to_symbol(id, self.ctx)
06474 v = Z3_optimize_assert_soft(self.ctx.ref(), self.optimize, arg.as_ast(), weight, id)
06475 return OptimizeObjective(self, v, False)
06476
06477 def maximize(self, arg):
06478 """Add objective function to maximize."""
06479 return OptimizeObjective(self, Z3_optimize_maximize(self.ctx.ref(), self.optimize, arg.as_ast()), True)
06480
06481 def minimize(self, arg):
06482 """Add objective function to minimize."""
06483 return OptimizeObjective(self, Z3_optimize_minimize(self.ctx.ref(), self.optimize, arg.as_ast()), False)
06484
06485 def push(self):
06486 """create a backtracking point for added rules, facts and assertions"""
06487 Z3_optimize_push(self.ctx.ref(), self.optimize)
06488
06489 def pop(self):
06490 """restore to previously created backtracking point"""
06491 Z3_optimize_pop(self.ctx.ref(), self.optimize)
06492
06493 def check(self):
06494 """Check satisfiability while optimizing objective functions."""
06495 return CheckSatResult(Z3_optimize_check(self.ctx.ref(), self.optimize))
06496
06497 def reason_unknown(self):
06498 """Return a string that describes why the last `check()` returned `unknown`."""
06499 return Z3_optimize_get_reason_unknown(self.ctx.ref(), self.optimize)
06500
06501 def model(self):
06502 """Return a model for the last check()."""
06503 try:
06504 return ModelRef(Z3_optimize_get_model(self.ctx.ref(), self.optimize), self.ctx)
06505 except Z3Exception:
06506 raise Z3Exception("model is not available")
06507
06508 def lower(self, obj):
06509 if not isinstance(obj, OptimizeObjective):
06510 raise Z3Exception("Expecting objective handle returned by maximize/minimize")
06511 return obj.lower()
06512
06513 def upper(self, obj):
06514 if not isinstance(obj, OptimizeObjective):
06515 raise Z3Exception("Expecting objective handle returned by maximize/minimize")
06516 return obj.upper()
06517
06518 def __repr__(self):
06519 """Return a formatted string with all added rules and constraints."""
06520 return self.sexpr()
06521
06522 def sexpr(self):
06523 """Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format.
06524 """
06525 return Z3_optimize_to_string(self.ctx.ref(), self.optimize)
06526
06527 def statistics(self):
06528 """Return statistics for the last `query()`.
06529 """
06530 return Statistics(Z3_optimize_get_statistics(self.ctx.ref(), self.optimize), self.ctx)
06531
06532
06533
06534
06535
06536
06537
06538
06539
06540 class ApplyResult(Z3PPObject):
06541 """An ApplyResult object contains the subgoals produced by a tactic when applied to a goal. It also contains model and proof converters."""
06542
06543 def __init__(self, result, ctx):
06544 self.result = result
06545 self.ctx = ctx
06546 Z3_apply_result_inc_ref(self.ctx.ref(), self.result)
06547
06548 def __del__(self):
06549 Z3_apply_result_dec_ref(self.ctx.ref(), self.result)
06550
06551 def __len__(self):
06552 """Return the number of subgoals in `self`.
06553
06554 >>> a, b = Ints('a b')
06555 >>> g = Goal()
06556 >>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b)
06557 >>> t = Tactic('split-clause')
06558 >>> r = t(g)
06559 >>> len(r)
06560 2
06561 >>> t = Then(Tactic('split-clause'), Tactic('split-clause'))
06562 >>> len(t(g))
06563 4
06564 >>> t = Then(Tactic('split-clause'), Tactic('split-clause'), Tactic('propagate-values'))
06565 >>> len(t(g))
06566 1
06567 """
06568 return int(Z3_apply_result_get_num_subgoals(self.ctx.ref(), self.result))
06569
06570 def __getitem__(self, idx):
06571 """Return one of the subgoals stored in ApplyResult object `self`.
06572
06573 >>> a, b = Ints('a b')
06574 >>> g = Goal()
06575 >>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b)
06576 >>> t = Tactic('split-clause')
06577 >>> r = t(g)
06578 >>> r[0]
06579 [a == 0, Or(b == 0, b == 1), a > b]
06580 >>> r[1]
06581 [a == 1, Or(b == 0, b == 1), a > b]
06582 """
06583 if idx >= len(self):
06584 raise IndexError
06585 return Goal(goal=Z3_apply_result_get_subgoal(self.ctx.ref(), self.result, idx), ctx=self.ctx)
06586
06587 def __repr__(self):
06588 return obj_to_string(self)
06589
06590 def sexpr(self):
06591 """Return a textual representation of the s-expression representing the set of subgoals in `self`."""
06592 return Z3_apply_result_to_string(self.ctx.ref(), self.result)
06593
06594 def convert_model(self, model, idx=0):
06595 """Convert a model for a subgoal into a model for the original goal.
06596
06597 >>> a, b = Ints('a b')
06598 >>> g = Goal()
06599 >>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b)
06600 >>> t = Then(Tactic('split-clause'), Tactic('solve-eqs'))
06601 >>> r = t(g)
06602 >>> r[0]
06603 [Or(b == 0, b == 1), Not(0 <= b)]
06604 >>> r[1]
06605 [Or(b == 0, b == 1), Not(1 <= b)]
06606 >>> # Remark: the subgoal r[0] is unsatisfiable
06607 >>> # Creating a solver for solving the second subgoal
06608 >>> s = Solver()
06609 >>> s.add(r[1])
06610 >>> s.check()
06611 sat
06612 >>> s.model()
06613 [b = 0]
06614 >>> # Model s.model() does not assign a value to `a`
06615 >>> # It is a model for subgoal `r[1]`, but not for goal `g`
06616 >>> # The method convert_model creates a model for `g` from a model for `r[1]`.
06617 >>> r.convert_model(s.model(), 1)
06618 [b = 0, a = 1]
06619 """
06620 if __debug__:
06621 _z3_assert(idx < len(self), "index out of bounds")
06622 _z3_assert(isinstance(model, ModelRef), "Z3 Model expected")
06623 return ModelRef(Z3_apply_result_convert_model(self.ctx.ref(), self.result, idx, model.model), self.ctx)
06624
06625 def as_expr(self):
06626 """Return a Z3 expression consisting of all subgoals.
06627
06628 >>> x = Int('x')
06629 >>> g = Goal()
06630 >>> g.add(x > 1)
06631 >>> g.add(Or(x == 2, x == 3))
06632 >>> r = Tactic('simplify')(g)
06633 >>> r
06634 [[Not(x <= 1), Or(x == 2, x == 3)]]
06635 >>> r.as_expr()
06636 And(Not(x <= 1), Or(x == 2, x == 3))
06637 >>> r = Tactic('split-clause')(g)
06638 >>> r
06639 [[x > 1, x == 2], [x > 1, x == 3]]
06640 >>> r.as_expr()
06641 Or(And(x > 1, x == 2), And(x > 1, x == 3))
06642 """
06643 sz = len(self)
06644 if sz == 0:
06645 return BoolVal(False, self.ctx)
06646 elif sz == 1:
06647 return self[0].as_expr()
06648 else:
06649 return Or([ self[i].as_expr() for i in range(len(self)) ])
06650
06651
06652
06653
06654
06655
06656 class Tactic:
06657 """Tactics transform, solver and/or simplify sets of constraints (Goal). A Tactic can be converted into a Solver using the method solver().
06658
06659 Several combinators are available for creating new tactics using the built-in ones: Then(), OrElse(), FailIf(), Repeat(), When(), Cond().
06660 """
06661 def __init__(self, tactic, ctx=None):
06662 self.ctx = _get_ctx(ctx)
06663 self.tactic = None
06664 if isinstance(tactic, TacticObj):
06665 self.tactic = tactic
06666 else:
06667 if __debug__:
06668 _z3_assert(isinstance(tactic, str), "tactic name expected")
06669 try:
06670 self.tactic = Z3_mk_tactic(self.ctx.ref(), str(tactic))
06671 except Z3Exception:
06672 raise Z3Exception("unknown tactic '%s'" % tactic)
06673 Z3_tactic_inc_ref(self.ctx.ref(), self.tactic)
06674
06675 def __del__(self):
06676 if self.tactic != None:
06677 Z3_tactic_dec_ref(self.ctx.ref(), self.tactic)
06678
06679 def solver(self):
06680 """Create a solver using the tactic `self`.
06681
06682 The solver supports the methods `push()` and `pop()`, but it
06683 will always solve each `check()` from scratch.
06684
06685 >>> t = Then('simplify', 'nlsat')
06686 >>> s = t.solver()
06687 >>> x = Real('x')
06688 >>> s.add(x**2 == 2, x > 0)
06689 >>> s.check()
06690 sat
06691 >>> s.model()
06692 [x = 1.4142135623?]
06693 """
06694 return Solver(Z3_mk_solver_from_tactic(self.ctx.ref(), self.tactic), self.ctx)
06695
06696 def apply(self, goal, *arguments, **keywords):
06697 """Apply tactic `self` to the given goal or Z3 Boolean expression using the given options.
06698
06699 >>> x, y = Ints('x y')
06700 >>> t = Tactic('solve-eqs')
06701 >>> t.apply(And(x == 0, y >= x + 1))
06702 [[y >= 1]]
06703 """
06704 if __debug__:
06705 _z3_assert(isinstance(goal, Goal) or isinstance(goal, BoolRef), "Z3 Goal or Boolean expressions expected")
06706 goal = _to_goal(goal)
06707 if len(arguments) > 0 or len(keywords) > 0:
06708 p = args2params(arguments, keywords, self.ctx)
06709 return ApplyResult(Z3_tactic_apply_ex(self.ctx.ref(), self.tactic, goal.goal, p.params), self.ctx)
06710 else:
06711 return ApplyResult(Z3_tactic_apply(self.ctx.ref(), self.tactic, goal.goal), self.ctx)
06712
06713 def __call__(self, goal, *arguments, **keywords):
06714 """Apply tactic `self` to the given goal or Z3 Boolean expression using the given options.
06715
06716 >>> x, y = Ints('x y')
06717 >>> t = Tactic('solve-eqs')
06718 >>> t(And(x == 0, y >= x + 1))
06719 [[y >= 1]]
06720 """
06721 return self.apply(goal, *arguments, **keywords)
06722
06723 def help(self):
06724 """Display a string containing a description of the available options for the `self` tactic."""
06725 print(Z3_tactic_get_help(self.ctx.ref(), self.tactic))
06726
06727 def param_descrs(self):
06728 """Return the parameter description set."""
06729 return ParamDescrsRef(Z3_tactic_get_param_descrs(self.ctx.ref(), self.tactic), self.ctx)
06730
06731 def _to_goal(a):
06732 if isinstance(a, BoolRef):
06733 goal = Goal(ctx = a.ctx)
06734 goal.add(a)
06735 return goal
06736 else:
06737 return a
06738
06739 def _to_tactic(t, ctx=None):
06740 if isinstance(t, Tactic):
06741 return t
06742 else:
06743 return Tactic(t, ctx)
06744
06745 def _and_then(t1, t2, ctx=None):
06746 t1 = _to_tactic(t1, ctx)
06747 t2 = _to_tactic(t2, ctx)
06748 if __debug__:
06749 _z3_assert(t1.ctx == t2.ctx, "Context mismatch")
06750 return Tactic(Z3_tactic_and_then(t1.ctx.ref(), t1.tactic, t2.tactic), t1.ctx)
06751
06752 def _or_else(t1, t2, ctx=None):
06753 t1 = _to_tactic(t1, ctx)
06754 t2 = _to_tactic(t2, ctx)
06755 if __debug__:
06756 _z3_assert(t1.ctx == t2.ctx, "Context mismatch")
06757 return Tactic(Z3_tactic_or_else(t1.ctx.ref(), t1.tactic, t2.tactic), t1.ctx)
06758
06759 def AndThen(*ts, **ks):
06760 """Return a tactic that applies the tactics in `*ts` in sequence.
06761
06762 >>> x, y = Ints('x y')
06763 >>> t = AndThen(Tactic('simplify'), Tactic('solve-eqs'))
06764 >>> t(And(x == 0, y > x + 1))
06765 [[Not(y <= 1)]]
06766 >>> t(And(x == 0, y > x + 1)).as_expr()
06767 Not(y <= 1)
06768 """
06769 if __debug__:
06770 _z3_assert(len(ts) >= 2, "At least two arguments expected")
06771 ctx = ks.get('ctx', None)
06772 num = len(ts)
06773 r = ts[0]
06774 for i in range(num - 1):
06775 r = _and_then(r, ts[i+1], ctx)
06776 return r
06777
06778 def Then(*ts, **ks):
06779 """Return a tactic that applies the tactics in `*ts` in sequence. Shorthand for AndThen(*ts, **ks).
06780
06781 >>> x, y = Ints('x y')
06782 >>> t = Then(Tactic('simplify'), Tactic('solve-eqs'))
06783 >>> t(And(x == 0, y > x + 1))
06784 [[Not(y <= 1)]]
06785 >>> t(And(x == 0, y > x + 1)).as_expr()
06786 Not(y <= 1)
06787 """
06788 return AndThen(*ts, **ks)
06789
06790 def OrElse(*ts, **ks):
06791 """Return a tactic that applies the tactics in `*ts` until one of them succeeds (it doesn't fail).
06792
06793 >>> x = Int('x')
06794 >>> t = OrElse(Tactic('split-clause'), Tactic('skip'))
06795 >>> # Tactic split-clause fails if there is no clause in the given goal.
06796 >>> t(x == 0)
06797 [[x == 0]]
06798 >>> t(Or(x == 0, x == 1))
06799 [[x == 0], [x == 1]]
06800 """
06801 if __debug__:
06802 _z3_assert(len(ts) >= 2, "At least two arguments expected")
06803 ctx = ks.get('ctx', None)
06804 num = len(ts)
06805 r = ts[0]
06806 for i in range(num - 1):
06807 r = _or_else(r, ts[i+1], ctx)
06808 return r
06809
06810 def ParOr(*ts, **ks):
06811 """Return a tactic that applies the tactics in `*ts` in parallel until one of them succeeds (it doesn't fail).
06812
06813 >>> x = Int('x')
06814 >>> t = ParOr(Tactic('simplify'), Tactic('fail'))
06815 >>> t(x + 1 == 2)
06816 [[x == 1]]
06817 """
06818 if __debug__:
06819 _z3_assert(len(ts) >= 2, "At least two arguments expected")
06820 ctx = _get_ctx(ks.get('ctx', None))
06821 ts = [ _to_tactic(t, ctx) for t in ts ]
06822 sz = len(ts)
06823 _args = (TacticObj * sz)()
06824 for i in range(sz):
06825 _args[i] = ts[i].tactic
06826 return Tactic(Z3_tactic_par_or(ctx.ref(), sz, _args), ctx)
06827
06828 def ParThen(t1, t2, ctx=None):
06829 """Return a tactic that applies t1 and then t2 to every subgoal produced by t1. The subgoals are processed in parallel.
06830
06831 >>> x, y = Ints('x y')
06832 >>> t = ParThen(Tactic('split-clause'), Tactic('propagate-values'))
06833 >>> t(And(Or(x == 1, x == 2), y == x + 1))
06834 [[x == 1, y == 2], [x == 2, y == 3]]
06835 """
06836 t1 = _to_tactic(t1, ctx)
06837 t2 = _to_tactic(t2, ctx)
06838 if __debug__:
06839 _z3_assert(t1.ctx == t2.ctx, "Context mismatch")
06840 return Tactic(Z3_tactic_par_and_then(t1.ctx.ref(), t1.tactic, t2.tactic), t1.ctx)
06841
06842 def ParAndThen(t1, t2, ctx=None):
06843 """Alias for ParThen(t1, t2, ctx)."""
06844 return ParThen(t1, t2, ctx)
06845
06846 def With(t, *args, **keys):
06847 """Return a tactic that applies tactic `t` using the given configuration options.
06848
06849 >>> x, y = Ints('x y')
06850 >>> t = With(Tactic('simplify'), som=True)
06851 >>> t((x + 1)*(y + 2) == 0)
06852 [[2*x + y + x*y == -2]]
06853 """
06854 ctx = keys.get('ctx', None)
06855 t = _to_tactic(t, ctx)
06856 p = args2params(args, keys, t.ctx)
06857 return Tactic(Z3_tactic_using_params(t.ctx.ref(), t.tactic, p.params), t.ctx)
06858
06859 def Repeat(t, max=4294967295, ctx=None):
06860 """Return a tactic that keeps applying `t` until the goal is not modified anymore or the maximum number of iterations `max` is reached.
06861
06862 >>> x, y = Ints('x y')
06863 >>> c = And(Or(x == 0, x == 1), Or(y == 0, y == 1), x > y)
06864 >>> t = Repeat(OrElse(Tactic('split-clause'), Tactic('skip')))
06865 >>> r = t(c)
06866 >>> for subgoal in r: print(subgoal)
06867 [x == 0, y == 0, x > y]
06868 [x == 0, y == 1, x > y]
06869 [x == 1, y == 0, x > y]
06870 [x == 1, y == 1, x > y]
06871 >>> t = Then(t, Tactic('propagate-values'))
06872 >>> t(c)
06873 [[x == 1, y == 0]]
06874 """
06875 t = _to_tactic(t, ctx)
06876 return Tactic(Z3_tactic_repeat(t.ctx.ref(), t.tactic, max), t.ctx)
06877
06878 def TryFor(t, ms, ctx=None):
06879 """Return a tactic that applies `t` to a given goal for `ms` milliseconds.
06880
06881 If `t` does not terminate in `ms` milliseconds, then it fails.
06882 """
06883 t = _to_tactic(t, ctx)
06884 return Tactic(Z3_tactic_try_for(t.ctx.ref(), t.tactic, ms), t.ctx)
06885
06886 def tactics(ctx=None):
06887 """Return a list of all available tactics in Z3.
06888
06889 >>> l = tactics()
06890 >>> l.count('simplify') == 1
06891 True
06892 """
06893 ctx = _get_ctx(ctx)
06894 return [ Z3_get_tactic_name(ctx.ref(), i) for i in range(Z3_get_num_tactics(ctx.ref())) ]
06895
06896 def tactic_description(name, ctx=None):
06897 """Return a short description for the tactic named `name`.
06898
06899 >>> d = tactic_description('simplify')
06900 """
06901 ctx = _get_ctx(ctx)
06902 return Z3_tactic_get_descr(ctx.ref(), name)
06903
06904 def describe_tactics():
06905 """Display a (tabular) description of all available tactics in Z3."""
06906 if in_html_mode():
06907 even = True
06908 print('<table border="1" cellpadding="2" cellspacing="0">')
06909 for t in tactics():
06910 if even:
06911 print('<tr style="background-color:#CFCFCF">')
06912 even = False
06913 else:
06914 print('<tr>')
06915 even = True
06916 print('<td>%s</td><td>%s</td></tr>' % (t, insert_line_breaks(tactic_description(t), 40)))
06917 print('</table>')
06918 else:
06919 for t in tactics():
06920 print('%s : %s' % (t, tactic_description(t)))
06921
06922 class Probe:
06923 """Probes are used to inspect a goal (aka problem) and collect information that may be used to decide which solver and/or preprocessing step will be used."""
06924 def __init__(self, probe, ctx=None):
06925 self.ctx = _get_ctx(ctx)
06926 self.probe = None
06927 if isinstance(probe, ProbeObj):
06928 self.probe = probe
06929 elif isinstance(probe, float):
06930 self.probe = Z3_probe_const(self.ctx.ref(), probe)
06931 elif _is_int(probe):
06932 self.probe = Z3_probe_const(self.ctx.ref(), float(probe))
06933 elif isinstance(probe, bool):
06934 if probe:
06935 self.probe = Z3_probe_const(self.ctx.ref(), 1.0)
06936 else:
06937 self.probe = Z3_probe_const(self.ctx.ref(), 0.0)
06938 else:
06939 if __debug__:
06940 _z3_assert(isinstance(probe, str), "probe name expected")
06941 try:
06942 self.probe = Z3_mk_probe(self.ctx.ref(), probe)
06943 except Z3Exception:
06944 raise Z3Exception("unknown probe '%s'" % probe)
06945 Z3_probe_inc_ref(self.ctx.ref(), self.probe)
06946
06947 def __del__(self):
06948 if self.probe != None:
06949 Z3_probe_dec_ref(self.ctx.ref(), self.probe)
06950
06951 def __lt__(self, other):
06952 """Return a probe that evaluates to "true" when the value returned by `self` is less than the value returned by `other`.
06953
06954 >>> p = Probe('size') < 10
06955 >>> x = Int('x')
06956 >>> g = Goal()
06957 >>> g.add(x > 0)
06958 >>> g.add(x < 10)
06959 >>> p(g)
06960 1.0
06961 """
06962 return Probe(Z3_probe_lt(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx)
06963
06964 def __gt__(self, other):
06965 """Return a probe that evaluates to "true" when the value returned by `self` is greater than the value returned by `other`.
06966
06967 >>> p = Probe('size') > 10
06968 >>> x = Int('x')
06969 >>> g = Goal()
06970 >>> g.add(x > 0)
06971 >>> g.add(x < 10)
06972 >>> p(g)
06973 0.0
06974 """
06975 return Probe(Z3_probe_gt(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx)
06976
06977 def __le__(self, other):
06978 """Return a probe that evaluates to "true" when the value returned by `self` is less than or equal to the value returned by `other`.
06979
06980 >>> p = Probe('size') <= 2
06981 >>> x = Int('x')
06982 >>> g = Goal()
06983 >>> g.add(x > 0)
06984 >>> g.add(x < 10)
06985 >>> p(g)
06986 1.0
06987 """
06988 return Probe(Z3_probe_le(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx)
06989
06990 def __ge__(self, other):
06991 """Return a probe that evaluates to "true" when the value returned by `self` is greater than or equal to the value returned by `other`.
06992
06993 >>> p = Probe('size') >= 2
06994 >>> x = Int('x')
06995 >>> g = Goal()
06996 >>> g.add(x > 0)
06997 >>> g.add(x < 10)
06998 >>> p(g)
06999 1.0
07000 """
07001 return Probe(Z3_probe_ge(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx)
07002
07003 def __eq__(self, other):
07004 """Return a probe that evaluates to "true" when the value returned by `self` is equal to the value returned by `other`.
07005
07006 >>> p = Probe('size') == 2
07007 >>> x = Int('x')
07008 >>> g = Goal()
07009 >>> g.add(x > 0)
07010 >>> g.add(x < 10)
07011 >>> p(g)
07012 1.0
07013 """
07014 return Probe(Z3_probe_eq(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx)
07015
07016 def __ne__(self, other):
07017 """Return a probe that evaluates to "true" when the value returned by `self` is not equal to the value returned by `other`.
07018
07019 >>> p = Probe('size') != 2
07020 >>> x = Int('x')
07021 >>> g = Goal()
07022 >>> g.add(x > 0)
07023 >>> g.add(x < 10)
07024 >>> p(g)
07025 0.0
07026 """
07027 p = self.__eq__(other)
07028 return Probe(Z3_probe_not(self.ctx.ref(), p.probe), self.ctx)
07029
07030 def __call__(self, goal):
07031 """Evaluate the probe `self` in the given goal.
07032
07033 >>> p = Probe('size')
07034 >>> x = Int('x')
07035 >>> g = Goal()
07036 >>> g.add(x > 0)
07037 >>> g.add(x < 10)
07038 >>> p(g)
07039 2.0
07040 >>> g.add(x < 20)
07041 >>> p(g)
07042 3.0
07043 >>> p = Probe('num-consts')
07044 >>> p(g)
07045 1.0
07046 >>> p = Probe('is-propositional')
07047 >>> p(g)
07048 0.0
07049 >>> p = Probe('is-qflia')
07050 >>> p(g)
07051 1.0
07052 """
07053 if __debug__:
07054 _z3_assert(isinstance(goal, Goal) or isinstance(goal, BoolRef), "Z3 Goal or Boolean expression expected")
07055 goal = _to_goal(goal)
07056 return Z3_probe_apply(self.ctx.ref(), self.probe, goal.goal)
07057
07058 def is_probe(p):
07059 """Return `True` if `p` is a Z3 probe.
07060
07061 >>> is_probe(Int('x'))
07062 False
07063 >>> is_probe(Probe('memory'))
07064 True
07065 """
07066 return isinstance(p, Probe)
07067
07068 def _to_probe(p, ctx=None):
07069 if is_probe(p):
07070 return p
07071 else:
07072 return Probe(p, ctx)
07073
07074 def probes(ctx=None):
07075 """Return a list of all available probes in Z3.
07076
07077 >>> l = probes()
07078 >>> l.count('memory') == 1
07079 True
07080 """
07081 ctx = _get_ctx(ctx)
07082 return [ Z3_get_probe_name(ctx.ref(), i) for i in range(Z3_get_num_probes(ctx.ref())) ]
07083
07084 def probe_description(name, ctx=None):
07085 """Return a short description for the probe named `name`.
07086
07087 >>> d = probe_description('memory')
07088 """
07089 ctx = _get_ctx(ctx)
07090 return Z3_probe_get_descr(ctx.ref(), name)
07091
07092 def describe_probes():
07093 """Display a (tabular) description of all available probes in Z3."""
07094 if in_html_mode():
07095 even = True
07096 print('<table border="1" cellpadding="2" cellspacing="0">')
07097 for p in probes():
07098 if even:
07099 print('<tr style="background-color:#CFCFCF">')
07100 even = False
07101 else:
07102 print('<tr>')
07103 even = True
07104 print('<td>%s</td><td>%s</td></tr>' % (p, insert_line_breaks(probe_description(p), 40)))
07105 print('</table>')
07106 else:
07107 for p in probes():
07108 print('%s : %s' % (p, probe_description(p)))
07109
07110 def _probe_nary(f, args, ctx):
07111 if __debug__:
07112 _z3_assert(len(args) > 0, "At least one argument expected")
07113 num = len(args)
07114 r = _to_probe(args[0], ctx)
07115 for i in range(num - 1):
07116 r = Probe(f(ctx.ref(), r.probe, _to_probe(args[i+1], ctx).probe), ctx)
07117 return r
07118
07119 def _probe_and(args, ctx):
07120 return _probe_nary(Z3_probe_and, args, ctx)
07121
07122 def _probe_or(args, ctx):
07123 return _probe_nary(Z3_probe_or, args, ctx)
07124
07125 def FailIf(p, ctx=None):
07126 """Return a tactic that fails if the probe `p` evaluates to true. Otherwise, it returns the input goal unmodified.
07127
07128 In the following example, the tactic applies 'simplify' if and only if there are more than 2 constraints in the goal.
07129
07130 >>> t = OrElse(FailIf(Probe('size') > 2), Tactic('simplify'))
07131 >>> x, y = Ints('x y')
07132 >>> g = Goal()
07133 >>> g.add(x > 0)
07134 >>> g.add(y > 0)
07135 >>> t(g)
07136 [[x > 0, y > 0]]
07137 >>> g.add(x == y + 1)
07138 >>> t(g)
07139 [[Not(x <= 0), Not(y <= 0), x == 1 + y]]
07140 """
07141 p = _to_probe(p, ctx)
07142 return Tactic(Z3_tactic_fail_if(p.ctx.ref(), p.probe), p.ctx)
07143
07144 def When(p, t, ctx=None):
07145 """Return a tactic that applies tactic `t` only if probe `p` evaluates to true. Otherwise, it returns the input goal unmodified.
07146
07147 >>> t = When(Probe('size') > 2, Tactic('simplify'))
07148 >>> x, y = Ints('x y')
07149 >>> g = Goal()
07150 >>> g.add(x > 0)
07151 >>> g.add(y > 0)
07152 >>> t(g)
07153 [[x > 0, y > 0]]
07154 >>> g.add(x == y + 1)
07155 >>> t(g)
07156 [[Not(x <= 0), Not(y <= 0), x == 1 + y]]
07157 """
07158 p = _to_probe(p, ctx)
07159 t = _to_tactic(t, ctx)
07160 return Tactic(Z3_tactic_when(t.ctx.ref(), p.probe, t.tactic), t.ctx)
07161
07162 def Cond(p, t1, t2, ctx=None):
07163 """Return a tactic that applies tactic `t1` to a goal if probe `p` evaluates to true, and `t2` otherwise.
07164
07165 >>> t = Cond(Probe('is-qfnra'), Tactic('qfnra'), Tactic('smt'))
07166 """
07167 p = _to_probe(p, ctx)
07168 t1 = _to_tactic(t1, ctx)
07169 t2 = _to_tactic(t2, ctx)
07170 return Tactic(Z3_tactic_cond(t1.ctx.ref(), p.probe, t1.tactic, t2.tactic), t1.ctx)
07171
07172
07173
07174
07175
07176
07177
07178 def simplify(a, *arguments, **keywords):
07179 """Simplify the expression `a` using the given options.
07180
07181 This function has many options. Use `help_simplify` to obtain the complete list.
07182
07183 >>> x = Int('x')
07184 >>> y = Int('y')
07185 >>> simplify(x + 1 + y + x + 1)
07186 2 + 2*x + y
07187 >>> simplify((x + 1)*(y + 1), som=True)
07188 1 + x + y + x*y
07189 >>> simplify(Distinct(x, y, 1), blast_distinct=True)
07190 And(Not(x == y), Not(x == 1), Not(y == 1))
07191 >>> simplify(And(x == 0, y == 1), elim_and=True)
07192 Not(Or(Not(x == 0), Not(y == 1)))
07193 """
07194 if __debug__:
07195 _z3_assert(is_expr(a), "Z3 expression expected")
07196 if len(arguments) > 0 or len(keywords) > 0:
07197 p = args2params(arguments, keywords, a.ctx)
07198 return _to_expr_ref(Z3_simplify_ex(a.ctx_ref(), a.as_ast(), p.params), a.ctx)
07199 else:
07200 return _to_expr_ref(Z3_simplify(a.ctx_ref(), a.as_ast()), a.ctx)
07201
07202 def help_simplify():
07203 """Return a string describing all options available for Z3 `simplify` procedure."""
07204 print(Z3_simplify_get_help(main_ctx().ref()))
07205
07206 def simplify_param_descrs():
07207 """Return the set of parameter descriptions for Z3 `simplify` procedure."""
07208 return ParamDescrsRef(Z3_simplify_get_param_descrs(main_ctx().ref()), main_ctx())
07209
07210 def substitute(t, *m):
07211 """Apply substitution m on t, m is a list of pairs of the form (from, to). Every occurrence in t of from is replaced with to.
07212
07213 >>> x = Int('x')
07214 >>> y = Int('y')
07215 >>> substitute(x + 1, (x, y + 1))
07216 y + 1 + 1
07217 >>> f = Function('f', IntSort(), IntSort())
07218 >>> substitute(f(x) + f(y), (f(x), IntVal(1)), (f(y), IntVal(1)))
07219 1 + 1
07220 """
07221 if isinstance(m, tuple):
07222 m1 = _get_args(m)
07223 if isinstance(m1, list):
07224 m = m1
07225 if __debug__:
07226 _z3_assert(is_expr(t), "Z3 expression expected")
07227 _z3_assert(all([isinstance(p, tuple) and is_expr(p[0]) and is_expr(p[1]) and p[0].sort().eq(p[1].sort()) for p in m]), "Z3 invalid substitution, expression pairs expected.")
07228 num = len(m)
07229 _from = (Ast * num)()
07230 _to = (Ast * num)()
07231 for i in range(num):
07232 _from[i] = m[i][0].as_ast()
07233 _to[i] = m[i][1].as_ast()
07234 return _to_expr_ref(Z3_substitute(t.ctx.ref(), t.as_ast(), num, _from, _to), t.ctx)
07235
07236 def substitute_vars(t, *m):
07237 """Substitute the free variables in t with the expression in m.
07238
07239 >>> v0 = Var(0, IntSort())
07240 >>> v1 = Var(1, IntSort())
07241 >>> x = Int('x')
07242 >>> f = Function('f', IntSort(), IntSort(), IntSort())
07243 >>> # replace v0 with x+1 and v1 with x
07244 >>> substitute_vars(f(v0, v1), x + 1, x)
07245 f(x + 1, x)
07246 """
07247 if __debug__:
07248 _z3_assert(is_expr(t), "Z3 expression expected")
07249 _z3_assert(all([is_expr(n) for n in m]), "Z3 invalid substitution, list of expressions expected.")
07250 num = len(m)
07251 _to = (Ast * num)()
07252 for i in range(num):
07253 _to[i] = m[i].as_ast()
07254 return _to_expr_ref(Z3_substitute_vars(t.ctx.ref(), t.as_ast(), num, _to), t.ctx)
07255
07256 def Sum(*args):
07257 """Create the sum of the Z3 expressions.
07258
07259 >>> a, b, c = Ints('a b c')
07260 >>> Sum(a, b, c)
07261 a + b + c
07262 >>> Sum([a, b, c])
07263 a + b + c
07264 >>> A = IntVector('a', 5)
07265 >>> Sum(A)
07266 a__0 + a__1 + a__2 + a__3 + a__4
07267 """
07268 args = _get_args(args)
07269 if __debug__:
07270 _z3_assert(len(args) > 0, "Non empty list of arguments expected")
07271 ctx = _ctx_from_ast_arg_list(args)
07272 if __debug__:
07273 _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression")
07274 args = _coerce_expr_list(args, ctx)
07275 if is_bv(args[0]):
07276 return _reduce(lambda a, b: a + b, args, 0)
07277 else:
07278 _args, sz = _to_ast_array(args)
07279 return ArithRef(Z3_mk_add(ctx.ref(), sz, _args), ctx)
07280
07281 def Product(*args):
07282 """Create the product of the Z3 expressions.
07283
07284 >>> a, b, c = Ints('a b c')
07285 >>> Product(a, b, c)
07286 a*b*c
07287 >>> Product([a, b, c])
07288 a*b*c
07289 >>> A = IntVector('a', 5)
07290 >>> Product(A)
07291 a__0*a__1*a__2*a__3*a__4
07292 """
07293 args = _get_args(args)
07294 if __debug__:
07295 _z3_assert(len(args) > 0, "Non empty list of arguments expected")
07296 ctx = _ctx_from_ast_arg_list(args)
07297 if __debug__:
07298 _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression")
07299 args = _coerce_expr_list(args, ctx)
07300 if is_bv(args[0]):
07301 return _reduce(lambda a, b: a * b, args, 1)
07302 else:
07303 _args, sz = _to_ast_array(args)
07304 return ArithRef(Z3_mk_mul(ctx.ref(), sz, _args), ctx)
07305
07306 def solve(*args, **keywords):
07307 """Solve the constraints `*args`.
07308
07309 This is a simple function for creating demonstrations. It creates a solver,
07310 configure it using the options in `keywords`, adds the constraints
07311 in `args`, and invokes check.
07312
07313 >>> a = Int('a')
07314 >>> solve(a > 0, a < 2)
07315 [a = 1]
07316 """
07317 s = Solver()
07318 s.set(**keywords)
07319 s.add(*args)
07320 if keywords.get('show', False):
07321 print(s)
07322 r = s.check()
07323 if r == unsat:
07324 print("no solution")
07325 elif r == unknown:
07326 print("failed to solve")
07327 try:
07328 print(s.model())
07329 except Z3Exception:
07330 return
07331 else:
07332 print(s.model())
07333
07334 def solve_using(s, *args, **keywords):
07335 """Solve the constraints `*args` using solver `s`.
07336
07337 This is a simple function for creating demonstrations. It is similar to `solve`,
07338 but it uses the given solver `s`.
07339 It configures solver `s` using the options in `keywords`, adds the constraints
07340 in `args`, and invokes check.
07341 """
07342 if __debug__:
07343 _z3_assert(isinstance(s, Solver), "Solver object expected")
07344 s.set(**keywords)
07345 s.add(*args)
07346 if keywords.get('show', False):
07347 print("Problem:")
07348 print(s)
07349 r = s.check()
07350 if r == unsat:
07351 print("no solution")
07352 elif r == unknown:
07353 print("failed to solve")
07354 try:
07355 print(s.model())
07356 except Z3Exception:
07357 return
07358 else:
07359 if keywords.get('show', False):
07360 print("Solution:")
07361 print(s.model())
07362
07363 def prove(claim, **keywords):
07364 """Try to prove the given claim.
07365
07366 This is a simple function for creating demonstrations. It tries to prove
07367 `claim` by showing the negation is unsatisfiable.
07368
07369 >>> p, q = Bools('p q')
07370 >>> prove(Not(And(p, q)) == Or(Not(p), Not(q)))
07371 proved
07372 """
07373 if __debug__:
07374 _z3_assert(is_bool(claim), "Z3 Boolean expression expected")
07375 s = Solver()
07376 s.set(**keywords)
07377 s.add(Not(claim))
07378 if keywords.get('show', False):
07379 print(s)
07380 r = s.check()
07381 if r == unsat:
07382 print("proved")
07383 elif r == unknown:
07384 print("failed to prove")
07385 print(s.model())
07386 else:
07387 print("counterexample")
07388 print(s.model())
07389
07390 def _solve_html(*args, **keywords):
07391 """Version of funcion `solve` used in RiSE4Fun."""
07392 s = Solver()
07393 s.set(**keywords)
07394 s.add(*args)
07395 if keywords.get('show', False):
07396 print("<b>Problem:</b>")
07397 print(s)
07398 r = s.check()
07399 if r == unsat:
07400 print("<b>no solution</b>")
07401 elif r == unknown:
07402 print("<b>failed to solve</b>")
07403 try:
07404 print(s.model())
07405 except Z3Exception:
07406 return
07407 else:
07408 if keywords.get('show', False):
07409 print("<b>Solution:</b>")
07410 print(s.model())
07411
07412 def _solve_using_html(s, *args, **keywords):
07413 """Version of funcion `solve_using` used in RiSE4Fun."""
07414 if __debug__:
07415 _z3_assert(isinstance(s, Solver), "Solver object expected")
07416 s.set(**keywords)
07417 s.add(*args)
07418 if keywords.get('show', False):
07419 print("<b>Problem:</b>")
07420 print(s)
07421 r = s.check()
07422 if r == unsat:
07423 print("<b>no solution</b>")
07424 elif r == unknown:
07425 print("<b>failed to solve</b>")
07426 try:
07427 print(s.model())
07428 except Z3Exception:
07429 return
07430 else:
07431 if keywords.get('show', False):
07432 print("<b>Solution:</b>")
07433 print(s.model())
07434
07435 def _prove_html(claim, **keywords):
07436 """Version of funcion `prove` used in RiSE4Fun."""
07437 if __debug__:
07438 _z3_assert(is_bool(claim), "Z3 Boolean expression expected")
07439 s = Solver()
07440 s.set(**keywords)
07441 s.add(Not(claim))
07442 if keywords.get('show', False):
07443 print(s)
07444 r = s.check()
07445 if r == unsat:
07446 print("<b>proved</b>")
07447 elif r == unknown:
07448 print("<b>failed to prove</b>")
07449 print(s.model())
07450 else:
07451 print("<b>counterexample</b>")
07452 print(s.model())
07453
07454 def _dict2sarray(sorts, ctx):
07455 sz = len(sorts)
07456 _names = (Symbol * sz)()
07457 _sorts = (Sort * sz) ()
07458 i = 0
07459 for k in sorts:
07460 v = sorts[k]
07461 if __debug__:
07462 _z3_assert(isinstance(k, str), "String expected")
07463 _z3_assert(is_sort(v), "Z3 sort expected")
07464 _names[i] = to_symbol(k, ctx)
07465 _sorts[i] = v.ast
07466 i = i + 1
07467 return sz, _names, _sorts
07468
07469 def _dict2darray(decls, ctx):
07470 sz = len(decls)
07471 _names = (Symbol * sz)()
07472 _decls = (FuncDecl * sz) ()
07473 i = 0
07474 for k in decls:
07475 v = decls[k]
07476 if __debug__:
07477 _z3_assert(isinstance(k, str), "String expected")
07478 _z3_assert(is_func_decl(v) or is_const(v), "Z3 declaration or constant expected")
07479 _names[i] = to_symbol(k, ctx)
07480 if is_const(v):
07481 _decls[i] = v.decl().ast
07482 else:
07483 _decls[i] = v.ast
07484 i = i + 1
07485 return sz, _names, _decls
07486
07487 def parse_smt2_string(s, sorts={}, decls={}, ctx=None):
07488 """Parse a string in SMT 2.0 format using the given sorts and decls.
07489
07490 The arguments sorts and decls are Python dictionaries used to initialize
07491 the symbol table used for the SMT 2.0 parser.
07492
07493 >>> parse_smt2_string('(declare-const x Int) (assert (> x 0)) (assert (< x 10))')
07494 And(x > 0, x < 10)
07495 >>> x, y = Ints('x y')
07496 >>> f = Function('f', IntSort(), IntSort())
07497 >>> parse_smt2_string('(assert (> (+ foo (g bar)) 0))', decls={ 'foo' : x, 'bar' : y, 'g' : f})
07498 x + f(y) > 0
07499 >>> parse_smt2_string('(declare-const a U) (assert (> a 0))', sorts={ 'U' : IntSort() })
07500 a > 0
07501 """
07502 ctx = _get_ctx(ctx)
07503 ssz, snames, ssorts = _dict2sarray(sorts, ctx)
07504 dsz, dnames, ddecls = _dict2darray(decls, ctx)
07505 return _to_expr_ref(Z3_parse_smtlib2_string(ctx.ref(), s, ssz, snames, ssorts, dsz, dnames, ddecls), ctx)
07506
07507 def parse_smt2_file(f, sorts={}, decls={}, ctx=None):
07508 """Parse a file in SMT 2.0 format using the given sorts and decls.
07509
07510 This function is similar to parse_smt2_string().
07511 """
07512 ctx = _get_ctx(ctx)
07513 ssz, snames, ssorts = _dict2sarray(sorts, ctx)
07514 dsz, dnames, ddecls = _dict2darray(decls, ctx)
07515 return _to_expr_ref(Z3_parse_smtlib2_file(ctx.ref(), f, ssz, snames, ssorts, dsz, dnames, ddecls), ctx)
07516
07517 def Interpolant(a,ctx=None):
07518 """Create an interpolation operator.
07519
07520 The argument is an interpolation pattern (see tree_interpolant).
07521
07522 >>> x = Int('x')
07523 >>> print Interpolant(x>0)
07524 interp(x > 0)
07525 """
07526 ctx = _get_ctx(_ctx_from_ast_arg_list([a], ctx))
07527 s = BoolSort(ctx)
07528 a = s.cast(a)
07529 return BoolRef(Z3_mk_interpolant(ctx.ref(), a.as_ast()), ctx)
07530
07531 def tree_interpolant(pat,p=None,ctx=None):
07532 """Compute interpolant for a tree of formulas.
07533
07534 The input is an interpolation pattern over a set of formulas C.
07535 The pattern pat is a formula combining the formulas in C using
07536 logical conjunction and the "interp" operator (see Interp). This
07537 interp operator is logically the identity operator. It marks the
07538 sub-formulas of the pattern for which interpolants should be
07539 computed. The interpolant is a map sigma from marked subformulas
07540 to formulas, such that, for each marked subformula phi of pat
07541 (where phi sigma is phi with sigma(psi) substituted for each
07542 subformula psi of phi such that psi in dom(sigma)):
07543
07544 1) phi sigma implies sigma(phi), and
07545
07546 2) sigma(phi) is in the common uninterpreted vocabulary between
07547 the formulas of C occurring in phi and those not occurring in
07548 phi
07549
07550 and moreover pat sigma implies false. In the simplest case
07551 an interpolant for the pattern "(and (interp A) B)" maps A
07552 to an interpolant for A /\ B.
07553
07554 The return value is a vector of formulas representing sigma. This
07555 vector contains sigma(phi) for each marked subformula of pat, in
07556 pre-order traversal. This means that subformulas of phi occur before phi
07557 in the vector. Also, subformulas that occur multiply in pat will
07558 occur multiply in the result vector.
07559
07560 If pat is satisfiable, raises an object of class ModelRef
07561 that represents a model of pat.
07562
07563 If parameters p are supplied, these are used in creating the
07564 solver that determines satisfiability.
07565
07566 >>> x = Int('x')
07567 >>> y = Int('y')
07568 >>> print tree_interpolant(And(Interpolant(x < 0), Interpolant(y > 2), x == y))
07569 [Not(x >= 0), Not(y <= 2)]
07570
07571 >>> g = And(Interpolant(x<0),x<2)
07572 >>> try:
07573 ... print tree_interpolant(g).sexpr()
07574 ... except ModelRef as m:
07575 ... print m.sexpr()
07576 (define-fun x () Int
07577 (- 1))
07578 """
07579 f = pat
07580 ctx = _get_ctx(_ctx_from_ast_arg_list([f], ctx))
07581 ptr = (AstVectorObj * 1)()
07582 mptr = (Model * 1)()
07583 if p == None:
07584 p = ParamsRef(ctx)
07585 res = Z3_compute_interpolant(ctx.ref(),f.as_ast(),p.params,ptr,mptr)
07586 if res == Z3_L_FALSE:
07587 return AstVector(ptr[0],ctx)
07588 raise ModelRef(mptr[0], ctx)
07589
07590 def binary_interpolant(a,b,p=None,ctx=None):
07591 """Compute an interpolant for a binary conjunction.
07592
07593 If a & b is unsatisfiable, returns an interpolant for a & b.
07594 This is a formula phi such that
07595
07596 1) a implies phi
07597 2) b implies not phi
07598 3) All the uninterpreted symbols of phi occur in both a and b.
07599
07600 If a & b is satisfiable, raises an object of class ModelRef
07601 that represents a model of a &b.
07602
07603 If parameters p are supplied, these are used in creating the
07604 solver that determines satisfiability.
07605
07606 x = Int('x')
07607 print binary_interpolant(x<0,x>2)
07608 Not(x >= 0)
07609 """
07610 f = And(Interpolant(a),b)
07611 return tree_interpolant(f,p,ctx)[0]
07612
07613 def sequence_interpolant(v,p=None,ctx=None):
07614 """Compute interpolant for a sequence of formulas.
07615
07616 If len(v) == N, and if the conjunction of the formulas in v is
07617 unsatisfiable, the interpolant is a sequence of formulas w
07618 such that len(w) = N-1 and v[0] implies w[0] and for i in 0..N-1:
07619
07620 1) w[i] & v[i+1] implies w[i+1] (or false if i+1 = N)
07621 2) All uninterpreted symbols in w[i] occur in both v[0]..v[i]
07622 and v[i+1]..v[n]
07623
07624 Requires len(v) >= 1.
07625
07626 If a & b is satisfiable, raises an object of class ModelRef
07627 that represents a model of a & b.
07628
07629 If parameters p are supplied, these are used in creating the
07630 solver that determines satisfiability.
07631
07632 >>> x = Int('x')
07633 >>> y = Int('y')
07634 >>> print sequence_interpolant([x < 0, y == x , y > 2])
07635 [Not(x >= 0), Not(y >= 0)]
07636 """
07637 f = v[0]
07638 for i in range(1,len(v)):
07639 f = And(Interpolant(f),v[i])
07640 return tree_interpolant(f,p,ctx)
07641
07642 #########################################
07643 #
07644 # Floating-Point Arithmetic
07645 #
07646 #########################################
07647
07648
07649 # Global default rounding mode
07650 _dflt_rounding_mode = Z3_OP_FPA_RM_TOWARD_ZERO
07651 _dflt_fpsort_ebits = 11
07652 _dflt_fpsort_sbits = 53
07653
07654 def get_default_rounding_mode(ctx=None):
07655 """Retrieves the global default rounding mode."""
07656 global _dflt_rounding_mode
07657 if _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_ZERO:
07658 return RTZ(ctx)
07659 elif _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_NEGATIVE:
07660 return RTN(ctx)
07661 elif _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_POSITIVE:
07662 return RTP(ctx)
07663 elif _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN:
07664 return RNE(ctx)
07665 elif _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY:
07666 return RNA(ctx)
07667
07668 def set_default_rounding_mode(rm, ctx=None):
07669 global _dflt_rounding_mode
07670 if is_fprm_value(rm):
07671 _dflt_rounding_mode = rm.decl().kind()
07672 else:
07673 _z3_assert(_dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_ZERO or
07674 _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_NEGATIVE or
07675 _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_POSITIVE or
07676 _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN or
07677 _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY,
07678 "illegal rounding mode")
07679 _dflt_rounding_mode = rm
07680
07681 def get_default_fp_sort(ctx=None):
07682 return FPSort(_dflt_fpsort_ebits, _dflt_fpsort_sbits, ctx)
07683
07684 def set_default_fp_sort(ebits, sbits, ctx=None):
07685 global _dflt_fpsort_ebits
07686 global _dflt_fpsort_sbits
07687 _dflt_fpsort_ebits = ebits
07688 _dflt_fpsort_sbits = sbits
07689
07690 def _dflt_rm(ctx=None):
07691 return get_default_rounding_mode(ctx)
07692
07693 def _dflt_fps(ctx=None):
07694 return get_default_fp_sort(ctx)
07695
07696 ### FP Sorts
07697
07698 class FPSortRef(SortRef):
07699 """Floating-point sort."""
07700
07701 def ebits(self):
07702 """Retrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`.
07703 >>> b = FPSort(8, 24)
07704 >>> b.ebits()
07705 8
07706 """
07707 return int(Z3_fpa_get_ebits(self.ctx_ref(), self.ast))
07708
07709 def sbits(self):
07710 """Retrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`.
07711 >>> b = FPSort(8, 24)
07712 >>> b.sbits()
07713 24
07714 """
07715 return int(Z3_fpa_get_sbits(self.ctx_ref(), self.ast))
07716
07717 def cast(self, val):
07718 """Try to cast `val` as a Floating-point expression
07719
07720 >>> b = FPSort(8, 24)
07721 >>> b.cast(1.0)
07722 1
07723 >>> b.cast(1.0).sexpr()
07724 '(fp #b0 #x7f #b00000000000000000000000)'
07725 """
07726 if is_expr(val):
07727 if __debug__:
07728 _z3_assert(self.ctx == val.ctx, "Context mismatch")
07729 return val
07730 else:
07731 return FPVal(val, None, self, self.ctx)
07732
07733
07734 def Float16(ctx=None):
07735 """Floating-point 16-bit (half) sort."""
07736 ctx = _get_ctx(ctx)
07737 return FPSortRef(Z3_mk_fpa_sort_16(ctx.ref()), ctx)
07738
07739 def FloatHalf(ctx=None):
07740 """Floating-point 16-bit (half) sort."""
07741 ctx = _get_ctx(ctx)
07742 return FPSortRef(Z3_mk_fpa_sort_half(ctx.ref()), ctx)
07743
07744 def Float32(ctx=None):
07745 """Floating-point 32-bit (single) sort."""
07746 ctx = _get_ctx(ctx)
07747 return FPSortRef(Z3_mk_fpa_sort_32(ctx.ref()), ctx)
07748
07749 def FloatSingle(ctx=None):
07750 """Floating-point 32-bit (single) sort."""
07751 ctx = _get_ctx(ctx)
07752 return FPSortRef(Z3_mk_fpa_sort_single(ctx.ref()), ctx)
07753
07754 def Float64(ctx=None):
07755 """Floating-point 64-bit (double) sort."""
07756 ctx = _get_ctx(ctx)
07757 return FPSortRef(Z3_mk_fpa_sort_64(ctx.ref()), ctx)
07758
07759 def FloatSingle(ctx=None):
07760 """Floating-point 64-bit (double) sort."""
07761 ctx = _get_ctx(ctx)
07762 return FPSortRef(Z3_mk_fpa_sort_double(ctx.ref()), ctx)
07763
07764 def Float128(ctx=None):
07765 """Floating-point 128-bit (quadruple) sort."""
07766 ctx = _get_ctx(ctx)
07767 return FPSortRef(Z3_mk_fpa_sort_128(ctx.ref()), ctx)
07768
07769 def FloatSingle(ctx=None):
07770 """Floating-point 128-bit (quadruple) sort."""
07771 ctx = _get_ctx(ctx)
07772 return FPSortRef(Z3_mk_fpa_sort_quadruple(ctx.ref()), ctx)
07773
07774 class FPRMSortRef(SortRef):
07775 """"Floating-point rounding mode sort."""
07776
07777
07778 def is_fp_sort(s):
07779 """Return True if `s` is a Z3 floating-point sort.
07780
07781 >>> is_fp_sort(FPSort(8, 24))
07782 True
07783 >>> is_fp_sort(IntSort())
07784 False
07785 """
07786 return isinstance(s, FPSortRef)
07787
07788 def is_fprm_sort(s):
07789 """Return True if `s` is a Z3 floating-point rounding mode sort.
07790
07791 >>> is_fprm_sort(FPSort(8, 24))
07792 False
07793 >>> is_fprm_sort(RNE().sort())
07794 True
07795 """
07796 return isinstance(s, FPRMSortRef)
07797
07798 ### FP Expressions
07799
07800 class FPRef(ExprRef):
07801 """Floating-point expressions."""
07802
07803 def sort(self):
07804 """Return the sort of the floating-point expression `self`.
07805
07806 >>> x = FP('1.0', FPSort(8, 24))
07807 >>> x.sort()
07808 FPSort(8, 24)
07809 >>> x.sort() == FPSort(8, 24)
07810 True
07811 """
07812 return FPSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
07813
07814 def ebits(self):
07815 """Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`.
07816 >>> b = FPSort(8, 24)
07817 >>> b.ebits()
07818 8
07819 """
07820 return self.sort().ebits();
07821
07822 def sbits(self):
07823 """Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`.
07824 >>> b = FPSort(8, 24)
07825 >>> b.sbits()
07826 24
07827 """
07828 return self.sort().sbits();
07829
07830 def as_string(self):
07831 """Return a Z3 floating point expression as a Python string."""
07832 return Z3_ast_to_string(self.ctx_ref(), self.as_ast())
07833
07834 def __le__(self, other):
07835 return fpLEQ(self, other)
07836
07837 def __lt__(self, other):
07838 return fpLEQ(self, other)
07839
07840 def __ge__(self, other):
07841 return fpGEQ(self, other)
07842
07843 def __gt__(self, other):
07844 return fpGT(self, other)
07845
07846 def __ne__(self, other):
07847 return fpNEQ(self, other)
07848
07849
07850 def __add__(self, other):
07851 """Create the Z3 expression `self + other`.
07852
07853 >>> x = FP('x', FPSort(8, 24))
07854 >>> y = FP('y', FPSort(8, 24))
07855 >>> x + y
07856 x + y
07857 >>> (x + y).sort()
07858 FPSort(8, 24)
07859 """
07860 a, b = z3._coerce_exprs(self, other)
07861 return fpAdd(_dflt_rm(), self, other)
07862
07863 def __radd__(self, other):
07864 """Create the Z3 expression `other + self`.
07865
07866 >>> x = FP('x', FPSort(8, 24))
07867 >>> 10 + x
07868 1.25*(2**3) + x
07869 """
07870 a, b = _coerce_exprs(self, other)
07871 return fpAdd(_dflt_rm(), other, self)
07872
07873 def __sub__(self, other):
07874 """Create the Z3 expression `self - other`.
07875
07876 >>> x = FP('x', FPSort(8, 24))
07877 >>> y = FP('y', FPSort(8, 24))
07878 >>> x - y
07879 x - y
07880 >>> (x - y).sort()
07881 FPSort(8, 24)
07882 """
07883 a, b = z3._coerce_exprs(self, other)
07884 return fpSub(_dflt_rm(), self, other)
07885
07886 def __rsub__(self, other):
07887 """Create the Z3 expression `other - self`.
07888
07889 >>> x = FP('x', FPSort(8, 24))
07890 >>> 10 - x
07891 1.25*(2**3) - x
07892 """
07893 a, b = _coerce_exprs(self, other)
07894 return fpSub(_dflt_rm(), other, self)
07895
07896 def __mul__(self, other):
07897 """Create the Z3 expression `self * other`.
07898
07899 >>> x = FP('x', FPSort(8, 24))
07900 >>> y = FP('y', FPSort(8, 24))
07901 >>> x * y
07902 x * y
07903 >>> (x * y).sort()
07904 FPSort(8, 24)
07905 >>> 10 * y
07906 1.25*(2**3) * y
07907 """
07908 a, b = z3._coerce_exprs(self, other)
07909 return fpMul(_dflt_rm(), self, other)
07910
07911 def __rmul__(self, other):
07912 """Create the Z3 expression `other * self`.
07913
07914 >>> x = FP('x', FPSort(8, 24))
07915 >>> y = FP('y', FPSort(8, 24))
07916 >>> x * y
07917 x * y
07918 >>> x * 10
07919 x * 1.25*(2**3)
07920 """
07921 a, b = _coerce_exprs(self, other)
07922 return fpMul(_dflt_rm(), other, self)
07923
07924 def __pos__(self):
07925 """Create the Z3 expression `+self`."""
07926 return self
07927
07928 def __neg__(self):
07929 """Create the Z3 expression `-self`."""
07930 return FPRef(fpNeg(self))
07931
07932 def __truediv__(self, other):
07933 """Create the Z3 expression division `self / other`."""
07934 return self.__div__(other)
07935
07936 def __rtruediv__(self, other):
07937 """Create the Z3 expression division `other / self`."""
07938 return self.__rdiv__(other)
07939
07940 def __mod__(self, other):
07941 """Create the Z3 expression mod `self % other`."""
07942 return fpRem(self, other)
07943
07944 def __rmod__(self, other):
07945 """Create the Z3 expression mod `other % self`."""
07946 return fpRem(other, self)
07947
07948 class FPRMRef(ExprRef):
07949 """Floating-point rounding mode expressions"""
07950
07951 def as_string(self):
07952 """Return a Z3 floating point expression as a Python string."""
07953 return Z3_ast_to_string(self.ctx_ref(), self.as_ast())
07954
07955
07956 def RoundNearestTiesToEven(ctx=None):
07957 ctx = _get_ctx(ctx)
07958 return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx)
07959
07960 def RNE (ctx=None):
07961 ctx = _get_ctx(ctx)
07962 return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx)
07963
07964 def RoundNearestTiesToAway(ctx=None):
07965 ctx = _get_ctx(ctx)
07966 return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx)
07967
07968 def RNA (ctx=None):
07969 ctx = _get_ctx(ctx)
07970 return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx)
07971
07972 def RoundTowardPositive(ctx=None):
07973 ctx = _get_ctx(ctx)
07974 return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx)
07975
07976 def RTP(ctx=None):
07977 ctx = _get_ctx(ctx)
07978 return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx)
07979
07980 def RoundTowardNegative(ctx=None):
07981 ctx = _get_ctx(ctx)
07982 return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx)
07983
07984 def RTN(ctx=None):
07985 ctx = _get_ctx(ctx)
07986 return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx)
07987
07988 def RoundTowardZero(ctx=None):
07989 ctx = _get_ctx(ctx)
07990 return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx)
07991
07992 def RTZ(ctx=None):
07993 ctx = _get_ctx(ctx)
07994 return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx)
07995
07996 def is_fprm(a):
07997 """Return `True` if `a` is a Z3 floating-point rounding mode expression.
07998
07999 >>> rm = RNE()
08000 >>> is_fprm(rm)
08001 True
08002 >>> rm = 1.0
08003 >>> is_fprm(rm)
08004 False
08005 """
08006 return isinstance(a, FPRMRef)
08007
08008 def is_fprm_value(a):
08009 """Return `True` if `a` is a Z3 floating-point rounding mode numeral value."""
08010 return is_fprm(a) and _is_numeral(a.ctx, a.ast)
08011
08012 ### FP Numerals
08013
08014 class FPNumRef(FPRef):
08015 def isNaN(self):
08016 return self.decl().kind() == Z3_OP_FPA_NAN
08017
08018 def isInf(self):
08019 return self.decl().kind() == Z3_OP_FPA_PLUS_INF or self.decl().kind() == Z3_OP_FPA_MINUS_INF
08020
08021 def isZero(self):
08022 return self.decl().kind() == Z3_OP_FPA_PLUS_ZERO or self.decl().kind() == Z3_OP_FPA_MINUS_ZERO
08023
08024 def isNegative(self):
08025 k = self.decl().kind()
08026 return (self.num_args() == 0 and (k == Z3_OP_FPA_MINUS_INF or k == Z3_OP_FPA_MINUS_ZERO)) or (self.sign() == True)
08027
08028 """
08029 The sign of the numeral
08030
08031 >>> x = FPNumRef(+1.0, FPSort(8, 24))
08032 >>> x.sign()
08033 False
08034 >>> x = FPNumRef(-1.0, FPSort(8, 24))
08035 >>> x.sign()
08036 True
08037 """
08038 def sign(self):
08039 l = (ctypes.c_int)()
08040 if Z3_fpa_get_numeral_sign(self.ctx.ref(), self.as_ast(), byref(l)) == False:
08041 raise Z3Exception("error retrieving the sign of a numeral.")
08042 return l.value != 0
08043
08044 """
08045 The significand of the numeral
08046
08047 >>> x = FPNumRef(2.5, FPSort(8, 24))
08048 1.25
08049 """
08050 def significand(self):
08051 return Z3_fpa_get_numeral_significand_string(self.ctx.ref(), self.as_ast())
08052
08053 """
08054 The exponent of the numeral
08055
08056 >>> x = FPNumRef(2.5, FPSort(8, 24))
08057 >>>
08058 1
08059 """
08060 def exponent(self):
08061 return Z3_fpa_get_numeral_exponent_string(self.ctx.ref(), self.as_ast())
08062
08063 """
08064 The exponent of the numeral as a long
08065
08066 >>> x = FPNumRef(2.5, FPSort(8, 24))
08067 1
08068 """
08069 def exponent_as_long(self):
08070 ptr = (ctypes.c_longlong * 1)()
08071 if not Z3_fpa_get_numeral_exponent_int64(self.ctx.ref(), self.as_ast(), ptr):
08072 raise Z3Exception("error retrieving the exponent of a numeral.")
08073 return ptr[0]
08074
08075 """
08076 The string representation of the numeral
08077
08078 >>> x = FPNumRef(20, FPSort(8, 24))
08079 1.25*(2**4)
08080 """
08081 def as_string(self):
08082 s = Z3_fpa_get_numeral_string(self.ctx.ref(), self.as_ast())
08083 return ("FPVal(%s, %s)" % (s, FPSortRef(self.sort()).as_string()))
08084
08085
08086 def _to_fpnum(num, ctx=None):
08087 if isinstance(num, FPNum):
08088 return num
08089 else:
08090 return FPNum(num, ctx)
08091
08092 def is_fp(a):
08093 """Return `True` if `a` is a Z3 floating-point expression.
08094
08095 >>> b = FP('b', FPSort(8, 24))
08096 >>> is_fp(b)
08097 True
08098 >>> is_fp(b + 1.0)
08099 True
08100 >>> is_fp(Int('x'))
08101 False
08102 """
08103 return isinstance(a, FPRef)
08104
08105 def is_fp_value(a):
08106 """Return `True` if `a` is a Z3 floating-point numeral value.
08107
08108 >>> b = FP('b', FPSort(8, 24))
08109 >>> is_fp_value(b)
08110 False
08111 >>> b = FPVal(1.0, FPSort(8, 24))
08112 >>> b
08113 1
08114 >>> is_fp_value(b)
08115 True
08116 """
08117 return is_fp(a) and _is_numeral(a.ctx, a.ast)
08118
08119 def FPSort(ebits, sbits, ctx=None):
08120 """Return a Z3 floating-point sort of the given sizes. If `ctx=None`, then the global context is used.
08121
08122 >>> Single = FPSort(8, 24)
08123 >>> Double = FPSort(11, 53)
08124 >>> Single
08125 FPSort(8, 24)
08126 >>> x = Const('x', Single)
08127 >>> eq(x, FP('x', FPSort(8, 24)))
08128 True
08129 """
08130 ctx = z3._get_ctx(ctx)
08131 return FPSortRef(Z3_mk_fpa_sort(ctx.ref(), ebits, sbits), ctx)
08132
08133 def _to_float_str(val):
08134 if isinstance(val, float):
08135 return str(val)
08136 elif isinstance(val, bool):
08137 if val:
08138 return "1.0"
08139 else:
08140 return "0.0"
08141 elif _is_int(val):
08142 return str(val)
08143 elif isinstance(val, str):
08144 return val
08145 if __debug__:
08146 _z3_assert(False, "Python value cannot be used as a double")
08147
08148 def fpNaN(s):
08149 _z3_assert(isinstance(s, FPSortRef), "sort mismatch")
08150 return FPNumRef(Z3_mk_fpa_nan(s.ctx_ref(), s.ast), s.ctx)
08151
08152 def fpPlusInfinity(s):
08153 _z3_assert(isinstance(s, FPSortRef), "sort mismatch")
08154 return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, False), s.ctx)
08155
08156 def fpMinusInfinity(s):
08157 _z3_assert(isinstance(s, FPSortRef), "sort mismatch")
08158 return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, True), s.ctx)
08159
08160 def fpInfinity(s, negative):
08161 _z3_assert(isinstance(s, FPSortRef), "sort mismatch")
08162 _z3_assert(isinstance(negative, bool), "expected Boolean flag")
08163 return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, negative), s.ctx)
08164
08165 def fpPlusZero(s):
08166 _z3_assert(isinstance(s, FPSortRef), "sort mismatch")
08167 return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, False), s.ctx)
08168
08169 def fpMinusZero(s):
08170 _z3_assert(isinstance(s, FPSortRef), "sort mismatch")
08171 return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, True), s.ctx)
08172
08173 def fpZero(s, negative):
08174 _z3_assert(isinstance(s, FPSortRef), "sort mismatch")
08175 _z3_assert(isinstance(negative, bool), "expected Boolean flag")
08176 return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, negative), s.ctx)
08177
08178 def FPVal(sig, exp=None, fps=None, ctx=None):
08179 """Return a floating-point value of value `val` and sort `fps`. If `ctx=None`, then the global context is used.
08180
08181 >>> v = FPVal(20.0, FPSort(8, 24))
08182 >>> v
08183 1.25*(2**4)
08184 >>> print("0x%.8x" % v.exponent_as_long())
08185 0x00000004
08186 >>> v = FPVal(2.25, FPSort(8, 24))
08187 >>> v
08188 1.125*(2**1)
08189 >>> v = FPVal(-2.25, FPSort(8, 24))
08190 >>> v
08191 -1.125*(2**1)
08192 """
08193 ctx = _get_ctx(ctx)
08194 if is_fp_sort(exp):
08195 fps = exp
08196 exp = None
08197 elif fps == None:
08198 fps = _dflt_fps(ctx)
08199 _z3_assert(is_fp_sort(fps), "sort mismatch")
08200 if exp == None:
08201 exp = 0
08202 val = _to_float_str(sig)
08203 val = val + 'p'
08204 val = val + _to_int_str(exp)
08205 return FPNumRef(Z3_mk_numeral(ctx.ref(), val, fps.ast), ctx)
08206
08207 def FP(name, fpsort, ctx=None):
08208 """Return a floating-point constant named `name`.
08209 `fpsort` is the floating-point sort.
08210 If `ctx=None`, then the global context is used.
08211
08212 >>> x = FP('x', FPSort(8, 24))
08213 >>> is_fp(x)
08214 True
08215 >>> x.ebits()
08216 8
08217 >>> x.sort()
08218 FPSort(8, 24)
08219 >>> word = FPSort(8, 24)
08220 >>> x2 = FP('x', word)
08221 >>> eq(x, x2)
08222 True
08223 """
08224 if isinstance(fpsort, FPSortRef):
08225 ctx = fpsort.ctx
08226 else:
08227 ctx = _get_ctx(ctx)
08228 return FPRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), fpsort.ast), ctx)
08229
08230 def FPs(names, fpsort, ctx=None):
08231 """Return an array of floating-point constants.
08232
08233 >>> x, y, z = FPs('x y z', FPSort(8, 24))
08234 >>> x.sort()
08235 FPSort(8, 24)
08236 >>> x.sbits()
08237 24
08238 >>> x.ebits()
08239 8
08240 >>> fpMul(RNE(), fpAdd(RNE(), x, y), z)
08241 fpMul(RNE(), fpAdd(RNE(), x, y), z)
08242 """
08243 ctx = z3._get_ctx(ctx)
08244 if isinstance(names, str):
08245 names = names.split(" ")
08246 return [FP(name, fpsort, ctx) for name in names]
08247
08248 def fpAbs(a):
08249 """Create a Z3 floating-point absolute value expression.
08250
08251 >>> s = FPSort(8, 24)
08252 >>> rm = RNE()
08253 >>> x = FPVal(1.0, s)
08254 >>> fpAbs(x)
08255 fpAbs(1)
08256 >>> y = FPVal(-20.0, s)
08257 >>> y
08258 -1.25*(2**4)
08259 >>> fpAbs(y)
08260 fpAbs(-1.25*(2**4))
08261 >>> fpAbs(-1.25*(2**4))
08262 fpAbs(-1.25*(2**4))
08263 >>> fpAbs(x).sort()
08264 FPSort(8, 24)
08265 """
08266 ctx = None
08267 if not is_expr(a):
08268 ctx =_get_ctx(ctx)
08269 s = get_default_fp_sort(ctx)
08270 a = FPVal(a, s)
08271 else:
08272 ctx = a.ctx
08273 if __debug__:
08274 _z3_assert(is_fp(a), "First argument must be Z3 floating-point expression")
08275 return FPRef(Z3_mk_fpa_abs(a.ctx_ref(), a.as_ast()), a.ctx)
08276
08277 def fpNeg(a):
08278 """Create a Z3 floating-point addition expression.
08279
08280 >>> s = FPSort(8, 24)
08281 >>> rm = RNE()
08282 >>> x = FP('x', s)
08283 >>> fpNeg(x)
08284 -x
08285 >>> fpNeg(x).sort()
08286 FPSort(8, 24)
08287 """
08288 ctx = None
08289 if not is_expr(a):
08290 ctx =_get_ctx(ctx)
08291 s = get_default_fp_sort(ctx)
08292 a = FPVal(a, s)
08293 else:
08294 ctx = a.ctx
08295 if __debug__:
08296 _z3_assert(is_fp(a), "First argument must be Z3 floating-point expression")
08297 return FPRef(Z3_mk_fpa_neg(a.ctx_ref(), a.as_ast()), a.ctx)
08298
08299 def fpAdd(rm, a, b):
08300 """Create a Z3 floating-point addition expression.
08301
08302 >>> s = FPSort(8, 24)
08303 >>> rm = RNE()
08304 >>> x = FP('x', s)
08305 >>> y = FP('y', s)
08306 >>> fpAdd(rm, x, y)
08307 fpAdd(RNE(), x, y)
08308 >>> fpAdd(rm, x, y).sort()
08309 FPSort(8, 24)
08310 """
08311 if __debug__:
08312 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08313 _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression")
08314 a, b = _coerce_exprs(a, b)
08315 return FPRef(Z3_mk_fpa_add(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx)
08316
08317 def fpSub(rm, a, b):
08318 """Create a Z3 floating-point subtraction expression.
08319
08320 >>> s = FPSort(8, 24)
08321 >>> rm = RNE()
08322 >>> x = FP('x', s)
08323 >>> y = FP('y', s)
08324 >>> fpSub(rm, x, y)
08325 fpSub(RNE(), x, y)
08326 >>> fpSub(rm, x, y).sort()
08327 FPSort(8, 24)
08328 """
08329 if __debug__:
08330 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08331 _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression")
08332 a, b = _coerce_exprs(a, b)
08333 return FPRef(Z3_mk_fpa_sub(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx)
08334
08335 def fpMul(rm, a, b):
08336 """Create a Z3 floating-point multiplication expression.
08337
08338 >>> s = FPSort(8, 24)
08339 >>> rm = RNE()
08340 >>> x = FP('x', s)
08341 >>> y = FP('y', s)
08342 >>> fpMul(rm, x, y)
08343 fpMul(RNE(), x, y)
08344 >>> fpMul(rm, x, y).sort()
08345 FPSort(8, 24)
08346 """
08347 if __debug__:
08348 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08349 _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression")
08350 a, b = _coerce_exprs(a, b)
08351 return FPRef(Z3_mk_fpa_mul(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx)
08352
08353 def fpDiv(rm, a, b):
08354 """Create a Z3 floating-point divison expression.
08355
08356 >>> s = FPSort(8, 24)
08357 >>> rm = RNE()
08358 >>> x = FP('x', s)
08359 >>> y = FP('y', s)
08360 >>> fpDiv(rm, x, y)
08361 fpDiv(RNE(), x, y)
08362 >>> fpDiv(rm, x, y).sort()
08363 FPSort(8, 24)
08364 """
08365 if __debug__:
08366 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08367 _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression")
08368 a, b = _coerce_exprs(a, b)
08369 return FPRef(Z3_mk_fpa_div(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx)
08370
08371 def fpRem(a, b):
08372 """Create a Z3 floating-point remainder expression.
08373
08374 >>> s = FPSort(8, 24)
08375 >>> x = FP('x', s)
08376 >>> y = FP('y', s)
08377 >>> fpRem(x, y)
08378 fpRem(x, y)
08379 >>> fpRem(x, y).sort()
08380 FPSort(8, 24)
08381 """
08382 if __debug__:
08383 _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression")
08384 a, b = _coerce_exprs(a, b)
08385 return FPRef(Z3_mk_fpa_rem(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
08386
08387 def fpMin(a, b):
08388 """Create a Z3 floating-point minimium expression.
08389
08390 >>> s = FPSort(8, 24)
08391 >>> rm = RNE()
08392 >>> x = FP('x', s)
08393 >>> y = FP('y', s)
08394 >>> fpMin(x, y)
08395 fpMin(x, y)
08396 >>> fpMin(x, y).sort()
08397 FPSort(8, 24)
08398 """
08399 if __debug__:
08400 _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression")
08401 a, b = _coerce_exprs(a, b)
08402 return FPRef(Z3_mk_fpa_min(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
08403
08404 def fpMax(a, b):
08405 """Create a Z3 floating-point maximum expression.
08406
08407 >>> s = FPSort(8, 24)
08408 >>> rm = RNE()
08409 >>> x = FP('x', s)
08410 >>> y = FP('y', s)
08411 >>> fpMax(x, y)
08412 fpMax(x, y)
08413 >>> fpMax(x, y).sort()
08414 FPSort(8, 24)
08415 """
08416 if __debug__:
08417 _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression")
08418 a, b = _coerce_exprs(a, b)
08419 return FPRef(Z3_mk_fpa_max(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
08420
08421 def fpFMA(rm, a, b, c):
08422 """Create a Z3 floating-point fused multiply-add expression.
08423 """
08424 if __debug__:
08425 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08426 _z3_assert(is_fp(a) or is_fp(b) or is_fp(c), "Second, third, or fourth argument must be a Z3 floating-point expression")
08427 a, b, c = _coerce_expr_list([a, b, c])
08428 return FPRef(Z3_mk_fpa_fma(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast(), c.as_ast()), rm.ctx)
08429
08430 def fpSqrt(rm, a):
08431 """Create a Z3 floating-point square root expression.
08432 """
08433 ctx = None
08434 if not is_expr(a):
08435 ctx =_get_ctx(ctx)
08436 s = get_default_fp_sort(ctx)
08437 a = FPVal(a, s)
08438 else:
08439 ctx = a.ctx
08440 if __debug__:
08441 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08442 _z3_assert(is_fp(a), "Second argument must be a Z3 floating-point expressions")
08443 return FPRef(Z3_mk_fpa_sqrt(rm.ctx_ref(), rm.as_ast(), a.as_ast()), rm.ctx)
08444
08445 def fpRoundToIntegral(rm, a):
08446 """Create a Z3 floating-point roundToIntegral expression.
08447 """
08448 ctx = None
08449 if not is_expr(a):
08450 ctx =_get_ctx(ctx)
08451 s = get_default_fp_sort(ctx)
08452 a = FPVal(a, s)
08453 else:
08454 ctx = a.ctx
08455 if __debug__:
08456 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08457 _z3_assert(is_fp(a), "Second argument must be a Z3 floating-point expressions")
08458 return FPRef(Z3_mk_fpa_round_to_integral(rm.ctx_ref(), rm.as_ast(), a.as_ast()), rm.ctx)
08459
08460 def fpIsNaN(a):
08461 """Create a Z3 floating-point isNaN expression.
08462 """
08463 if __debug__:
08464 _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
08465 return FPRef(Z3_mk_fpa_is_nan(a.ctx_ref(), a.as_ast()), a.ctx)
08466
08467 def fpIsInfinite(a):
08468 """Create a Z3 floating-point isNaN expression.
08469 """
08470 if __debug__:
08471 _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
08472 return FPRef(Z3_mk_fpa_is_infinite(a.ctx_ref(), a.as_ast()), a.ctx)
08473
08474 def fpIsZero(a):
08475 """Create a Z3 floating-point isNaN expression.
08476 """
08477 if __debug__:
08478 _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
08479 return FPRef(Z3_mk_fpa_is_zero(a.ctx_ref(), a.as_ast()), a.ctx)
08480
08481 def fpIsNormal(a):
08482 """Create a Z3 floating-point isNaN expression.
08483 """
08484 if __debug__:
08485 _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
08486 return FPRef(Z3_mk_fpa_is_normal(a.ctx_ref(), a.as_ast()), a.ctx)
08487
08488 def fpIsSubnormal(a):
08489 """Create a Z3 floating-point isNaN expression.
08490 """
08491 if __debug__:
08492 _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
08493 return FPRef(Z3_mk_fpa_is_subnormal(a.ctx_ref(), a.as_ast()), a.ctx)
08494
08495 def fpIsNegative(a):
08496 """Create a Z3 floating-point isNaN expression.
08497 """
08498 if __debug__:
08499 _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
08500 return FPRef(Z3_mk_fpa_is_negative(a.ctx_ref(), a.as_ast()), a.ctx)
08501
08502 def fpIsPositive(a):
08503 """Create a Z3 floating-point isNaN expression.
08504 """
08505 if __debug__:
08506 _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
08507 return FPRef(Z3_mk_fpa_is_positive(a.ctx_ref(), a.as_ast()), a.ctx)
08508
08509 def _check_fp_args(a, b):
08510 if __debug__:
08511 _z3_assert(is_fp(a) or is_fp(b), "At least one of the arguments must be a Z3 floating-point expression")
08512
08513 def fpLT(a, b):
08514 """Create the Z3 floating-point expression `other <= self`.
08515
08516 >>> x, y = FPs('x y', FPSort(8, 24))
08517 >>> fpLT(x, y)
08518 x < y
08519 >>> (x <= y).sexpr()
08520 '(fp.leq x y)'
08521 """
08522 _check_fp_args(a, b)
08523 a, b = _coerce_exprs(a, b)
08524 return BoolRef(Z3_mk_fpa_lt(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
08525
08526 def fpLEQ(a, b):
08527 """Create the Z3 floating-point expression `other <= self`.
08528
08529 >>> x, y = FPs('x y', FPSort(8, 24))
08530 >>> fpLEQ(x, y)
08531 x <= y
08532 >>> (x <= y).sexpr()
08533 '(fp.leq x y)'
08534 """
08535 _check_fp_args(a, b)
08536 a, b = _coerce_exprs(a, b)
08537 return BoolRef(Z3_mk_fpa_leq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
08538
08539 def fpGT(a, b):
08540 """Create the Z3 floating-point expression `other <= self`.
08541
08542 >>> x, y = FPs('x y', FPSort(8, 24))
08543 >>> fpGT(x, y)
08544 x > y
08545 >>> (x > y).sexpr()
08546 '(fp.gt x y)'
08547 """
08548 _check_fp_args(a, b)
08549 a, b = _coerce_exprs(a, b)
08550 return BoolRef(Z3_mk_fpa_gt(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
08551
08552
08553 def fpGEQ(a, b):
08554 """Create the Z3 floating-point expression `other <= self`.
08555
08556 >>> x, y = FPs('x y', FPSort(8, 24))
08557 >>> x + y
08558 x + y
08559 >>> fpGEQ(x, y)
08560 x >= y
08561 >>> (x >= y).sexpr()
08562 '(fp.geq x y)'
08563 """
08564 _check_fp_args(a, b)
08565 a, b = _coerce_exprs(a, b)
08566 return BoolRef(Z3_mk_fpa_geq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
08567
08568 def fpEQ(a, b):
08569 """Create the Z3 floating-point expression `other <= self`.
08570
08571 >>> x, y = FPs('x y', FPSort(8, 24))
08572 >>> fpEQ(x, y)
08573 fpEQ(x, y)
08574 >>> fpEQ(x, y).sexpr()
08575 '(fp.eq x y)'
08576 """
08577 _check_fp_args(a, b)
08578 a, b = _coerce_exprs(a, b)
08579 return BoolRef(Z3_mk_fpa_eq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
08580
08581 def fpNEQ(a, b):
08582 """Create the Z3 floating-point expression `other <= self`.
08583
08584 >>> x, y = FPs('x y', FPSort(8, 24))
08585 >>> fpNEQ(x, y)
08586 Not(fpEQ(x, y))
08587 >>> (x != y).sexpr()
08588 '(not (fp.eq x y))'
08589 """
08590 _check_fp_args(a, b)
08591 a, b = _coerce_exprs(a, b)
08592 return Not(BoolRef(Z3_mk_fpa_eq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx), a.ctx)
08593
08594
08595
08596 def fpFP(sgn, exp, sig):
08597 """Create the Z3 floating-point value `fpFP(sgn, sig, exp)` from the three bit-vectorssgn, sig, and exp."""
08598 _z3_assert(is_bv(sgn) and is_bv(exp) and is_bv(sig), "sort mismatch")
08599 _z3_assert(sgn.sort().size() == 1, "sort mismatch")
08600 return FPRef(Z3_mk_fpa_fp(sgn.ctx_ref(), sgn.ast, exp.ast, sig.ast), sgn.ctx)
08601
08602
08603 def fpToFP(a1, a2=None, a3=None):
08604 """Create a Z3 floating-point conversion expression from other terms."""
08605 if is_bv(a1) and is_fp_sort(a2):
08606 return FPRef(Z3_mk_fpa_to_fp_bv(a1.ctx_ref(), a1.ast, a2.ast), a1.ctx)
08607 elif is_fprm(a1) and is_fp(a2) and is_fp_sort(a3):
08608 return FPRef(Z3_mk_fpa_to_fp_float(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx)
08609 elif is_fprm(a1) and is_real(a2) and is_fp_sort(a3):
08610 return FPRef(Z3_mk_fpa_to_fp_real(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx)
08611 elif is_fprm(a1) and is_bv(a2) and is_fp_sort(a3):
08612 return FPRef(Z3_mk_fpa_to_fp_signed(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx)
08613 else:
08614 raise Z3Exception("Unsupported combination of arguments for conversion to floating-point term.")
08615
08616 def fpToFPUnsigned(rm, x, s):
08617 """Create a Z3 floating-point conversion expression, from unsigned bit-vector to floating-point expression."""
08618 if __debug__:
08619 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08620 _z3_assert(is_bv(x), "Second argument must be a Z3 bit-vector expression")
08621 _z3_assert(is_fp_sort(s), "Third argument must be Z3 floating-point sort")
08622 return FPRef(Z3_mk_fpa_to_fp_unsigned(rm.ctx_ref(), rm.ast, x.ast, s.ast), rm.ctx)
08623
08624 def fpToSBV(rm, x, s):
08625 """Create a Z3 floating-point conversion expression, from floating-point expression to signed bit-vector.
08626
08627 >>> x = FP('x', FPSort(8, 24))
08628 >>> y = fpToSBV(RTZ(), x, BitVecSort(32))
08629 >>> print is_fp(x)
08630 True
08631 >>> print is_bv(y)
08632 True
08633 >>> print is_fp(y)
08634 False
08635 >>> print is_bv(x)
08636 False
08637 """
08638 if __debug__:
08639 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08640 _z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression")
08641 _z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort")
08642 return BitVecRef(Z3_mk_fpa_to_sbv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx)
08643
08644 def fpToUBV(rm, x, s):
08645 """Create a Z3 floating-point conversion expression, from floating-point expression to unsigned bit-vector.
08646
08647 >>> x = FP('x', FPSort(8, 24))
08648 >>> y = fpToUBV(RTZ(), x, BitVecSort(32))
08649 >>> print is_fp(x)
08650 True
08651 >>> print is_bv(y)
08652 True
08653 >>> print is_fp(y)
08654 False
08655 >>> print is_bv(x)
08656 False
08657 """
08658 if __debug__:
08659 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
08660 _z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression")
08661 _z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort")
08662 return BitVecRef(Z3_mk_fpa_to_ubv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx)
08663
08664 def fpToReal(x):
08665 """Create a Z3 floating-point conversion expression, from floating-point expression to real.
08666
08667 >>> x = FP('x', FPSort(8, 24))
08668 >>> y = fpToReal(x)
08669 >>> print is_fp(x)
08670 True
08671 >>> print is_real(y)
08672 True
08673 >>> print is_fp(y)
08674 False
08675 >>> print is_real(x)
08676 False
08677 """
08678 if __debug__:
08679 _z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression")
08680 return ArithRef(Z3_mk_fpa_to_real(x.ctx_ref(), x.ast), x.ctx)
08681
08682 def fpToIEEEBV(x):
08683 """\brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format.
08684
08685 The size of the resulting bit-vector is automatically determined.
08686
08687 Note that IEEE 754-2008 allows multiple different representations of NaN. This conversion
08688 knows only one NaN and it will always produce the same bit-vector represenatation of
08689 that NaN.
08690
08691 >>> x = FP('x', FPSort(8, 24))
08692 >>> y = fpToIEEEBV(x)
08693 >>> print is_fp(x)
08694 True
08695 >>> print is_bv(y)
08696 True
08697 >>> print is_fp(y)
08698 False
08699 >>> print is_bv(x)
08700 False
08701 """
08702 if __debug__:
08703 _z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression")
08704 return BitVecRef(Z3_mk_fpa_to_ieee_bv(x.ctx_ref(), x.ast), x.ctx)