1############################################ 2# Copyright (c) 2012 Microsoft Corporation 3# 4# Z3 Python interface 5# 6# Author: Leonardo de Moura (leonardo) 7############################################ 8 9"""Z3 is a high performance theorem prover developed at Microsoft Research. 10 11Z3 is used in many applications such as: software/hardware verification and testing, 12constraint solving, analysis of hybrid systems, security, biology (in silico analysis), 13and geometrical problems. 14 15Several online tutorials for Z3Py are available at: 16http://rise4fun.com/Z3Py/tutorial/guide 17 18Please send feedback, comments and/or corrections on the Issue tracker for 19https://github.com/Z3prover/z3.git. Your comments are very valuable. 20 21Small example: 22 23>>> x = Int('x') 24>>> y = Int('y') 25>>> s = Solver() 26>>> s.add(x > 0) 27>>> s.add(x < 2) 28>>> s.add(y == x + 1) 29>>> s.check() 30sat 31>>> m = s.model() 32>>> m[x] 331 34>>> m[y] 352 36 37Z3 exceptions: 38 39>>> try: 40... x = BitVec('x', 32) 41... y = Bool('y') 42... # the expression x + y is type incorrect 43... n = x + y 44... except Z3Exception as ex: 45... print("failed: %s" % ex) 46failed: sort mismatch 47""" 48from . import z3core 49from .z3core import * 50from .z3types import * 51from .z3consts import * 52from .z3printer import * 53from fractions import Fraction 54import sys 55import io 56import math 57import copy 58if sys.version_info.major >= 3: 59 from typing import Iterable 60 61Z3_DEBUG = __debug__ 62 63 64def z3_debug(): 65 global Z3_DEBUG 66 return Z3_DEBUG 67 68 69if sys.version_info.major < 3: 70 def _is_int(v): 71 return isinstance(v, (int, long)) 72else: 73 def _is_int(v): 74 return isinstance(v, int) 75 76 77def enable_trace(msg): 78 Z3_enable_trace(msg) 79 80 81def disable_trace(msg): 82 Z3_disable_trace(msg) 83 84 85def get_version_string(): 86 major = ctypes.c_uint(0) 87 minor = ctypes.c_uint(0) 88 build = ctypes.c_uint(0) 89 rev = ctypes.c_uint(0) 90 Z3_get_version(major, minor, build, rev) 91 return "%s.%s.%s" % (major.value, minor.value, build.value) 92 93 94def get_version(): 95 major = ctypes.c_uint(0) 96 minor = ctypes.c_uint(0) 97 build = ctypes.c_uint(0) 98 rev = ctypes.c_uint(0) 99 Z3_get_version(major, minor, build, rev) 100 return (major.value, minor.value, build.value, rev.value) 101 102 103def get_full_version(): 104 return Z3_get_full_version() 105 106# We use _z3_assert instead of the assert command because we want to 107# produce nice error messages in Z3Py at rise4fun.com 108 109 110def _z3_assert(cond, msg): 111 if not cond: 112 raise Z3Exception(msg) 113 114 115def _z3_check_cint_overflow(n, name): 116 _z3_assert(ctypes.c_int(n).value == n, name + " is too large") 117 118 119def open_log(fname): 120 """Log interaction to a file. This function must be invoked immediately after init(). """ 121 Z3_open_log(fname) 122 123 124def append_log(s): 125 """Append user-defined string to interaction log. """ 126 Z3_append_log(s) 127 128 129def to_symbol(s, ctx=None): 130 """Convert an integer or string into a Z3 symbol.""" 131 if _is_int(s): 132 return Z3_mk_int_symbol(_get_ctx(ctx).ref(), s) 133 else: 134 return Z3_mk_string_symbol(_get_ctx(ctx).ref(), s) 135 136 137def _symbol2py(ctx, s): 138 """Convert a Z3 symbol back into a Python object. """ 139 if Z3_get_symbol_kind(ctx.ref(), s) == Z3_INT_SYMBOL: 140 return "k!%s" % Z3_get_symbol_int(ctx.ref(), s) 141 else: 142 return Z3_get_symbol_string(ctx.ref(), s) 143 144# Hack for having nary functions that can receive one argument that is the 145# list of arguments. 146# Use this when function takes a single list of arguments 147 148 149def _get_args(args): 150 try: 151 if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)): 152 return args[0] 153 elif len(args) == 1 and (isinstance(args[0], set) or isinstance(args[0], AstVector)): 154 return [arg for arg in args[0]] 155 else: 156 return args 157 except TypeError: # len is not necessarily defined when args is not a sequence (use reflection?) 158 return args 159 160# Use this when function takes multiple arguments 161 162 163def _get_args_ast_list(args): 164 try: 165 if isinstance(args, (set, AstVector, tuple)): 166 return [arg for arg in args] 167 else: 168 return args 169 except Exception: 170 return args 171 172 173def _to_param_value(val): 174 if isinstance(val, bool): 175 return "true" if val else "false" 176 return str(val) 177 178 179def z3_error_handler(c, e): 180 # Do nothing error handler, just avoid exit(0) 181 # The wrappers in z3core.py will raise a Z3Exception if an error is detected 182 return 183 184 185class Context: 186 """A Context manages all other Z3 objects, global configuration options, etc. 187 188 Z3Py uses a default global context. For most applications this is sufficient. 189 An application may use multiple Z3 contexts. Objects created in one context 190 cannot be used in another one. However, several objects may be "translated" from 191 one context to another. It is not safe to access Z3 objects from multiple threads. 192 The only exception is the method `interrupt()` that can be used to interrupt() a long 193 computation. 194 The initialization method receives global configuration options for the new context. 195 """ 196 197 def __init__(self, *args, **kws): 198 if z3_debug(): 199 _z3_assert(len(args) % 2 == 0, "Argument list must have an even number of elements.") 200 conf = Z3_mk_config() 201 for key in kws: 202 value = kws[key] 203 Z3_set_param_value(conf, str(key).upper(), _to_param_value(value)) 204 prev = None 205 for a in args: 206 if prev is None: 207 prev = a 208 else: 209 Z3_set_param_value(conf, str(prev), _to_param_value(a)) 210 prev = None 211 self.ctx = Z3_mk_context_rc(conf) 212 self.eh = Z3_set_error_handler(self.ctx, z3_error_handler) 213 Z3_set_ast_print_mode(self.ctx, Z3_PRINT_SMTLIB2_COMPLIANT) 214 Z3_del_config(conf) 215 216 def __del__(self): 217 Z3_del_context(self.ctx) 218 self.ctx = None 219 self.eh = None 220 221 def ref(self): 222 """Return a reference to the actual C pointer to the Z3 context.""" 223 return self.ctx 224 225 def interrupt(self): 226 """Interrupt a solver performing a satisfiability test, a tactic processing a goal, or simplify functions. 227 228 This method can be invoked from a thread different from the one executing the 229 interruptible procedure. 230 """ 231 Z3_interrupt(self.ref()) 232 233 234# Global Z3 context 235_main_ctx = None 236 237 238def main_ctx(): 239 """Return a reference to the global Z3 context. 240 241 >>> x = Real('x') 242 >>> x.ctx == main_ctx() 243 True 244 >>> c = Context() 245 >>> c == main_ctx() 246 False 247 >>> x2 = Real('x', c) 248 >>> x2.ctx == c 249 True 250 >>> eq(x, x2) 251 False 252 """ 253 global _main_ctx 254 if _main_ctx is None: 255 _main_ctx = Context() 256 return _main_ctx 257 258 259def _get_ctx(ctx): 260 if ctx is None: 261 return main_ctx() 262 else: 263 return ctx 264 265 266def get_ctx(ctx): 267 return _get_ctx(ctx) 268 269 270def set_param(*args, **kws): 271 """Set Z3 global (or module) parameters. 272 273 >>> set_param(precision=10) 274 """ 275 if z3_debug(): 276 _z3_assert(len(args) % 2 == 0, "Argument list must have an even number of elements.") 277 new_kws = {} 278 for k in kws: 279 v = kws[k] 280 if not set_pp_option(k, v): 281 new_kws[k] = v 282 for key in new_kws: 283 value = new_kws[key] 284 Z3_global_param_set(str(key).upper(), _to_param_value(value)) 285 prev = None 286 for a in args: 287 if prev is None: 288 prev = a 289 else: 290 Z3_global_param_set(str(prev), _to_param_value(a)) 291 prev = None 292 293 294def reset_params(): 295 """Reset all global (or module) parameters. 296 """ 297 Z3_global_param_reset_all() 298 299 300def set_option(*args, **kws): 301 """Alias for 'set_param' for backward compatibility. 302 """ 303 return set_param(*args, **kws) 304 305 306def get_param(name): 307 """Return the value of a Z3 global (or module) parameter 308 309 >>> get_param('nlsat.reorder') 310 'true' 311 """ 312 ptr = (ctypes.c_char_p * 1)() 313 if Z3_global_param_get(str(name), ptr): 314 r = z3core._to_pystr(ptr[0]) 315 return r 316 raise Z3Exception("failed to retrieve value for '%s'" % name) 317 318######################################### 319# 320# ASTs base class 321# 322######################################### 323 324# Mark objects that use pretty printer 325 326 327class Z3PPObject: 328 """Superclass for all Z3 objects that have support for pretty printing.""" 329 330 def use_pp(self): 331 return True 332 333 def _repr_html_(self): 334 in_html = in_html_mode() 335 set_html_mode(True) 336 res = repr(self) 337 set_html_mode(in_html) 338 return res 339 340 341class AstRef(Z3PPObject): 342 """AST are Direct Acyclic Graphs (DAGs) used to represent sorts, declarations and expressions.""" 343 344 def __init__(self, ast, ctx=None): 345 self.ast = ast 346 self.ctx = _get_ctx(ctx) 347 Z3_inc_ref(self.ctx.ref(), self.as_ast()) 348 349 def __del__(self): 350 if self.ctx.ref() is not None and self.ast is not None: 351 Z3_dec_ref(self.ctx.ref(), self.as_ast()) 352 self.ast = None 353 354 def __deepcopy__(self, memo={}): 355 return _to_ast_ref(self.ast, self.ctx) 356 357 def __str__(self): 358 return obj_to_string(self) 359 360 def __repr__(self): 361 return obj_to_string(self) 362 363 def __eq__(self, other): 364 return self.eq(other) 365 366 def __hash__(self): 367 return self.hash() 368 369 def __nonzero__(self): 370 return self.__bool__() 371 372 def __bool__(self): 373 if is_true(self): 374 return True 375 elif is_false(self): 376 return False 377 elif is_eq(self) and self.num_args() == 2: 378 return self.arg(0).eq(self.arg(1)) 379 else: 380 raise Z3Exception("Symbolic expressions cannot be cast to concrete Boolean values.") 381 382 def sexpr(self): 383 """Return a string representing the AST node in s-expression notation. 384 385 >>> x = Int('x') 386 >>> ((x + 1)*x).sexpr() 387 '(* (+ x 1) x)' 388 """ 389 return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) 390 391 def as_ast(self): 392 """Return a pointer to the corresponding C Z3_ast object.""" 393 return self.ast 394 395 def get_id(self): 396 """Return unique identifier for object. It can be used for hash-tables and maps.""" 397 return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) 398 399 def ctx_ref(self): 400 """Return a reference to the C context where this AST node is stored.""" 401 return self.ctx.ref() 402 403 def eq(self, other): 404 """Return `True` if `self` and `other` are structurally identical. 405 406 >>> x = Int('x') 407 >>> n1 = x + 1 408 >>> n2 = 1 + x 409 >>> n1.eq(n2) 410 False 411 >>> n1 = simplify(n1) 412 >>> n2 = simplify(n2) 413 >>> n1.eq(n2) 414 True 415 """ 416 if z3_debug(): 417 _z3_assert(is_ast(other), "Z3 AST expected") 418 return Z3_is_eq_ast(self.ctx_ref(), self.as_ast(), other.as_ast()) 419 420 def translate(self, target): 421 """Translate `self` to the context `target`. That is, return a copy of `self` in the context `target`. 422 423 >>> c1 = Context() 424 >>> c2 = Context() 425 >>> x = Int('x', c1) 426 >>> y = Int('y', c2) 427 >>> # Nodes in different contexts can't be mixed. 428 >>> # However, we can translate nodes from one context to another. 429 >>> x.translate(c2) + y 430 x + y 431 """ 432 if z3_debug(): 433 _z3_assert(isinstance(target, Context), "argument must be a Z3 context") 434 return _to_ast_ref(Z3_translate(self.ctx.ref(), self.as_ast(), target.ref()), target) 435 436 def __copy__(self): 437 return self.translate(self.ctx) 438 439 def hash(self): 440 """Return a hashcode for the `self`. 441 442 >>> n1 = simplify(Int('x') + 1) 443 >>> n2 = simplify(2 + Int('x') - 1) 444 >>> n1.hash() == n2.hash() 445 True 446 """ 447 return Z3_get_ast_hash(self.ctx_ref(), self.as_ast()) 448 449 450def is_ast(a): 451 """Return `True` if `a` is an AST node. 452 453 >>> is_ast(10) 454 False 455 >>> is_ast(IntVal(10)) 456 True 457 >>> is_ast(Int('x')) 458 True 459 >>> is_ast(BoolSort()) 460 True 461 >>> is_ast(Function('f', IntSort(), IntSort())) 462 True 463 >>> is_ast("x") 464 False 465 >>> is_ast(Solver()) 466 False 467 """ 468 return isinstance(a, AstRef) 469 470 471def eq(a, b): 472 """Return `True` if `a` and `b` are structurally identical AST nodes. 473 474 >>> x = Int('x') 475 >>> y = Int('y') 476 >>> eq(x, y) 477 False 478 >>> eq(x + 1, x + 1) 479 True 480 >>> eq(x + 1, 1 + x) 481 False 482 >>> eq(simplify(x + 1), simplify(1 + x)) 483 True 484 """ 485 if z3_debug(): 486 _z3_assert(is_ast(a) and is_ast(b), "Z3 ASTs expected") 487 return a.eq(b) 488 489 490def _ast_kind(ctx, a): 491 if is_ast(a): 492 a = a.as_ast() 493 return Z3_get_ast_kind(ctx.ref(), a) 494 495 496def _ctx_from_ast_arg_list(args, default_ctx=None): 497 ctx = None 498 for a in args: 499 if is_ast(a) or is_probe(a): 500 if ctx is None: 501 ctx = a.ctx 502 else: 503 if z3_debug(): 504 _z3_assert(ctx == a.ctx, "Context mismatch") 505 if ctx is None: 506 ctx = default_ctx 507 return ctx 508 509 510def _ctx_from_ast_args(*args): 511 return _ctx_from_ast_arg_list(args) 512 513 514def _to_func_decl_array(args): 515 sz = len(args) 516 _args = (FuncDecl * sz)() 517 for i in range(sz): 518 _args[i] = args[i].as_func_decl() 519 return _args, sz 520 521 522def _to_ast_array(args): 523 sz = len(args) 524 _args = (Ast * sz)() 525 for i in range(sz): 526 _args[i] = args[i].as_ast() 527 return _args, sz 528 529 530def _to_ref_array(ref, args): 531 sz = len(args) 532 _args = (ref * sz)() 533 for i in range(sz): 534 _args[i] = args[i].as_ast() 535 return _args, sz 536 537 538def _to_ast_ref(a, ctx): 539 k = _ast_kind(ctx, a) 540 if k == Z3_SORT_AST: 541 return _to_sort_ref(a, ctx) 542 elif k == Z3_FUNC_DECL_AST: 543 return _to_func_decl_ref(a, ctx) 544 else: 545 return _to_expr_ref(a, ctx) 546 547 548######################################### 549# 550# Sorts 551# 552######################################### 553 554def _sort_kind(ctx, s): 555 return Z3_get_sort_kind(ctx.ref(), s) 556 557 558class SortRef(AstRef): 559 """A Sort is essentially a type. Every Z3 expression has a sort. A sort is an AST node.""" 560 561 def as_ast(self): 562 return Z3_sort_to_ast(self.ctx_ref(), self.ast) 563 564 def get_id(self): 565 return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) 566 567 def kind(self): 568 """Return the Z3 internal kind of a sort. 569 This method can be used to test if `self` is one of the Z3 builtin sorts. 570 571 >>> b = BoolSort() 572 >>> b.kind() == Z3_BOOL_SORT 573 True 574 >>> b.kind() == Z3_INT_SORT 575 False 576 >>> A = ArraySort(IntSort(), IntSort()) 577 >>> A.kind() == Z3_ARRAY_SORT 578 True 579 >>> A.kind() == Z3_INT_SORT 580 False 581 """ 582 return _sort_kind(self.ctx, self.ast) 583 584 def subsort(self, other): 585 """Return `True` if `self` is a subsort of `other`. 586 587 >>> IntSort().subsort(RealSort()) 588 True 589 """ 590 return False 591 592 def cast(self, val): 593 """Try to cast `val` as an element of sort `self`. 594 595 This method is used in Z3Py to convert Python objects such as integers, 596 floats, longs and strings into Z3 expressions. 597 598 >>> x = Int('x') 599 >>> RealSort().cast(x) 600 ToReal(x) 601 """ 602 if z3_debug(): 603 _z3_assert(is_expr(val), "Z3 expression expected") 604 _z3_assert(self.eq(val.sort()), "Sort mismatch") 605 return val 606 607 def name(self): 608 """Return the name (string) of sort `self`. 609 610 >>> BoolSort().name() 611 'Bool' 612 >>> ArraySort(IntSort(), IntSort()).name() 613 'Array' 614 """ 615 return _symbol2py(self.ctx, Z3_get_sort_name(self.ctx_ref(), self.ast)) 616 617 def __eq__(self, other): 618 """Return `True` if `self` and `other` are the same Z3 sort. 619 620 >>> p = Bool('p') 621 >>> p.sort() == BoolSort() 622 True 623 >>> p.sort() == IntSort() 624 False 625 """ 626 if other is None: 627 return False 628 return Z3_is_eq_sort(self.ctx_ref(), self.ast, other.ast) 629 630 def __ne__(self, other): 631 """Return `True` if `self` and `other` are not the same Z3 sort. 632 633 >>> p = Bool('p') 634 >>> p.sort() != BoolSort() 635 False 636 >>> p.sort() != IntSort() 637 True 638 """ 639 return not Z3_is_eq_sort(self.ctx_ref(), self.ast, other.ast) 640 641 def __hash__(self): 642 """ Hash code. """ 643 return AstRef.__hash__(self) 644 645 646def is_sort(s): 647 """Return `True` if `s` is a Z3 sort. 648 649 >>> is_sort(IntSort()) 650 True 651 >>> is_sort(Int('x')) 652 False 653 >>> is_expr(Int('x')) 654 True 655 """ 656 return isinstance(s, SortRef) 657 658 659def _to_sort_ref(s, ctx): 660 if z3_debug(): 661 _z3_assert(isinstance(s, Sort), "Z3 Sort expected") 662 k = _sort_kind(ctx, s) 663 if k == Z3_BOOL_SORT: 664 return BoolSortRef(s, ctx) 665 elif k == Z3_INT_SORT or k == Z3_REAL_SORT: 666 return ArithSortRef(s, ctx) 667 elif k == Z3_BV_SORT: 668 return BitVecSortRef(s, ctx) 669 elif k == Z3_ARRAY_SORT: 670 return ArraySortRef(s, ctx) 671 elif k == Z3_DATATYPE_SORT: 672 return DatatypeSortRef(s, ctx) 673 elif k == Z3_FINITE_DOMAIN_SORT: 674 return FiniteDomainSortRef(s, ctx) 675 elif k == Z3_FLOATING_POINT_SORT: 676 return FPSortRef(s, ctx) 677 elif k == Z3_ROUNDING_MODE_SORT: 678 return FPRMSortRef(s, ctx) 679 elif k == Z3_RE_SORT: 680 return ReSortRef(s, ctx) 681 elif k == Z3_SEQ_SORT: 682 return SeqSortRef(s, ctx) 683 elif k == Z3_CHAR_SORT: 684 return CharSortRef(s, ctx) 685 return SortRef(s, ctx) 686 687 688def _sort(ctx, a): 689 return _to_sort_ref(Z3_get_sort(ctx.ref(), a), ctx) 690 691 692def DeclareSort(name, ctx=None): 693 """Create a new uninterpreted sort named `name`. 694 695 If `ctx=None`, then the new sort is declared in the global Z3Py context. 696 697 >>> A = DeclareSort('A') 698 >>> a = Const('a', A) 699 >>> b = Const('b', A) 700 >>> a.sort() == A 701 True 702 >>> b.sort() == A 703 True 704 >>> a == b 705 a == b 706 """ 707 ctx = _get_ctx(ctx) 708 return SortRef(Z3_mk_uninterpreted_sort(ctx.ref(), to_symbol(name, ctx)), ctx) 709 710######################################### 711# 712# Function Declarations 713# 714######################################### 715 716 717class FuncDeclRef(AstRef): 718 """Function declaration. Every constant and function have an associated declaration. 719 720 The declaration assigns a name, a sort (i.e., type), and for function 721 the sort (i.e., type) of each of its arguments. Note that, in Z3, 722 a constant is a function with 0 arguments. 723 """ 724 725 def as_ast(self): 726 return Z3_func_decl_to_ast(self.ctx_ref(), self.ast) 727 728 def get_id(self): 729 return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) 730 731 def as_func_decl(self): 732 return self.ast 733 734 def name(self): 735 """Return the name of the function declaration `self`. 736 737 >>> f = Function('f', IntSort(), IntSort()) 738 >>> f.name() 739 'f' 740 >>> isinstance(f.name(), str) 741 True 742 """ 743 return _symbol2py(self.ctx, Z3_get_decl_name(self.ctx_ref(), self.ast)) 744 745 def arity(self): 746 """Return the number of arguments of a function declaration. 747 If `self` is a constant, then `self.arity()` is 0. 748 749 >>> f = Function('f', IntSort(), RealSort(), BoolSort()) 750 >>> f.arity() 751 2 752 """ 753 return int(Z3_get_arity(self.ctx_ref(), self.ast)) 754 755 def domain(self, i): 756 """Return the sort of the argument `i` of a function declaration. 757 This method assumes that `0 <= i < self.arity()`. 758 759 >>> f = Function('f', IntSort(), RealSort(), BoolSort()) 760 >>> f.domain(0) 761 Int 762 >>> f.domain(1) 763 Real 764 """ 765 if z3_debug(): 766 _z3_assert(i < self.arity(), "Index out of bounds") 767 return _to_sort_ref(Z3_get_domain(self.ctx_ref(), self.ast, i), self.ctx) 768 769 def range(self): 770 """Return the sort of the range of a function declaration. 771 For constants, this is the sort of the constant. 772 773 >>> f = Function('f', IntSort(), RealSort(), BoolSort()) 774 >>> f.range() 775 Bool 776 """ 777 return _to_sort_ref(Z3_get_range(self.ctx_ref(), self.ast), self.ctx) 778 779 def kind(self): 780 """Return the internal kind of a function declaration. 781 It can be used to identify Z3 built-in functions such as addition, multiplication, etc. 782 783 >>> x = Int('x') 784 >>> d = (x + 1).decl() 785 >>> d.kind() == Z3_OP_ADD 786 True 787 >>> d.kind() == Z3_OP_MUL 788 False 789 """ 790 return Z3_get_decl_kind(self.ctx_ref(), self.ast) 791 792 def params(self): 793 ctx = self.ctx 794 n = Z3_get_decl_num_parameters(self.ctx_ref(), self.ast) 795 result = [None for i in range(n)] 796 for i in range(n): 797 k = Z3_get_decl_parameter_kind(self.ctx_ref(), self.ast, i) 798 if k == Z3_PARAMETER_INT: 799 result[i] = Z3_get_decl_int_parameter(self.ctx_ref(), self.ast, i) 800 elif k == Z3_PARAMETER_DOUBLE: 801 result[i] = Z3_get_decl_double_parameter(self.ctx_ref(), self.ast, i) 802 elif k == Z3_PARAMETER_RATIONAL: 803 result[i] = Z3_get_decl_rational_parameter(self.ctx_ref(), self.ast, i) 804 elif k == Z3_PARAMETER_SYMBOL: 805 result[i] = Z3_get_decl_symbol_parameter(self.ctx_ref(), self.ast, i) 806 elif k == Z3_PARAMETER_SORT: 807 result[i] = SortRef(Z3_get_decl_sort_parameter(self.ctx_ref(), self.ast, i), ctx) 808 elif k == Z3_PARAMETER_AST: 809 result[i] = ExprRef(Z3_get_decl_ast_parameter(self.ctx_ref(), self.ast, i), ctx) 810 elif k == Z3_PARAMETER_FUNC_DECL: 811 result[i] = FuncDeclRef(Z3_get_decl_func_decl_parameter(self.ctx_ref(), self.ast, i), ctx) 812 else: 813 assert(False) 814 return result 815 816 def __call__(self, *args): 817 """Create a Z3 application expression using the function `self`, and the given arguments. 818 819 The arguments must be Z3 expressions. This method assumes that 820 the sorts of the elements in `args` match the sorts of the 821 domain. Limited coercion is supported. For example, if 822 args[0] is a Python integer, and the function expects a Z3 823 integer, then the argument is automatically converted into a 824 Z3 integer. 825 826 >>> f = Function('f', IntSort(), RealSort(), BoolSort()) 827 >>> x = Int('x') 828 >>> y = Real('y') 829 >>> f(x, y) 830 f(x, y) 831 >>> f(x, x) 832 f(x, ToReal(x)) 833 """ 834 args = _get_args(args) 835 num = len(args) 836 if z3_debug(): 837 _z3_assert(num == self.arity(), "Incorrect number of arguments to %s" % self) 838 _args = (Ast * num)() 839 saved = [] 840 for i in range(num): 841 # self.domain(i).cast(args[i]) may create a new Z3 expression, 842 # then we must save in 'saved' to prevent it from being garbage collected. 843 tmp = self.domain(i).cast(args[i]) 844 saved.append(tmp) 845 _args[i] = tmp.as_ast() 846 return _to_expr_ref(Z3_mk_app(self.ctx_ref(), self.ast, len(args), _args), self.ctx) 847 848 849def is_func_decl(a): 850 """Return `True` if `a` is a Z3 function declaration. 851 852 >>> f = Function('f', IntSort(), IntSort()) 853 >>> is_func_decl(f) 854 True 855 >>> x = Real('x') 856 >>> is_func_decl(x) 857 False 858 """ 859 return isinstance(a, FuncDeclRef) 860 861 862def Function(name, *sig): 863 """Create a new Z3 uninterpreted function with the given sorts. 864 865 >>> f = Function('f', IntSort(), IntSort()) 866 >>> f(f(0)) 867 f(f(0)) 868 """ 869 sig = _get_args(sig) 870 if z3_debug(): 871 _z3_assert(len(sig) > 0, "At least two arguments expected") 872 arity = len(sig) - 1 873 rng = sig[arity] 874 if z3_debug(): 875 _z3_assert(is_sort(rng), "Z3 sort expected") 876 dom = (Sort * arity)() 877 for i in range(arity): 878 if z3_debug(): 879 _z3_assert(is_sort(sig[i]), "Z3 sort expected") 880 dom[i] = sig[i].ast 881 ctx = rng.ctx 882 return FuncDeclRef(Z3_mk_func_decl(ctx.ref(), to_symbol(name, ctx), arity, dom, rng.ast), ctx) 883 884 885def FreshFunction(*sig): 886 """Create a new fresh Z3 uninterpreted function with the given sorts. 887 """ 888 sig = _get_args(sig) 889 if z3_debug(): 890 _z3_assert(len(sig) > 0, "At least two arguments expected") 891 arity = len(sig) - 1 892 rng = sig[arity] 893 if z3_debug(): 894 _z3_assert(is_sort(rng), "Z3 sort expected") 895 dom = (z3.Sort * arity)() 896 for i in range(arity): 897 if z3_debug(): 898 _z3_assert(is_sort(sig[i]), "Z3 sort expected") 899 dom[i] = sig[i].ast 900 ctx = rng.ctx 901 return FuncDeclRef(Z3_mk_fresh_func_decl(ctx.ref(), "f", arity, dom, rng.ast), ctx) 902 903 904def _to_func_decl_ref(a, ctx): 905 return FuncDeclRef(a, ctx) 906 907 908def RecFunction(name, *sig): 909 """Create a new Z3 recursive with the given sorts.""" 910 sig = _get_args(sig) 911 if z3_debug(): 912 _z3_assert(len(sig) > 0, "At least two arguments expected") 913 arity = len(sig) - 1 914 rng = sig[arity] 915 if z3_debug(): 916 _z3_assert(is_sort(rng), "Z3 sort expected") 917 dom = (Sort * arity)() 918 for i in range(arity): 919 if z3_debug(): 920 _z3_assert(is_sort(sig[i]), "Z3 sort expected") 921 dom[i] = sig[i].ast 922 ctx = rng.ctx 923 return FuncDeclRef(Z3_mk_rec_func_decl(ctx.ref(), to_symbol(name, ctx), arity, dom, rng.ast), ctx) 924 925 926def RecAddDefinition(f, args, body): 927 """Set the body of a recursive function. 928 Recursive definitions can be simplified if they are applied to ground 929 arguments. 930 >>> ctx = Context() 931 >>> fac = RecFunction('fac', IntSort(ctx), IntSort(ctx)) 932 >>> n = Int('n', ctx) 933 >>> RecAddDefinition(fac, n, If(n == 0, 1, n*fac(n-1))) 934 >>> simplify(fac(5)) 935 120 936 >>> s = Solver(ctx=ctx) 937 >>> s.add(fac(n) < 3) 938 >>> s.check() 939 sat 940 >>> s.model().eval(fac(5)) 941 120 942 """ 943 if is_app(args): 944 args = [args] 945 ctx = body.ctx 946 args = _get_args(args) 947 n = len(args) 948 _args = (Ast * n)() 949 for i in range(n): 950 _args[i] = args[i].ast 951 Z3_add_rec_def(ctx.ref(), f.ast, n, _args, body.ast) 952 953######################################### 954# 955# Expressions 956# 957######################################### 958 959 960class ExprRef(AstRef): 961 """Constraints, formulas and terms are expressions in Z3. 962 963 Expressions are ASTs. Every expression has a sort. 964 There are three main kinds of expressions: 965 function applications, quantifiers and bounded variables. 966 A constant is a function application with 0 arguments. 967 For quantifier free problems, all expressions are 968 function applications. 969 """ 970 971 def as_ast(self): 972 return self.ast 973 974 def get_id(self): 975 return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) 976 977 def sort(self): 978 """Return the sort of expression `self`. 979 980 >>> x = Int('x') 981 >>> (x + 1).sort() 982 Int 983 >>> y = Real('y') 984 >>> (x + y).sort() 985 Real 986 """ 987 return _sort(self.ctx, self.as_ast()) 988 989 def sort_kind(self): 990 """Shorthand for `self.sort().kind()`. 991 992 >>> a = Array('a', IntSort(), IntSort()) 993 >>> a.sort_kind() == Z3_ARRAY_SORT 994 True 995 >>> a.sort_kind() == Z3_INT_SORT 996 False 997 """ 998 return self.sort().kind() 999 1000 def __eq__(self, other): 1001 """Return a Z3 expression that represents the constraint `self == other`. 1002 1003 If `other` is `None`, then this method simply returns `False`. 1004 1005 >>> a = Int('a') 1006 >>> b = Int('b') 1007 >>> a == b 1008 a == b 1009 >>> a is None 1010 False 1011 """ 1012 if other is None: 1013 return False 1014 a, b = _coerce_exprs(self, other) 1015 return BoolRef(Z3_mk_eq(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 1016 1017 def __hash__(self): 1018 """ Hash code. """ 1019 return AstRef.__hash__(self) 1020 1021 def __ne__(self, other): 1022 """Return a Z3 expression that represents the constraint `self != other`. 1023 1024 If `other` is `None`, then this method simply returns `True`. 1025 1026 >>> a = Int('a') 1027 >>> b = Int('b') 1028 >>> a != b 1029 a != b 1030 >>> a is not None 1031 True 1032 """ 1033 if other is None: 1034 return True 1035 a, b = _coerce_exprs(self, other) 1036 _args, sz = _to_ast_array((a, b)) 1037 return BoolRef(Z3_mk_distinct(self.ctx_ref(), 2, _args), self.ctx) 1038 1039 def params(self): 1040 return self.decl().params() 1041 1042 def decl(self): 1043 """Return the Z3 function declaration associated with a Z3 application. 1044 1045 >>> f = Function('f', IntSort(), IntSort()) 1046 >>> a = Int('a') 1047 >>> t = f(a) 1048 >>> eq(t.decl(), f) 1049 True 1050 >>> (a + 1).decl() 1051 + 1052 """ 1053 if z3_debug(): 1054 _z3_assert(is_app(self), "Z3 application expected") 1055 return FuncDeclRef(Z3_get_app_decl(self.ctx_ref(), self.as_ast()), self.ctx) 1056 1057 def num_args(self): 1058 """Return the number of arguments of a Z3 application. 1059 1060 >>> a = Int('a') 1061 >>> b = Int('b') 1062 >>> (a + b).num_args() 1063 2 1064 >>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort()) 1065 >>> t = f(a, b, 0) 1066 >>> t.num_args() 1067 3 1068 """ 1069 if z3_debug(): 1070 _z3_assert(is_app(self), "Z3 application expected") 1071 return int(Z3_get_app_num_args(self.ctx_ref(), self.as_ast())) 1072 1073 def arg(self, idx): 1074 """Return argument `idx` of the application `self`. 1075 1076 This method assumes that `self` is a function application with at least `idx+1` arguments. 1077 1078 >>> a = Int('a') 1079 >>> b = Int('b') 1080 >>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort()) 1081 >>> t = f(a, b, 0) 1082 >>> t.arg(0) 1083 a 1084 >>> t.arg(1) 1085 b 1086 >>> t.arg(2) 1087 0 1088 """ 1089 if z3_debug(): 1090 _z3_assert(is_app(self), "Z3 application expected") 1091 _z3_assert(idx < self.num_args(), "Invalid argument index") 1092 return _to_expr_ref(Z3_get_app_arg(self.ctx_ref(), self.as_ast(), idx), self.ctx) 1093 1094 def children(self): 1095 """Return a list containing the children of the given expression 1096 1097 >>> a = Int('a') 1098 >>> b = Int('b') 1099 >>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort()) 1100 >>> t = f(a, b, 0) 1101 >>> t.children() 1102 [a, b, 0] 1103 """ 1104 if is_app(self): 1105 return [self.arg(i) for i in range(self.num_args())] 1106 else: 1107 return [] 1108 1109 1110def _to_expr_ref(a, ctx): 1111 if isinstance(a, Pattern): 1112 return PatternRef(a, ctx) 1113 ctx_ref = ctx.ref() 1114 k = Z3_get_ast_kind(ctx_ref, a) 1115 if k == Z3_QUANTIFIER_AST: 1116 return QuantifierRef(a, ctx) 1117 sk = Z3_get_sort_kind(ctx_ref, Z3_get_sort(ctx_ref, a)) 1118 if sk == Z3_BOOL_SORT: 1119 return BoolRef(a, ctx) 1120 if sk == Z3_INT_SORT: 1121 if k == Z3_NUMERAL_AST: 1122 return IntNumRef(a, ctx) 1123 return ArithRef(a, ctx) 1124 if sk == Z3_REAL_SORT: 1125 if k == Z3_NUMERAL_AST: 1126 return RatNumRef(a, ctx) 1127 if _is_algebraic(ctx, a): 1128 return AlgebraicNumRef(a, ctx) 1129 return ArithRef(a, ctx) 1130 if sk == Z3_BV_SORT: 1131 if k == Z3_NUMERAL_AST: 1132 return BitVecNumRef(a, ctx) 1133 else: 1134 return BitVecRef(a, ctx) 1135 if sk == Z3_ARRAY_SORT: 1136 return ArrayRef(a, ctx) 1137 if sk == Z3_DATATYPE_SORT: 1138 return DatatypeRef(a, ctx) 1139 if sk == Z3_FLOATING_POINT_SORT: 1140 if k == Z3_APP_AST and _is_numeral(ctx, a): 1141 return FPNumRef(a, ctx) 1142 else: 1143 return FPRef(a, ctx) 1144 if sk == Z3_FINITE_DOMAIN_SORT: 1145 if k == Z3_NUMERAL_AST: 1146 return FiniteDomainNumRef(a, ctx) 1147 else: 1148 return FiniteDomainRef(a, ctx) 1149 if sk == Z3_ROUNDING_MODE_SORT: 1150 return FPRMRef(a, ctx) 1151 if sk == Z3_SEQ_SORT: 1152 return SeqRef(a, ctx) 1153 if sk == Z3_RE_SORT: 1154 return ReRef(a, ctx) 1155 return ExprRef(a, ctx) 1156 1157 1158def _coerce_expr_merge(s, a): 1159 if is_expr(a): 1160 s1 = a.sort() 1161 if s is None: 1162 return s1 1163 if s1.eq(s): 1164 return s 1165 elif s.subsort(s1): 1166 return s1 1167 elif s1.subsort(s): 1168 return s 1169 else: 1170 if z3_debug(): 1171 _z3_assert(s1.ctx == s.ctx, "context mismatch") 1172 _z3_assert(False, "sort mismatch") 1173 else: 1174 return s 1175 1176 1177def _coerce_exprs(a, b, ctx=None): 1178 if not is_expr(a) and not is_expr(b): 1179 a = _py2expr(a, ctx) 1180 b = _py2expr(b, ctx) 1181 if isinstance(a, str) and isinstance(b, SeqRef): 1182 a = StringVal(a, b.ctx) 1183 if isinstance(b, str) and isinstance(a, SeqRef): 1184 b = StringVal(b, a.ctx) 1185 s = None 1186 s = _coerce_expr_merge(s, a) 1187 s = _coerce_expr_merge(s, b) 1188 a = s.cast(a) 1189 b = s.cast(b) 1190 return (a, b) 1191 1192 1193def _reduce(func, sequence, initial): 1194 result = initial 1195 for element in sequence: 1196 result = func(result, element) 1197 return result 1198 1199 1200def _coerce_expr_list(alist, ctx=None): 1201 has_expr = False 1202 for a in alist: 1203 if is_expr(a): 1204 has_expr = True 1205 break 1206 if not has_expr: 1207 alist = [_py2expr(a, ctx) for a in alist] 1208 s = _reduce(_coerce_expr_merge, alist, None) 1209 return [s.cast(a) for a in alist] 1210 1211 1212def is_expr(a): 1213 """Return `True` if `a` is a Z3 expression. 1214 1215 >>> a = Int('a') 1216 >>> is_expr(a) 1217 True 1218 >>> is_expr(a + 1) 1219 True 1220 >>> is_expr(IntSort()) 1221 False 1222 >>> is_expr(1) 1223 False 1224 >>> is_expr(IntVal(1)) 1225 True 1226 >>> x = Int('x') 1227 >>> is_expr(ForAll(x, x >= 0)) 1228 True 1229 >>> is_expr(FPVal(1.0)) 1230 True 1231 """ 1232 return isinstance(a, ExprRef) 1233 1234 1235def is_app(a): 1236 """Return `True` if `a` is a Z3 function application. 1237 1238 Note that, constants are function applications with 0 arguments. 1239 1240 >>> a = Int('a') 1241 >>> is_app(a) 1242 True 1243 >>> is_app(a + 1) 1244 True 1245 >>> is_app(IntSort()) 1246 False 1247 >>> is_app(1) 1248 False 1249 >>> is_app(IntVal(1)) 1250 True 1251 >>> x = Int('x') 1252 >>> is_app(ForAll(x, x >= 0)) 1253 False 1254 """ 1255 if not isinstance(a, ExprRef): 1256 return False 1257 k = _ast_kind(a.ctx, a) 1258 return k == Z3_NUMERAL_AST or k == Z3_APP_AST 1259 1260 1261def is_const(a): 1262 """Return `True` if `a` is Z3 constant/variable expression. 1263 1264 >>> a = Int('a') 1265 >>> is_const(a) 1266 True 1267 >>> is_const(a + 1) 1268 False 1269 >>> is_const(1) 1270 False 1271 >>> is_const(IntVal(1)) 1272 True 1273 >>> x = Int('x') 1274 >>> is_const(ForAll(x, x >= 0)) 1275 False 1276 """ 1277 return is_app(a) and a.num_args() == 0 1278 1279 1280def is_var(a): 1281 """Return `True` if `a` is variable. 1282 1283 Z3 uses de-Bruijn indices for representing bound variables in 1284 quantifiers. 1285 1286 >>> x = Int('x') 1287 >>> is_var(x) 1288 False 1289 >>> is_const(x) 1290 True 1291 >>> f = Function('f', IntSort(), IntSort()) 1292 >>> # Z3 replaces x with bound variables when ForAll is executed. 1293 >>> q = ForAll(x, f(x) == x) 1294 >>> b = q.body() 1295 >>> b 1296 f(Var(0)) == Var(0) 1297 >>> b.arg(1) 1298 Var(0) 1299 >>> is_var(b.arg(1)) 1300 True 1301 """ 1302 return is_expr(a) and _ast_kind(a.ctx, a) == Z3_VAR_AST 1303 1304 1305def get_var_index(a): 1306 """Return the de-Bruijn index of the Z3 bounded variable `a`. 1307 1308 >>> x = Int('x') 1309 >>> y = Int('y') 1310 >>> is_var(x) 1311 False 1312 >>> is_const(x) 1313 True 1314 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 1315 >>> # Z3 replaces x and y with bound variables when ForAll is executed. 1316 >>> q = ForAll([x, y], f(x, y) == x + y) 1317 >>> q.body() 1318 f(Var(1), Var(0)) == Var(1) + Var(0) 1319 >>> b = q.body() 1320 >>> b.arg(0) 1321 f(Var(1), Var(0)) 1322 >>> v1 = b.arg(0).arg(0) 1323 >>> v2 = b.arg(0).arg(1) 1324 >>> v1 1325 Var(1) 1326 >>> v2 1327 Var(0) 1328 >>> get_var_index(v1) 1329 1 1330 >>> get_var_index(v2) 1331 0 1332 """ 1333 if z3_debug(): 1334 _z3_assert(is_var(a), "Z3 bound variable expected") 1335 return int(Z3_get_index_value(a.ctx.ref(), a.as_ast())) 1336 1337 1338def is_app_of(a, k): 1339 """Return `True` if `a` is an application of the given kind `k`. 1340 1341 >>> x = Int('x') 1342 >>> n = x + 1 1343 >>> is_app_of(n, Z3_OP_ADD) 1344 True 1345 >>> is_app_of(n, Z3_OP_MUL) 1346 False 1347 """ 1348 return is_app(a) and a.decl().kind() == k 1349 1350 1351def If(a, b, c, ctx=None): 1352 """Create a Z3 if-then-else expression. 1353 1354 >>> x = Int('x') 1355 >>> y = Int('y') 1356 >>> max = If(x > y, x, y) 1357 >>> max 1358 If(x > y, x, y) 1359 >>> simplify(max) 1360 If(x <= y, y, x) 1361 """ 1362 if isinstance(a, Probe) or isinstance(b, Tactic) or isinstance(c, Tactic): 1363 return Cond(a, b, c, ctx) 1364 else: 1365 ctx = _get_ctx(_ctx_from_ast_arg_list([a, b, c], ctx)) 1366 s = BoolSort(ctx) 1367 a = s.cast(a) 1368 b, c = _coerce_exprs(b, c, ctx) 1369 if z3_debug(): 1370 _z3_assert(a.ctx == b.ctx, "Context mismatch") 1371 return _to_expr_ref(Z3_mk_ite(ctx.ref(), a.as_ast(), b.as_ast(), c.as_ast()), ctx) 1372 1373 1374def Distinct(*args): 1375 """Create a Z3 distinct expression. 1376 1377 >>> x = Int('x') 1378 >>> y = Int('y') 1379 >>> Distinct(x, y) 1380 x != y 1381 >>> z = Int('z') 1382 >>> Distinct(x, y, z) 1383 Distinct(x, y, z) 1384 >>> simplify(Distinct(x, y, z)) 1385 Distinct(x, y, z) 1386 >>> simplify(Distinct(x, y, z), blast_distinct=True) 1387 And(Not(x == y), Not(x == z), Not(y == z)) 1388 """ 1389 args = _get_args(args) 1390 ctx = _ctx_from_ast_arg_list(args) 1391 if z3_debug(): 1392 _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression") 1393 args = _coerce_expr_list(args, ctx) 1394 _args, sz = _to_ast_array(args) 1395 return BoolRef(Z3_mk_distinct(ctx.ref(), sz, _args), ctx) 1396 1397 1398def _mk_bin(f, a, b): 1399 args = (Ast * 2)() 1400 if z3_debug(): 1401 _z3_assert(a.ctx == b.ctx, "Context mismatch") 1402 args[0] = a.as_ast() 1403 args[1] = b.as_ast() 1404 return f(a.ctx.ref(), 2, args) 1405 1406 1407def Const(name, sort): 1408 """Create a constant of the given sort. 1409 1410 >>> Const('x', IntSort()) 1411 x 1412 """ 1413 if z3_debug(): 1414 _z3_assert(isinstance(sort, SortRef), "Z3 sort expected") 1415 ctx = sort.ctx 1416 return _to_expr_ref(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), sort.ast), ctx) 1417 1418 1419def Consts(names, sort): 1420 """Create several constants of the given sort. 1421 1422 `names` is a string containing the names of all constants to be created. 1423 Blank spaces separate the names of different constants. 1424 1425 >>> x, y, z = Consts('x y z', IntSort()) 1426 >>> x + y + z 1427 x + y + z 1428 """ 1429 if isinstance(names, str): 1430 names = names.split(" ") 1431 return [Const(name, sort) for name in names] 1432 1433 1434def FreshConst(sort, prefix="c"): 1435 """Create a fresh constant of a specified sort""" 1436 ctx = _get_ctx(sort.ctx) 1437 return _to_expr_ref(Z3_mk_fresh_const(ctx.ref(), prefix, sort.ast), ctx) 1438 1439 1440def Var(idx, s): 1441 """Create a Z3 free variable. Free variables are used to create quantified formulas. 1442 1443 >>> Var(0, IntSort()) 1444 Var(0) 1445 >>> eq(Var(0, IntSort()), Var(0, BoolSort())) 1446 False 1447 """ 1448 if z3_debug(): 1449 _z3_assert(is_sort(s), "Z3 sort expected") 1450 return _to_expr_ref(Z3_mk_bound(s.ctx_ref(), idx, s.ast), s.ctx) 1451 1452 1453def RealVar(idx, ctx=None): 1454 """ 1455 Create a real free variable. Free variables are used to create quantified formulas. 1456 They are also used to create polynomials. 1457 1458 >>> RealVar(0) 1459 Var(0) 1460 """ 1461 return Var(idx, RealSort(ctx)) 1462 1463 1464def RealVarVector(n, ctx=None): 1465 """ 1466 Create a list of Real free variables. 1467 The variables have ids: 0, 1, ..., n-1 1468 1469 >>> x0, x1, x2, x3 = RealVarVector(4) 1470 >>> x2 1471 Var(2) 1472 """ 1473 return [RealVar(i, ctx) for i in range(n)] 1474 1475######################################### 1476# 1477# Booleans 1478# 1479######################################### 1480 1481 1482class BoolSortRef(SortRef): 1483 """Boolean sort.""" 1484 1485 def cast(self, val): 1486 """Try to cast `val` as a Boolean. 1487 1488 >>> x = BoolSort().cast(True) 1489 >>> x 1490 True 1491 >>> is_expr(x) 1492 True 1493 >>> is_expr(True) 1494 False 1495 >>> x.sort() 1496 Bool 1497 """ 1498 if isinstance(val, bool): 1499 return BoolVal(val, self.ctx) 1500 if z3_debug(): 1501 if not is_expr(val): 1502 msg = "True, False or Z3 Boolean expression expected. Received %s of type %s" 1503 _z3_assert(is_expr(val), msg % (val, type(val))) 1504 if not self.eq(val.sort()): 1505 _z3_assert(self.eq(val.sort()), "Value cannot be converted into a Z3 Boolean value") 1506 return val 1507 1508 def subsort(self, other): 1509 return isinstance(other, ArithSortRef) 1510 1511 def is_int(self): 1512 return True 1513 1514 def is_bool(self): 1515 return True 1516 1517 1518class BoolRef(ExprRef): 1519 """All Boolean expressions are instances of this class.""" 1520 1521 def sort(self): 1522 return BoolSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) 1523 1524 def __rmul__(self, other): 1525 return self * other 1526 1527 def __mul__(self, other): 1528 """Create the Z3 expression `self * other`. 1529 """ 1530 if other == 1: 1531 return self 1532 if other == 0: 1533 return 0 1534 return If(self, other, 0) 1535 1536 1537def is_bool(a): 1538 """Return `True` if `a` is a Z3 Boolean expression. 1539 1540 >>> p = Bool('p') 1541 >>> is_bool(p) 1542 True 1543 >>> q = Bool('q') 1544 >>> is_bool(And(p, q)) 1545 True 1546 >>> x = Real('x') 1547 >>> is_bool(x) 1548 False 1549 >>> is_bool(x == 0) 1550 True 1551 """ 1552 return isinstance(a, BoolRef) 1553 1554 1555def is_true(a): 1556 """Return `True` if `a` is the Z3 true expression. 1557 1558 >>> p = Bool('p') 1559 >>> is_true(p) 1560 False 1561 >>> is_true(simplify(p == p)) 1562 True 1563 >>> x = Real('x') 1564 >>> is_true(x == 0) 1565 False 1566 >>> # True is a Python Boolean expression 1567 >>> is_true(True) 1568 False 1569 """ 1570 return is_app_of(a, Z3_OP_TRUE) 1571 1572 1573def is_false(a): 1574 """Return `True` if `a` is the Z3 false expression. 1575 1576 >>> p = Bool('p') 1577 >>> is_false(p) 1578 False 1579 >>> is_false(False) 1580 False 1581 >>> is_false(BoolVal(False)) 1582 True 1583 """ 1584 return is_app_of(a, Z3_OP_FALSE) 1585 1586 1587def is_and(a): 1588 """Return `True` if `a` is a Z3 and expression. 1589 1590 >>> p, q = Bools('p q') 1591 >>> is_and(And(p, q)) 1592 True 1593 >>> is_and(Or(p, q)) 1594 False 1595 """ 1596 return is_app_of(a, Z3_OP_AND) 1597 1598 1599def is_or(a): 1600 """Return `True` if `a` is a Z3 or expression. 1601 1602 >>> p, q = Bools('p q') 1603 >>> is_or(Or(p, q)) 1604 True 1605 >>> is_or(And(p, q)) 1606 False 1607 """ 1608 return is_app_of(a, Z3_OP_OR) 1609 1610 1611def is_implies(a): 1612 """Return `True` if `a` is a Z3 implication expression. 1613 1614 >>> p, q = Bools('p q') 1615 >>> is_implies(Implies(p, q)) 1616 True 1617 >>> is_implies(And(p, q)) 1618 False 1619 """ 1620 return is_app_of(a, Z3_OP_IMPLIES) 1621 1622 1623def is_not(a): 1624 """Return `True` if `a` is a Z3 not expression. 1625 1626 >>> p = Bool('p') 1627 >>> is_not(p) 1628 False 1629 >>> is_not(Not(p)) 1630 True 1631 """ 1632 return is_app_of(a, Z3_OP_NOT) 1633 1634 1635def is_eq(a): 1636 """Return `True` if `a` is a Z3 equality expression. 1637 1638 >>> x, y = Ints('x y') 1639 >>> is_eq(x == y) 1640 True 1641 """ 1642 return is_app_of(a, Z3_OP_EQ) 1643 1644 1645def is_distinct(a): 1646 """Return `True` if `a` is a Z3 distinct expression. 1647 1648 >>> x, y, z = Ints('x y z') 1649 >>> is_distinct(x == y) 1650 False 1651 >>> is_distinct(Distinct(x, y, z)) 1652 True 1653 """ 1654 return is_app_of(a, Z3_OP_DISTINCT) 1655 1656 1657def BoolSort(ctx=None): 1658 """Return the Boolean Z3 sort. If `ctx=None`, then the global context is used. 1659 1660 >>> BoolSort() 1661 Bool 1662 >>> p = Const('p', BoolSort()) 1663 >>> is_bool(p) 1664 True 1665 >>> r = Function('r', IntSort(), IntSort(), BoolSort()) 1666 >>> r(0, 1) 1667 r(0, 1) 1668 >>> is_bool(r(0, 1)) 1669 True 1670 """ 1671 ctx = _get_ctx(ctx) 1672 return BoolSortRef(Z3_mk_bool_sort(ctx.ref()), ctx) 1673 1674 1675def BoolVal(val, ctx=None): 1676 """Return the Boolean value `True` or `False`. If `ctx=None`, then the global context is used. 1677 1678 >>> BoolVal(True) 1679 True 1680 >>> is_true(BoolVal(True)) 1681 True 1682 >>> is_true(True) 1683 False 1684 >>> is_false(BoolVal(False)) 1685 True 1686 """ 1687 ctx = _get_ctx(ctx) 1688 if val: 1689 return BoolRef(Z3_mk_true(ctx.ref()), ctx) 1690 else: 1691 return BoolRef(Z3_mk_false(ctx.ref()), ctx) 1692 1693 1694def Bool(name, ctx=None): 1695 """Return a Boolean constant named `name`. If `ctx=None`, then the global context is used. 1696 1697 >>> p = Bool('p') 1698 >>> q = Bool('q') 1699 >>> And(p, q) 1700 And(p, q) 1701 """ 1702 ctx = _get_ctx(ctx) 1703 return BoolRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), BoolSort(ctx).ast), ctx) 1704 1705 1706def Bools(names, ctx=None): 1707 """Return a tuple of Boolean constants. 1708 1709 `names` is a single string containing all names separated by blank spaces. 1710 If `ctx=None`, then the global context is used. 1711 1712 >>> p, q, r = Bools('p q r') 1713 >>> And(p, Or(q, r)) 1714 And(p, Or(q, r)) 1715 """ 1716 ctx = _get_ctx(ctx) 1717 if isinstance(names, str): 1718 names = names.split(" ") 1719 return [Bool(name, ctx) for name in names] 1720 1721 1722def BoolVector(prefix, sz, ctx=None): 1723 """Return a list of Boolean constants of size `sz`. 1724 1725 The constants are named using the given prefix. 1726 If `ctx=None`, then the global context is used. 1727 1728 >>> P = BoolVector('p', 3) 1729 >>> P 1730 [p__0, p__1, p__2] 1731 >>> And(P) 1732 And(p__0, p__1, p__2) 1733 """ 1734 return [Bool("%s__%s" % (prefix, i)) for i in range(sz)] 1735 1736 1737def FreshBool(prefix="b", ctx=None): 1738 """Return a fresh Boolean constant in the given context using the given prefix. 1739 1740 If `ctx=None`, then the global context is used. 1741 1742 >>> b1 = FreshBool() 1743 >>> b2 = FreshBool() 1744 >>> eq(b1, b2) 1745 False 1746 """ 1747 ctx = _get_ctx(ctx) 1748 return BoolRef(Z3_mk_fresh_const(ctx.ref(), prefix, BoolSort(ctx).ast), ctx) 1749 1750 1751def Implies(a, b, ctx=None): 1752 """Create a Z3 implies expression. 1753 1754 >>> p, q = Bools('p q') 1755 >>> Implies(p, q) 1756 Implies(p, q) 1757 """ 1758 ctx = _get_ctx(_ctx_from_ast_arg_list([a, b], ctx)) 1759 s = BoolSort(ctx) 1760 a = s.cast(a) 1761 b = s.cast(b) 1762 return BoolRef(Z3_mk_implies(ctx.ref(), a.as_ast(), b.as_ast()), ctx) 1763 1764 1765def Xor(a, b, ctx=None): 1766 """Create a Z3 Xor expression. 1767 1768 >>> p, q = Bools('p q') 1769 >>> Xor(p, q) 1770 Xor(p, q) 1771 >>> simplify(Xor(p, q)) 1772 Not(p) == q 1773 """ 1774 ctx = _get_ctx(_ctx_from_ast_arg_list([a, b], ctx)) 1775 s = BoolSort(ctx) 1776 a = s.cast(a) 1777 b = s.cast(b) 1778 return BoolRef(Z3_mk_xor(ctx.ref(), a.as_ast(), b.as_ast()), ctx) 1779 1780 1781def Not(a, ctx=None): 1782 """Create a Z3 not expression or probe. 1783 1784 >>> p = Bool('p') 1785 >>> Not(Not(p)) 1786 Not(Not(p)) 1787 >>> simplify(Not(Not(p))) 1788 p 1789 """ 1790 ctx = _get_ctx(_ctx_from_ast_arg_list([a], ctx)) 1791 if is_probe(a): 1792 # Not is also used to build probes 1793 return Probe(Z3_probe_not(ctx.ref(), a.probe), ctx) 1794 else: 1795 s = BoolSort(ctx) 1796 a = s.cast(a) 1797 return BoolRef(Z3_mk_not(ctx.ref(), a.as_ast()), ctx) 1798 1799 1800def mk_not(a): 1801 if is_not(a): 1802 return a.arg(0) 1803 else: 1804 return Not(a) 1805 1806 1807def _has_probe(args): 1808 """Return `True` if one of the elements of the given collection is a Z3 probe.""" 1809 for arg in args: 1810 if is_probe(arg): 1811 return True 1812 return False 1813 1814 1815def And(*args): 1816 """Create a Z3 and-expression or and-probe. 1817 1818 >>> p, q, r = Bools('p q r') 1819 >>> And(p, q, r) 1820 And(p, q, r) 1821 >>> P = BoolVector('p', 5) 1822 >>> And(P) 1823 And(p__0, p__1, p__2, p__3, p__4) 1824 """ 1825 last_arg = None 1826 if len(args) > 0: 1827 last_arg = args[len(args) - 1] 1828 if isinstance(last_arg, Context): 1829 ctx = args[len(args) - 1] 1830 args = args[:len(args) - 1] 1831 elif len(args) == 1 and isinstance(args[0], AstVector): 1832 ctx = args[0].ctx 1833 args = [a for a in args[0]] 1834 else: 1835 ctx = None 1836 args = _get_args(args) 1837 ctx = _get_ctx(_ctx_from_ast_arg_list(args, ctx)) 1838 if z3_debug(): 1839 _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression or probe") 1840 if _has_probe(args): 1841 return _probe_and(args, ctx) 1842 else: 1843 args = _coerce_expr_list(args, ctx) 1844 _args, sz = _to_ast_array(args) 1845 return BoolRef(Z3_mk_and(ctx.ref(), sz, _args), ctx) 1846 1847 1848def Or(*args): 1849 """Create a Z3 or-expression or or-probe. 1850 1851 >>> p, q, r = Bools('p q r') 1852 >>> Or(p, q, r) 1853 Or(p, q, r) 1854 >>> P = BoolVector('p', 5) 1855 >>> Or(P) 1856 Or(p__0, p__1, p__2, p__3, p__4) 1857 """ 1858 last_arg = None 1859 if len(args) > 0: 1860 last_arg = args[len(args) - 1] 1861 if isinstance(last_arg, Context): 1862 ctx = args[len(args) - 1] 1863 args = args[:len(args) - 1] 1864 elif len(args) == 1 and isinstance(args[0], AstVector): 1865 ctx = args[0].ctx 1866 args = [a for a in args[0]] 1867 else: 1868 ctx = None 1869 args = _get_args(args) 1870 ctx = _get_ctx(_ctx_from_ast_arg_list(args, ctx)) 1871 if z3_debug(): 1872 _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression or probe") 1873 if _has_probe(args): 1874 return _probe_or(args, ctx) 1875 else: 1876 args = _coerce_expr_list(args, ctx) 1877 _args, sz = _to_ast_array(args) 1878 return BoolRef(Z3_mk_or(ctx.ref(), sz, _args), ctx) 1879 1880######################################### 1881# 1882# Patterns 1883# 1884######################################### 1885 1886 1887class PatternRef(ExprRef): 1888 """Patterns are hints for quantifier instantiation. 1889 1890 """ 1891 1892 def as_ast(self): 1893 return Z3_pattern_to_ast(self.ctx_ref(), self.ast) 1894 1895 def get_id(self): 1896 return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) 1897 1898 1899def is_pattern(a): 1900 """Return `True` if `a` is a Z3 pattern (hint for quantifier instantiation. 1901 1902 >>> f = Function('f', IntSort(), IntSort()) 1903 >>> x = Int('x') 1904 >>> q = ForAll(x, f(x) == 0, patterns = [ f(x) ]) 1905 >>> q 1906 ForAll(x, f(x) == 0) 1907 >>> q.num_patterns() 1908 1 1909 >>> is_pattern(q.pattern(0)) 1910 True 1911 >>> q.pattern(0) 1912 f(Var(0)) 1913 """ 1914 return isinstance(a, PatternRef) 1915 1916 1917def MultiPattern(*args): 1918 """Create a Z3 multi-pattern using the given expressions `*args` 1919 1920 >>> f = Function('f', IntSort(), IntSort()) 1921 >>> g = Function('g', IntSort(), IntSort()) 1922 >>> x = Int('x') 1923 >>> q = ForAll(x, f(x) != g(x), patterns = [ MultiPattern(f(x), g(x)) ]) 1924 >>> q 1925 ForAll(x, f(x) != g(x)) 1926 >>> q.num_patterns() 1927 1 1928 >>> is_pattern(q.pattern(0)) 1929 True 1930 >>> q.pattern(0) 1931 MultiPattern(f(Var(0)), g(Var(0))) 1932 """ 1933 if z3_debug(): 1934 _z3_assert(len(args) > 0, "At least one argument expected") 1935 _z3_assert(all([is_expr(a) for a in args]), "Z3 expressions expected") 1936 ctx = args[0].ctx 1937 args, sz = _to_ast_array(args) 1938 return PatternRef(Z3_mk_pattern(ctx.ref(), sz, args), ctx) 1939 1940 1941def _to_pattern(arg): 1942 if is_pattern(arg): 1943 return arg 1944 else: 1945 return MultiPattern(arg) 1946 1947######################################### 1948# 1949# Quantifiers 1950# 1951######################################### 1952 1953 1954class QuantifierRef(BoolRef): 1955 """Universally and Existentially quantified formulas.""" 1956 1957 def as_ast(self): 1958 return self.ast 1959 1960 def get_id(self): 1961 return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) 1962 1963 def sort(self): 1964 """Return the Boolean sort or sort of Lambda.""" 1965 if self.is_lambda(): 1966 return _sort(self.ctx, self.as_ast()) 1967 return BoolSort(self.ctx) 1968 1969 def is_forall(self): 1970 """Return `True` if `self` is a universal quantifier. 1971 1972 >>> f = Function('f', IntSort(), IntSort()) 1973 >>> x = Int('x') 1974 >>> q = ForAll(x, f(x) == 0) 1975 >>> q.is_forall() 1976 True 1977 >>> q = Exists(x, f(x) != 0) 1978 >>> q.is_forall() 1979 False 1980 """ 1981 return Z3_is_quantifier_forall(self.ctx_ref(), self.ast) 1982 1983 def is_exists(self): 1984 """Return `True` if `self` is an existential quantifier. 1985 1986 >>> f = Function('f', IntSort(), IntSort()) 1987 >>> x = Int('x') 1988 >>> q = ForAll(x, f(x) == 0) 1989 >>> q.is_exists() 1990 False 1991 >>> q = Exists(x, f(x) != 0) 1992 >>> q.is_exists() 1993 True 1994 """ 1995 return Z3_is_quantifier_exists(self.ctx_ref(), self.ast) 1996 1997 def is_lambda(self): 1998 """Return `True` if `self` is a lambda expression. 1999 2000 >>> f = Function('f', IntSort(), IntSort()) 2001 >>> x = Int('x') 2002 >>> q = Lambda(x, f(x)) 2003 >>> q.is_lambda() 2004 True 2005 >>> q = Exists(x, f(x) != 0) 2006 >>> q.is_lambda() 2007 False 2008 """ 2009 return Z3_is_lambda(self.ctx_ref(), self.ast) 2010 2011 def __getitem__(self, arg): 2012 """Return the Z3 expression `self[arg]`. 2013 """ 2014 if z3_debug(): 2015 _z3_assert(self.is_lambda(), "quantifier should be a lambda expression") 2016 arg = self.sort().domain().cast(arg) 2017 return _to_expr_ref(Z3_mk_select(self.ctx_ref(), self.as_ast(), arg.as_ast()), self.ctx) 2018 2019 def weight(self): 2020 """Return the weight annotation of `self`. 2021 2022 >>> f = Function('f', IntSort(), IntSort()) 2023 >>> x = Int('x') 2024 >>> q = ForAll(x, f(x) == 0) 2025 >>> q.weight() 2026 1 2027 >>> q = ForAll(x, f(x) == 0, weight=10) 2028 >>> q.weight() 2029 10 2030 """ 2031 return int(Z3_get_quantifier_weight(self.ctx_ref(), self.ast)) 2032 2033 def num_patterns(self): 2034 """Return the number of patterns (i.e., quantifier instantiation hints) in `self`. 2035 2036 >>> f = Function('f', IntSort(), IntSort()) 2037 >>> g = Function('g', IntSort(), IntSort()) 2038 >>> x = Int('x') 2039 >>> q = ForAll(x, f(x) != g(x), patterns = [ f(x), g(x) ]) 2040 >>> q.num_patterns() 2041 2 2042 """ 2043 return int(Z3_get_quantifier_num_patterns(self.ctx_ref(), self.ast)) 2044 2045 def pattern(self, idx): 2046 """Return a pattern (i.e., quantifier instantiation hints) in `self`. 2047 2048 >>> f = Function('f', IntSort(), IntSort()) 2049 >>> g = Function('g', IntSort(), IntSort()) 2050 >>> x = Int('x') 2051 >>> q = ForAll(x, f(x) != g(x), patterns = [ f(x), g(x) ]) 2052 >>> q.num_patterns() 2053 2 2054 >>> q.pattern(0) 2055 f(Var(0)) 2056 >>> q.pattern(1) 2057 g(Var(0)) 2058 """ 2059 if z3_debug(): 2060 _z3_assert(idx < self.num_patterns(), "Invalid pattern idx") 2061 return PatternRef(Z3_get_quantifier_pattern_ast(self.ctx_ref(), self.ast, idx), self.ctx) 2062 2063 def num_no_patterns(self): 2064 """Return the number of no-patterns.""" 2065 return Z3_get_quantifier_num_no_patterns(self.ctx_ref(), self.ast) 2066 2067 def no_pattern(self, idx): 2068 """Return a no-pattern.""" 2069 if z3_debug(): 2070 _z3_assert(idx < self.num_no_patterns(), "Invalid no-pattern idx") 2071 return _to_expr_ref(Z3_get_quantifier_no_pattern_ast(self.ctx_ref(), self.ast, idx), self.ctx) 2072 2073 def body(self): 2074 """Return the expression being quantified. 2075 2076 >>> f = Function('f', IntSort(), IntSort()) 2077 >>> x = Int('x') 2078 >>> q = ForAll(x, f(x) == 0) 2079 >>> q.body() 2080 f(Var(0)) == 0 2081 """ 2082 return _to_expr_ref(Z3_get_quantifier_body(self.ctx_ref(), self.ast), self.ctx) 2083 2084 def num_vars(self): 2085 """Return the number of variables bounded by this quantifier. 2086 2087 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 2088 >>> x = Int('x') 2089 >>> y = Int('y') 2090 >>> q = ForAll([x, y], f(x, y) >= x) 2091 >>> q.num_vars() 2092 2 2093 """ 2094 return int(Z3_get_quantifier_num_bound(self.ctx_ref(), self.ast)) 2095 2096 def var_name(self, idx): 2097 """Return a string representing a name used when displaying the quantifier. 2098 2099 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 2100 >>> x = Int('x') 2101 >>> y = Int('y') 2102 >>> q = ForAll([x, y], f(x, y) >= x) 2103 >>> q.var_name(0) 2104 'x' 2105 >>> q.var_name(1) 2106 'y' 2107 """ 2108 if z3_debug(): 2109 _z3_assert(idx < self.num_vars(), "Invalid variable idx") 2110 return _symbol2py(self.ctx, Z3_get_quantifier_bound_name(self.ctx_ref(), self.ast, idx)) 2111 2112 def var_sort(self, idx): 2113 """Return the sort of a bound variable. 2114 2115 >>> f = Function('f', IntSort(), RealSort(), IntSort()) 2116 >>> x = Int('x') 2117 >>> y = Real('y') 2118 >>> q = ForAll([x, y], f(x, y) >= x) 2119 >>> q.var_sort(0) 2120 Int 2121 >>> q.var_sort(1) 2122 Real 2123 """ 2124 if z3_debug(): 2125 _z3_assert(idx < self.num_vars(), "Invalid variable idx") 2126 return _to_sort_ref(Z3_get_quantifier_bound_sort(self.ctx_ref(), self.ast, idx), self.ctx) 2127 2128 def children(self): 2129 """Return a list containing a single element self.body() 2130 2131 >>> f = Function('f', IntSort(), IntSort()) 2132 >>> x = Int('x') 2133 >>> q = ForAll(x, f(x) == 0) 2134 >>> q.children() 2135 [f(Var(0)) == 0] 2136 """ 2137 return [self.body()] 2138 2139 2140def is_quantifier(a): 2141 """Return `True` if `a` is a Z3 quantifier. 2142 2143 >>> f = Function('f', IntSort(), IntSort()) 2144 >>> x = Int('x') 2145 >>> q = ForAll(x, f(x) == 0) 2146 >>> is_quantifier(q) 2147 True 2148 >>> is_quantifier(f(x)) 2149 False 2150 """ 2151 return isinstance(a, QuantifierRef) 2152 2153 2154def _mk_quantifier(is_forall, vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]): 2155 if z3_debug(): 2156 _z3_assert(is_bool(body) or is_app(vs) or (len(vs) > 0 and is_app(vs[0])), "Z3 expression expected") 2157 _z3_assert(is_const(vs) or (len(vs) > 0 and all([is_const(v) for v in vs])), "Invalid bounded variable(s)") 2158 _z3_assert(all([is_pattern(a) or is_expr(a) for a in patterns]), "Z3 patterns expected") 2159 _z3_assert(all([is_expr(p) for p in no_patterns]), "no patterns are Z3 expressions") 2160 if is_app(vs): 2161 ctx = vs.ctx 2162 vs = [vs] 2163 else: 2164 ctx = vs[0].ctx 2165 if not is_expr(body): 2166 body = BoolVal(body, ctx) 2167 num_vars = len(vs) 2168 if num_vars == 0: 2169 return body 2170 _vs = (Ast * num_vars)() 2171 for i in range(num_vars): 2172 # TODO: Check if is constant 2173 _vs[i] = vs[i].as_ast() 2174 patterns = [_to_pattern(p) for p in patterns] 2175 num_pats = len(patterns) 2176 _pats = (Pattern * num_pats)() 2177 for i in range(num_pats): 2178 _pats[i] = patterns[i].ast 2179 _no_pats, num_no_pats = _to_ast_array(no_patterns) 2180 qid = to_symbol(qid, ctx) 2181 skid = to_symbol(skid, ctx) 2182 return QuantifierRef(Z3_mk_quantifier_const_ex(ctx.ref(), is_forall, weight, qid, skid, 2183 num_vars, _vs, 2184 num_pats, _pats, 2185 num_no_pats, _no_pats, 2186 body.as_ast()), ctx) 2187 2188 2189def ForAll(vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]): 2190 """Create a Z3 forall formula. 2191 2192 The parameters `weight`, `qid`, `skid`, `patterns` and `no_patterns` are optional annotations. 2193 2194 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 2195 >>> x = Int('x') 2196 >>> y = Int('y') 2197 >>> ForAll([x, y], f(x, y) >= x) 2198 ForAll([x, y], f(x, y) >= x) 2199 >>> ForAll([x, y], f(x, y) >= x, patterns=[ f(x, y) ]) 2200 ForAll([x, y], f(x, y) >= x) 2201 >>> ForAll([x, y], f(x, y) >= x, weight=10) 2202 ForAll([x, y], f(x, y) >= x) 2203 """ 2204 return _mk_quantifier(True, vs, body, weight, qid, skid, patterns, no_patterns) 2205 2206 2207def Exists(vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]): 2208 """Create a Z3 exists formula. 2209 2210 The parameters `weight`, `qif`, `skid`, `patterns` and `no_patterns` are optional annotations. 2211 2212 2213 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 2214 >>> x = Int('x') 2215 >>> y = Int('y') 2216 >>> q = Exists([x, y], f(x, y) >= x, skid="foo") 2217 >>> q 2218 Exists([x, y], f(x, y) >= x) 2219 >>> is_quantifier(q) 2220 True 2221 >>> r = Tactic('nnf')(q).as_expr() 2222 >>> is_quantifier(r) 2223 False 2224 """ 2225 return _mk_quantifier(False, vs, body, weight, qid, skid, patterns, no_patterns) 2226 2227 2228def Lambda(vs, body): 2229 """Create a Z3 lambda expression. 2230 2231 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 2232 >>> mem0 = Array('mem0', IntSort(), IntSort()) 2233 >>> lo, hi, e, i = Ints('lo hi e i') 2234 >>> mem1 = Lambda([i], If(And(lo <= i, i <= hi), e, mem0[i])) 2235 >>> mem1 2236 Lambda(i, If(And(lo <= i, i <= hi), e, mem0[i])) 2237 """ 2238 ctx = body.ctx 2239 if is_app(vs): 2240 vs = [vs] 2241 num_vars = len(vs) 2242 _vs = (Ast * num_vars)() 2243 for i in range(num_vars): 2244 # TODO: Check if is constant 2245 _vs[i] = vs[i].as_ast() 2246 return QuantifierRef(Z3_mk_lambda_const(ctx.ref(), num_vars, _vs, body.as_ast()), ctx) 2247 2248######################################### 2249# 2250# Arithmetic 2251# 2252######################################### 2253 2254 2255class ArithSortRef(SortRef): 2256 """Real and Integer sorts.""" 2257 2258 def is_real(self): 2259 """Return `True` if `self` is of the sort Real. 2260 2261 >>> x = Real('x') 2262 >>> x.is_real() 2263 True 2264 >>> (x + 1).is_real() 2265 True 2266 >>> x = Int('x') 2267 >>> x.is_real() 2268 False 2269 """ 2270 return self.kind() == Z3_REAL_SORT 2271 2272 def is_int(self): 2273 """Return `True` if `self` is of the sort Integer. 2274 2275 >>> x = Int('x') 2276 >>> x.is_int() 2277 True 2278 >>> (x + 1).is_int() 2279 True 2280 >>> x = Real('x') 2281 >>> x.is_int() 2282 False 2283 """ 2284 return self.kind() == Z3_INT_SORT 2285 2286 def subsort(self, other): 2287 """Return `True` if `self` is a subsort of `other`.""" 2288 return self.is_int() and is_arith_sort(other) and other.is_real() 2289 2290 def cast(self, val): 2291 """Try to cast `val` as an Integer or Real. 2292 2293 >>> IntSort().cast(10) 2294 10 2295 >>> is_int(IntSort().cast(10)) 2296 True 2297 >>> is_int(10) 2298 False 2299 >>> RealSort().cast(10) 2300 10 2301 >>> is_real(RealSort().cast(10)) 2302 True 2303 """ 2304 if is_expr(val): 2305 if z3_debug(): 2306 _z3_assert(self.ctx == val.ctx, "Context mismatch") 2307 val_s = val.sort() 2308 if self.eq(val_s): 2309 return val 2310 if val_s.is_int() and self.is_real(): 2311 return ToReal(val) 2312 if val_s.is_bool() and self.is_int(): 2313 return If(val, 1, 0) 2314 if val_s.is_bool() and self.is_real(): 2315 return ToReal(If(val, 1, 0)) 2316 if z3_debug(): 2317 _z3_assert(False, "Z3 Integer/Real expression expected") 2318 else: 2319 if self.is_int(): 2320 return IntVal(val, self.ctx) 2321 if self.is_real(): 2322 return RealVal(val, self.ctx) 2323 if z3_debug(): 2324 msg = "int, long, float, string (numeral), or Z3 Integer/Real expression expected. Got %s" 2325 _z3_assert(False, msg % self) 2326 2327 2328def is_arith_sort(s): 2329 """Return `True` if s is an arithmetical sort (type). 2330 2331 >>> is_arith_sort(IntSort()) 2332 True 2333 >>> is_arith_sort(RealSort()) 2334 True 2335 >>> is_arith_sort(BoolSort()) 2336 False 2337 >>> n = Int('x') + 1 2338 >>> is_arith_sort(n.sort()) 2339 True 2340 """ 2341 return isinstance(s, ArithSortRef) 2342 2343 2344class ArithRef(ExprRef): 2345 """Integer and Real expressions.""" 2346 2347 def sort(self): 2348 """Return the sort (type) of the arithmetical expression `self`. 2349 2350 >>> Int('x').sort() 2351 Int 2352 >>> (Real('x') + 1).sort() 2353 Real 2354 """ 2355 return ArithSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) 2356 2357 def is_int(self): 2358 """Return `True` if `self` is an integer expression. 2359 2360 >>> x = Int('x') 2361 >>> x.is_int() 2362 True 2363 >>> (x + 1).is_int() 2364 True 2365 >>> y = Real('y') 2366 >>> (x + y).is_int() 2367 False 2368 """ 2369 return self.sort().is_int() 2370 2371 def is_real(self): 2372 """Return `True` if `self` is an real expression. 2373 2374 >>> x = Real('x') 2375 >>> x.is_real() 2376 True 2377 >>> (x + 1).is_real() 2378 True 2379 """ 2380 return self.sort().is_real() 2381 2382 def __add__(self, other): 2383 """Create the Z3 expression `self + other`. 2384 2385 >>> x = Int('x') 2386 >>> y = Int('y') 2387 >>> x + y 2388 x + y 2389 >>> (x + y).sort() 2390 Int 2391 """ 2392 a, b = _coerce_exprs(self, other) 2393 return ArithRef(_mk_bin(Z3_mk_add, a, b), self.ctx) 2394 2395 def __radd__(self, other): 2396 """Create the Z3 expression `other + self`. 2397 2398 >>> x = Int('x') 2399 >>> 10 + x 2400 10 + x 2401 """ 2402 a, b = _coerce_exprs(self, other) 2403 return ArithRef(_mk_bin(Z3_mk_add, b, a), self.ctx) 2404 2405 def __mul__(self, other): 2406 """Create the Z3 expression `self * other`. 2407 2408 >>> x = Real('x') 2409 >>> y = Real('y') 2410 >>> x * y 2411 x*y 2412 >>> (x * y).sort() 2413 Real 2414 """ 2415 if isinstance(other, BoolRef): 2416 return If(other, self, 0) 2417 a, b = _coerce_exprs(self, other) 2418 return ArithRef(_mk_bin(Z3_mk_mul, a, b), self.ctx) 2419 2420 def __rmul__(self, other): 2421 """Create the Z3 expression `other * self`. 2422 2423 >>> x = Real('x') 2424 >>> 10 * x 2425 10*x 2426 """ 2427 a, b = _coerce_exprs(self, other) 2428 return ArithRef(_mk_bin(Z3_mk_mul, b, a), self.ctx) 2429 2430 def __sub__(self, other): 2431 """Create the Z3 expression `self - other`. 2432 2433 >>> x = Int('x') 2434 >>> y = Int('y') 2435 >>> x - y 2436 x - y 2437 >>> (x - y).sort() 2438 Int 2439 """ 2440 a, b = _coerce_exprs(self, other) 2441 return ArithRef(_mk_bin(Z3_mk_sub, a, b), self.ctx) 2442 2443 def __rsub__(self, other): 2444 """Create the Z3 expression `other - self`. 2445 2446 >>> x = Int('x') 2447 >>> 10 - x 2448 10 - x 2449 """ 2450 a, b = _coerce_exprs(self, other) 2451 return ArithRef(_mk_bin(Z3_mk_sub, b, a), self.ctx) 2452 2453 def __pow__(self, other): 2454 """Create the Z3 expression `self**other` (** is the power operator). 2455 2456 >>> x = Real('x') 2457 >>> x**3 2458 x**3 2459 >>> (x**3).sort() 2460 Real 2461 >>> simplify(IntVal(2)**8) 2462 256 2463 """ 2464 a, b = _coerce_exprs(self, other) 2465 return ArithRef(Z3_mk_power(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 2466 2467 def __rpow__(self, other): 2468 """Create the Z3 expression `other**self` (** is the power operator). 2469 2470 >>> x = Real('x') 2471 >>> 2**x 2472 2**x 2473 >>> (2**x).sort() 2474 Real 2475 >>> simplify(2**IntVal(8)) 2476 256 2477 """ 2478 a, b = _coerce_exprs(self, other) 2479 return ArithRef(Z3_mk_power(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 2480 2481 def __div__(self, other): 2482 """Create the Z3 expression `other/self`. 2483 2484 >>> x = Int('x') 2485 >>> y = Int('y') 2486 >>> x/y 2487 x/y 2488 >>> (x/y).sort() 2489 Int 2490 >>> (x/y).sexpr() 2491 '(div x y)' 2492 >>> x = Real('x') 2493 >>> y = Real('y') 2494 >>> x/y 2495 x/y 2496 >>> (x/y).sort() 2497 Real 2498 >>> (x/y).sexpr() 2499 '(/ x y)' 2500 """ 2501 a, b = _coerce_exprs(self, other) 2502 return ArithRef(Z3_mk_div(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 2503 2504 def __truediv__(self, other): 2505 """Create the Z3 expression `other/self`.""" 2506 return self.__div__(other) 2507 2508 def __rdiv__(self, other): 2509 """Create the Z3 expression `other/self`. 2510 2511 >>> x = Int('x') 2512 >>> 10/x 2513 10/x 2514 >>> (10/x).sexpr() 2515 '(div 10 x)' 2516 >>> x = Real('x') 2517 >>> 10/x 2518 10/x 2519 >>> (10/x).sexpr() 2520 '(/ 10.0 x)' 2521 """ 2522 a, b = _coerce_exprs(self, other) 2523 return ArithRef(Z3_mk_div(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 2524 2525 def __rtruediv__(self, other): 2526 """Create the Z3 expression `other/self`.""" 2527 return self.__rdiv__(other) 2528 2529 def __mod__(self, other): 2530 """Create the Z3 expression `other%self`. 2531 2532 >>> x = Int('x') 2533 >>> y = Int('y') 2534 >>> x % y 2535 x%y 2536 >>> simplify(IntVal(10) % IntVal(3)) 2537 1 2538 """ 2539 a, b = _coerce_exprs(self, other) 2540 if z3_debug(): 2541 _z3_assert(a.is_int(), "Z3 integer expression expected") 2542 return ArithRef(Z3_mk_mod(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 2543 2544 def __rmod__(self, other): 2545 """Create the Z3 expression `other%self`. 2546 2547 >>> x = Int('x') 2548 >>> 10 % x 2549 10%x 2550 """ 2551 a, b = _coerce_exprs(self, other) 2552 if z3_debug(): 2553 _z3_assert(a.is_int(), "Z3 integer expression expected") 2554 return ArithRef(Z3_mk_mod(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 2555 2556 def __neg__(self): 2557 """Return an expression representing `-self`. 2558 2559 >>> x = Int('x') 2560 >>> -x 2561 -x 2562 >>> simplify(-(-x)) 2563 x 2564 """ 2565 return ArithRef(Z3_mk_unary_minus(self.ctx_ref(), self.as_ast()), self.ctx) 2566 2567 def __pos__(self): 2568 """Return `self`. 2569 2570 >>> x = Int('x') 2571 >>> +x 2572 x 2573 """ 2574 return self 2575 2576 def __le__(self, other): 2577 """Create the Z3 expression `other <= self`. 2578 2579 >>> x, y = Ints('x y') 2580 >>> x <= y 2581 x <= y 2582 >>> y = Real('y') 2583 >>> x <= y 2584 ToReal(x) <= y 2585 """ 2586 a, b = _coerce_exprs(self, other) 2587 return BoolRef(Z3_mk_le(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 2588 2589 def __lt__(self, other): 2590 """Create the Z3 expression `other < self`. 2591 2592 >>> x, y = Ints('x y') 2593 >>> x < y 2594 x < y 2595 >>> y = Real('y') 2596 >>> x < y 2597 ToReal(x) < y 2598 """ 2599 a, b = _coerce_exprs(self, other) 2600 return BoolRef(Z3_mk_lt(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 2601 2602 def __gt__(self, other): 2603 """Create the Z3 expression `other > self`. 2604 2605 >>> x, y = Ints('x y') 2606 >>> x > y 2607 x > y 2608 >>> y = Real('y') 2609 >>> x > y 2610 ToReal(x) > y 2611 """ 2612 a, b = _coerce_exprs(self, other) 2613 return BoolRef(Z3_mk_gt(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 2614 2615 def __ge__(self, other): 2616 """Create the Z3 expression `other >= self`. 2617 2618 >>> x, y = Ints('x y') 2619 >>> x >= y 2620 x >= y 2621 >>> y = Real('y') 2622 >>> x >= y 2623 ToReal(x) >= y 2624 """ 2625 a, b = _coerce_exprs(self, other) 2626 return BoolRef(Z3_mk_ge(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 2627 2628 2629def is_arith(a): 2630 """Return `True` if `a` is an arithmetical expression. 2631 2632 >>> x = Int('x') 2633 >>> is_arith(x) 2634 True 2635 >>> is_arith(x + 1) 2636 True 2637 >>> is_arith(1) 2638 False 2639 >>> is_arith(IntVal(1)) 2640 True 2641 >>> y = Real('y') 2642 >>> is_arith(y) 2643 True 2644 >>> is_arith(y + 1) 2645 True 2646 """ 2647 return isinstance(a, ArithRef) 2648 2649 2650def is_int(a): 2651 """Return `True` if `a` is an integer expression. 2652 2653 >>> x = Int('x') 2654 >>> is_int(x + 1) 2655 True 2656 >>> is_int(1) 2657 False 2658 >>> is_int(IntVal(1)) 2659 True 2660 >>> y = Real('y') 2661 >>> is_int(y) 2662 False 2663 >>> is_int(y + 1) 2664 False 2665 """ 2666 return is_arith(a) and a.is_int() 2667 2668 2669def is_real(a): 2670 """Return `True` if `a` is a real expression. 2671 2672 >>> x = Int('x') 2673 >>> is_real(x + 1) 2674 False 2675 >>> y = Real('y') 2676 >>> is_real(y) 2677 True 2678 >>> is_real(y + 1) 2679 True 2680 >>> is_real(1) 2681 False 2682 >>> is_real(RealVal(1)) 2683 True 2684 """ 2685 return is_arith(a) and a.is_real() 2686 2687 2688def _is_numeral(ctx, a): 2689 return Z3_is_numeral_ast(ctx.ref(), a) 2690 2691 2692def _is_algebraic(ctx, a): 2693 return Z3_is_algebraic_number(ctx.ref(), a) 2694 2695 2696def is_int_value(a): 2697 """Return `True` if `a` is an integer value of sort Int. 2698 2699 >>> is_int_value(IntVal(1)) 2700 True 2701 >>> is_int_value(1) 2702 False 2703 >>> is_int_value(Int('x')) 2704 False 2705 >>> n = Int('x') + 1 2706 >>> n 2707 x + 1 2708 >>> n.arg(1) 2709 1 2710 >>> is_int_value(n.arg(1)) 2711 True 2712 >>> is_int_value(RealVal("1/3")) 2713 False 2714 >>> is_int_value(RealVal(1)) 2715 False 2716 """ 2717 return is_arith(a) and a.is_int() and _is_numeral(a.ctx, a.as_ast()) 2718 2719 2720def is_rational_value(a): 2721 """Return `True` if `a` is rational value of sort Real. 2722 2723 >>> is_rational_value(RealVal(1)) 2724 True 2725 >>> is_rational_value(RealVal("3/5")) 2726 True 2727 >>> is_rational_value(IntVal(1)) 2728 False 2729 >>> is_rational_value(1) 2730 False 2731 >>> n = Real('x') + 1 2732 >>> n.arg(1) 2733 1 2734 >>> is_rational_value(n.arg(1)) 2735 True 2736 >>> is_rational_value(Real('x')) 2737 False 2738 """ 2739 return is_arith(a) and a.is_real() and _is_numeral(a.ctx, a.as_ast()) 2740 2741 2742def is_algebraic_value(a): 2743 """Return `True` if `a` is an algebraic value of sort Real. 2744 2745 >>> is_algebraic_value(RealVal("3/5")) 2746 False 2747 >>> n = simplify(Sqrt(2)) 2748 >>> n 2749 1.4142135623? 2750 >>> is_algebraic_value(n) 2751 True 2752 """ 2753 return is_arith(a) and a.is_real() and _is_algebraic(a.ctx, a.as_ast()) 2754 2755 2756def is_add(a): 2757 """Return `True` if `a` is an expression of the form b + c. 2758 2759 >>> x, y = Ints('x y') 2760 >>> is_add(x + y) 2761 True 2762 >>> is_add(x - y) 2763 False 2764 """ 2765 return is_app_of(a, Z3_OP_ADD) 2766 2767 2768def is_mul(a): 2769 """Return `True` if `a` is an expression of the form b * c. 2770 2771 >>> x, y = Ints('x y') 2772 >>> is_mul(x * y) 2773 True 2774 >>> is_mul(x - y) 2775 False 2776 """ 2777 return is_app_of(a, Z3_OP_MUL) 2778 2779 2780def is_sub(a): 2781 """Return `True` if `a` is an expression of the form b - c. 2782 2783 >>> x, y = Ints('x y') 2784 >>> is_sub(x - y) 2785 True 2786 >>> is_sub(x + y) 2787 False 2788 """ 2789 return is_app_of(a, Z3_OP_SUB) 2790 2791 2792def is_div(a): 2793 """Return `True` if `a` is an expression of the form b / c. 2794 2795 >>> x, y = Reals('x y') 2796 >>> is_div(x / y) 2797 True 2798 >>> is_div(x + y) 2799 False 2800 >>> x, y = Ints('x y') 2801 >>> is_div(x / y) 2802 False 2803 >>> is_idiv(x / y) 2804 True 2805 """ 2806 return is_app_of(a, Z3_OP_DIV) 2807 2808 2809def is_idiv(a): 2810 """Return `True` if `a` is an expression of the form b div c. 2811 2812 >>> x, y = Ints('x y') 2813 >>> is_idiv(x / y) 2814 True 2815 >>> is_idiv(x + y) 2816 False 2817 """ 2818 return is_app_of(a, Z3_OP_IDIV) 2819 2820 2821def is_mod(a): 2822 """Return `True` if `a` is an expression of the form b % c. 2823 2824 >>> x, y = Ints('x y') 2825 >>> is_mod(x % y) 2826 True 2827 >>> is_mod(x + y) 2828 False 2829 """ 2830 return is_app_of(a, Z3_OP_MOD) 2831 2832 2833def is_le(a): 2834 """Return `True` if `a` is an expression of the form b <= c. 2835 2836 >>> x, y = Ints('x y') 2837 >>> is_le(x <= y) 2838 True 2839 >>> is_le(x < y) 2840 False 2841 """ 2842 return is_app_of(a, Z3_OP_LE) 2843 2844 2845def is_lt(a): 2846 """Return `True` if `a` is an expression of the form b < c. 2847 2848 >>> x, y = Ints('x y') 2849 >>> is_lt(x < y) 2850 True 2851 >>> is_lt(x == y) 2852 False 2853 """ 2854 return is_app_of(a, Z3_OP_LT) 2855 2856 2857def is_ge(a): 2858 """Return `True` if `a` is an expression of the form b >= c. 2859 2860 >>> x, y = Ints('x y') 2861 >>> is_ge(x >= y) 2862 True 2863 >>> is_ge(x == y) 2864 False 2865 """ 2866 return is_app_of(a, Z3_OP_GE) 2867 2868 2869def is_gt(a): 2870 """Return `True` if `a` is an expression of the form b > c. 2871 2872 >>> x, y = Ints('x y') 2873 >>> is_gt(x > y) 2874 True 2875 >>> is_gt(x == y) 2876 False 2877 """ 2878 return is_app_of(a, Z3_OP_GT) 2879 2880 2881def is_is_int(a): 2882 """Return `True` if `a` is an expression of the form IsInt(b). 2883 2884 >>> x = Real('x') 2885 >>> is_is_int(IsInt(x)) 2886 True 2887 >>> is_is_int(x) 2888 False 2889 """ 2890 return is_app_of(a, Z3_OP_IS_INT) 2891 2892 2893def is_to_real(a): 2894 """Return `True` if `a` is an expression of the form ToReal(b). 2895 2896 >>> x = Int('x') 2897 >>> n = ToReal(x) 2898 >>> n 2899 ToReal(x) 2900 >>> is_to_real(n) 2901 True 2902 >>> is_to_real(x) 2903 False 2904 """ 2905 return is_app_of(a, Z3_OP_TO_REAL) 2906 2907 2908def is_to_int(a): 2909 """Return `True` if `a` is an expression of the form ToInt(b). 2910 2911 >>> x = Real('x') 2912 >>> n = ToInt(x) 2913 >>> n 2914 ToInt(x) 2915 >>> is_to_int(n) 2916 True 2917 >>> is_to_int(x) 2918 False 2919 """ 2920 return is_app_of(a, Z3_OP_TO_INT) 2921 2922 2923class IntNumRef(ArithRef): 2924 """Integer values.""" 2925 2926 def as_long(self): 2927 """Return a Z3 integer numeral as a Python long (bignum) numeral. 2928 2929 >>> v = IntVal(1) 2930 >>> v + 1 2931 1 + 1 2932 >>> v.as_long() + 1 2933 2 2934 """ 2935 if z3_debug(): 2936 _z3_assert(self.is_int(), "Integer value expected") 2937 return int(self.as_string()) 2938 2939 def as_string(self): 2940 """Return a Z3 integer numeral as a Python string. 2941 >>> v = IntVal(100) 2942 >>> v.as_string() 2943 '100' 2944 """ 2945 return Z3_get_numeral_string(self.ctx_ref(), self.as_ast()) 2946 2947 def as_binary_string(self): 2948 """Return a Z3 integer numeral as a Python binary string. 2949 >>> v = IntVal(10) 2950 >>> v.as_binary_string() 2951 '1010' 2952 """ 2953 return Z3_get_numeral_binary_string(self.ctx_ref(), self.as_ast()) 2954 2955 2956class RatNumRef(ArithRef): 2957 """Rational values.""" 2958 2959 def numerator(self): 2960 """ Return the numerator of a Z3 rational numeral. 2961 2962 >>> is_rational_value(RealVal("3/5")) 2963 True 2964 >>> n = RealVal("3/5") 2965 >>> n.numerator() 2966 3 2967 >>> is_rational_value(Q(3,5)) 2968 True 2969 >>> Q(3,5).numerator() 2970 3 2971 """ 2972 return IntNumRef(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx) 2973 2974 def denominator(self): 2975 """ Return the denominator of a Z3 rational numeral. 2976 2977 >>> is_rational_value(Q(3,5)) 2978 True 2979 >>> n = Q(3,5) 2980 >>> n.denominator() 2981 5 2982 """ 2983 return IntNumRef(Z3_get_denominator(self.ctx_ref(), self.as_ast()), self.ctx) 2984 2985 def numerator_as_long(self): 2986 """ Return the numerator as a Python long. 2987 2988 >>> v = RealVal(10000000000) 2989 >>> v 2990 10000000000 2991 >>> v + 1 2992 10000000000 + 1 2993 >>> v.numerator_as_long() + 1 == 10000000001 2994 True 2995 """ 2996 return self.numerator().as_long() 2997 2998 def denominator_as_long(self): 2999 """ Return the denominator as a Python long. 3000 3001 >>> v = RealVal("1/3") 3002 >>> v 3003 1/3 3004 >>> v.denominator_as_long() 3005 3 3006 """ 3007 return self.denominator().as_long() 3008 3009 def is_int(self): 3010 return False 3011 3012 def is_real(self): 3013 return True 3014 3015 def is_int_value(self): 3016 return self.denominator().is_int() and self.denominator_as_long() == 1 3017 3018 def as_long(self): 3019 _z3_assert(self.is_int_value(), "Expected integer fraction") 3020 return self.numerator_as_long() 3021 3022 def as_decimal(self, prec): 3023 """ Return a Z3 rational value as a string in decimal notation using at most `prec` decimal places. 3024 3025 >>> v = RealVal("1/5") 3026 >>> v.as_decimal(3) 3027 '0.2' 3028 >>> v = RealVal("1/3") 3029 >>> v.as_decimal(3) 3030 '0.333?' 3031 """ 3032 return Z3_get_numeral_decimal_string(self.ctx_ref(), self.as_ast(), prec) 3033 3034 def as_string(self): 3035 """Return a Z3 rational numeral as a Python string. 3036 3037 >>> v = Q(3,6) 3038 >>> v.as_string() 3039 '1/2' 3040 """ 3041 return Z3_get_numeral_string(self.ctx_ref(), self.as_ast()) 3042 3043 def as_fraction(self): 3044 """Return a Z3 rational as a Python Fraction object. 3045 3046 >>> v = RealVal("1/5") 3047 >>> v.as_fraction() 3048 Fraction(1, 5) 3049 """ 3050 return Fraction(self.numerator_as_long(), self.denominator_as_long()) 3051 3052 3053class AlgebraicNumRef(ArithRef): 3054 """Algebraic irrational values.""" 3055 3056 def approx(self, precision=10): 3057 """Return a Z3 rational number that approximates the algebraic number `self`. 3058 The result `r` is such that |r - self| <= 1/10^precision 3059 3060 >>> x = simplify(Sqrt(2)) 3061 >>> x.approx(20) 3062 6838717160008073720548335/4835703278458516698824704 3063 >>> x.approx(5) 3064 2965821/2097152 3065 """ 3066 return RatNumRef(Z3_get_algebraic_number_upper(self.ctx_ref(), self.as_ast(), precision), self.ctx) 3067 3068 def as_decimal(self, prec): 3069 """Return a string representation of the algebraic number `self` in decimal notation 3070 using `prec` decimal places. 3071 3072 >>> x = simplify(Sqrt(2)) 3073 >>> x.as_decimal(10) 3074 '1.4142135623?' 3075 >>> x.as_decimal(20) 3076 '1.41421356237309504880?' 3077 """ 3078 return Z3_get_numeral_decimal_string(self.ctx_ref(), self.as_ast(), prec) 3079 3080 def poly(self): 3081 return AstVector(Z3_algebraic_get_poly(self.ctx_ref(), self.as_ast()), self.ctx) 3082 3083 def index(self): 3084 return Z3_algebraic_get_i(self.ctx_ref(), self.as_ast()) 3085 3086 3087def _py2expr(a, ctx=None): 3088 if isinstance(a, bool): 3089 return BoolVal(a, ctx) 3090 if _is_int(a): 3091 return IntVal(a, ctx) 3092 if isinstance(a, float): 3093 return RealVal(a, ctx) 3094 if isinstance(a, str): 3095 return StringVal(a, ctx) 3096 if is_expr(a): 3097 return a 3098 if z3_debug(): 3099 _z3_assert(False, "Python bool, int, long or float expected") 3100 3101 3102def IntSort(ctx=None): 3103 """Return the integer sort in the given context. If `ctx=None`, then the global context is used. 3104 3105 >>> IntSort() 3106 Int 3107 >>> x = Const('x', IntSort()) 3108 >>> is_int(x) 3109 True 3110 >>> x.sort() == IntSort() 3111 True 3112 >>> x.sort() == BoolSort() 3113 False 3114 """ 3115 ctx = _get_ctx(ctx) 3116 return ArithSortRef(Z3_mk_int_sort(ctx.ref()), ctx) 3117 3118 3119def RealSort(ctx=None): 3120 """Return the real sort in the given context. If `ctx=None`, then the global context is used. 3121 3122 >>> RealSort() 3123 Real 3124 >>> x = Const('x', RealSort()) 3125 >>> is_real(x) 3126 True 3127 >>> is_int(x) 3128 False 3129 >>> x.sort() == RealSort() 3130 True 3131 """ 3132 ctx = _get_ctx(ctx) 3133 return ArithSortRef(Z3_mk_real_sort(ctx.ref()), ctx) 3134 3135 3136def _to_int_str(val): 3137 if isinstance(val, float): 3138 return str(int(val)) 3139 elif isinstance(val, bool): 3140 if val: 3141 return "1" 3142 else: 3143 return "0" 3144 elif _is_int(val): 3145 return str(val) 3146 elif isinstance(val, str): 3147 return val 3148 if z3_debug(): 3149 _z3_assert(False, "Python value cannot be used as a Z3 integer") 3150 3151 3152def IntVal(val, ctx=None): 3153 """Return a Z3 integer value. If `ctx=None`, then the global context is used. 3154 3155 >>> IntVal(1) 3156 1 3157 >>> IntVal("100") 3158 100 3159 """ 3160 ctx = _get_ctx(ctx) 3161 return IntNumRef(Z3_mk_numeral(ctx.ref(), _to_int_str(val), IntSort(ctx).ast), ctx) 3162 3163 3164def RealVal(val, ctx=None): 3165 """Return a Z3 real value. 3166 3167 `val` may be a Python int, long, float or string representing a number in decimal or rational notation. 3168 If `ctx=None`, then the global context is used. 3169 3170 >>> RealVal(1) 3171 1 3172 >>> RealVal(1).sort() 3173 Real 3174 >>> RealVal("3/5") 3175 3/5 3176 >>> RealVal("1.5") 3177 3/2 3178 """ 3179 ctx = _get_ctx(ctx) 3180 return RatNumRef(Z3_mk_numeral(ctx.ref(), str(val), RealSort(ctx).ast), ctx) 3181 3182 3183def RatVal(a, b, ctx=None): 3184 """Return a Z3 rational a/b. 3185 3186 If `ctx=None`, then the global context is used. 3187 3188 >>> RatVal(3,5) 3189 3/5 3190 >>> RatVal(3,5).sort() 3191 Real 3192 """ 3193 if z3_debug(): 3194 _z3_assert(_is_int(a) or isinstance(a, str), "First argument cannot be converted into an integer") 3195 _z3_assert(_is_int(b) or isinstance(b, str), "Second argument cannot be converted into an integer") 3196 return simplify(RealVal(a, ctx) / RealVal(b, ctx)) 3197 3198 3199def Q(a, b, ctx=None): 3200 """Return a Z3 rational a/b. 3201 3202 If `ctx=None`, then the global context is used. 3203 3204 >>> Q(3,5) 3205 3/5 3206 >>> Q(3,5).sort() 3207 Real 3208 """ 3209 return simplify(RatVal(a, b, ctx=ctx)) 3210 3211 3212def Int(name, ctx=None): 3213 """Return an integer constant named `name`. If `ctx=None`, then the global context is used. 3214 3215 >>> x = Int('x') 3216 >>> is_int(x) 3217 True 3218 >>> is_int(x + 1) 3219 True 3220 """ 3221 ctx = _get_ctx(ctx) 3222 return ArithRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), IntSort(ctx).ast), ctx) 3223 3224 3225def Ints(names, ctx=None): 3226 """Return a tuple of Integer constants. 3227 3228 >>> x, y, z = Ints('x y z') 3229 >>> Sum(x, y, z) 3230 x + y + z 3231 """ 3232 ctx = _get_ctx(ctx) 3233 if isinstance(names, str): 3234 names = names.split(" ") 3235 return [Int(name, ctx) for name in names] 3236 3237 3238def IntVector(prefix, sz, ctx=None): 3239 """Return a list of integer constants of size `sz`. 3240 3241 >>> X = IntVector('x', 3) 3242 >>> X 3243 [x__0, x__1, x__2] 3244 >>> Sum(X) 3245 x__0 + x__1 + x__2 3246 """ 3247 ctx = _get_ctx(ctx) 3248 return [Int("%s__%s" % (prefix, i), ctx) for i in range(sz)] 3249 3250 3251def FreshInt(prefix="x", ctx=None): 3252 """Return a fresh integer constant in the given context using the given prefix. 3253 3254 >>> x = FreshInt() 3255 >>> y = FreshInt() 3256 >>> eq(x, y) 3257 False 3258 >>> x.sort() 3259 Int 3260 """ 3261 ctx = _get_ctx(ctx) 3262 return ArithRef(Z3_mk_fresh_const(ctx.ref(), prefix, IntSort(ctx).ast), ctx) 3263 3264 3265def Real(name, ctx=None): 3266 """Return a real constant named `name`. If `ctx=None`, then the global context is used. 3267 3268 >>> x = Real('x') 3269 >>> is_real(x) 3270 True 3271 >>> is_real(x + 1) 3272 True 3273 """ 3274 ctx = _get_ctx(ctx) 3275 return ArithRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), RealSort(ctx).ast), ctx) 3276 3277 3278def Reals(names, ctx=None): 3279 """Return a tuple of real constants. 3280 3281 >>> x, y, z = Reals('x y z') 3282 >>> Sum(x, y, z) 3283 x + y + z 3284 >>> Sum(x, y, z).sort() 3285 Real 3286 """ 3287 ctx = _get_ctx(ctx) 3288 if isinstance(names, str): 3289 names = names.split(" ") 3290 return [Real(name, ctx) for name in names] 3291 3292 3293def RealVector(prefix, sz, ctx=None): 3294 """Return a list of real constants of size `sz`. 3295 3296 >>> X = RealVector('x', 3) 3297 >>> X 3298 [x__0, x__1, x__2] 3299 >>> Sum(X) 3300 x__0 + x__1 + x__2 3301 >>> Sum(X).sort() 3302 Real 3303 """ 3304 ctx = _get_ctx(ctx) 3305 return [Real("%s__%s" % (prefix, i), ctx) for i in range(sz)] 3306 3307 3308def FreshReal(prefix="b", ctx=None): 3309 """Return a fresh real constant in the given context using the given prefix. 3310 3311 >>> x = FreshReal() 3312 >>> y = FreshReal() 3313 >>> eq(x, y) 3314 False 3315 >>> x.sort() 3316 Real 3317 """ 3318 ctx = _get_ctx(ctx) 3319 return ArithRef(Z3_mk_fresh_const(ctx.ref(), prefix, RealSort(ctx).ast), ctx) 3320 3321 3322def ToReal(a): 3323 """ Return the Z3 expression ToReal(a). 3324 3325 >>> x = Int('x') 3326 >>> x.sort() 3327 Int 3328 >>> n = ToReal(x) 3329 >>> n 3330 ToReal(x) 3331 >>> n.sort() 3332 Real 3333 """ 3334 if z3_debug(): 3335 _z3_assert(a.is_int(), "Z3 integer expression expected.") 3336 ctx = a.ctx 3337 return ArithRef(Z3_mk_int2real(ctx.ref(), a.as_ast()), ctx) 3338 3339 3340def ToInt(a): 3341 """ Return the Z3 expression ToInt(a). 3342 3343 >>> x = Real('x') 3344 >>> x.sort() 3345 Real 3346 >>> n = ToInt(x) 3347 >>> n 3348 ToInt(x) 3349 >>> n.sort() 3350 Int 3351 """ 3352 if z3_debug(): 3353 _z3_assert(a.is_real(), "Z3 real expression expected.") 3354 ctx = a.ctx 3355 return ArithRef(Z3_mk_real2int(ctx.ref(), a.as_ast()), ctx) 3356 3357 3358def IsInt(a): 3359 """ Return the Z3 predicate IsInt(a). 3360 3361 >>> x = Real('x') 3362 >>> IsInt(x + "1/2") 3363 IsInt(x + 1/2) 3364 >>> solve(IsInt(x + "1/2"), x > 0, x < 1) 3365 [x = 1/2] 3366 >>> solve(IsInt(x + "1/2"), x > 0, x < 1, x != "1/2") 3367 no solution 3368 """ 3369 if z3_debug(): 3370 _z3_assert(a.is_real(), "Z3 real expression expected.") 3371 ctx = a.ctx 3372 return BoolRef(Z3_mk_is_int(ctx.ref(), a.as_ast()), ctx) 3373 3374 3375def Sqrt(a, ctx=None): 3376 """ Return a Z3 expression which represents the square root of a. 3377 3378 >>> x = Real('x') 3379 >>> Sqrt(x) 3380 x**(1/2) 3381 """ 3382 if not is_expr(a): 3383 ctx = _get_ctx(ctx) 3384 a = RealVal(a, ctx) 3385 return a ** "1/2" 3386 3387 3388def Cbrt(a, ctx=None): 3389 """ Return a Z3 expression which represents the cubic root of a. 3390 3391 >>> x = Real('x') 3392 >>> Cbrt(x) 3393 x**(1/3) 3394 """ 3395 if not is_expr(a): 3396 ctx = _get_ctx(ctx) 3397 a = RealVal(a, ctx) 3398 return a ** "1/3" 3399 3400######################################### 3401# 3402# Bit-Vectors 3403# 3404######################################### 3405 3406 3407class BitVecSortRef(SortRef): 3408 """Bit-vector sort.""" 3409 3410 def size(self): 3411 """Return the size (number of bits) of the bit-vector sort `self`. 3412 3413 >>> b = BitVecSort(32) 3414 >>> b.size() 3415 32 3416 """ 3417 return int(Z3_get_bv_sort_size(self.ctx_ref(), self.ast)) 3418 3419 def subsort(self, other): 3420 return is_bv_sort(other) and self.size() < other.size() 3421 3422 def cast(self, val): 3423 """Try to cast `val` as a Bit-Vector. 3424 3425 >>> b = BitVecSort(32) 3426 >>> b.cast(10) 3427 10 3428 >>> b.cast(10).sexpr() 3429 '#x0000000a' 3430 """ 3431 if is_expr(val): 3432 if z3_debug(): 3433 _z3_assert(self.ctx == val.ctx, "Context mismatch") 3434 # Idea: use sign_extend if sort of val is a bitvector of smaller size 3435 return val 3436 else: 3437 return BitVecVal(val, self) 3438 3439 3440def is_bv_sort(s): 3441 """Return True if `s` is a Z3 bit-vector sort. 3442 3443 >>> is_bv_sort(BitVecSort(32)) 3444 True 3445 >>> is_bv_sort(IntSort()) 3446 False 3447 """ 3448 return isinstance(s, BitVecSortRef) 3449 3450 3451class BitVecRef(ExprRef): 3452 """Bit-vector expressions.""" 3453 3454 def sort(self): 3455 """Return the sort of the bit-vector expression `self`. 3456 3457 >>> x = BitVec('x', 32) 3458 >>> x.sort() 3459 BitVec(32) 3460 >>> x.sort() == BitVecSort(32) 3461 True 3462 """ 3463 return BitVecSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) 3464 3465 def size(self): 3466 """Return the number of bits of the bit-vector expression `self`. 3467 3468 >>> x = BitVec('x', 32) 3469 >>> (x + 1).size() 3470 32 3471 >>> Concat(x, x).size() 3472 64 3473 """ 3474 return self.sort().size() 3475 3476 def __add__(self, other): 3477 """Create the Z3 expression `self + other`. 3478 3479 >>> x = BitVec('x', 32) 3480 >>> y = BitVec('y', 32) 3481 >>> x + y 3482 x + y 3483 >>> (x + y).sort() 3484 BitVec(32) 3485 """ 3486 a, b = _coerce_exprs(self, other) 3487 return BitVecRef(Z3_mk_bvadd(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3488 3489 def __radd__(self, other): 3490 """Create the Z3 expression `other + self`. 3491 3492 >>> x = BitVec('x', 32) 3493 >>> 10 + x 3494 10 + x 3495 """ 3496 a, b = _coerce_exprs(self, other) 3497 return BitVecRef(Z3_mk_bvadd(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3498 3499 def __mul__(self, other): 3500 """Create the Z3 expression `self * other`. 3501 3502 >>> x = BitVec('x', 32) 3503 >>> y = BitVec('y', 32) 3504 >>> x * y 3505 x*y 3506 >>> (x * y).sort() 3507 BitVec(32) 3508 """ 3509 a, b = _coerce_exprs(self, other) 3510 return BitVecRef(Z3_mk_bvmul(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3511 3512 def __rmul__(self, other): 3513 """Create the Z3 expression `other * self`. 3514 3515 >>> x = BitVec('x', 32) 3516 >>> 10 * x 3517 10*x 3518 """ 3519 a, b = _coerce_exprs(self, other) 3520 return BitVecRef(Z3_mk_bvmul(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3521 3522 def __sub__(self, other): 3523 """Create the Z3 expression `self - other`. 3524 3525 >>> x = BitVec('x', 32) 3526 >>> y = BitVec('y', 32) 3527 >>> x - y 3528 x - y 3529 >>> (x - y).sort() 3530 BitVec(32) 3531 """ 3532 a, b = _coerce_exprs(self, other) 3533 return BitVecRef(Z3_mk_bvsub(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3534 3535 def __rsub__(self, other): 3536 """Create the Z3 expression `other - self`. 3537 3538 >>> x = BitVec('x', 32) 3539 >>> 10 - x 3540 10 - x 3541 """ 3542 a, b = _coerce_exprs(self, other) 3543 return BitVecRef(Z3_mk_bvsub(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3544 3545 def __or__(self, other): 3546 """Create the Z3 expression bitwise-or `self | other`. 3547 3548 >>> x = BitVec('x', 32) 3549 >>> y = BitVec('y', 32) 3550 >>> x | y 3551 x | y 3552 >>> (x | y).sort() 3553 BitVec(32) 3554 """ 3555 a, b = _coerce_exprs(self, other) 3556 return BitVecRef(Z3_mk_bvor(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3557 3558 def __ror__(self, other): 3559 """Create the Z3 expression bitwise-or `other | self`. 3560 3561 >>> x = BitVec('x', 32) 3562 >>> 10 | x 3563 10 | x 3564 """ 3565 a, b = _coerce_exprs(self, other) 3566 return BitVecRef(Z3_mk_bvor(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3567 3568 def __and__(self, other): 3569 """Create the Z3 expression bitwise-and `self & other`. 3570 3571 >>> x = BitVec('x', 32) 3572 >>> y = BitVec('y', 32) 3573 >>> x & y 3574 x & y 3575 >>> (x & y).sort() 3576 BitVec(32) 3577 """ 3578 a, b = _coerce_exprs(self, other) 3579 return BitVecRef(Z3_mk_bvand(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3580 3581 def __rand__(self, other): 3582 """Create the Z3 expression bitwise-or `other & self`. 3583 3584 >>> x = BitVec('x', 32) 3585 >>> 10 & x 3586 10 & x 3587 """ 3588 a, b = _coerce_exprs(self, other) 3589 return BitVecRef(Z3_mk_bvand(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3590 3591 def __xor__(self, other): 3592 """Create the Z3 expression bitwise-xor `self ^ other`. 3593 3594 >>> x = BitVec('x', 32) 3595 >>> y = BitVec('y', 32) 3596 >>> x ^ y 3597 x ^ y 3598 >>> (x ^ y).sort() 3599 BitVec(32) 3600 """ 3601 a, b = _coerce_exprs(self, other) 3602 return BitVecRef(Z3_mk_bvxor(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3603 3604 def __rxor__(self, other): 3605 """Create the Z3 expression bitwise-xor `other ^ self`. 3606 3607 >>> x = BitVec('x', 32) 3608 >>> 10 ^ x 3609 10 ^ x 3610 """ 3611 a, b = _coerce_exprs(self, other) 3612 return BitVecRef(Z3_mk_bvxor(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3613 3614 def __pos__(self): 3615 """Return `self`. 3616 3617 >>> x = BitVec('x', 32) 3618 >>> +x 3619 x 3620 """ 3621 return self 3622 3623 def __neg__(self): 3624 """Return an expression representing `-self`. 3625 3626 >>> x = BitVec('x', 32) 3627 >>> -x 3628 -x 3629 >>> simplify(-(-x)) 3630 x 3631 """ 3632 return BitVecRef(Z3_mk_bvneg(self.ctx_ref(), self.as_ast()), self.ctx) 3633 3634 def __invert__(self): 3635 """Create the Z3 expression bitwise-not `~self`. 3636 3637 >>> x = BitVec('x', 32) 3638 >>> ~x 3639 ~x 3640 >>> simplify(~(~x)) 3641 x 3642 """ 3643 return BitVecRef(Z3_mk_bvnot(self.ctx_ref(), self.as_ast()), self.ctx) 3644 3645 def __div__(self, other): 3646 """Create the Z3 expression (signed) division `self / other`. 3647 3648 Use the function UDiv() for unsigned division. 3649 3650 >>> x = BitVec('x', 32) 3651 >>> y = BitVec('y', 32) 3652 >>> x / y 3653 x/y 3654 >>> (x / y).sort() 3655 BitVec(32) 3656 >>> (x / y).sexpr() 3657 '(bvsdiv x y)' 3658 >>> UDiv(x, y).sexpr() 3659 '(bvudiv x y)' 3660 """ 3661 a, b = _coerce_exprs(self, other) 3662 return BitVecRef(Z3_mk_bvsdiv(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3663 3664 def __truediv__(self, other): 3665 """Create the Z3 expression (signed) division `self / other`.""" 3666 return self.__div__(other) 3667 3668 def __rdiv__(self, other): 3669 """Create the Z3 expression (signed) division `other / self`. 3670 3671 Use the function UDiv() for unsigned division. 3672 3673 >>> x = BitVec('x', 32) 3674 >>> 10 / x 3675 10/x 3676 >>> (10 / x).sexpr() 3677 '(bvsdiv #x0000000a x)' 3678 >>> UDiv(10, x).sexpr() 3679 '(bvudiv #x0000000a x)' 3680 """ 3681 a, b = _coerce_exprs(self, other) 3682 return BitVecRef(Z3_mk_bvsdiv(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3683 3684 def __rtruediv__(self, other): 3685 """Create the Z3 expression (signed) division `other / self`.""" 3686 return self.__rdiv__(other) 3687 3688 def __mod__(self, other): 3689 """Create the Z3 expression (signed) mod `self % other`. 3690 3691 Use the function URem() for unsigned remainder, and SRem() for signed remainder. 3692 3693 >>> x = BitVec('x', 32) 3694 >>> y = BitVec('y', 32) 3695 >>> x % y 3696 x%y 3697 >>> (x % y).sort() 3698 BitVec(32) 3699 >>> (x % y).sexpr() 3700 '(bvsmod x y)' 3701 >>> URem(x, y).sexpr() 3702 '(bvurem x y)' 3703 >>> SRem(x, y).sexpr() 3704 '(bvsrem x y)' 3705 """ 3706 a, b = _coerce_exprs(self, other) 3707 return BitVecRef(Z3_mk_bvsmod(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3708 3709 def __rmod__(self, other): 3710 """Create the Z3 expression (signed) mod `other % self`. 3711 3712 Use the function URem() for unsigned remainder, and SRem() for signed remainder. 3713 3714 >>> x = BitVec('x', 32) 3715 >>> 10 % x 3716 10%x 3717 >>> (10 % x).sexpr() 3718 '(bvsmod #x0000000a x)' 3719 >>> URem(10, x).sexpr() 3720 '(bvurem #x0000000a x)' 3721 >>> SRem(10, x).sexpr() 3722 '(bvsrem #x0000000a x)' 3723 """ 3724 a, b = _coerce_exprs(self, other) 3725 return BitVecRef(Z3_mk_bvsmod(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3726 3727 def __le__(self, other): 3728 """Create the Z3 expression (signed) `other <= self`. 3729 3730 Use the function ULE() for unsigned less than or equal to. 3731 3732 >>> x, y = BitVecs('x y', 32) 3733 >>> x <= y 3734 x <= y 3735 >>> (x <= y).sexpr() 3736 '(bvsle x y)' 3737 >>> ULE(x, y).sexpr() 3738 '(bvule x y)' 3739 """ 3740 a, b = _coerce_exprs(self, other) 3741 return BoolRef(Z3_mk_bvsle(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3742 3743 def __lt__(self, other): 3744 """Create the Z3 expression (signed) `other < self`. 3745 3746 Use the function ULT() for unsigned less than. 3747 3748 >>> x, y = BitVecs('x y', 32) 3749 >>> x < y 3750 x < y 3751 >>> (x < y).sexpr() 3752 '(bvslt x y)' 3753 >>> ULT(x, y).sexpr() 3754 '(bvult x y)' 3755 """ 3756 a, b = _coerce_exprs(self, other) 3757 return BoolRef(Z3_mk_bvslt(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3758 3759 def __gt__(self, other): 3760 """Create the Z3 expression (signed) `other > self`. 3761 3762 Use the function UGT() for unsigned greater than. 3763 3764 >>> x, y = BitVecs('x y', 32) 3765 >>> x > y 3766 x > y 3767 >>> (x > y).sexpr() 3768 '(bvsgt x y)' 3769 >>> UGT(x, y).sexpr() 3770 '(bvugt x y)' 3771 """ 3772 a, b = _coerce_exprs(self, other) 3773 return BoolRef(Z3_mk_bvsgt(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3774 3775 def __ge__(self, other): 3776 """Create the Z3 expression (signed) `other >= self`. 3777 3778 Use the function UGE() for unsigned greater than or equal to. 3779 3780 >>> x, y = BitVecs('x y', 32) 3781 >>> x >= y 3782 x >= y 3783 >>> (x >= y).sexpr() 3784 '(bvsge x y)' 3785 >>> UGE(x, y).sexpr() 3786 '(bvuge x y)' 3787 """ 3788 a, b = _coerce_exprs(self, other) 3789 return BoolRef(Z3_mk_bvsge(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3790 3791 def __rshift__(self, other): 3792 """Create the Z3 expression (arithmetical) right shift `self >> other` 3793 3794 Use the function LShR() for the right logical shift 3795 3796 >>> x, y = BitVecs('x y', 32) 3797 >>> x >> y 3798 x >> y 3799 >>> (x >> y).sexpr() 3800 '(bvashr x y)' 3801 >>> LShR(x, y).sexpr() 3802 '(bvlshr x y)' 3803 >>> BitVecVal(4, 3) 3804 4 3805 >>> BitVecVal(4, 3).as_signed_long() 3806 -4 3807 >>> simplify(BitVecVal(4, 3) >> 1).as_signed_long() 3808 -2 3809 >>> simplify(BitVecVal(4, 3) >> 1) 3810 6 3811 >>> simplify(LShR(BitVecVal(4, 3), 1)) 3812 2 3813 >>> simplify(BitVecVal(2, 3) >> 1) 3814 1 3815 >>> simplify(LShR(BitVecVal(2, 3), 1)) 3816 1 3817 """ 3818 a, b = _coerce_exprs(self, other) 3819 return BitVecRef(Z3_mk_bvashr(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3820 3821 def __lshift__(self, other): 3822 """Create the Z3 expression left shift `self << other` 3823 3824 >>> x, y = BitVecs('x y', 32) 3825 >>> x << y 3826 x << y 3827 >>> (x << y).sexpr() 3828 '(bvshl x y)' 3829 >>> simplify(BitVecVal(2, 3) << 1) 3830 4 3831 """ 3832 a, b = _coerce_exprs(self, other) 3833 return BitVecRef(Z3_mk_bvshl(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx) 3834 3835 def __rrshift__(self, other): 3836 """Create the Z3 expression (arithmetical) right shift `other` >> `self`. 3837 3838 Use the function LShR() for the right logical shift 3839 3840 >>> x = BitVec('x', 32) 3841 >>> 10 >> x 3842 10 >> x 3843 >>> (10 >> x).sexpr() 3844 '(bvashr #x0000000a x)' 3845 """ 3846 a, b = _coerce_exprs(self, other) 3847 return BitVecRef(Z3_mk_bvashr(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3848 3849 def __rlshift__(self, other): 3850 """Create the Z3 expression left shift `other << self`. 3851 3852 Use the function LShR() for the right logical shift 3853 3854 >>> x = BitVec('x', 32) 3855 >>> 10 << x 3856 10 << x 3857 >>> (10 << x).sexpr() 3858 '(bvshl #x0000000a x)' 3859 """ 3860 a, b = _coerce_exprs(self, other) 3861 return BitVecRef(Z3_mk_bvshl(self.ctx_ref(), b.as_ast(), a.as_ast()), self.ctx) 3862 3863 3864class BitVecNumRef(BitVecRef): 3865 """Bit-vector values.""" 3866 3867 def as_long(self): 3868 """Return a Z3 bit-vector numeral as a Python long (bignum) numeral. 3869 3870 >>> v = BitVecVal(0xbadc0de, 32) 3871 >>> v 3872 195936478 3873 >>> print("0x%.8x" % v.as_long()) 3874 0x0badc0de 3875 """ 3876 return int(self.as_string()) 3877 3878 def as_signed_long(self): 3879 """Return a Z3 bit-vector numeral as a Python long (bignum) numeral. 3880 The most significant bit is assumed to be the sign. 3881 3882 >>> BitVecVal(4, 3).as_signed_long() 3883 -4 3884 >>> BitVecVal(7, 3).as_signed_long() 3885 -1 3886 >>> BitVecVal(3, 3).as_signed_long() 3887 3 3888 >>> BitVecVal(2**32 - 1, 32).as_signed_long() 3889 -1 3890 >>> BitVecVal(2**64 - 1, 64).as_signed_long() 3891 -1 3892 """ 3893 sz = self.size() 3894 val = self.as_long() 3895 if val >= 2**(sz - 1): 3896 val = val - 2**sz 3897 if val < -2**(sz - 1): 3898 val = val + 2**sz 3899 return int(val) 3900 3901 def as_string(self): 3902 return Z3_get_numeral_string(self.ctx_ref(), self.as_ast()) 3903 3904 def as_binary_string(self): 3905 return Z3_get_numeral_binary_string(self.ctx_ref(), self.as_ast()) 3906 3907 3908def is_bv(a): 3909 """Return `True` if `a` is a Z3 bit-vector expression. 3910 3911 >>> b = BitVec('b', 32) 3912 >>> is_bv(b) 3913 True 3914 >>> is_bv(b + 10) 3915 True 3916 >>> is_bv(Int('x')) 3917 False 3918 """ 3919 return isinstance(a, BitVecRef) 3920 3921 3922def is_bv_value(a): 3923 """Return `True` if `a` is a Z3 bit-vector numeral value. 3924 3925 >>> b = BitVec('b', 32) 3926 >>> is_bv_value(b) 3927 False 3928 >>> b = BitVecVal(10, 32) 3929 >>> b 3930 10 3931 >>> is_bv_value(b) 3932 True 3933 """ 3934 return is_bv(a) and _is_numeral(a.ctx, a.as_ast()) 3935 3936 3937def BV2Int(a, is_signed=False): 3938 """Return the Z3 expression BV2Int(a). 3939 3940 >>> b = BitVec('b', 3) 3941 >>> BV2Int(b).sort() 3942 Int 3943 >>> x = Int('x') 3944 >>> x > BV2Int(b) 3945 x > BV2Int(b) 3946 >>> x > BV2Int(b, is_signed=False) 3947 x > BV2Int(b) 3948 >>> x > BV2Int(b, is_signed=True) 3949 x > If(b < 0, BV2Int(b) - 8, BV2Int(b)) 3950 >>> solve(x > BV2Int(b), b == 1, x < 3) 3951 [x = 2, b = 1] 3952 """ 3953 if z3_debug(): 3954 _z3_assert(is_bv(a), "First argument must be a Z3 bit-vector expression") 3955 ctx = a.ctx 3956 # investigate problem with bv2int 3957 return ArithRef(Z3_mk_bv2int(ctx.ref(), a.as_ast(), is_signed), ctx) 3958 3959 3960def Int2BV(a, num_bits): 3961 """Return the z3 expression Int2BV(a, num_bits). 3962 It is a bit-vector of width num_bits and represents the 3963 modulo of a by 2^num_bits 3964 """ 3965 ctx = a.ctx 3966 return BitVecRef(Z3_mk_int2bv(ctx.ref(), num_bits, a.as_ast()), ctx) 3967 3968 3969def BitVecSort(sz, ctx=None): 3970 """Return a Z3 bit-vector sort of the given size. If `ctx=None`, then the global context is used. 3971 3972 >>> Byte = BitVecSort(8) 3973 >>> Word = BitVecSort(16) 3974 >>> Byte 3975 BitVec(8) 3976 >>> x = Const('x', Byte) 3977 >>> eq(x, BitVec('x', 8)) 3978 True 3979 """ 3980 ctx = _get_ctx(ctx) 3981 return BitVecSortRef(Z3_mk_bv_sort(ctx.ref(), sz), ctx) 3982 3983 3984def BitVecVal(val, bv, ctx=None): 3985 """Return a bit-vector value with the given number of bits. If `ctx=None`, then the global context is used. 3986 3987 >>> v = BitVecVal(10, 32) 3988 >>> v 3989 10 3990 >>> print("0x%.8x" % v.as_long()) 3991 0x0000000a 3992 """ 3993 if is_bv_sort(bv): 3994 ctx = bv.ctx 3995 return BitVecNumRef(Z3_mk_numeral(ctx.ref(), _to_int_str(val), bv.ast), ctx) 3996 else: 3997 ctx = _get_ctx(ctx) 3998 return BitVecNumRef(Z3_mk_numeral(ctx.ref(), _to_int_str(val), BitVecSort(bv, ctx).ast), ctx) 3999 4000 4001def BitVec(name, bv, ctx=None): 4002 """Return a bit-vector constant named `name`. `bv` may be the number of bits of a bit-vector sort. 4003 If `ctx=None`, then the global context is used. 4004 4005 >>> x = BitVec('x', 16) 4006 >>> is_bv(x) 4007 True 4008 >>> x.size() 4009 16 4010 >>> x.sort() 4011 BitVec(16) 4012 >>> word = BitVecSort(16) 4013 >>> x2 = BitVec('x', word) 4014 >>> eq(x, x2) 4015 True 4016 """ 4017 if isinstance(bv, BitVecSortRef): 4018 ctx = bv.ctx 4019 else: 4020 ctx = _get_ctx(ctx) 4021 bv = BitVecSort(bv, ctx) 4022 return BitVecRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), bv.ast), ctx) 4023 4024 4025def BitVecs(names, bv, ctx=None): 4026 """Return a tuple of bit-vector constants of size bv. 4027 4028 >>> x, y, z = BitVecs('x y z', 16) 4029 >>> x.size() 4030 16 4031 >>> x.sort() 4032 BitVec(16) 4033 >>> Sum(x, y, z) 4034 0 + x + y + z 4035 >>> Product(x, y, z) 4036 1*x*y*z 4037 >>> simplify(Product(x, y, z)) 4038 x*y*z 4039 """ 4040 ctx = _get_ctx(ctx) 4041 if isinstance(names, str): 4042 names = names.split(" ") 4043 return [BitVec(name, bv, ctx) for name in names] 4044 4045 4046def Concat(*args): 4047 """Create a Z3 bit-vector concatenation expression. 4048 4049 >>> v = BitVecVal(1, 4) 4050 >>> Concat(v, v+1, v) 4051 Concat(Concat(1, 1 + 1), 1) 4052 >>> simplify(Concat(v, v+1, v)) 4053 289 4054 >>> print("%.3x" % simplify(Concat(v, v+1, v)).as_long()) 4055 121 4056 """ 4057 args = _get_args(args) 4058 sz = len(args) 4059 if z3_debug(): 4060 _z3_assert(sz >= 2, "At least two arguments expected.") 4061 4062 ctx = None 4063 for a in args: 4064 if is_expr(a): 4065 ctx = a.ctx 4066 break 4067 if is_seq(args[0]) or isinstance(args[0], str): 4068 args = [_coerce_seq(s, ctx) for s in args] 4069 if z3_debug(): 4070 _z3_assert(all([is_seq(a) for a in args]), "All arguments must be sequence expressions.") 4071 v = (Ast * sz)() 4072 for i in range(sz): 4073 v[i] = args[i].as_ast() 4074 return SeqRef(Z3_mk_seq_concat(ctx.ref(), sz, v), ctx) 4075 4076 if is_re(args[0]): 4077 if z3_debug(): 4078 _z3_assert(all([is_re(a) for a in args]), "All arguments must be regular expressions.") 4079 v = (Ast * sz)() 4080 for i in range(sz): 4081 v[i] = args[i].as_ast() 4082 return ReRef(Z3_mk_re_concat(ctx.ref(), sz, v), ctx) 4083 4084 if z3_debug(): 4085 _z3_assert(all([is_bv(a) for a in args]), "All arguments must be Z3 bit-vector expressions.") 4086 r = args[0] 4087 for i in range(sz - 1): 4088 r = BitVecRef(Z3_mk_concat(ctx.ref(), r.as_ast(), args[i + 1].as_ast()), ctx) 4089 return r 4090 4091 4092def Extract(high, low, a): 4093 """Create a Z3 bit-vector extraction expression. 4094 Extract is overloaded to also work on sequence extraction. 4095 The functions SubString and SubSeq are redirected to Extract. 4096 For this case, the arguments are reinterpreted as: 4097 high - is a sequence (string) 4098 low - is an offset 4099 a - is the length to be extracted 4100 4101 >>> x = BitVec('x', 8) 4102 >>> Extract(6, 2, x) 4103 Extract(6, 2, x) 4104 >>> Extract(6, 2, x).sort() 4105 BitVec(5) 4106 >>> simplify(Extract(StringVal("abcd"),2,1)) 4107 "c" 4108 """ 4109 if isinstance(high, str): 4110 high = StringVal(high) 4111 if is_seq(high): 4112 s = high 4113 offset, length = _coerce_exprs(low, a, s.ctx) 4114 return SeqRef(Z3_mk_seq_extract(s.ctx_ref(), s.as_ast(), offset.as_ast(), length.as_ast()), s.ctx) 4115 if z3_debug(): 4116 _z3_assert(low <= high, "First argument must be greater than or equal to second argument") 4117 _z3_assert(_is_int(high) and high >= 0 and _is_int(low) and low >= 0, 4118 "First and second arguments must be non negative integers") 4119 _z3_assert(is_bv(a), "Third argument must be a Z3 bit-vector expression") 4120 return BitVecRef(Z3_mk_extract(a.ctx_ref(), high, low, a.as_ast()), a.ctx) 4121 4122 4123def _check_bv_args(a, b): 4124 if z3_debug(): 4125 _z3_assert(is_bv(a) or is_bv(b), "First or second argument must be a Z3 bit-vector expression") 4126 4127 4128def ULE(a, b): 4129 """Create the Z3 expression (unsigned) `other <= self`. 4130 4131 Use the operator <= for signed less than or equal to. 4132 4133 >>> x, y = BitVecs('x y', 32) 4134 >>> ULE(x, y) 4135 ULE(x, y) 4136 >>> (x <= y).sexpr() 4137 '(bvsle x y)' 4138 >>> ULE(x, y).sexpr() 4139 '(bvule x y)' 4140 """ 4141 _check_bv_args(a, b) 4142 a, b = _coerce_exprs(a, b) 4143 return BoolRef(Z3_mk_bvule(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4144 4145 4146def ULT(a, b): 4147 """Create the Z3 expression (unsigned) `other < self`. 4148 4149 Use the operator < for signed less than. 4150 4151 >>> x, y = BitVecs('x y', 32) 4152 >>> ULT(x, y) 4153 ULT(x, y) 4154 >>> (x < y).sexpr() 4155 '(bvslt x y)' 4156 >>> ULT(x, y).sexpr() 4157 '(bvult x y)' 4158 """ 4159 _check_bv_args(a, b) 4160 a, b = _coerce_exprs(a, b) 4161 return BoolRef(Z3_mk_bvult(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4162 4163 4164def UGE(a, b): 4165 """Create the Z3 expression (unsigned) `other >= self`. 4166 4167 Use the operator >= for signed greater than or equal to. 4168 4169 >>> x, y = BitVecs('x y', 32) 4170 >>> UGE(x, y) 4171 UGE(x, y) 4172 >>> (x >= y).sexpr() 4173 '(bvsge x y)' 4174 >>> UGE(x, y).sexpr() 4175 '(bvuge x y)' 4176 """ 4177 _check_bv_args(a, b) 4178 a, b = _coerce_exprs(a, b) 4179 return BoolRef(Z3_mk_bvuge(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4180 4181 4182def UGT(a, b): 4183 """Create the Z3 expression (unsigned) `other > self`. 4184 4185 Use the operator > for signed greater than. 4186 4187 >>> x, y = BitVecs('x y', 32) 4188 >>> UGT(x, y) 4189 UGT(x, y) 4190 >>> (x > y).sexpr() 4191 '(bvsgt x y)' 4192 >>> UGT(x, y).sexpr() 4193 '(bvugt x y)' 4194 """ 4195 _check_bv_args(a, b) 4196 a, b = _coerce_exprs(a, b) 4197 return BoolRef(Z3_mk_bvugt(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4198 4199 4200def UDiv(a, b): 4201 """Create the Z3 expression (unsigned) division `self / other`. 4202 4203 Use the operator / for signed division. 4204 4205 >>> x = BitVec('x', 32) 4206 >>> y = BitVec('y', 32) 4207 >>> UDiv(x, y) 4208 UDiv(x, y) 4209 >>> UDiv(x, y).sort() 4210 BitVec(32) 4211 >>> (x / y).sexpr() 4212 '(bvsdiv x y)' 4213 >>> UDiv(x, y).sexpr() 4214 '(bvudiv x y)' 4215 """ 4216 _check_bv_args(a, b) 4217 a, b = _coerce_exprs(a, b) 4218 return BitVecRef(Z3_mk_bvudiv(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4219 4220 4221def URem(a, b): 4222 """Create the Z3 expression (unsigned) remainder `self % other`. 4223 4224 Use the operator % for signed modulus, and SRem() for signed remainder. 4225 4226 >>> x = BitVec('x', 32) 4227 >>> y = BitVec('y', 32) 4228 >>> URem(x, y) 4229 URem(x, y) 4230 >>> URem(x, y).sort() 4231 BitVec(32) 4232 >>> (x % y).sexpr() 4233 '(bvsmod x y)' 4234 >>> URem(x, y).sexpr() 4235 '(bvurem x y)' 4236 """ 4237 _check_bv_args(a, b) 4238 a, b = _coerce_exprs(a, b) 4239 return BitVecRef(Z3_mk_bvurem(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4240 4241 4242def SRem(a, b): 4243 """Create the Z3 expression signed remainder. 4244 4245 Use the operator % for signed modulus, and URem() for unsigned remainder. 4246 4247 >>> x = BitVec('x', 32) 4248 >>> y = BitVec('y', 32) 4249 >>> SRem(x, y) 4250 SRem(x, y) 4251 >>> SRem(x, y).sort() 4252 BitVec(32) 4253 >>> (x % y).sexpr() 4254 '(bvsmod x y)' 4255 >>> SRem(x, y).sexpr() 4256 '(bvsrem x y)' 4257 """ 4258 _check_bv_args(a, b) 4259 a, b = _coerce_exprs(a, b) 4260 return BitVecRef(Z3_mk_bvsrem(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4261 4262 4263def LShR(a, b): 4264 """Create the Z3 expression logical right shift. 4265 4266 Use the operator >> for the arithmetical right shift. 4267 4268 >>> x, y = BitVecs('x y', 32) 4269 >>> LShR(x, y) 4270 LShR(x, y) 4271 >>> (x >> y).sexpr() 4272 '(bvashr x y)' 4273 >>> LShR(x, y).sexpr() 4274 '(bvlshr x y)' 4275 >>> BitVecVal(4, 3) 4276 4 4277 >>> BitVecVal(4, 3).as_signed_long() 4278 -4 4279 >>> simplify(BitVecVal(4, 3) >> 1).as_signed_long() 4280 -2 4281 >>> simplify(BitVecVal(4, 3) >> 1) 4282 6 4283 >>> simplify(LShR(BitVecVal(4, 3), 1)) 4284 2 4285 >>> simplify(BitVecVal(2, 3) >> 1) 4286 1 4287 >>> simplify(LShR(BitVecVal(2, 3), 1)) 4288 1 4289 """ 4290 _check_bv_args(a, b) 4291 a, b = _coerce_exprs(a, b) 4292 return BitVecRef(Z3_mk_bvlshr(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4293 4294 4295def RotateLeft(a, b): 4296 """Return an expression representing `a` rotated to the left `b` times. 4297 4298 >>> a, b = BitVecs('a b', 16) 4299 >>> RotateLeft(a, b) 4300 RotateLeft(a, b) 4301 >>> simplify(RotateLeft(a, 0)) 4302 a 4303 >>> simplify(RotateLeft(a, 16)) 4304 a 4305 """ 4306 _check_bv_args(a, b) 4307 a, b = _coerce_exprs(a, b) 4308 return BitVecRef(Z3_mk_ext_rotate_left(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4309 4310 4311def RotateRight(a, b): 4312 """Return an expression representing `a` rotated to the right `b` times. 4313 4314 >>> a, b = BitVecs('a b', 16) 4315 >>> RotateRight(a, b) 4316 RotateRight(a, b) 4317 >>> simplify(RotateRight(a, 0)) 4318 a 4319 >>> simplify(RotateRight(a, 16)) 4320 a 4321 """ 4322 _check_bv_args(a, b) 4323 a, b = _coerce_exprs(a, b) 4324 return BitVecRef(Z3_mk_ext_rotate_right(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4325 4326 4327def SignExt(n, a): 4328 """Return a bit-vector expression with `n` extra sign-bits. 4329 4330 >>> x = BitVec('x', 16) 4331 >>> n = SignExt(8, x) 4332 >>> n.size() 4333 24 4334 >>> n 4335 SignExt(8, x) 4336 >>> n.sort() 4337 BitVec(24) 4338 >>> v0 = BitVecVal(2, 2) 4339 >>> v0 4340 2 4341 >>> v0.size() 4342 2 4343 >>> v = simplify(SignExt(6, v0)) 4344 >>> v 4345 254 4346 >>> v.size() 4347 8 4348 >>> print("%.x" % v.as_long()) 4349 fe 4350 """ 4351 if z3_debug(): 4352 _z3_assert(_is_int(n), "First argument must be an integer") 4353 _z3_assert(is_bv(a), "Second argument must be a Z3 bit-vector expression") 4354 return BitVecRef(Z3_mk_sign_ext(a.ctx_ref(), n, a.as_ast()), a.ctx) 4355 4356 4357def ZeroExt(n, a): 4358 """Return a bit-vector expression with `n` extra zero-bits. 4359 4360 >>> x = BitVec('x', 16) 4361 >>> n = ZeroExt(8, x) 4362 >>> n.size() 4363 24 4364 >>> n 4365 ZeroExt(8, x) 4366 >>> n.sort() 4367 BitVec(24) 4368 >>> v0 = BitVecVal(2, 2) 4369 >>> v0 4370 2 4371 >>> v0.size() 4372 2 4373 >>> v = simplify(ZeroExt(6, v0)) 4374 >>> v 4375 2 4376 >>> v.size() 4377 8 4378 """ 4379 if z3_debug(): 4380 _z3_assert(_is_int(n), "First argument must be an integer") 4381 _z3_assert(is_bv(a), "Second argument must be a Z3 bit-vector expression") 4382 return BitVecRef(Z3_mk_zero_ext(a.ctx_ref(), n, a.as_ast()), a.ctx) 4383 4384 4385def RepeatBitVec(n, a): 4386 """Return an expression representing `n` copies of `a`. 4387 4388 >>> x = BitVec('x', 8) 4389 >>> n = RepeatBitVec(4, x) 4390 >>> n 4391 RepeatBitVec(4, x) 4392 >>> n.size() 4393 32 4394 >>> v0 = BitVecVal(10, 4) 4395 >>> print("%.x" % v0.as_long()) 4396 a 4397 >>> v = simplify(RepeatBitVec(4, v0)) 4398 >>> v.size() 4399 16 4400 >>> print("%.x" % v.as_long()) 4401 aaaa 4402 """ 4403 if z3_debug(): 4404 _z3_assert(_is_int(n), "First argument must be an integer") 4405 _z3_assert(is_bv(a), "Second argument must be a Z3 bit-vector expression") 4406 return BitVecRef(Z3_mk_repeat(a.ctx_ref(), n, a.as_ast()), a.ctx) 4407 4408 4409def BVRedAnd(a): 4410 """Return the reduction-and expression of `a`.""" 4411 if z3_debug(): 4412 _z3_assert(is_bv(a), "First argument must be a Z3 bit-vector expression") 4413 return BitVecRef(Z3_mk_bvredand(a.ctx_ref(), a.as_ast()), a.ctx) 4414 4415 4416def BVRedOr(a): 4417 """Return the reduction-or expression of `a`.""" 4418 if z3_debug(): 4419 _z3_assert(is_bv(a), "First argument must be a Z3 bit-vector expression") 4420 return BitVecRef(Z3_mk_bvredor(a.ctx_ref(), a.as_ast()), a.ctx) 4421 4422 4423def BVAddNoOverflow(a, b, signed): 4424 """A predicate the determines that bit-vector addition does not overflow""" 4425 _check_bv_args(a, b) 4426 a, b = _coerce_exprs(a, b) 4427 return BoolRef(Z3_mk_bvadd_no_overflow(a.ctx_ref(), a.as_ast(), b.as_ast(), signed), a.ctx) 4428 4429 4430def BVAddNoUnderflow(a, b): 4431 """A predicate the determines that signed bit-vector addition does not underflow""" 4432 _check_bv_args(a, b) 4433 a, b = _coerce_exprs(a, b) 4434 return BoolRef(Z3_mk_bvadd_no_underflow(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4435 4436 4437def BVSubNoOverflow(a, b): 4438 """A predicate the determines that bit-vector subtraction does not overflow""" 4439 _check_bv_args(a, b) 4440 a, b = _coerce_exprs(a, b) 4441 return BoolRef(Z3_mk_bvsub_no_overflow(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4442 4443 4444def BVSubNoUnderflow(a, b, signed): 4445 """A predicate the determines that bit-vector subtraction does not underflow""" 4446 _check_bv_args(a, b) 4447 a, b = _coerce_exprs(a, b) 4448 return BoolRef(Z3_mk_bvsub_no_underflow(a.ctx_ref(), a.as_ast(), b.as_ast(), signed), a.ctx) 4449 4450 4451def BVSDivNoOverflow(a, b): 4452 """A predicate the determines that bit-vector signed division does not overflow""" 4453 _check_bv_args(a, b) 4454 a, b = _coerce_exprs(a, b) 4455 return BoolRef(Z3_mk_bvsdiv_no_overflow(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4456 4457 4458def BVSNegNoOverflow(a): 4459 """A predicate the determines that bit-vector unary negation does not overflow""" 4460 if z3_debug(): 4461 _z3_assert(is_bv(a), "First argument must be a Z3 bit-vector expression") 4462 return BoolRef(Z3_mk_bvneg_no_overflow(a.ctx_ref(), a.as_ast()), a.ctx) 4463 4464 4465def BVMulNoOverflow(a, b, signed): 4466 """A predicate the determines that bit-vector multiplication does not overflow""" 4467 _check_bv_args(a, b) 4468 a, b = _coerce_exprs(a, b) 4469 return BoolRef(Z3_mk_bvmul_no_overflow(a.ctx_ref(), a.as_ast(), b.as_ast(), signed), a.ctx) 4470 4471 4472def BVMulNoUnderflow(a, b): 4473 """A predicate the determines that bit-vector signed multiplication does not underflow""" 4474 _check_bv_args(a, b) 4475 a, b = _coerce_exprs(a, b) 4476 return BoolRef(Z3_mk_bvmul_no_underflow(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 4477 4478 4479######################################### 4480# 4481# Arrays 4482# 4483######################################### 4484 4485class ArraySortRef(SortRef): 4486 """Array sorts.""" 4487 4488 def domain(self): 4489 """Return the domain of the array sort `self`. 4490 4491 >>> A = ArraySort(IntSort(), BoolSort()) 4492 >>> A.domain() 4493 Int 4494 """ 4495 return _to_sort_ref(Z3_get_array_sort_domain(self.ctx_ref(), self.ast), self.ctx) 4496 4497 def range(self): 4498 """Return the range of the array sort `self`. 4499 4500 >>> A = ArraySort(IntSort(), BoolSort()) 4501 >>> A.range() 4502 Bool 4503 """ 4504 return _to_sort_ref(Z3_get_array_sort_range(self.ctx_ref(), self.ast), self.ctx) 4505 4506 4507class ArrayRef(ExprRef): 4508 """Array expressions. """ 4509 4510 def sort(self): 4511 """Return the array sort of the array expression `self`. 4512 4513 >>> a = Array('a', IntSort(), BoolSort()) 4514 >>> a.sort() 4515 Array(Int, Bool) 4516 """ 4517 return ArraySortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) 4518 4519 def domain(self): 4520 """Shorthand for `self.sort().domain()`. 4521 4522 >>> a = Array('a', IntSort(), BoolSort()) 4523 >>> a.domain() 4524 Int 4525 """ 4526 return self.sort().domain() 4527 4528 def range(self): 4529 """Shorthand for `self.sort().range()`. 4530 4531 >>> a = Array('a', IntSort(), BoolSort()) 4532 >>> a.range() 4533 Bool 4534 """ 4535 return self.sort().range() 4536 4537 def __getitem__(self, arg): 4538 """Return the Z3 expression `self[arg]`. 4539 4540 >>> a = Array('a', IntSort(), BoolSort()) 4541 >>> i = Int('i') 4542 >>> a[i] 4543 a[i] 4544 >>> a[i].sexpr() 4545 '(select a i)' 4546 """ 4547 arg = self.domain().cast(arg) 4548 return _to_expr_ref(Z3_mk_select(self.ctx_ref(), self.as_ast(), arg.as_ast()), self.ctx) 4549 4550 def default(self): 4551 return _to_expr_ref(Z3_mk_array_default(self.ctx_ref(), self.as_ast()), self.ctx) 4552 4553 4554def is_array_sort(a): 4555 return Z3_get_sort_kind(a.ctx.ref(), Z3_get_sort(a.ctx.ref(), a.ast)) == Z3_ARRAY_SORT 4556 4557 4558def is_array(a): 4559 """Return `True` if `a` is a Z3 array expression. 4560 4561 >>> a = Array('a', IntSort(), IntSort()) 4562 >>> is_array(a) 4563 True 4564 >>> is_array(Store(a, 0, 1)) 4565 True 4566 >>> is_array(a[0]) 4567 False 4568 """ 4569 return isinstance(a, ArrayRef) 4570 4571 4572def is_const_array(a): 4573 """Return `True` if `a` is a Z3 constant array. 4574 4575 >>> a = K(IntSort(), 10) 4576 >>> is_const_array(a) 4577 True 4578 >>> a = Array('a', IntSort(), IntSort()) 4579 >>> is_const_array(a) 4580 False 4581 """ 4582 return is_app_of(a, Z3_OP_CONST_ARRAY) 4583 4584 4585def is_K(a): 4586 """Return `True` if `a` is a Z3 constant array. 4587 4588 >>> a = K(IntSort(), 10) 4589 >>> is_K(a) 4590 True 4591 >>> a = Array('a', IntSort(), IntSort()) 4592 >>> is_K(a) 4593 False 4594 """ 4595 return is_app_of(a, Z3_OP_CONST_ARRAY) 4596 4597 4598def is_map(a): 4599 """Return `True` if `a` is a Z3 map array expression. 4600 4601 >>> f = Function('f', IntSort(), IntSort()) 4602 >>> b = Array('b', IntSort(), IntSort()) 4603 >>> a = Map(f, b) 4604 >>> a 4605 Map(f, b) 4606 >>> is_map(a) 4607 True 4608 >>> is_map(b) 4609 False 4610 """ 4611 return is_app_of(a, Z3_OP_ARRAY_MAP) 4612 4613 4614def is_default(a): 4615 """Return `True` if `a` is a Z3 default array expression. 4616 >>> d = Default(K(IntSort(), 10)) 4617 >>> is_default(d) 4618 True 4619 """ 4620 return is_app_of(a, Z3_OP_ARRAY_DEFAULT) 4621 4622 4623def get_map_func(a): 4624 """Return the function declaration associated with a Z3 map array expression. 4625 4626 >>> f = Function('f', IntSort(), IntSort()) 4627 >>> b = Array('b', IntSort(), IntSort()) 4628 >>> a = Map(f, b) 4629 >>> eq(f, get_map_func(a)) 4630 True 4631 >>> get_map_func(a) 4632 f 4633 >>> get_map_func(a)(0) 4634 f(0) 4635 """ 4636 if z3_debug(): 4637 _z3_assert(is_map(a), "Z3 array map expression expected.") 4638 return FuncDeclRef( 4639 Z3_to_func_decl( 4640 a.ctx_ref(), 4641 Z3_get_decl_ast_parameter(a.ctx_ref(), a.decl().ast, 0), 4642 ), 4643 ctx=a.ctx, 4644 ) 4645 4646 4647def ArraySort(*sig): 4648 """Return the Z3 array sort with the given domain and range sorts. 4649 4650 >>> A = ArraySort(IntSort(), BoolSort()) 4651 >>> A 4652 Array(Int, Bool) 4653 >>> A.domain() 4654 Int 4655 >>> A.range() 4656 Bool 4657 >>> AA = ArraySort(IntSort(), A) 4658 >>> AA 4659 Array(Int, Array(Int, Bool)) 4660 """ 4661 sig = _get_args(sig) 4662 if z3_debug(): 4663 _z3_assert(len(sig) > 1, "At least two arguments expected") 4664 arity = len(sig) - 1 4665 r = sig[arity] 4666 d = sig[0] 4667 if z3_debug(): 4668 for s in sig: 4669 _z3_assert(is_sort(s), "Z3 sort expected") 4670 _z3_assert(s.ctx == r.ctx, "Context mismatch") 4671 ctx = d.ctx 4672 if len(sig) == 2: 4673 return ArraySortRef(Z3_mk_array_sort(ctx.ref(), d.ast, r.ast), ctx) 4674 dom = (Sort * arity)() 4675 for i in range(arity): 4676 dom[i] = sig[i].ast 4677 return ArraySortRef(Z3_mk_array_sort_n(ctx.ref(), arity, dom, r.ast), ctx) 4678 4679 4680def Array(name, dom, rng): 4681 """Return an array constant named `name` with the given domain and range sorts. 4682 4683 >>> a = Array('a', IntSort(), IntSort()) 4684 >>> a.sort() 4685 Array(Int, Int) 4686 >>> a[0] 4687 a[0] 4688 """ 4689 s = ArraySort(dom, rng) 4690 ctx = s.ctx 4691 return ArrayRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), s.ast), ctx) 4692 4693 4694def Update(a, i, v): 4695 """Return a Z3 store array expression. 4696 4697 >>> a = Array('a', IntSort(), IntSort()) 4698 >>> i, v = Ints('i v') 4699 >>> s = Update(a, i, v) 4700 >>> s.sort() 4701 Array(Int, Int) 4702 >>> prove(s[i] == v) 4703 proved 4704 >>> j = Int('j') 4705 >>> prove(Implies(i != j, s[j] == a[j])) 4706 proved 4707 """ 4708 if z3_debug(): 4709 _z3_assert(is_array_sort(a), "First argument must be a Z3 array expression") 4710 i = a.sort().domain().cast(i) 4711 v = a.sort().range().cast(v) 4712 ctx = a.ctx 4713 return _to_expr_ref(Z3_mk_store(ctx.ref(), a.as_ast(), i.as_ast(), v.as_ast()), ctx) 4714 4715 4716def Default(a): 4717 """ Return a default value for array expression. 4718 >>> b = K(IntSort(), 1) 4719 >>> prove(Default(b) == 1) 4720 proved 4721 """ 4722 if z3_debug(): 4723 _z3_assert(is_array_sort(a), "First argument must be a Z3 array expression") 4724 return a.default() 4725 4726 4727def Store(a, i, v): 4728 """Return a Z3 store array expression. 4729 4730 >>> a = Array('a', IntSort(), IntSort()) 4731 >>> i, v = Ints('i v') 4732 >>> s = Store(a, i, v) 4733 >>> s.sort() 4734 Array(Int, Int) 4735 >>> prove(s[i] == v) 4736 proved 4737 >>> j = Int('j') 4738 >>> prove(Implies(i != j, s[j] == a[j])) 4739 proved 4740 """ 4741 return Update(a, i, v) 4742 4743 4744def Select(a, i): 4745 """Return a Z3 select array expression. 4746 4747 >>> a = Array('a', IntSort(), IntSort()) 4748 >>> i = Int('i') 4749 >>> Select(a, i) 4750 a[i] 4751 >>> eq(Select(a, i), a[i]) 4752 True 4753 """ 4754 if z3_debug(): 4755 _z3_assert(is_array_sort(a), "First argument must be a Z3 array expression") 4756 return a[i] 4757 4758 4759def Map(f, *args): 4760 """Return a Z3 map array expression. 4761 4762 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 4763 >>> a1 = Array('a1', IntSort(), IntSort()) 4764 >>> a2 = Array('a2', IntSort(), IntSort()) 4765 >>> b = Map(f, a1, a2) 4766 >>> b 4767 Map(f, a1, a2) 4768 >>> prove(b[0] == f(a1[0], a2[0])) 4769 proved 4770 """ 4771 args = _get_args(args) 4772 if z3_debug(): 4773 _z3_assert(len(args) > 0, "At least one Z3 array expression expected") 4774 _z3_assert(is_func_decl(f), "First argument must be a Z3 function declaration") 4775 _z3_assert(all([is_array(a) for a in args]), "Z3 array expected expected") 4776 _z3_assert(len(args) == f.arity(), "Number of arguments mismatch") 4777 _args, sz = _to_ast_array(args) 4778 ctx = f.ctx 4779 return ArrayRef(Z3_mk_map(ctx.ref(), f.ast, sz, _args), ctx) 4780 4781 4782def K(dom, v): 4783 """Return a Z3 constant array expression. 4784 4785 >>> a = K(IntSort(), 10) 4786 >>> a 4787 K(Int, 10) 4788 >>> a.sort() 4789 Array(Int, Int) 4790 >>> i = Int('i') 4791 >>> a[i] 4792 K(Int, 10)[i] 4793 >>> simplify(a[i]) 4794 10 4795 """ 4796 if z3_debug(): 4797 _z3_assert(is_sort(dom), "Z3 sort expected") 4798 ctx = dom.ctx 4799 if not is_expr(v): 4800 v = _py2expr(v, ctx) 4801 return ArrayRef(Z3_mk_const_array(ctx.ref(), dom.ast, v.as_ast()), ctx) 4802 4803 4804def Ext(a, b): 4805 """Return extensionality index for one-dimensional arrays. 4806 >> a, b = Consts('a b', SetSort(IntSort())) 4807 >> Ext(a, b) 4808 Ext(a, b) 4809 """ 4810 ctx = a.ctx 4811 if z3_debug(): 4812 _z3_assert(is_array_sort(a) and is_array(b), "arguments must be arrays") 4813 return _to_expr_ref(Z3_mk_array_ext(ctx.ref(), a.as_ast(), b.as_ast()), ctx) 4814 4815 4816def SetHasSize(a, k): 4817 ctx = a.ctx 4818 k = _py2expr(k, ctx) 4819 return _to_expr_ref(Z3_mk_set_has_size(ctx.ref(), a.as_ast(), k.as_ast()), ctx) 4820 4821 4822def is_select(a): 4823 """Return `True` if `a` is a Z3 array select application. 4824 4825 >>> a = Array('a', IntSort(), IntSort()) 4826 >>> is_select(a) 4827 False 4828 >>> i = Int('i') 4829 >>> is_select(a[i]) 4830 True 4831 """ 4832 return is_app_of(a, Z3_OP_SELECT) 4833 4834 4835def is_store(a): 4836 """Return `True` if `a` is a Z3 array store application. 4837 4838 >>> a = Array('a', IntSort(), IntSort()) 4839 >>> is_store(a) 4840 False 4841 >>> is_store(Store(a, 0, 1)) 4842 True 4843 """ 4844 return is_app_of(a, Z3_OP_STORE) 4845 4846######################################### 4847# 4848# Sets 4849# 4850######################################### 4851 4852 4853def SetSort(s): 4854 """ Create a set sort over element sort s""" 4855 return ArraySort(s, BoolSort()) 4856 4857 4858def EmptySet(s): 4859 """Create the empty set 4860 >>> EmptySet(IntSort()) 4861 K(Int, False) 4862 """ 4863 ctx = s.ctx 4864 return ArrayRef(Z3_mk_empty_set(ctx.ref(), s.ast), ctx) 4865 4866 4867def FullSet(s): 4868 """Create the full set 4869 >>> FullSet(IntSort()) 4870 K(Int, True) 4871 """ 4872 ctx = s.ctx 4873 return ArrayRef(Z3_mk_full_set(ctx.ref(), s.ast), ctx) 4874 4875 4876def SetUnion(*args): 4877 """ Take the union of sets 4878 >>> a = Const('a', SetSort(IntSort())) 4879 >>> b = Const('b', SetSort(IntSort())) 4880 >>> SetUnion(a, b) 4881 union(a, b) 4882 """ 4883 args = _get_args(args) 4884 ctx = _ctx_from_ast_arg_list(args) 4885 _args, sz = _to_ast_array(args) 4886 return ArrayRef(Z3_mk_set_union(ctx.ref(), sz, _args), ctx) 4887 4888 4889def SetIntersect(*args): 4890 """ Take the union of sets 4891 >>> a = Const('a', SetSort(IntSort())) 4892 >>> b = Const('b', SetSort(IntSort())) 4893 >>> SetIntersect(a, b) 4894 intersection(a, b) 4895 """ 4896 args = _get_args(args) 4897 ctx = _ctx_from_ast_arg_list(args) 4898 _args, sz = _to_ast_array(args) 4899 return ArrayRef(Z3_mk_set_intersect(ctx.ref(), sz, _args), ctx) 4900 4901 4902def SetAdd(s, e): 4903 """ Add element e to set s 4904 >>> a = Const('a', SetSort(IntSort())) 4905 >>> SetAdd(a, 1) 4906 Store(a, 1, True) 4907 """ 4908 ctx = _ctx_from_ast_arg_list([s, e]) 4909 e = _py2expr(e, ctx) 4910 return ArrayRef(Z3_mk_set_add(ctx.ref(), s.as_ast(), e.as_ast()), ctx) 4911 4912 4913def SetDel(s, e): 4914 """ Remove element e to set s 4915 >>> a = Const('a', SetSort(IntSort())) 4916 >>> SetDel(a, 1) 4917 Store(a, 1, False) 4918 """ 4919 ctx = _ctx_from_ast_arg_list([s, e]) 4920 e = _py2expr(e, ctx) 4921 return ArrayRef(Z3_mk_set_del(ctx.ref(), s.as_ast(), e.as_ast()), ctx) 4922 4923 4924def SetComplement(s): 4925 """ The complement of set s 4926 >>> a = Const('a', SetSort(IntSort())) 4927 >>> SetComplement(a) 4928 complement(a) 4929 """ 4930 ctx = s.ctx 4931 return ArrayRef(Z3_mk_set_complement(ctx.ref(), s.as_ast()), ctx) 4932 4933 4934def SetDifference(a, b): 4935 """ The set difference of a and b 4936 >>> a = Const('a', SetSort(IntSort())) 4937 >>> b = Const('b', SetSort(IntSort())) 4938 >>> SetDifference(a, b) 4939 setminus(a, b) 4940 """ 4941 ctx = _ctx_from_ast_arg_list([a, b]) 4942 return ArrayRef(Z3_mk_set_difference(ctx.ref(), a.as_ast(), b.as_ast()), ctx) 4943 4944 4945def IsMember(e, s): 4946 """ Check if e is a member of set s 4947 >>> a = Const('a', SetSort(IntSort())) 4948 >>> IsMember(1, a) 4949 a[1] 4950 """ 4951 ctx = _ctx_from_ast_arg_list([s, e]) 4952 e = _py2expr(e, ctx) 4953 return BoolRef(Z3_mk_set_member(ctx.ref(), e.as_ast(), s.as_ast()), ctx) 4954 4955 4956def IsSubset(a, b): 4957 """ Check if a is a subset of b 4958 >>> a = Const('a', SetSort(IntSort())) 4959 >>> b = Const('b', SetSort(IntSort())) 4960 >>> IsSubset(a, b) 4961 subset(a, b) 4962 """ 4963 ctx = _ctx_from_ast_arg_list([a, b]) 4964 return BoolRef(Z3_mk_set_subset(ctx.ref(), a.as_ast(), b.as_ast()), ctx) 4965 4966 4967######################################### 4968# 4969# Datatypes 4970# 4971######################################### 4972 4973def _valid_accessor(acc): 4974 """Return `True` if acc is pair of the form (String, Datatype or Sort). """ 4975 if not isinstance(acc, tuple): 4976 return False 4977 if len(acc) != 2: 4978 return False 4979 return isinstance(acc[0], str) and (isinstance(acc[1], Datatype) or is_sort(acc[1])) 4980 4981 4982class Datatype: 4983 """Helper class for declaring Z3 datatypes. 4984 4985 >>> List = Datatype('List') 4986 >>> List.declare('cons', ('car', IntSort()), ('cdr', List)) 4987 >>> List.declare('nil') 4988 >>> List = List.create() 4989 >>> # List is now a Z3 declaration 4990 >>> List.nil 4991 nil 4992 >>> List.cons(10, List.nil) 4993 cons(10, nil) 4994 >>> List.cons(10, List.nil).sort() 4995 List 4996 >>> cons = List.cons 4997 >>> nil = List.nil 4998 >>> car = List.car 4999 >>> cdr = List.cdr 5000 >>> n = cons(1, cons(0, nil)) 5001 >>> n 5002 cons(1, cons(0, nil)) 5003 >>> simplify(cdr(n)) 5004 cons(0, nil) 5005 >>> simplify(car(n)) 5006 1 5007 """ 5008 5009 def __init__(self, name, ctx=None): 5010 self.ctx = _get_ctx(ctx) 5011 self.name = name 5012 self.constructors = [] 5013 5014 def __deepcopy__(self, memo={}): 5015 r = Datatype(self.name, self.ctx) 5016 r.constructors = copy.deepcopy(self.constructors) 5017 return r 5018 5019 def declare_core(self, name, rec_name, *args): 5020 if z3_debug(): 5021 _z3_assert(isinstance(name, str), "String expected") 5022 _z3_assert(isinstance(rec_name, str), "String expected") 5023 _z3_assert( 5024 all([_valid_accessor(a) for a in args]), 5025 "Valid list of accessors expected. An accessor is a pair of the form (String, Datatype|Sort)", 5026 ) 5027 self.constructors.append((name, rec_name, args)) 5028 5029 def declare(self, name, *args): 5030 """Declare constructor named `name` with the given accessors `args`. 5031 Each accessor is a pair `(name, sort)`, where `name` is a string and `sort` a Z3 sort 5032 or a reference to the datatypes being declared. 5033 5034 In the following example `List.declare('cons', ('car', IntSort()), ('cdr', List))` 5035 declares the constructor named `cons` that builds a new List using an integer and a List. 5036 It also declares the accessors `car` and `cdr`. The accessor `car` extracts the integer 5037 of a `cons` cell, and `cdr` the list of a `cons` cell. After all constructors were declared, 5038 we use the method create() to create the actual datatype in Z3. 5039 5040 >>> List = Datatype('List') 5041 >>> List.declare('cons', ('car', IntSort()), ('cdr', List)) 5042 >>> List.declare('nil') 5043 >>> List = List.create() 5044 """ 5045 if z3_debug(): 5046 _z3_assert(isinstance(name, str), "String expected") 5047 _z3_assert(name != "", "Constructor name cannot be empty") 5048 return self.declare_core(name, "is-" + name, *args) 5049 5050 def __repr__(self): 5051 return "Datatype(%s, %s)" % (self.name, self.constructors) 5052 5053 def create(self): 5054 """Create a Z3 datatype based on the constructors declared using the method `declare()`. 5055 5056 The function `CreateDatatypes()` must be used to define mutually recursive datatypes. 5057 5058 >>> List = Datatype('List') 5059 >>> List.declare('cons', ('car', IntSort()), ('cdr', List)) 5060 >>> List.declare('nil') 5061 >>> List = List.create() 5062 >>> List.nil 5063 nil 5064 >>> List.cons(10, List.nil) 5065 cons(10, nil) 5066 """ 5067 return CreateDatatypes([self])[0] 5068 5069 5070class ScopedConstructor: 5071 """Auxiliary object used to create Z3 datatypes.""" 5072 5073 def __init__(self, c, ctx): 5074 self.c = c 5075 self.ctx = ctx 5076 5077 def __del__(self): 5078 if self.ctx.ref() is not None: 5079 Z3_del_constructor(self.ctx.ref(), self.c) 5080 5081 5082class ScopedConstructorList: 5083 """Auxiliary object used to create Z3 datatypes.""" 5084 5085 def __init__(self, c, ctx): 5086 self.c = c 5087 self.ctx = ctx 5088 5089 def __del__(self): 5090 if self.ctx.ref() is not None: 5091 Z3_del_constructor_list(self.ctx.ref(), self.c) 5092 5093 5094def CreateDatatypes(*ds): 5095 """Create mutually recursive Z3 datatypes using 1 or more Datatype helper objects. 5096 5097 In the following example we define a Tree-List using two mutually recursive datatypes. 5098 5099 >>> TreeList = Datatype('TreeList') 5100 >>> Tree = Datatype('Tree') 5101 >>> # Tree has two constructors: leaf and node 5102 >>> Tree.declare('leaf', ('val', IntSort())) 5103 >>> # a node contains a list of trees 5104 >>> Tree.declare('node', ('children', TreeList)) 5105 >>> TreeList.declare('nil') 5106 >>> TreeList.declare('cons', ('car', Tree), ('cdr', TreeList)) 5107 >>> Tree, TreeList = CreateDatatypes(Tree, TreeList) 5108 >>> Tree.val(Tree.leaf(10)) 5109 val(leaf(10)) 5110 >>> simplify(Tree.val(Tree.leaf(10))) 5111 10 5112 >>> n1 = Tree.node(TreeList.cons(Tree.leaf(10), TreeList.cons(Tree.leaf(20), TreeList.nil))) 5113 >>> n1 5114 node(cons(leaf(10), cons(leaf(20), nil))) 5115 >>> n2 = Tree.node(TreeList.cons(n1, TreeList.nil)) 5116 >>> simplify(n2 == n1) 5117 False 5118 >>> simplify(TreeList.car(Tree.children(n2)) == n1) 5119 True 5120 """ 5121 ds = _get_args(ds) 5122 if z3_debug(): 5123 _z3_assert(len(ds) > 0, "At least one Datatype must be specified") 5124 _z3_assert(all([isinstance(d, Datatype) for d in ds]), "Arguments must be Datatypes") 5125 _z3_assert(all([d.ctx == ds[0].ctx for d in ds]), "Context mismatch") 5126 _z3_assert(all([d.constructors != [] for d in ds]), "Non-empty Datatypes expected") 5127 ctx = ds[0].ctx 5128 num = len(ds) 5129 names = (Symbol * num)() 5130 out = (Sort * num)() 5131 clists = (ConstructorList * num)() 5132 to_delete = [] 5133 for i in range(num): 5134 d = ds[i] 5135 names[i] = to_symbol(d.name, ctx) 5136 num_cs = len(d.constructors) 5137 cs = (Constructor * num_cs)() 5138 for j in range(num_cs): 5139 c = d.constructors[j] 5140 cname = to_symbol(c[0], ctx) 5141 rname = to_symbol(c[1], ctx) 5142 fs = c[2] 5143 num_fs = len(fs) 5144 fnames = (Symbol * num_fs)() 5145 sorts = (Sort * num_fs)() 5146 refs = (ctypes.c_uint * num_fs)() 5147 for k in range(num_fs): 5148 fname = fs[k][0] 5149 ftype = fs[k][1] 5150 fnames[k] = to_symbol(fname, ctx) 5151 if isinstance(ftype, Datatype): 5152 if z3_debug(): 5153 _z3_assert( 5154 ds.count(ftype) == 1, 5155 "One and only one occurrence of each datatype is expected", 5156 ) 5157 sorts[k] = None 5158 refs[k] = ds.index(ftype) 5159 else: 5160 if z3_debug(): 5161 _z3_assert(is_sort(ftype), "Z3 sort expected") 5162 sorts[k] = ftype.ast 5163 refs[k] = 0 5164 cs[j] = Z3_mk_constructor(ctx.ref(), cname, rname, num_fs, fnames, sorts, refs) 5165 to_delete.append(ScopedConstructor(cs[j], ctx)) 5166 clists[i] = Z3_mk_constructor_list(ctx.ref(), num_cs, cs) 5167 to_delete.append(ScopedConstructorList(clists[i], ctx)) 5168 Z3_mk_datatypes(ctx.ref(), num, names, out, clists) 5169 result = [] 5170 # Create a field for every constructor, recognizer and accessor 5171 for i in range(num): 5172 dref = DatatypeSortRef(out[i], ctx) 5173 num_cs = dref.num_constructors() 5174 for j in range(num_cs): 5175 cref = dref.constructor(j) 5176 cref_name = cref.name() 5177 cref_arity = cref.arity() 5178 if cref.arity() == 0: 5179 cref = cref() 5180 setattr(dref, cref_name, cref) 5181 rref = dref.recognizer(j) 5182 setattr(dref, "is_" + cref_name, rref) 5183 for k in range(cref_arity): 5184 aref = dref.accessor(j, k) 5185 setattr(dref, aref.name(), aref) 5186 result.append(dref) 5187 return tuple(result) 5188 5189 5190class DatatypeSortRef(SortRef): 5191 """Datatype sorts.""" 5192 5193 def num_constructors(self): 5194 """Return the number of constructors in the given Z3 datatype. 5195 5196 >>> List = Datatype('List') 5197 >>> List.declare('cons', ('car', IntSort()), ('cdr', List)) 5198 >>> List.declare('nil') 5199 >>> List = List.create() 5200 >>> # List is now a Z3 declaration 5201 >>> List.num_constructors() 5202 2 5203 """ 5204 return int(Z3_get_datatype_sort_num_constructors(self.ctx_ref(), self.ast)) 5205 5206 def constructor(self, idx): 5207 """Return a constructor of the datatype `self`. 5208 5209 >>> List = Datatype('List') 5210 >>> List.declare('cons', ('car', IntSort()), ('cdr', List)) 5211 >>> List.declare('nil') 5212 >>> List = List.create() 5213 >>> # List is now a Z3 declaration 5214 >>> List.num_constructors() 5215 2 5216 >>> List.constructor(0) 5217 cons 5218 >>> List.constructor(1) 5219 nil 5220 """ 5221 if z3_debug(): 5222 _z3_assert(idx < self.num_constructors(), "Invalid constructor index") 5223 return FuncDeclRef(Z3_get_datatype_sort_constructor(self.ctx_ref(), self.ast, idx), self.ctx) 5224 5225 def recognizer(self, idx): 5226 """In Z3, each constructor has an associated recognizer predicate. 5227 5228 If the constructor is named `name`, then the recognizer `is_name`. 5229 5230 >>> List = Datatype('List') 5231 >>> List.declare('cons', ('car', IntSort()), ('cdr', List)) 5232 >>> List.declare('nil') 5233 >>> List = List.create() 5234 >>> # List is now a Z3 declaration 5235 >>> List.num_constructors() 5236 2 5237 >>> List.recognizer(0) 5238 is(cons) 5239 >>> List.recognizer(1) 5240 is(nil) 5241 >>> simplify(List.is_nil(List.cons(10, List.nil))) 5242 False 5243 >>> simplify(List.is_cons(List.cons(10, List.nil))) 5244 True 5245 >>> l = Const('l', List) 5246 >>> simplify(List.is_cons(l)) 5247 is(cons, l) 5248 """ 5249 if z3_debug(): 5250 _z3_assert(idx < self.num_constructors(), "Invalid recognizer index") 5251 return FuncDeclRef(Z3_get_datatype_sort_recognizer(self.ctx_ref(), self.ast, idx), self.ctx) 5252 5253 def accessor(self, i, j): 5254 """In Z3, each constructor has 0 or more accessor. 5255 The number of accessors is equal to the arity of the constructor. 5256 5257 >>> List = Datatype('List') 5258 >>> List.declare('cons', ('car', IntSort()), ('cdr', List)) 5259 >>> List.declare('nil') 5260 >>> List = List.create() 5261 >>> List.num_constructors() 5262 2 5263 >>> List.constructor(0) 5264 cons 5265 >>> num_accs = List.constructor(0).arity() 5266 >>> num_accs 5267 2 5268 >>> List.accessor(0, 0) 5269 car 5270 >>> List.accessor(0, 1) 5271 cdr 5272 >>> List.constructor(1) 5273 nil 5274 >>> num_accs = List.constructor(1).arity() 5275 >>> num_accs 5276 0 5277 """ 5278 if z3_debug(): 5279 _z3_assert(i < self.num_constructors(), "Invalid constructor index") 5280 _z3_assert(j < self.constructor(i).arity(), "Invalid accessor index") 5281 return FuncDeclRef( 5282 Z3_get_datatype_sort_constructor_accessor(self.ctx_ref(), self.ast, i, j), 5283 ctx=self.ctx, 5284 ) 5285 5286 5287class DatatypeRef(ExprRef): 5288 """Datatype expressions.""" 5289 5290 def sort(self): 5291 """Return the datatype sort of the datatype expression `self`.""" 5292 return DatatypeSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) 5293 5294 5295def TupleSort(name, sorts, ctx=None): 5296 """Create a named tuple sort base on a set of underlying sorts 5297 Example: 5298 >>> pair, mk_pair, (first, second) = TupleSort("pair", [IntSort(), StringSort()]) 5299 """ 5300 tuple = Datatype(name, ctx) 5301 projects = [("project%d" % i, sorts[i]) for i in range(len(sorts))] 5302 tuple.declare(name, *projects) 5303 tuple = tuple.create() 5304 return tuple, tuple.constructor(0), [tuple.accessor(0, i) for i in range(len(sorts))] 5305 5306 5307def DisjointSum(name, sorts, ctx=None): 5308 """Create a named tagged union sort base on a set of underlying sorts 5309 Example: 5310 >>> sum, ((inject0, extract0), (inject1, extract1)) = DisjointSum("+", [IntSort(), StringSort()]) 5311 """ 5312 sum = Datatype(name, ctx) 5313 for i in range(len(sorts)): 5314 sum.declare("inject%d" % i, ("project%d" % i, sorts[i])) 5315 sum = sum.create() 5316 return sum, [(sum.constructor(i), sum.accessor(i, 0)) for i in range(len(sorts))] 5317 5318 5319def EnumSort(name, values, ctx=None): 5320 """Return a new enumeration sort named `name` containing the given values. 5321 5322 The result is a pair (sort, list of constants). 5323 Example: 5324 >>> Color, (red, green, blue) = EnumSort('Color', ['red', 'green', 'blue']) 5325 """ 5326 if z3_debug(): 5327 _z3_assert(isinstance(name, str), "Name must be a string") 5328 _z3_assert(all([isinstance(v, str) for v in values]), "Eumeration sort values must be strings") 5329 _z3_assert(len(values) > 0, "At least one value expected") 5330 ctx = _get_ctx(ctx) 5331 num = len(values) 5332 _val_names = (Symbol * num)() 5333 for i in range(num): 5334 _val_names[i] = to_symbol(values[i]) 5335 _values = (FuncDecl * num)() 5336 _testers = (FuncDecl * num)() 5337 name = to_symbol(name) 5338 S = DatatypeSortRef(Z3_mk_enumeration_sort(ctx.ref(), name, num, _val_names, _values, _testers), ctx) 5339 V = [] 5340 for i in range(num): 5341 V.append(FuncDeclRef(_values[i], ctx)) 5342 V = [a() for a in V] 5343 return S, V 5344 5345######################################### 5346# 5347# Parameter Sets 5348# 5349######################################### 5350 5351 5352class ParamsRef: 5353 """Set of parameters used to configure Solvers, Tactics and Simplifiers in Z3. 5354 5355 Consider using the function `args2params` to create instances of this object. 5356 """ 5357 5358 def __init__(self, ctx=None, params=None): 5359 self.ctx = _get_ctx(ctx) 5360 if params is None: 5361 self.params = Z3_mk_params(self.ctx.ref()) 5362 else: 5363 self.params = params 5364 Z3_params_inc_ref(self.ctx.ref(), self.params) 5365 5366 def __deepcopy__(self, memo={}): 5367 return ParamsRef(self.ctx, self.params) 5368 5369 def __del__(self): 5370 if self.ctx.ref() is not None: 5371 Z3_params_dec_ref(self.ctx.ref(), self.params) 5372 5373 def set(self, name, val): 5374 """Set parameter name with value val.""" 5375 if z3_debug(): 5376 _z3_assert(isinstance(name, str), "parameter name must be a string") 5377 name_sym = to_symbol(name, self.ctx) 5378 if isinstance(val, bool): 5379 Z3_params_set_bool(self.ctx.ref(), self.params, name_sym, val) 5380 elif _is_int(val): 5381 Z3_params_set_uint(self.ctx.ref(), self.params, name_sym, val) 5382 elif isinstance(val, float): 5383 Z3_params_set_double(self.ctx.ref(), self.params, name_sym, val) 5384 elif isinstance(val, str): 5385 Z3_params_set_symbol(self.ctx.ref(), self.params, name_sym, to_symbol(val, self.ctx)) 5386 else: 5387 if z3_debug(): 5388 _z3_assert(False, "invalid parameter value") 5389 5390 def __repr__(self): 5391 return Z3_params_to_string(self.ctx.ref(), self.params) 5392 5393 def validate(self, ds): 5394 _z3_assert(isinstance(ds, ParamDescrsRef), "parameter description set expected") 5395 Z3_params_validate(self.ctx.ref(), self.params, ds.descr) 5396 5397 5398def args2params(arguments, keywords, ctx=None): 5399 """Convert python arguments into a Z3_params object. 5400 A ':' is added to the keywords, and '_' is replaced with '-' 5401 5402 >>> args2params(['model', True, 'relevancy', 2], {'elim_and' : True}) 5403 (params model true relevancy 2 elim_and true) 5404 """ 5405 if z3_debug(): 5406 _z3_assert(len(arguments) % 2 == 0, "Argument list must have an even number of elements.") 5407 prev = None 5408 r = ParamsRef(ctx) 5409 for a in arguments: 5410 if prev is None: 5411 prev = a 5412 else: 5413 r.set(prev, a) 5414 prev = None 5415 for k in keywords: 5416 v = keywords[k] 5417 r.set(k, v) 5418 return r 5419 5420 5421class ParamDescrsRef: 5422 """Set of parameter descriptions for Solvers, Tactics and Simplifiers in Z3. 5423 """ 5424 5425 def __init__(self, descr, ctx=None): 5426 _z3_assert(isinstance(descr, ParamDescrs), "parameter description object expected") 5427 self.ctx = _get_ctx(ctx) 5428 self.descr = descr 5429 Z3_param_descrs_inc_ref(self.ctx.ref(), self.descr) 5430 5431 def __deepcopy__(self, memo={}): 5432 return ParamsDescrsRef(self.descr, self.ctx) 5433 5434 def __del__(self): 5435 if self.ctx.ref() is not None: 5436 Z3_param_descrs_dec_ref(self.ctx.ref(), self.descr) 5437 5438 def size(self): 5439 """Return the size of in the parameter description `self`. 5440 """ 5441 return int(Z3_param_descrs_size(self.ctx.ref(), self.descr)) 5442 5443 def __len__(self): 5444 """Return the size of in the parameter description `self`. 5445 """ 5446 return self.size() 5447 5448 def get_name(self, i): 5449 """Return the i-th parameter name in the parameter description `self`. 5450 """ 5451 return _symbol2py(self.ctx, Z3_param_descrs_get_name(self.ctx.ref(), self.descr, i)) 5452 5453 def get_kind(self, n): 5454 """Return the kind of the parameter named `n`. 5455 """ 5456 return Z3_param_descrs_get_kind(self.ctx.ref(), self.descr, to_symbol(n, self.ctx)) 5457 5458 def get_documentation(self, n): 5459 """Return the documentation string of the parameter named `n`. 5460 """ 5461 return Z3_param_descrs_get_documentation(self.ctx.ref(), self.descr, to_symbol(n, self.ctx)) 5462 5463 def __getitem__(self, arg): 5464 if _is_int(arg): 5465 return self.get_name(arg) 5466 else: 5467 return self.get_kind(arg) 5468 5469 def __repr__(self): 5470 return Z3_param_descrs_to_string(self.ctx.ref(), self.descr) 5471 5472######################################### 5473# 5474# Goals 5475# 5476######################################### 5477 5478 5479class Goal(Z3PPObject): 5480 """Goal is a collection of constraints we want to find a solution or show to be unsatisfiable (infeasible). 5481 5482 Goals are processed using Tactics. A Tactic transforms a goal into a set of subgoals. 5483 A goal has a solution if one of its subgoals has a solution. 5484 A goal is unsatisfiable if all subgoals are unsatisfiable. 5485 """ 5486 5487 def __init__(self, models=True, unsat_cores=False, proofs=False, ctx=None, goal=None): 5488 if z3_debug(): 5489 _z3_assert(goal is None or ctx is not None, 5490 "If goal is different from None, then ctx must be also different from None") 5491 self.ctx = _get_ctx(ctx) 5492 self.goal = goal 5493 if self.goal is None: 5494 self.goal = Z3_mk_goal(self.ctx.ref(), models, unsat_cores, proofs) 5495 Z3_goal_inc_ref(self.ctx.ref(), self.goal) 5496 5497 def __del__(self): 5498 if self.goal is not None and self.ctx.ref() is not None: 5499 Z3_goal_dec_ref(self.ctx.ref(), self.goal) 5500 5501 def depth(self): 5502 """Return the depth of the goal `self`. 5503 The depth corresponds to the number of tactics applied to `self`. 5504 5505 >>> x, y = Ints('x y') 5506 >>> g = Goal() 5507 >>> g.add(x == 0, y >= x + 1) 5508 >>> g.depth() 5509 0 5510 >>> r = Then('simplify', 'solve-eqs')(g) 5511 >>> # r has 1 subgoal 5512 >>> len(r) 5513 1 5514 >>> r[0].depth() 5515 2 5516 """ 5517 return int(Z3_goal_depth(self.ctx.ref(), self.goal)) 5518 5519 def inconsistent(self): 5520 """Return `True` if `self` contains the `False` constraints. 5521 5522 >>> x, y = Ints('x y') 5523 >>> g = Goal() 5524 >>> g.inconsistent() 5525 False 5526 >>> g.add(x == 0, x == 1) 5527 >>> g 5528 [x == 0, x == 1] 5529 >>> g.inconsistent() 5530 False 5531 >>> g2 = Tactic('propagate-values')(g)[0] 5532 >>> g2.inconsistent() 5533 True 5534 """ 5535 return Z3_goal_inconsistent(self.ctx.ref(), self.goal) 5536 5537 def prec(self): 5538 """Return the precision (under-approximation, over-approximation, or precise) of the goal `self`. 5539 5540 >>> g = Goal() 5541 >>> g.prec() == Z3_GOAL_PRECISE 5542 True 5543 >>> x, y = Ints('x y') 5544 >>> g.add(x == y + 1) 5545 >>> g.prec() == Z3_GOAL_PRECISE 5546 True 5547 >>> t = With(Tactic('add-bounds'), add_bound_lower=0, add_bound_upper=10) 5548 >>> g2 = t(g)[0] 5549 >>> g2 5550 [x == y + 1, x <= 10, x >= 0, y <= 10, y >= 0] 5551 >>> g2.prec() == Z3_GOAL_PRECISE 5552 False 5553 >>> g2.prec() == Z3_GOAL_UNDER 5554 True 5555 """ 5556 return Z3_goal_precision(self.ctx.ref(), self.goal) 5557 5558 def precision(self): 5559 """Alias for `prec()`. 5560 5561 >>> g = Goal() 5562 >>> g.precision() == Z3_GOAL_PRECISE 5563 True 5564 """ 5565 return self.prec() 5566 5567 def size(self): 5568 """Return the number of constraints in the goal `self`. 5569 5570 >>> g = Goal() 5571 >>> g.size() 5572 0 5573 >>> x, y = Ints('x y') 5574 >>> g.add(x == 0, y > x) 5575 >>> g.size() 5576 2 5577 """ 5578 return int(Z3_goal_size(self.ctx.ref(), self.goal)) 5579 5580 def __len__(self): 5581 """Return the number of constraints in the goal `self`. 5582 5583 >>> g = Goal() 5584 >>> len(g) 5585 0 5586 >>> x, y = Ints('x y') 5587 >>> g.add(x == 0, y > x) 5588 >>> len(g) 5589 2 5590 """ 5591 return self.size() 5592 5593 def get(self, i): 5594 """Return a constraint in the goal `self`. 5595 5596 >>> g = Goal() 5597 >>> x, y = Ints('x y') 5598 >>> g.add(x == 0, y > x) 5599 >>> g.get(0) 5600 x == 0 5601 >>> g.get(1) 5602 y > x 5603 """ 5604 return _to_expr_ref(Z3_goal_formula(self.ctx.ref(), self.goal, i), self.ctx) 5605 5606 def __getitem__(self, arg): 5607 """Return a constraint in the goal `self`. 5608 5609 >>> g = Goal() 5610 >>> x, y = Ints('x y') 5611 >>> g.add(x == 0, y > x) 5612 >>> g[0] 5613 x == 0 5614 >>> g[1] 5615 y > x 5616 """ 5617 if arg >= len(self): 5618 raise IndexError 5619 return self.get(arg) 5620 5621 def assert_exprs(self, *args): 5622 """Assert constraints into the goal. 5623 5624 >>> x = Int('x') 5625 >>> g = Goal() 5626 >>> g.assert_exprs(x > 0, x < 2) 5627 >>> g 5628 [x > 0, x < 2] 5629 """ 5630 args = _get_args(args) 5631 s = BoolSort(self.ctx) 5632 for arg in args: 5633 arg = s.cast(arg) 5634 Z3_goal_assert(self.ctx.ref(), self.goal, arg.as_ast()) 5635 5636 def append(self, *args): 5637 """Add constraints. 5638 5639 >>> x = Int('x') 5640 >>> g = Goal() 5641 >>> g.append(x > 0, x < 2) 5642 >>> g 5643 [x > 0, x < 2] 5644 """ 5645 self.assert_exprs(*args) 5646 5647 def insert(self, *args): 5648 """Add constraints. 5649 5650 >>> x = Int('x') 5651 >>> g = Goal() 5652 >>> g.insert(x > 0, x < 2) 5653 >>> g 5654 [x > 0, x < 2] 5655 """ 5656 self.assert_exprs(*args) 5657 5658 def add(self, *args): 5659 """Add constraints. 5660 5661 >>> x = Int('x') 5662 >>> g = Goal() 5663 >>> g.add(x > 0, x < 2) 5664 >>> g 5665 [x > 0, x < 2] 5666 """ 5667 self.assert_exprs(*args) 5668 5669 def convert_model(self, model): 5670 """Retrieve model from a satisfiable goal 5671 >>> a, b = Ints('a b') 5672 >>> g = Goal() 5673 >>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b) 5674 >>> t = Then(Tactic('split-clause'), Tactic('solve-eqs')) 5675 >>> r = t(g) 5676 >>> r[0] 5677 [Or(b == 0, b == 1), Not(0 <= b)] 5678 >>> r[1] 5679 [Or(b == 0, b == 1), Not(1 <= b)] 5680 >>> # Remark: the subgoal r[0] is unsatisfiable 5681 >>> # Creating a solver for solving the second subgoal 5682 >>> s = Solver() 5683 >>> s.add(r[1]) 5684 >>> s.check() 5685 sat 5686 >>> s.model() 5687 [b = 0] 5688 >>> # Model s.model() does not assign a value to `a` 5689 >>> # It is a model for subgoal `r[1]`, but not for goal `g` 5690 >>> # The method convert_model creates a model for `g` from a model for `r[1]`. 5691 >>> r[1].convert_model(s.model()) 5692 [b = 0, a = 1] 5693 """ 5694 if z3_debug(): 5695 _z3_assert(isinstance(model, ModelRef), "Z3 Model expected") 5696 return ModelRef(Z3_goal_convert_model(self.ctx.ref(), self.goal, model.model), self.ctx) 5697 5698 def __repr__(self): 5699 return obj_to_string(self) 5700 5701 def sexpr(self): 5702 """Return a textual representation of the s-expression representing the goal.""" 5703 return Z3_goal_to_string(self.ctx.ref(), self.goal) 5704 5705 def dimacs(self, include_names=True): 5706 """Return a textual representation of the goal in DIMACS format.""" 5707 return Z3_goal_to_dimacs_string(self.ctx.ref(), self.goal, include_names) 5708 5709 def translate(self, target): 5710 """Copy goal `self` to context `target`. 5711 5712 >>> x = Int('x') 5713 >>> g = Goal() 5714 >>> g.add(x > 10) 5715 >>> g 5716 [x > 10] 5717 >>> c2 = Context() 5718 >>> g2 = g.translate(c2) 5719 >>> g2 5720 [x > 10] 5721 >>> g.ctx == main_ctx() 5722 True 5723 >>> g2.ctx == c2 5724 True 5725 >>> g2.ctx == main_ctx() 5726 False 5727 """ 5728 if z3_debug(): 5729 _z3_assert(isinstance(target, Context), "target must be a context") 5730 return Goal(goal=Z3_goal_translate(self.ctx.ref(), self.goal, target.ref()), ctx=target) 5731 5732 def __copy__(self): 5733 return self.translate(self.ctx) 5734 5735 def __deepcopy__(self, memo={}): 5736 return self.translate(self.ctx) 5737 5738 def simplify(self, *arguments, **keywords): 5739 """Return a new simplified goal. 5740 5741 This method is essentially invoking the simplify tactic. 5742 5743 >>> g = Goal() 5744 >>> x = Int('x') 5745 >>> g.add(x + 1 >= 2) 5746 >>> g 5747 [x + 1 >= 2] 5748 >>> g2 = g.simplify() 5749 >>> g2 5750 [x >= 1] 5751 >>> # g was not modified 5752 >>> g 5753 [x + 1 >= 2] 5754 """ 5755 t = Tactic("simplify") 5756 return t.apply(self, *arguments, **keywords)[0] 5757 5758 def as_expr(self): 5759 """Return goal `self` as a single Z3 expression. 5760 5761 >>> x = Int('x') 5762 >>> g = Goal() 5763 >>> g.as_expr() 5764 True 5765 >>> g.add(x > 1) 5766 >>> g.as_expr() 5767 x > 1 5768 >>> g.add(x < 10) 5769 >>> g.as_expr() 5770 And(x > 1, x < 10) 5771 """ 5772 sz = len(self) 5773 if sz == 0: 5774 return BoolVal(True, self.ctx) 5775 elif sz == 1: 5776 return self.get(0) 5777 else: 5778 return And([self.get(i) for i in range(len(self))], self.ctx) 5779 5780######################################### 5781# 5782# AST Vector 5783# 5784######################################### 5785 5786 5787class AstVector(Z3PPObject): 5788 """A collection (vector) of ASTs.""" 5789 5790 def __init__(self, v=None, ctx=None): 5791 self.vector = None 5792 if v is None: 5793 self.ctx = _get_ctx(ctx) 5794 self.vector = Z3_mk_ast_vector(self.ctx.ref()) 5795 else: 5796 self.vector = v 5797 assert ctx is not None 5798 self.ctx = ctx 5799 Z3_ast_vector_inc_ref(self.ctx.ref(), self.vector) 5800 5801 def __del__(self): 5802 if self.vector is not None and self.ctx.ref() is not None: 5803 Z3_ast_vector_dec_ref(self.ctx.ref(), self.vector) 5804 5805 def __len__(self): 5806 """Return the size of the vector `self`. 5807 5808 >>> A = AstVector() 5809 >>> len(A) 5810 0 5811 >>> A.push(Int('x')) 5812 >>> A.push(Int('x')) 5813 >>> len(A) 5814 2 5815 """ 5816 return int(Z3_ast_vector_size(self.ctx.ref(), self.vector)) 5817 5818 def __getitem__(self, i): 5819 """Return the AST at position `i`. 5820 5821 >>> A = AstVector() 5822 >>> A.push(Int('x') + 1) 5823 >>> A.push(Int('y')) 5824 >>> A[0] 5825 x + 1 5826 >>> A[1] 5827 y 5828 """ 5829 5830 if isinstance(i, int): 5831 if i < 0: 5832 i += self.__len__() 5833 5834 if i >= self.__len__(): 5835 raise IndexError 5836 return _to_ast_ref(Z3_ast_vector_get(self.ctx.ref(), self.vector, i), self.ctx) 5837 5838 elif isinstance(i, slice): 5839 result = [] 5840 for ii in range(*i.indices(self.__len__())): 5841 result.append(_to_ast_ref( 5842 Z3_ast_vector_get(self.ctx.ref(), self.vector, ii), 5843 self.ctx, 5844 )) 5845 return result 5846 5847 def __setitem__(self, i, v): 5848 """Update AST at position `i`. 5849 5850 >>> A = AstVector() 5851 >>> A.push(Int('x') + 1) 5852 >>> A.push(Int('y')) 5853 >>> A[0] 5854 x + 1 5855 >>> A[0] = Int('x') 5856 >>> A[0] 5857 x 5858 """ 5859 if i >= self.__len__(): 5860 raise IndexError 5861 Z3_ast_vector_set(self.ctx.ref(), self.vector, i, v.as_ast()) 5862 5863 def push(self, v): 5864 """Add `v` in the end of the vector. 5865 5866 >>> A = AstVector() 5867 >>> len(A) 5868 0 5869 >>> A.push(Int('x')) 5870 >>> len(A) 5871 1 5872 """ 5873 Z3_ast_vector_push(self.ctx.ref(), self.vector, v.as_ast()) 5874 5875 def resize(self, sz): 5876 """Resize the vector to `sz` elements. 5877 5878 >>> A = AstVector() 5879 >>> A.resize(10) 5880 >>> len(A) 5881 10 5882 >>> for i in range(10): A[i] = Int('x') 5883 >>> A[5] 5884 x 5885 """ 5886 Z3_ast_vector_resize(self.ctx.ref(), self.vector, sz) 5887 5888 def __contains__(self, item): 5889 """Return `True` if the vector contains `item`. 5890 5891 >>> x = Int('x') 5892 >>> A = AstVector() 5893 >>> x in A 5894 False 5895 >>> A.push(x) 5896 >>> x in A 5897 True 5898 >>> (x+1) in A 5899 False 5900 >>> A.push(x+1) 5901 >>> (x+1) in A 5902 True 5903 >>> A 5904 [x, x + 1] 5905 """ 5906 for elem in self: 5907 if elem.eq(item): 5908 return True 5909 return False 5910 5911 def translate(self, other_ctx): 5912 """Copy vector `self` to context `other_ctx`. 5913 5914 >>> x = Int('x') 5915 >>> A = AstVector() 5916 >>> A.push(x) 5917 >>> c2 = Context() 5918 >>> B = A.translate(c2) 5919 >>> B 5920 [x] 5921 """ 5922 return AstVector( 5923 Z3_ast_vector_translate(self.ctx.ref(), self.vector, other_ctx.ref()), 5924 ctx=other_ctx, 5925 ) 5926 5927 def __copy__(self): 5928 return self.translate(self.ctx) 5929 5930 def __deepcopy__(self, memo={}): 5931 return self.translate(self.ctx) 5932 5933 def __repr__(self): 5934 return obj_to_string(self) 5935 5936 def sexpr(self): 5937 """Return a textual representation of the s-expression representing the vector.""" 5938 return Z3_ast_vector_to_string(self.ctx.ref(), self.vector) 5939 5940######################################### 5941# 5942# AST Map 5943# 5944######################################### 5945 5946 5947class AstMap: 5948 """A mapping from ASTs to ASTs.""" 5949 5950 def __init__(self, m=None, ctx=None): 5951 self.map = None 5952 if m is None: 5953 self.ctx = _get_ctx(ctx) 5954 self.map = Z3_mk_ast_map(self.ctx.ref()) 5955 else: 5956 self.map = m 5957 assert ctx is not None 5958 self.ctx = ctx 5959 Z3_ast_map_inc_ref(self.ctx.ref(), self.map) 5960 5961 def __deepcopy__(self, memo={}): 5962 return AstMap(self.map, self.ctx) 5963 5964 def __del__(self): 5965 if self.map is not None and self.ctx.ref() is not None: 5966 Z3_ast_map_dec_ref(self.ctx.ref(), self.map) 5967 5968 def __len__(self): 5969 """Return the size of the map. 5970 5971 >>> M = AstMap() 5972 >>> len(M) 5973 0 5974 >>> x = Int('x') 5975 >>> M[x] = IntVal(1) 5976 >>> len(M) 5977 1 5978 """ 5979 return int(Z3_ast_map_size(self.ctx.ref(), self.map)) 5980 5981 def __contains__(self, key): 5982 """Return `True` if the map contains key `key`. 5983 5984 >>> M = AstMap() 5985 >>> x = Int('x') 5986 >>> M[x] = x + 1 5987 >>> x in M 5988 True 5989 >>> x+1 in M 5990 False 5991 """ 5992 return Z3_ast_map_contains(self.ctx.ref(), self.map, key.as_ast()) 5993 5994 def __getitem__(self, key): 5995 """Retrieve the value associated with key `key`. 5996 5997 >>> M = AstMap() 5998 >>> x = Int('x') 5999 >>> M[x] = x + 1 6000 >>> M[x] 6001 x + 1 6002 """ 6003 return _to_ast_ref(Z3_ast_map_find(self.ctx.ref(), self.map, key.as_ast()), self.ctx) 6004 6005 def __setitem__(self, k, v): 6006 """Add/Update key `k` with value `v`. 6007 6008 >>> M = AstMap() 6009 >>> x = Int('x') 6010 >>> M[x] = x + 1 6011 >>> len(M) 6012 1 6013 >>> M[x] 6014 x + 1 6015 >>> M[x] = IntVal(1) 6016 >>> M[x] 6017 1 6018 """ 6019 Z3_ast_map_insert(self.ctx.ref(), self.map, k.as_ast(), v.as_ast()) 6020 6021 def __repr__(self): 6022 return Z3_ast_map_to_string(self.ctx.ref(), self.map) 6023 6024 def erase(self, k): 6025 """Remove the entry associated with key `k`. 6026 6027 >>> M = AstMap() 6028 >>> x = Int('x') 6029 >>> M[x] = x + 1 6030 >>> len(M) 6031 1 6032 >>> M.erase(x) 6033 >>> len(M) 6034 0 6035 """ 6036 Z3_ast_map_erase(self.ctx.ref(), self.map, k.as_ast()) 6037 6038 def reset(self): 6039 """Remove all entries from the map. 6040 6041 >>> M = AstMap() 6042 >>> x = Int('x') 6043 >>> M[x] = x + 1 6044 >>> M[x+x] = IntVal(1) 6045 >>> len(M) 6046 2 6047 >>> M.reset() 6048 >>> len(M) 6049 0 6050 """ 6051 Z3_ast_map_reset(self.ctx.ref(), self.map) 6052 6053 def keys(self): 6054 """Return an AstVector containing all keys in the map. 6055 6056 >>> M = AstMap() 6057 >>> x = Int('x') 6058 >>> M[x] = x + 1 6059 >>> M[x+x] = IntVal(1) 6060 >>> M.keys() 6061 [x, x + x] 6062 """ 6063 return AstVector(Z3_ast_map_keys(self.ctx.ref(), self.map), self.ctx) 6064 6065######################################### 6066# 6067# Model 6068# 6069######################################### 6070 6071 6072class FuncEntry: 6073 """Store the value of the interpretation of a function in a particular point.""" 6074 6075 def __init__(self, entry, ctx): 6076 self.entry = entry 6077 self.ctx = ctx 6078 Z3_func_entry_inc_ref(self.ctx.ref(), self.entry) 6079 6080 def __deepcopy__(self, memo={}): 6081 return FuncEntry(self.entry, self.ctx) 6082 6083 def __del__(self): 6084 if self.ctx.ref() is not None: 6085 Z3_func_entry_dec_ref(self.ctx.ref(), self.entry) 6086 6087 def num_args(self): 6088 """Return the number of arguments in the given entry. 6089 6090 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 6091 >>> s = Solver() 6092 >>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10) 6093 >>> s.check() 6094 sat 6095 >>> m = s.model() 6096 >>> f_i = m[f] 6097 >>> f_i.num_entries() 6098 1 6099 >>> e = f_i.entry(0) 6100 >>> e.num_args() 6101 2 6102 """ 6103 return int(Z3_func_entry_get_num_args(self.ctx.ref(), self.entry)) 6104 6105 def arg_value(self, idx): 6106 """Return the value of argument `idx`. 6107 6108 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 6109 >>> s = Solver() 6110 >>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10) 6111 >>> s.check() 6112 sat 6113 >>> m = s.model() 6114 >>> f_i = m[f] 6115 >>> f_i.num_entries() 6116 1 6117 >>> e = f_i.entry(0) 6118 >>> e 6119 [1, 2, 20] 6120 >>> e.num_args() 6121 2 6122 >>> e.arg_value(0) 6123 1 6124 >>> e.arg_value(1) 6125 2 6126 >>> try: 6127 ... e.arg_value(2) 6128 ... except IndexError: 6129 ... print("index error") 6130 index error 6131 """ 6132 if idx >= self.num_args(): 6133 raise IndexError 6134 return _to_expr_ref(Z3_func_entry_get_arg(self.ctx.ref(), self.entry, idx), self.ctx) 6135 6136 def value(self): 6137 """Return the value of the function at point `self`. 6138 6139 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 6140 >>> s = Solver() 6141 >>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10) 6142 >>> s.check() 6143 sat 6144 >>> m = s.model() 6145 >>> f_i = m[f] 6146 >>> f_i.num_entries() 6147 1 6148 >>> e = f_i.entry(0) 6149 >>> e 6150 [1, 2, 20] 6151 >>> e.num_args() 6152 2 6153 >>> e.value() 6154 20 6155 """ 6156 return _to_expr_ref(Z3_func_entry_get_value(self.ctx.ref(), self.entry), self.ctx) 6157 6158 def as_list(self): 6159 """Return entry `self` as a Python list. 6160 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 6161 >>> s = Solver() 6162 >>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10) 6163 >>> s.check() 6164 sat 6165 >>> m = s.model() 6166 >>> f_i = m[f] 6167 >>> f_i.num_entries() 6168 1 6169 >>> e = f_i.entry(0) 6170 >>> e.as_list() 6171 [1, 2, 20] 6172 """ 6173 args = [self.arg_value(i) for i in range(self.num_args())] 6174 args.append(self.value()) 6175 return args 6176 6177 def __repr__(self): 6178 return repr(self.as_list()) 6179 6180 6181class FuncInterp(Z3PPObject): 6182 """Stores the interpretation of a function in a Z3 model.""" 6183 6184 def __init__(self, f, ctx): 6185 self.f = f 6186 self.ctx = ctx 6187 if self.f is not None: 6188 Z3_func_interp_inc_ref(self.ctx.ref(), self.f) 6189 6190 def __del__(self): 6191 if self.f is not None and self.ctx.ref() is not None: 6192 Z3_func_interp_dec_ref(self.ctx.ref(), self.f) 6193 6194 def else_value(self): 6195 """ 6196 Return the `else` value for a function interpretation. 6197 Return None if Z3 did not specify the `else` value for 6198 this object. 6199 6200 >>> f = Function('f', IntSort(), IntSort()) 6201 >>> s = Solver() 6202 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0) 6203 >>> s.check() 6204 sat 6205 >>> m = s.model() 6206 >>> m[f] 6207 [2 -> 0, else -> 1] 6208 >>> m[f].else_value() 6209 1 6210 """ 6211 r = Z3_func_interp_get_else(self.ctx.ref(), self.f) 6212 if r: 6213 return _to_expr_ref(r, self.ctx) 6214 else: 6215 return None 6216 6217 def num_entries(self): 6218 """Return the number of entries/points in the function interpretation `self`. 6219 6220 >>> f = Function('f', IntSort(), IntSort()) 6221 >>> s = Solver() 6222 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0) 6223 >>> s.check() 6224 sat 6225 >>> m = s.model() 6226 >>> m[f] 6227 [2 -> 0, else -> 1] 6228 >>> m[f].num_entries() 6229 1 6230 """ 6231 return int(Z3_func_interp_get_num_entries(self.ctx.ref(), self.f)) 6232 6233 def arity(self): 6234 """Return the number of arguments for each entry in the function interpretation `self`. 6235 6236 >>> f = Function('f', IntSort(), IntSort()) 6237 >>> s = Solver() 6238 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0) 6239 >>> s.check() 6240 sat 6241 >>> m = s.model() 6242 >>> m[f].arity() 6243 1 6244 """ 6245 return int(Z3_func_interp_get_arity(self.ctx.ref(), self.f)) 6246 6247 def entry(self, idx): 6248 """Return an entry at position `idx < self.num_entries()` in the function interpretation `self`. 6249 6250 >>> f = Function('f', IntSort(), IntSort()) 6251 >>> s = Solver() 6252 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0) 6253 >>> s.check() 6254 sat 6255 >>> m = s.model() 6256 >>> m[f] 6257 [2 -> 0, else -> 1] 6258 >>> m[f].num_entries() 6259 1 6260 >>> m[f].entry(0) 6261 [2, 0] 6262 """ 6263 if idx >= self.num_entries(): 6264 raise IndexError 6265 return FuncEntry(Z3_func_interp_get_entry(self.ctx.ref(), self.f, idx), self.ctx) 6266 6267 def translate(self, other_ctx): 6268 """Copy model 'self' to context 'other_ctx'. 6269 """ 6270 return ModelRef(Z3_model_translate(self.ctx.ref(), self.model, other_ctx.ref()), other_ctx) 6271 6272 def __copy__(self): 6273 return self.translate(self.ctx) 6274 6275 def __deepcopy__(self, memo={}): 6276 return self.translate(self.ctx) 6277 6278 def as_list(self): 6279 """Return the function interpretation as a Python list. 6280 >>> f = Function('f', IntSort(), IntSort()) 6281 >>> s = Solver() 6282 >>> s.add(f(0) == 1, f(1) == 1, f(2) == 0) 6283 >>> s.check() 6284 sat 6285 >>> m = s.model() 6286 >>> m[f] 6287 [2 -> 0, else -> 1] 6288 >>> m[f].as_list() 6289 [[2, 0], 1] 6290 """ 6291 r = [self.entry(i).as_list() for i in range(self.num_entries())] 6292 r.append(self.else_value()) 6293 return r 6294 6295 def __repr__(self): 6296 return obj_to_string(self) 6297 6298 6299class ModelRef(Z3PPObject): 6300 """Model/Solution of a satisfiability problem (aka system of constraints).""" 6301 6302 def __init__(self, m, ctx): 6303 assert ctx is not None 6304 self.model = m 6305 self.ctx = ctx 6306 Z3_model_inc_ref(self.ctx.ref(), self.model) 6307 6308 def __del__(self): 6309 if self.ctx.ref() is not None: 6310 Z3_model_dec_ref(self.ctx.ref(), self.model) 6311 6312 def __repr__(self): 6313 return obj_to_string(self) 6314 6315 def sexpr(self): 6316 """Return a textual representation of the s-expression representing the model.""" 6317 return Z3_model_to_string(self.ctx.ref(), self.model) 6318 6319 def eval(self, t, model_completion=False): 6320 """Evaluate the expression `t` in the model `self`. 6321 If `model_completion` is enabled, then a default interpretation is automatically added 6322 for symbols that do not have an interpretation in the model `self`. 6323 6324 >>> x = Int('x') 6325 >>> s = Solver() 6326 >>> s.add(x > 0, x < 2) 6327 >>> s.check() 6328 sat 6329 >>> m = s.model() 6330 >>> m.eval(x + 1) 6331 2 6332 >>> m.eval(x == 1) 6333 True 6334 >>> y = Int('y') 6335 >>> m.eval(y + x) 6336 1 + y 6337 >>> m.eval(y) 6338 y 6339 >>> m.eval(y, model_completion=True) 6340 0 6341 >>> # Now, m contains an interpretation for y 6342 >>> m.eval(y + x) 6343 1 6344 """ 6345 r = (Ast * 1)() 6346 if Z3_model_eval(self.ctx.ref(), self.model, t.as_ast(), model_completion, r): 6347 return _to_expr_ref(r[0], self.ctx) 6348 raise Z3Exception("failed to evaluate expression in the model") 6349 6350 def evaluate(self, t, model_completion=False): 6351 """Alias for `eval`. 6352 6353 >>> x = Int('x') 6354 >>> s = Solver() 6355 >>> s.add(x > 0, x < 2) 6356 >>> s.check() 6357 sat 6358 >>> m = s.model() 6359 >>> m.evaluate(x + 1) 6360 2 6361 >>> m.evaluate(x == 1) 6362 True 6363 >>> y = Int('y') 6364 >>> m.evaluate(y + x) 6365 1 + y 6366 >>> m.evaluate(y) 6367 y 6368 >>> m.evaluate(y, model_completion=True) 6369 0 6370 >>> # Now, m contains an interpretation for y 6371 >>> m.evaluate(y + x) 6372 1 6373 """ 6374 return self.eval(t, model_completion) 6375 6376 def __len__(self): 6377 """Return the number of constant and function declarations in the model `self`. 6378 6379 >>> f = Function('f', IntSort(), IntSort()) 6380 >>> x = Int('x') 6381 >>> s = Solver() 6382 >>> s.add(x > 0, f(x) != x) 6383 >>> s.check() 6384 sat 6385 >>> m = s.model() 6386 >>> len(m) 6387 2 6388 """ 6389 num_consts = int(Z3_model_get_num_consts(self.ctx.ref(), self.model)) 6390 num_funcs = int(Z3_model_get_num_funcs(self.ctx.ref(), self.model)) 6391 return num_consts + num_funcs 6392 6393 def get_interp(self, decl): 6394 """Return the interpretation for a given declaration or constant. 6395 6396 >>> f = Function('f', IntSort(), IntSort()) 6397 >>> x = Int('x') 6398 >>> s = Solver() 6399 >>> s.add(x > 0, x < 2, f(x) == 0) 6400 >>> s.check() 6401 sat 6402 >>> m = s.model() 6403 >>> m[x] 6404 1 6405 >>> m[f] 6406 [else -> 0] 6407 """ 6408 if z3_debug(): 6409 _z3_assert(isinstance(decl, FuncDeclRef) or is_const(decl), "Z3 declaration expected") 6410 if is_const(decl): 6411 decl = decl.decl() 6412 try: 6413 if decl.arity() == 0: 6414 _r = Z3_model_get_const_interp(self.ctx.ref(), self.model, decl.ast) 6415 if _r.value is None: 6416 return None 6417 r = _to_expr_ref(_r, self.ctx) 6418 if is_as_array(r): 6419 return self.get_interp(get_as_array_func(r)) 6420 else: 6421 return r 6422 else: 6423 return FuncInterp(Z3_model_get_func_interp(self.ctx.ref(), self.model, decl.ast), self.ctx) 6424 except Z3Exception: 6425 return None 6426 6427 def num_sorts(self): 6428 """Return the number of uninterpreted sorts that contain an interpretation in the model `self`. 6429 6430 >>> A = DeclareSort('A') 6431 >>> a, b = Consts('a b', A) 6432 >>> s = Solver() 6433 >>> s.add(a != b) 6434 >>> s.check() 6435 sat 6436 >>> m = s.model() 6437 >>> m.num_sorts() 6438 1 6439 """ 6440 return int(Z3_model_get_num_sorts(self.ctx.ref(), self.model)) 6441 6442 def get_sort(self, idx): 6443 """Return the uninterpreted sort at position `idx` < self.num_sorts(). 6444 6445 >>> A = DeclareSort('A') 6446 >>> B = DeclareSort('B') 6447 >>> a1, a2 = Consts('a1 a2', A) 6448 >>> b1, b2 = Consts('b1 b2', B) 6449 >>> s = Solver() 6450 >>> s.add(a1 != a2, b1 != b2) 6451 >>> s.check() 6452 sat 6453 >>> m = s.model() 6454 >>> m.num_sorts() 6455 2 6456 >>> m.get_sort(0) 6457 A 6458 >>> m.get_sort(1) 6459 B 6460 """ 6461 if idx >= self.num_sorts(): 6462 raise IndexError 6463 return _to_sort_ref(Z3_model_get_sort(self.ctx.ref(), self.model, idx), self.ctx) 6464 6465 def sorts(self): 6466 """Return all uninterpreted sorts that have an interpretation in the model `self`. 6467 6468 >>> A = DeclareSort('A') 6469 >>> B = DeclareSort('B') 6470 >>> a1, a2 = Consts('a1 a2', A) 6471 >>> b1, b2 = Consts('b1 b2', B) 6472 >>> s = Solver() 6473 >>> s.add(a1 != a2, b1 != b2) 6474 >>> s.check() 6475 sat 6476 >>> m = s.model() 6477 >>> m.sorts() 6478 [A, B] 6479 """ 6480 return [self.get_sort(i) for i in range(self.num_sorts())] 6481 6482 def get_universe(self, s): 6483 """Return the interpretation for the uninterpreted sort `s` in the model `self`. 6484 6485 >>> A = DeclareSort('A') 6486 >>> a, b = Consts('a b', A) 6487 >>> s = Solver() 6488 >>> s.add(a != b) 6489 >>> s.check() 6490 sat 6491 >>> m = s.model() 6492 >>> m.get_universe(A) 6493 [A!val!1, A!val!0] 6494 """ 6495 if z3_debug(): 6496 _z3_assert(isinstance(s, SortRef), "Z3 sort expected") 6497 try: 6498 return AstVector(Z3_model_get_sort_universe(self.ctx.ref(), self.model, s.ast), self.ctx) 6499 except Z3Exception: 6500 return None 6501 6502 def __getitem__(self, idx): 6503 """If `idx` is an integer, then the declaration at position `idx` in the model `self` is returned. 6504 If `idx` is a declaration, then the actual interpretation is returned. 6505 6506 The elements can be retrieved using position or the actual declaration. 6507 6508 >>> f = Function('f', IntSort(), IntSort()) 6509 >>> x = Int('x') 6510 >>> s = Solver() 6511 >>> s.add(x > 0, x < 2, f(x) == 0) 6512 >>> s.check() 6513 sat 6514 >>> m = s.model() 6515 >>> len(m) 6516 2 6517 >>> m[0] 6518 x 6519 >>> m[1] 6520 f 6521 >>> m[x] 6522 1 6523 >>> m[f] 6524 [else -> 0] 6525 >>> for d in m: print("%s -> %s" % (d, m[d])) 6526 x -> 1 6527 f -> [else -> 0] 6528 """ 6529 if _is_int(idx): 6530 if idx >= len(self): 6531 raise IndexError 6532 num_consts = Z3_model_get_num_consts(self.ctx.ref(), self.model) 6533 if (idx < num_consts): 6534 return FuncDeclRef(Z3_model_get_const_decl(self.ctx.ref(), self.model, idx), self.ctx) 6535 else: 6536 return FuncDeclRef(Z3_model_get_func_decl(self.ctx.ref(), self.model, idx - num_consts), self.ctx) 6537 if isinstance(idx, FuncDeclRef): 6538 return self.get_interp(idx) 6539 if is_const(idx): 6540 return self.get_interp(idx.decl()) 6541 if isinstance(idx, SortRef): 6542 return self.get_universe(idx) 6543 if z3_debug(): 6544 _z3_assert(False, "Integer, Z3 declaration, or Z3 constant expected") 6545 return None 6546 6547 def decls(self): 6548 """Return a list with all symbols that have an interpretation in the model `self`. 6549 >>> f = Function('f', IntSort(), IntSort()) 6550 >>> x = Int('x') 6551 >>> s = Solver() 6552 >>> s.add(x > 0, x < 2, f(x) == 0) 6553 >>> s.check() 6554 sat 6555 >>> m = s.model() 6556 >>> m.decls() 6557 [x, f] 6558 """ 6559 r = [] 6560 for i in range(Z3_model_get_num_consts(self.ctx.ref(), self.model)): 6561 r.append(FuncDeclRef(Z3_model_get_const_decl(self.ctx.ref(), self.model, i), self.ctx)) 6562 for i in range(Z3_model_get_num_funcs(self.ctx.ref(), self.model)): 6563 r.append(FuncDeclRef(Z3_model_get_func_decl(self.ctx.ref(), self.model, i), self.ctx)) 6564 return r 6565 6566 def update_value(self, x, value): 6567 """Update the interpretation of a constant""" 6568 if is_expr(x): 6569 x = x.decl() 6570 if not is_func_decl(x) or x.arity() != 0: 6571 raise Z3Exception("Expecting 0-ary function or constant expression") 6572 value = _py2expr(value) 6573 Z3_add_const_interp(x.ctx_ref(), self.model, x.ast, value.ast) 6574 6575 def translate(self, target): 6576 """Translate `self` to the context `target`. That is, return a copy of `self` in the context `target`. 6577 """ 6578 if z3_debug(): 6579 _z3_assert(isinstance(target, Context), "argument must be a Z3 context") 6580 model = Z3_model_translate(self.ctx.ref(), self.model, target.ref()) 6581 return ModelRef(model, target) 6582 6583 def __copy__(self): 6584 return self.translate(self.ctx) 6585 6586 def __deepcopy__(self, memo={}): 6587 return self.translate(self.ctx) 6588 6589 6590def Model(ctx=None): 6591 ctx = _get_ctx(ctx) 6592 return ModelRef(Z3_mk_model(ctx.ref()), ctx) 6593 6594 6595def is_as_array(n): 6596 """Return true if n is a Z3 expression of the form (_ as-array f).""" 6597 return isinstance(n, ExprRef) and Z3_is_as_array(n.ctx.ref(), n.as_ast()) 6598 6599 6600def get_as_array_func(n): 6601 """Return the function declaration f associated with a Z3 expression of the form (_ as-array f).""" 6602 if z3_debug(): 6603 _z3_assert(is_as_array(n), "as-array Z3 expression expected.") 6604 return FuncDeclRef(Z3_get_as_array_func_decl(n.ctx.ref(), n.as_ast()), n.ctx) 6605 6606######################################### 6607# 6608# Statistics 6609# 6610######################################### 6611 6612 6613class Statistics: 6614 """Statistics for `Solver.check()`.""" 6615 6616 def __init__(self, stats, ctx): 6617 self.stats = stats 6618 self.ctx = ctx 6619 Z3_stats_inc_ref(self.ctx.ref(), self.stats) 6620 6621 def __deepcopy__(self, memo={}): 6622 return Statistics(self.stats, self.ctx) 6623 6624 def __del__(self): 6625 if self.ctx.ref() is not None: 6626 Z3_stats_dec_ref(self.ctx.ref(), self.stats) 6627 6628 def __repr__(self): 6629 if in_html_mode(): 6630 out = io.StringIO() 6631 even = True 6632 out.write(u('<table border="1" cellpadding="2" cellspacing="0">')) 6633 for k, v in self: 6634 if even: 6635 out.write(u('<tr style="background-color:#CFCFCF">')) 6636 even = False 6637 else: 6638 out.write(u("<tr>")) 6639 even = True 6640 out.write(u("<td>%s</td><td>%s</td></tr>" % (k, v))) 6641 out.write(u("</table>")) 6642 return out.getvalue() 6643 else: 6644 return Z3_stats_to_string(self.ctx.ref(), self.stats) 6645 6646 def __len__(self): 6647 """Return the number of statistical counters. 6648 6649 >>> x = Int('x') 6650 >>> s = Then('simplify', 'nlsat').solver() 6651 >>> s.add(x > 0) 6652 >>> s.check() 6653 sat 6654 >>> st = s.statistics() 6655 >>> len(st) 6656 6 6657 """ 6658 return int(Z3_stats_size(self.ctx.ref(), self.stats)) 6659 6660 def __getitem__(self, idx): 6661 """Return the value of statistical counter at position `idx`. The result is a pair (key, value). 6662 6663 >>> x = Int('x') 6664 >>> s = Then('simplify', 'nlsat').solver() 6665 >>> s.add(x > 0) 6666 >>> s.check() 6667 sat 6668 >>> st = s.statistics() 6669 >>> len(st) 6670 6 6671 >>> st[0] 6672 ('nlsat propagations', 2) 6673 >>> st[1] 6674 ('nlsat stages', 2) 6675 """ 6676 if idx >= len(self): 6677 raise IndexError 6678 if Z3_stats_is_uint(self.ctx.ref(), self.stats, idx): 6679 val = int(Z3_stats_get_uint_value(self.ctx.ref(), self.stats, idx)) 6680 else: 6681 val = Z3_stats_get_double_value(self.ctx.ref(), self.stats, idx) 6682 return (Z3_stats_get_key(self.ctx.ref(), self.stats, idx), val) 6683 6684 def keys(self): 6685 """Return the list of statistical counters. 6686 6687 >>> x = Int('x') 6688 >>> s = Then('simplify', 'nlsat').solver() 6689 >>> s.add(x > 0) 6690 >>> s.check() 6691 sat 6692 >>> st = s.statistics() 6693 """ 6694 return [Z3_stats_get_key(self.ctx.ref(), self.stats, idx) for idx in range(len(self))] 6695 6696 def get_key_value(self, key): 6697 """Return the value of a particular statistical counter. 6698 6699 >>> x = Int('x') 6700 >>> s = Then('simplify', 'nlsat').solver() 6701 >>> s.add(x > 0) 6702 >>> s.check() 6703 sat 6704 >>> st = s.statistics() 6705 >>> st.get_key_value('nlsat propagations') 6706 2 6707 """ 6708 for idx in range(len(self)): 6709 if key == Z3_stats_get_key(self.ctx.ref(), self.stats, idx): 6710 if Z3_stats_is_uint(self.ctx.ref(), self.stats, idx): 6711 return int(Z3_stats_get_uint_value(self.ctx.ref(), self.stats, idx)) 6712 else: 6713 return Z3_stats_get_double_value(self.ctx.ref(), self.stats, idx) 6714 raise Z3Exception("unknown key") 6715 6716 def __getattr__(self, name): 6717 """Access the value of statistical using attributes. 6718 6719 Remark: to access a counter containing blank spaces (e.g., 'nlsat propagations'), 6720 we should use '_' (e.g., 'nlsat_propagations'). 6721 6722 >>> x = Int('x') 6723 >>> s = Then('simplify', 'nlsat').solver() 6724 >>> s.add(x > 0) 6725 >>> s.check() 6726 sat 6727 >>> st = s.statistics() 6728 >>> st.nlsat_propagations 6729 2 6730 >>> st.nlsat_stages 6731 2 6732 """ 6733 key = name.replace("_", " ") 6734 try: 6735 return self.get_key_value(key) 6736 except Z3Exception: 6737 raise AttributeError 6738 6739######################################### 6740# 6741# Solver 6742# 6743######################################### 6744 6745 6746class CheckSatResult: 6747 """Represents the result of a satisfiability check: sat, unsat, unknown. 6748 6749 >>> s = Solver() 6750 >>> s.check() 6751 sat 6752 >>> r = s.check() 6753 >>> isinstance(r, CheckSatResult) 6754 True 6755 """ 6756 6757 def __init__(self, r): 6758 self.r = r 6759 6760 def __deepcopy__(self, memo={}): 6761 return CheckSatResult(self.r) 6762 6763 def __eq__(self, other): 6764 return isinstance(other, CheckSatResult) and self.r == other.r 6765 6766 def __ne__(self, other): 6767 return not self.__eq__(other) 6768 6769 def __repr__(self): 6770 if in_html_mode(): 6771 if self.r == Z3_L_TRUE: 6772 return "<b>sat</b>" 6773 elif self.r == Z3_L_FALSE: 6774 return "<b>unsat</b>" 6775 else: 6776 return "<b>unknown</b>" 6777 else: 6778 if self.r == Z3_L_TRUE: 6779 return "sat" 6780 elif self.r == Z3_L_FALSE: 6781 return "unsat" 6782 else: 6783 return "unknown" 6784 6785 def _repr_html_(self): 6786 in_html = in_html_mode() 6787 set_html_mode(True) 6788 res = repr(self) 6789 set_html_mode(in_html) 6790 return res 6791 6792 6793sat = CheckSatResult(Z3_L_TRUE) 6794unsat = CheckSatResult(Z3_L_FALSE) 6795unknown = CheckSatResult(Z3_L_UNDEF) 6796 6797 6798class Solver(Z3PPObject): 6799 """ 6800 Solver API provides methods for implementing the main SMT 2.0 commands: 6801 push, pop, check, get-model, etc. 6802 """ 6803 6804 def __init__(self, solver=None, ctx=None, logFile=None): 6805 assert solver is None or ctx is not None 6806 self.ctx = _get_ctx(ctx) 6807 self.backtrack_level = 4000000000 6808 self.solver = None 6809 if solver is None: 6810 self.solver = Z3_mk_solver(self.ctx.ref()) 6811 else: 6812 self.solver = solver 6813 Z3_solver_inc_ref(self.ctx.ref(), self.solver) 6814 if logFile is not None: 6815 self.set("smtlib2_log", logFile) 6816 6817 def __del__(self): 6818 if self.solver is not None and self.ctx.ref() is not None: 6819 Z3_solver_dec_ref(self.ctx.ref(), self.solver) 6820 6821 def set(self, *args, **keys): 6822 """Set a configuration option. 6823 The method `help()` return a string containing all available options. 6824 6825 >>> s = Solver() 6826 >>> # The option MBQI can be set using three different approaches. 6827 >>> s.set(mbqi=True) 6828 >>> s.set('MBQI', True) 6829 >>> s.set(':mbqi', True) 6830 """ 6831 p = args2params(args, keys, self.ctx) 6832 Z3_solver_set_params(self.ctx.ref(), self.solver, p.params) 6833 6834 def push(self): 6835 """Create a backtracking point. 6836 6837 >>> x = Int('x') 6838 >>> s = Solver() 6839 >>> s.add(x > 0) 6840 >>> s 6841 [x > 0] 6842 >>> s.push() 6843 >>> s.add(x < 1) 6844 >>> s 6845 [x > 0, x < 1] 6846 >>> s.check() 6847 unsat 6848 >>> s.pop() 6849 >>> s.check() 6850 sat 6851 >>> s 6852 [x > 0] 6853 """ 6854 Z3_solver_push(self.ctx.ref(), self.solver) 6855 6856 def pop(self, num=1): 6857 """Backtrack \\c num backtracking points. 6858 6859 >>> x = Int('x') 6860 >>> s = Solver() 6861 >>> s.add(x > 0) 6862 >>> s 6863 [x > 0] 6864 >>> s.push() 6865 >>> s.add(x < 1) 6866 >>> s 6867 [x > 0, x < 1] 6868 >>> s.check() 6869 unsat 6870 >>> s.pop() 6871 >>> s.check() 6872 sat 6873 >>> s 6874 [x > 0] 6875 """ 6876 Z3_solver_pop(self.ctx.ref(), self.solver, num) 6877 6878 def num_scopes(self): 6879 """Return the current number of backtracking points. 6880 6881 >>> s = Solver() 6882 >>> s.num_scopes() 6883 0 6884 >>> s.push() 6885 >>> s.num_scopes() 6886 1 6887 >>> s.push() 6888 >>> s.num_scopes() 6889 2 6890 >>> s.pop() 6891 >>> s.num_scopes() 6892 1 6893 """ 6894 return Z3_solver_get_num_scopes(self.ctx.ref(), self.solver) 6895 6896 def reset(self): 6897 """Remove all asserted constraints and backtracking points created using `push()`. 6898 6899 >>> x = Int('x') 6900 >>> s = Solver() 6901 >>> s.add(x > 0) 6902 >>> s 6903 [x > 0] 6904 >>> s.reset() 6905 >>> s 6906 [] 6907 """ 6908 Z3_solver_reset(self.ctx.ref(), self.solver) 6909 6910 def assert_exprs(self, *args): 6911 """Assert constraints into the solver. 6912 6913 >>> x = Int('x') 6914 >>> s = Solver() 6915 >>> s.assert_exprs(x > 0, x < 2) 6916 >>> s 6917 [x > 0, x < 2] 6918 """ 6919 args = _get_args(args) 6920 s = BoolSort(self.ctx) 6921 for arg in args: 6922 if isinstance(arg, Goal) or isinstance(arg, AstVector): 6923 for f in arg: 6924 Z3_solver_assert(self.ctx.ref(), self.solver, f.as_ast()) 6925 else: 6926 arg = s.cast(arg) 6927 Z3_solver_assert(self.ctx.ref(), self.solver, arg.as_ast()) 6928 6929 def add(self, *args): 6930 """Assert constraints into the solver. 6931 6932 >>> x = Int('x') 6933 >>> s = Solver() 6934 >>> s.add(x > 0, x < 2) 6935 >>> s 6936 [x > 0, x < 2] 6937 """ 6938 self.assert_exprs(*args) 6939 6940 def __iadd__(self, fml): 6941 self.add(fml) 6942 return self 6943 6944 def append(self, *args): 6945 """Assert constraints into the solver. 6946 6947 >>> x = Int('x') 6948 >>> s = Solver() 6949 >>> s.append(x > 0, x < 2) 6950 >>> s 6951 [x > 0, x < 2] 6952 """ 6953 self.assert_exprs(*args) 6954 6955 def insert(self, *args): 6956 """Assert constraints into the solver. 6957 6958 >>> x = Int('x') 6959 >>> s = Solver() 6960 >>> s.insert(x > 0, x < 2) 6961 >>> s 6962 [x > 0, x < 2] 6963 """ 6964 self.assert_exprs(*args) 6965 6966 def assert_and_track(self, a, p): 6967 """Assert constraint `a` and track it in the unsat core using the Boolean constant `p`. 6968 6969 If `p` is a string, it will be automatically converted into a Boolean constant. 6970 6971 >>> x = Int('x') 6972 >>> p3 = Bool('p3') 6973 >>> s = Solver() 6974 >>> s.set(unsat_core=True) 6975 >>> s.assert_and_track(x > 0, 'p1') 6976 >>> s.assert_and_track(x != 1, 'p2') 6977 >>> s.assert_and_track(x < 0, p3) 6978 >>> print(s.check()) 6979 unsat 6980 >>> c = s.unsat_core() 6981 >>> len(c) 6982 2 6983 >>> Bool('p1') in c 6984 True 6985 >>> Bool('p2') in c 6986 False 6987 >>> p3 in c 6988 True 6989 """ 6990 if isinstance(p, str): 6991 p = Bool(p, self.ctx) 6992 _z3_assert(isinstance(a, BoolRef), "Boolean expression expected") 6993 _z3_assert(isinstance(p, BoolRef) and is_const(p), "Boolean expression expected") 6994 Z3_solver_assert_and_track(self.ctx.ref(), self.solver, a.as_ast(), p.as_ast()) 6995 6996 def check(self, *assumptions): 6997 """Check whether the assertions in the given solver plus the optional assumptions are consistent or not. 6998 6999 >>> x = Int('x') 7000 >>> s = Solver() 7001 >>> s.check() 7002 sat 7003 >>> s.add(x > 0, x < 2) 7004 >>> s.check() 7005 sat 7006 >>> s.model().eval(x) 7007 1 7008 >>> s.add(x < 1) 7009 >>> s.check() 7010 unsat 7011 >>> s.reset() 7012 >>> s.add(2**x == 4) 7013 >>> s.check() 7014 unknown 7015 """ 7016 s = BoolSort(self.ctx) 7017 assumptions = _get_args(assumptions) 7018 num = len(assumptions) 7019 _assumptions = (Ast * num)() 7020 for i in range(num): 7021 _assumptions[i] = s.cast(assumptions[i]).as_ast() 7022 r = Z3_solver_check_assumptions(self.ctx.ref(), self.solver, num, _assumptions) 7023 return CheckSatResult(r) 7024 7025 def model(self): 7026 """Return a model for the last `check()`. 7027 7028 This function raises an exception if 7029 a model is not available (e.g., last `check()` returned unsat). 7030 7031 >>> s = Solver() 7032 >>> a = Int('a') 7033 >>> s.add(a + 2 == 0) 7034 >>> s.check() 7035 sat 7036 >>> s.model() 7037 [a = -2] 7038 """ 7039 try: 7040 return ModelRef(Z3_solver_get_model(self.ctx.ref(), self.solver), self.ctx) 7041 except Z3Exception: 7042 raise Z3Exception("model is not available") 7043 7044 def import_model_converter(self, other): 7045 """Import model converter from other into the current solver""" 7046 Z3_solver_import_model_converter(self.ctx.ref(), other.solver, self.solver) 7047 7048 def unsat_core(self): 7049 """Return a subset (as an AST vector) of the assumptions provided to the last check(). 7050 7051 These are the assumptions Z3 used in the unsatisfiability proof. 7052 Assumptions are available in Z3. They are used to extract unsatisfiable cores. 7053 They may be also used to "retract" assumptions. Note that, assumptions are not really 7054 "soft constraints", but they can be used to implement them. 7055 7056 >>> p1, p2, p3 = Bools('p1 p2 p3') 7057 >>> x, y = Ints('x y') 7058 >>> s = Solver() 7059 >>> s.add(Implies(p1, x > 0)) 7060 >>> s.add(Implies(p2, y > x)) 7061 >>> s.add(Implies(p2, y < 1)) 7062 >>> s.add(Implies(p3, y > -3)) 7063 >>> s.check(p1, p2, p3) 7064 unsat 7065 >>> core = s.unsat_core() 7066 >>> len(core) 7067 2 7068 >>> p1 in core 7069 True 7070 >>> p2 in core 7071 True 7072 >>> p3 in core 7073 False 7074 >>> # "Retracting" p2 7075 >>> s.check(p1, p3) 7076 sat 7077 """ 7078 return AstVector(Z3_solver_get_unsat_core(self.ctx.ref(), self.solver), self.ctx) 7079 7080 def consequences(self, assumptions, variables): 7081 """Determine fixed values for the variables based on the solver state and assumptions. 7082 >>> s = Solver() 7083 >>> a, b, c, d = Bools('a b c d') 7084 >>> s.add(Implies(a,b), Implies(b, c)) 7085 >>> s.consequences([a],[b,c,d]) 7086 (sat, [Implies(a, b), Implies(a, c)]) 7087 >>> s.consequences([Not(c),d],[a,b,c,d]) 7088 (sat, [Implies(d, d), Implies(Not(c), Not(c)), Implies(Not(c), Not(b)), Implies(Not(c), Not(a))]) 7089 """ 7090 if isinstance(assumptions, list): 7091 _asms = AstVector(None, self.ctx) 7092 for a in assumptions: 7093 _asms.push(a) 7094 assumptions = _asms 7095 if isinstance(variables, list): 7096 _vars = AstVector(None, self.ctx) 7097 for a in variables: 7098 _vars.push(a) 7099 variables = _vars 7100 _z3_assert(isinstance(assumptions, AstVector), "ast vector expected") 7101 _z3_assert(isinstance(variables, AstVector), "ast vector expected") 7102 consequences = AstVector(None, self.ctx) 7103 r = Z3_solver_get_consequences(self.ctx.ref(), self.solver, assumptions.vector, 7104 variables.vector, consequences.vector) 7105 sz = len(consequences) 7106 consequences = [consequences[i] for i in range(sz)] 7107 return CheckSatResult(r), consequences 7108 7109 def from_file(self, filename): 7110 """Parse assertions from a file""" 7111 Z3_solver_from_file(self.ctx.ref(), self.solver, filename) 7112 7113 def from_string(self, s): 7114 """Parse assertions from a string""" 7115 Z3_solver_from_string(self.ctx.ref(), self.solver, s) 7116 7117 def cube(self, vars=None): 7118 """Get set of cubes 7119 The method takes an optional set of variables that restrict which 7120 variables may be used as a starting point for cubing. 7121 If vars is not None, then the first case split is based on a variable in 7122 this set. 7123 """ 7124 self.cube_vs = AstVector(None, self.ctx) 7125 if vars is not None: 7126 for v in vars: 7127 self.cube_vs.push(v) 7128 while True: 7129 lvl = self.backtrack_level 7130 self.backtrack_level = 4000000000 7131 r = AstVector(Z3_solver_cube(self.ctx.ref(), self.solver, self.cube_vs.vector, lvl), self.ctx) 7132 if (len(r) == 1 and is_false(r[0])): 7133 return 7134 yield r 7135 if (len(r) == 0): 7136 return 7137 7138 def cube_vars(self): 7139 """Access the set of variables that were touched by the most recently generated cube. 7140 This set of variables can be used as a starting point for additional cubes. 7141 The idea is that variables that appear in clauses that are reduced by the most recent 7142 cube are likely more useful to cube on.""" 7143 return self.cube_vs 7144 7145 def proof(self): 7146 """Return a proof for the last `check()`. Proof construction must be enabled.""" 7147 return _to_expr_ref(Z3_solver_get_proof(self.ctx.ref(), self.solver), self.ctx) 7148 7149 def assertions(self): 7150 """Return an AST vector containing all added constraints. 7151 7152 >>> s = Solver() 7153 >>> s.assertions() 7154 [] 7155 >>> a = Int('a') 7156 >>> s.add(a > 0) 7157 >>> s.add(a < 10) 7158 >>> s.assertions() 7159 [a > 0, a < 10] 7160 """ 7161 return AstVector(Z3_solver_get_assertions(self.ctx.ref(), self.solver), self.ctx) 7162 7163 def units(self): 7164 """Return an AST vector containing all currently inferred units. 7165 """ 7166 return AstVector(Z3_solver_get_units(self.ctx.ref(), self.solver), self.ctx) 7167 7168 def non_units(self): 7169 """Return an AST vector containing all atomic formulas in solver state that are not units. 7170 """ 7171 return AstVector(Z3_solver_get_non_units(self.ctx.ref(), self.solver), self.ctx) 7172 7173 def trail_levels(self): 7174 """Return trail and decision levels of the solver state after a check() call. 7175 """ 7176 trail = self.trail() 7177 levels = (ctypes.c_uint * len(trail))() 7178 Z3_solver_get_levels(self.ctx.ref(), self.solver, trail.vector, len(trail), levels) 7179 return trail, levels 7180 7181 def trail(self): 7182 """Return trail of the solver state after a check() call. 7183 """ 7184 return AstVector(Z3_solver_get_trail(self.ctx.ref(), self.solver), self.ctx) 7185 7186 def statistics(self): 7187 """Return statistics for the last `check()`. 7188 7189 >>> s = SimpleSolver() 7190 >>> x = Int('x') 7191 >>> s.add(x > 0) 7192 >>> s.check() 7193 sat 7194 >>> st = s.statistics() 7195 >>> st.get_key_value('final checks') 7196 1 7197 >>> len(st) > 0 7198 True 7199 >>> st[0] != 0 7200 True 7201 """ 7202 return Statistics(Z3_solver_get_statistics(self.ctx.ref(), self.solver), self.ctx) 7203 7204 def reason_unknown(self): 7205 """Return a string describing why the last `check()` returned `unknown`. 7206 7207 >>> x = Int('x') 7208 >>> s = SimpleSolver() 7209 >>> s.add(2**x == 4) 7210 >>> s.check() 7211 unknown 7212 >>> s.reason_unknown() 7213 '(incomplete (theory arithmetic))' 7214 """ 7215 return Z3_solver_get_reason_unknown(self.ctx.ref(), self.solver) 7216 7217 def help(self): 7218 """Display a string describing all available options.""" 7219 print(Z3_solver_get_help(self.ctx.ref(), self.solver)) 7220 7221 def param_descrs(self): 7222 """Return the parameter description set.""" 7223 return ParamDescrsRef(Z3_solver_get_param_descrs(self.ctx.ref(), self.solver), self.ctx) 7224 7225 def __repr__(self): 7226 """Return a formatted string with all added constraints.""" 7227 return obj_to_string(self) 7228 7229 def translate(self, target): 7230 """Translate `self` to the context `target`. That is, return a copy of `self` in the context `target`. 7231 7232 >>> c1 = Context() 7233 >>> c2 = Context() 7234 >>> s1 = Solver(ctx=c1) 7235 >>> s2 = s1.translate(c2) 7236 """ 7237 if z3_debug(): 7238 _z3_assert(isinstance(target, Context), "argument must be a Z3 context") 7239 solver = Z3_solver_translate(self.ctx.ref(), self.solver, target.ref()) 7240 return Solver(solver, target) 7241 7242 def __copy__(self): 7243 return self.translate(self.ctx) 7244 7245 def __deepcopy__(self, memo={}): 7246 return self.translate(self.ctx) 7247 7248 def sexpr(self): 7249 """Return a formatted string (in Lisp-like format) with all added constraints. 7250 We say the string is in s-expression format. 7251 7252 >>> x = Int('x') 7253 >>> s = Solver() 7254 >>> s.add(x > 0) 7255 >>> s.add(x < 2) 7256 >>> r = s.sexpr() 7257 """ 7258 return Z3_solver_to_string(self.ctx.ref(), self.solver) 7259 7260 def dimacs(self, include_names=True): 7261 """Return a textual representation of the solver in DIMACS format.""" 7262 return Z3_solver_to_dimacs_string(self.ctx.ref(), self.solver, include_names) 7263 7264 def to_smt2(self): 7265 """return SMTLIB2 formatted benchmark for solver's assertions""" 7266 es = self.assertions() 7267 sz = len(es) 7268 sz1 = sz 7269 if sz1 > 0: 7270 sz1 -= 1 7271 v = (Ast * sz1)() 7272 for i in range(sz1): 7273 v[i] = es[i].as_ast() 7274 if sz > 0: 7275 e = es[sz1].as_ast() 7276 else: 7277 e = BoolVal(True, self.ctx).as_ast() 7278 return Z3_benchmark_to_smtlib_string( 7279 self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e, 7280 ) 7281 7282 7283def SolverFor(logic, ctx=None, logFile=None): 7284 """Create a solver customized for the given logic. 7285 7286 The parameter `logic` is a string. It should be contains 7287 the name of a SMT-LIB logic. 7288 See http://www.smtlib.org/ for the name of all available logics. 7289 7290 >>> s = SolverFor("QF_LIA") 7291 >>> x = Int('x') 7292 >>> s.add(x > 0) 7293 >>> s.add(x < 2) 7294 >>> s.check() 7295 sat 7296 >>> s.model() 7297 [x = 1] 7298 """ 7299 ctx = _get_ctx(ctx) 7300 logic = to_symbol(logic) 7301 return Solver(Z3_mk_solver_for_logic(ctx.ref(), logic), ctx, logFile) 7302 7303 7304def SimpleSolver(ctx=None, logFile=None): 7305 """Return a simple general purpose solver with limited amount of preprocessing. 7306 7307 >>> s = SimpleSolver() 7308 >>> x = Int('x') 7309 >>> s.add(x > 0) 7310 >>> s.check() 7311 sat 7312 """ 7313 ctx = _get_ctx(ctx) 7314 return Solver(Z3_mk_simple_solver(ctx.ref()), ctx, logFile) 7315 7316######################################### 7317# 7318# Fixedpoint 7319# 7320######################################### 7321 7322 7323class Fixedpoint(Z3PPObject): 7324 """Fixedpoint API provides methods for solving with recursive predicates""" 7325 7326 def __init__(self, fixedpoint=None, ctx=None): 7327 assert fixedpoint is None or ctx is not None 7328 self.ctx = _get_ctx(ctx) 7329 self.fixedpoint = None 7330 if fixedpoint is None: 7331 self.fixedpoint = Z3_mk_fixedpoint(self.ctx.ref()) 7332 else: 7333 self.fixedpoint = fixedpoint 7334 Z3_fixedpoint_inc_ref(self.ctx.ref(), self.fixedpoint) 7335 self.vars = [] 7336 7337 def __deepcopy__(self, memo={}): 7338 return FixedPoint(self.fixedpoint, self.ctx) 7339 7340 def __del__(self): 7341 if self.fixedpoint is not None and self.ctx.ref() is not None: 7342 Z3_fixedpoint_dec_ref(self.ctx.ref(), self.fixedpoint) 7343 7344 def set(self, *args, **keys): 7345 """Set a configuration option. The method `help()` return a string containing all available options. 7346 """ 7347 p = args2params(args, keys, self.ctx) 7348 Z3_fixedpoint_set_params(self.ctx.ref(), self.fixedpoint, p.params) 7349 7350 def help(self): 7351 """Display a string describing all available options.""" 7352 print(Z3_fixedpoint_get_help(self.ctx.ref(), self.fixedpoint)) 7353 7354 def param_descrs(self): 7355 """Return the parameter description set.""" 7356 return ParamDescrsRef(Z3_fixedpoint_get_param_descrs(self.ctx.ref(), self.fixedpoint), self.ctx) 7357 7358 def assert_exprs(self, *args): 7359 """Assert constraints as background axioms for the fixedpoint solver.""" 7360 args = _get_args(args) 7361 s = BoolSort(self.ctx) 7362 for arg in args: 7363 if isinstance(arg, Goal) or isinstance(arg, AstVector): 7364 for f in arg: 7365 f = self.abstract(f) 7366 Z3_fixedpoint_assert(self.ctx.ref(), self.fixedpoint, f.as_ast()) 7367 else: 7368 arg = s.cast(arg) 7369 arg = self.abstract(arg) 7370 Z3_fixedpoint_assert(self.ctx.ref(), self.fixedpoint, arg.as_ast()) 7371 7372 def add(self, *args): 7373 """Assert constraints as background axioms for the fixedpoint solver. Alias for assert_expr.""" 7374 self.assert_exprs(*args) 7375 7376 def __iadd__(self, fml): 7377 self.add(fml) 7378 return self 7379 7380 def append(self, *args): 7381 """Assert constraints as background axioms for the fixedpoint solver. Alias for assert_expr.""" 7382 self.assert_exprs(*args) 7383 7384 def insert(self, *args): 7385 """Assert constraints as background axioms for the fixedpoint solver. Alias for assert_expr.""" 7386 self.assert_exprs(*args) 7387 7388 def add_rule(self, head, body=None, name=None): 7389 """Assert rules defining recursive predicates to the fixedpoint solver. 7390 >>> a = Bool('a') 7391 >>> b = Bool('b') 7392 >>> s = Fixedpoint() 7393 >>> s.register_relation(a.decl()) 7394 >>> s.register_relation(b.decl()) 7395 >>> s.fact(a) 7396 >>> s.rule(b, a) 7397 >>> s.query(b) 7398 sat 7399 """ 7400 if name is None: 7401 name = "" 7402 name = to_symbol(name, self.ctx) 7403 if body is None: 7404 head = self.abstract(head) 7405 Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, head.as_ast(), name) 7406 else: 7407 body = _get_args(body) 7408 f = self.abstract(Implies(And(body, self.ctx), head)) 7409 Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) 7410 7411 def rule(self, head, body=None, name=None): 7412 """Assert rules defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" 7413 self.add_rule(head, body, name) 7414 7415 def fact(self, head, name=None): 7416 """Assert facts defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" 7417 self.add_rule(head, None, name) 7418 7419 def query(self, *query): 7420 """Query the fixedpoint engine whether formula is derivable. 7421 You can also pass an tuple or list of recursive predicates. 7422 """ 7423 query = _get_args(query) 7424 sz = len(query) 7425 if sz >= 1 and isinstance(query[0], FuncDeclRef): 7426 _decls = (FuncDecl * sz)() 7427 i = 0 7428 for q in query: 7429 _decls[i] = q.ast 7430 i = i + 1 7431 r = Z3_fixedpoint_query_relations(self.ctx.ref(), self.fixedpoint, sz, _decls) 7432 else: 7433 if sz == 1: 7434 query = query[0] 7435 else: 7436 query = And(query, self.ctx) 7437 query = self.abstract(query, False) 7438 r = Z3_fixedpoint_query(self.ctx.ref(), self.fixedpoint, query.as_ast()) 7439 return CheckSatResult(r) 7440 7441 def query_from_lvl(self, lvl, *query): 7442 """Query the fixedpoint engine whether formula is derivable starting at the given query level. 7443 """ 7444 query = _get_args(query) 7445 sz = len(query) 7446 if sz >= 1 and isinstance(query[0], FuncDecl): 7447 _z3_assert(False, "unsupported") 7448 else: 7449 if sz == 1: 7450 query = query[0] 7451 else: 7452 query = And(query) 7453 query = self.abstract(query, False) 7454 r = Z3_fixedpoint_query_from_lvl(self.ctx.ref(), self.fixedpoint, query.as_ast(), lvl) 7455 return CheckSatResult(r) 7456 7457 def update_rule(self, head, body, name): 7458 """update rule""" 7459 if name is None: 7460 name = "" 7461 name = to_symbol(name, self.ctx) 7462 body = _get_args(body) 7463 f = self.abstract(Implies(And(body, self.ctx), head)) 7464 Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) 7465 7466 def get_answer(self): 7467 """Retrieve answer from last query call.""" 7468 r = Z3_fixedpoint_get_answer(self.ctx.ref(), self.fixedpoint) 7469 return _to_expr_ref(r, self.ctx) 7470 7471 def get_ground_sat_answer(self): 7472 """Retrieve a ground cex from last query call.""" 7473 r = Z3_fixedpoint_get_ground_sat_answer(self.ctx.ref(), self.fixedpoint) 7474 return _to_expr_ref(r, self.ctx) 7475 7476 def get_rules_along_trace(self): 7477 """retrieve rules along the counterexample trace""" 7478 return AstVector(Z3_fixedpoint_get_rules_along_trace(self.ctx.ref(), self.fixedpoint), self.ctx) 7479 7480 def get_rule_names_along_trace(self): 7481 """retrieve rule names along the counterexample trace""" 7482 # this is a hack as I don't know how to return a list of symbols from C++; 7483 # obtain names as a single string separated by semicolons 7484 names = _symbol2py(self.ctx, Z3_fixedpoint_get_rule_names_along_trace(self.ctx.ref(), self.fixedpoint)) 7485 # split into individual names 7486 return names.split(";") 7487 7488 def get_num_levels(self, predicate): 7489 """Retrieve number of levels used for predicate in PDR engine""" 7490 return Z3_fixedpoint_get_num_levels(self.ctx.ref(), self.fixedpoint, predicate.ast) 7491 7492 def get_cover_delta(self, level, predicate): 7493 """Retrieve properties known about predicate for the level'th unfolding. 7494 -1 is treated as the limit (infinity) 7495 """ 7496 r = Z3_fixedpoint_get_cover_delta(self.ctx.ref(), self.fixedpoint, level, predicate.ast) 7497 return _to_expr_ref(r, self.ctx) 7498 7499 def add_cover(self, level, predicate, property): 7500 """Add property to predicate for the level'th unfolding. 7501 -1 is treated as infinity (infinity) 7502 """ 7503 Z3_fixedpoint_add_cover(self.ctx.ref(), self.fixedpoint, level, predicate.ast, property.ast) 7504 7505 def register_relation(self, *relations): 7506 """Register relation as recursive""" 7507 relations = _get_args(relations) 7508 for f in relations: 7509 Z3_fixedpoint_register_relation(self.ctx.ref(), self.fixedpoint, f.ast) 7510 7511 def set_predicate_representation(self, f, *representations): 7512 """Control how relation is represented""" 7513 representations = _get_args(representations) 7514 representations = [to_symbol(s) for s in representations] 7515 sz = len(representations) 7516 args = (Symbol * sz)() 7517 for i in range(sz): 7518 args[i] = representations[i] 7519 Z3_fixedpoint_set_predicate_representation(self.ctx.ref(), self.fixedpoint, f.ast, sz, args) 7520 7521 def parse_string(self, s): 7522 """Parse rules and queries from a string""" 7523 return AstVector(Z3_fixedpoint_from_string(self.ctx.ref(), self.fixedpoint, s), self.ctx) 7524 7525 def parse_file(self, f): 7526 """Parse rules and queries from a file""" 7527 return AstVector(Z3_fixedpoint_from_file(self.ctx.ref(), self.fixedpoint, f), self.ctx) 7528 7529 def get_rules(self): 7530 """retrieve rules that have been added to fixedpoint context""" 7531 return AstVector(Z3_fixedpoint_get_rules(self.ctx.ref(), self.fixedpoint), self.ctx) 7532 7533 def get_assertions(self): 7534 """retrieve assertions that have been added to fixedpoint context""" 7535 return AstVector(Z3_fixedpoint_get_assertions(self.ctx.ref(), self.fixedpoint), self.ctx) 7536 7537 def __repr__(self): 7538 """Return a formatted string with all added rules and constraints.""" 7539 return self.sexpr() 7540 7541 def sexpr(self): 7542 """Return a formatted string (in Lisp-like format) with all added constraints. 7543 We say the string is in s-expression format. 7544 """ 7545 return Z3_fixedpoint_to_string(self.ctx.ref(), self.fixedpoint, 0, (Ast * 0)()) 7546 7547 def to_string(self, queries): 7548 """Return a formatted string (in Lisp-like format) with all added constraints. 7549 We say the string is in s-expression format. 7550 Include also queries. 7551 """ 7552 args, len = _to_ast_array(queries) 7553 return Z3_fixedpoint_to_string(self.ctx.ref(), self.fixedpoint, len, args) 7554 7555 def statistics(self): 7556 """Return statistics for the last `query()`. 7557 """ 7558 return Statistics(Z3_fixedpoint_get_statistics(self.ctx.ref(), self.fixedpoint), self.ctx) 7559 7560 def reason_unknown(self): 7561 """Return a string describing why the last `query()` returned `unknown`. 7562 """ 7563 return Z3_fixedpoint_get_reason_unknown(self.ctx.ref(), self.fixedpoint) 7564 7565 def declare_var(self, *vars): 7566 """Add variable or several variables. 7567 The added variable or variables will be bound in the rules 7568 and queries 7569 """ 7570 vars = _get_args(vars) 7571 for v in vars: 7572 self.vars += [v] 7573 7574 def abstract(self, fml, is_forall=True): 7575 if self.vars == []: 7576 return fml 7577 if is_forall: 7578 return ForAll(self.vars, fml) 7579 else: 7580 return Exists(self.vars, fml) 7581 7582 7583######################################### 7584# 7585# Finite domains 7586# 7587######################################### 7588 7589class FiniteDomainSortRef(SortRef): 7590 """Finite domain sort.""" 7591 7592 def size(self): 7593 """Return the size of the finite domain sort""" 7594 r = (ctypes.c_ulonglong * 1)() 7595 if Z3_get_finite_domain_sort_size(self.ctx_ref(), self.ast, r): 7596 return r[0] 7597 else: 7598 raise Z3Exception("Failed to retrieve finite domain sort size") 7599 7600 7601def FiniteDomainSort(name, sz, ctx=None): 7602 """Create a named finite domain sort of a given size sz""" 7603 if not isinstance(name, Symbol): 7604 name = to_symbol(name) 7605 ctx = _get_ctx(ctx) 7606 return FiniteDomainSortRef(Z3_mk_finite_domain_sort(ctx.ref(), name, sz), ctx) 7607 7608 7609def is_finite_domain_sort(s): 7610 """Return True if `s` is a Z3 finite-domain sort. 7611 7612 >>> is_finite_domain_sort(FiniteDomainSort('S', 100)) 7613 True 7614 >>> is_finite_domain_sort(IntSort()) 7615 False 7616 """ 7617 return isinstance(s, FiniteDomainSortRef) 7618 7619 7620class FiniteDomainRef(ExprRef): 7621 """Finite-domain expressions.""" 7622 7623 def sort(self): 7624 """Return the sort of the finite-domain expression `self`.""" 7625 return FiniteDomainSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) 7626 7627 def as_string(self): 7628 """Return a Z3 floating point expression as a Python string.""" 7629 return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) 7630 7631 7632def is_finite_domain(a): 7633 """Return `True` if `a` is a Z3 finite-domain expression. 7634 7635 >>> s = FiniteDomainSort('S', 100) 7636 >>> b = Const('b', s) 7637 >>> is_finite_domain(b) 7638 True 7639 >>> is_finite_domain(Int('x')) 7640 False 7641 """ 7642 return isinstance(a, FiniteDomainRef) 7643 7644 7645class FiniteDomainNumRef(FiniteDomainRef): 7646 """Integer values.""" 7647 7648 def as_long(self): 7649 """Return a Z3 finite-domain numeral as a Python long (bignum) numeral. 7650 7651 >>> s = FiniteDomainSort('S', 100) 7652 >>> v = FiniteDomainVal(3, s) 7653 >>> v 7654 3 7655 >>> v.as_long() + 1 7656 4 7657 """ 7658 return int(self.as_string()) 7659 7660 def as_string(self): 7661 """Return a Z3 finite-domain numeral as a Python string. 7662 7663 >>> s = FiniteDomainSort('S', 100) 7664 >>> v = FiniteDomainVal(42, s) 7665 >>> v.as_string() 7666 '42' 7667 """ 7668 return Z3_get_numeral_string(self.ctx_ref(), self.as_ast()) 7669 7670 7671def FiniteDomainVal(val, sort, ctx=None): 7672 """Return a Z3 finite-domain value. If `ctx=None`, then the global context is used. 7673 7674 >>> s = FiniteDomainSort('S', 256) 7675 >>> FiniteDomainVal(255, s) 7676 255 7677 >>> FiniteDomainVal('100', s) 7678 100 7679 """ 7680 if z3_debug(): 7681 _z3_assert(is_finite_domain_sort(sort), "Expected finite-domain sort") 7682 ctx = sort.ctx 7683 return FiniteDomainNumRef(Z3_mk_numeral(ctx.ref(), _to_int_str(val), sort.ast), ctx) 7684 7685 7686def is_finite_domain_value(a): 7687 """Return `True` if `a` is a Z3 finite-domain value. 7688 7689 >>> s = FiniteDomainSort('S', 100) 7690 >>> b = Const('b', s) 7691 >>> is_finite_domain_value(b) 7692 False 7693 >>> b = FiniteDomainVal(10, s) 7694 >>> b 7695 10 7696 >>> is_finite_domain_value(b) 7697 True 7698 """ 7699 return is_finite_domain(a) and _is_numeral(a.ctx, a.as_ast()) 7700 7701 7702######################################### 7703# 7704# Optimize 7705# 7706######################################### 7707 7708class OptimizeObjective: 7709 def __init__(self, opt, value, is_max): 7710 self._opt = opt 7711 self._value = value 7712 self._is_max = is_max 7713 7714 def lower(self): 7715 opt = self._opt 7716 return _to_expr_ref(Z3_optimize_get_lower(opt.ctx.ref(), opt.optimize, self._value), opt.ctx) 7717 7718 def upper(self): 7719 opt = self._opt 7720 return _to_expr_ref(Z3_optimize_get_upper(opt.ctx.ref(), opt.optimize, self._value), opt.ctx) 7721 7722 def lower_values(self): 7723 opt = self._opt 7724 return AstVector(Z3_optimize_get_lower_as_vector(opt.ctx.ref(), opt.optimize, self._value), opt.ctx) 7725 7726 def upper_values(self): 7727 opt = self._opt 7728 return AstVector(Z3_optimize_get_upper_as_vector(opt.ctx.ref(), opt.optimize, self._value), opt.ctx) 7729 7730 def value(self): 7731 if self._is_max: 7732 return self.upper() 7733 else: 7734 return self.lower() 7735 7736 def __str__(self): 7737 return "%s:%s" % (self._value, self._is_max) 7738 7739 7740_on_models = {} 7741 7742 7743def _global_on_model(ctx): 7744 (fn, mdl) = _on_models[ctx] 7745 fn(mdl) 7746 7747 7748_on_model_eh = on_model_eh_type(_global_on_model) 7749 7750 7751class Optimize(Z3PPObject): 7752 """Optimize API provides methods for solving using objective functions and weighted soft constraints""" 7753 7754 def __init__(self, ctx=None): 7755 self.ctx = _get_ctx(ctx) 7756 self.optimize = Z3_mk_optimize(self.ctx.ref()) 7757 self._on_models_id = None 7758 Z3_optimize_inc_ref(self.ctx.ref(), self.optimize) 7759 7760 def __deepcopy__(self, memo={}): 7761 return Optimize(self.optimize, self.ctx) 7762 7763 def __del__(self): 7764 if self.optimize is not None and self.ctx.ref() is not None: 7765 Z3_optimize_dec_ref(self.ctx.ref(), self.optimize) 7766 if self._on_models_id is not None: 7767 del _on_models[self._on_models_id] 7768 7769 def set(self, *args, **keys): 7770 """Set a configuration option. 7771 The method `help()` return a string containing all available options. 7772 """ 7773 p = args2params(args, keys, self.ctx) 7774 Z3_optimize_set_params(self.ctx.ref(), self.optimize, p.params) 7775 7776 def help(self): 7777 """Display a string describing all available options.""" 7778 print(Z3_optimize_get_help(self.ctx.ref(), self.optimize)) 7779 7780 def param_descrs(self): 7781 """Return the parameter description set.""" 7782 return ParamDescrsRef(Z3_optimize_get_param_descrs(self.ctx.ref(), self.optimize), self.ctx) 7783 7784 def assert_exprs(self, *args): 7785 """Assert constraints as background axioms for the optimize solver.""" 7786 args = _get_args(args) 7787 s = BoolSort(self.ctx) 7788 for arg in args: 7789 if isinstance(arg, Goal) or isinstance(arg, AstVector): 7790 for f in arg: 7791 Z3_optimize_assert(self.ctx.ref(), self.optimize, f.as_ast()) 7792 else: 7793 arg = s.cast(arg) 7794 Z3_optimize_assert(self.ctx.ref(), self.optimize, arg.as_ast()) 7795 7796 def add(self, *args): 7797 """Assert constraints as background axioms for the optimize solver. Alias for assert_expr.""" 7798 self.assert_exprs(*args) 7799 7800 def __iadd__(self, fml): 7801 self.add(fml) 7802 return self 7803 7804 def assert_and_track(self, a, p): 7805 """Assert constraint `a` and track it in the unsat core using the Boolean constant `p`. 7806 7807 If `p` is a string, it will be automatically converted into a Boolean constant. 7808 7809 >>> x = Int('x') 7810 >>> p3 = Bool('p3') 7811 >>> s = Optimize() 7812 >>> s.assert_and_track(x > 0, 'p1') 7813 >>> s.assert_and_track(x != 1, 'p2') 7814 >>> s.assert_and_track(x < 0, p3) 7815 >>> print(s.check()) 7816 unsat 7817 >>> c = s.unsat_core() 7818 >>> len(c) 7819 2 7820 >>> Bool('p1') in c 7821 True 7822 >>> Bool('p2') in c 7823 False 7824 >>> p3 in c 7825 True 7826 """ 7827 if isinstance(p, str): 7828 p = Bool(p, self.ctx) 7829 _z3_assert(isinstance(a, BoolRef), "Boolean expression expected") 7830 _z3_assert(isinstance(p, BoolRef) and is_const(p), "Boolean expression expected") 7831 Z3_optimize_assert_and_track(self.ctx.ref(), self.optimize, a.as_ast(), p.as_ast()) 7832 7833 def add_soft(self, arg, weight="1", id=None): 7834 """Add soft constraint with optional weight and optional identifier. 7835 If no weight is supplied, then the penalty for violating the soft constraint 7836 is 1. 7837 Soft constraints are grouped by identifiers. Soft constraints that are 7838 added without identifiers are grouped by default. 7839 """ 7840 if _is_int(weight): 7841 weight = "%d" % weight 7842 elif isinstance(weight, float): 7843 weight = "%f" % weight 7844 if not isinstance(weight, str): 7845 raise Z3Exception("weight should be a string or an integer") 7846 if id is None: 7847 id = "" 7848 id = to_symbol(id, self.ctx) 7849 7850 def asoft(a): 7851 v = Z3_optimize_assert_soft(self.ctx.ref(), self.optimize, a.as_ast(), weight, id) 7852 return OptimizeObjective(self, v, False) 7853 if sys.version_info.major >= 3 and isinstance(arg, Iterable): 7854 return [asoft(a) for a in arg] 7855 return asoft(arg) 7856 7857 def maximize(self, arg): 7858 """Add objective function to maximize.""" 7859 return OptimizeObjective( 7860 self, 7861 Z3_optimize_maximize(self.ctx.ref(), self.optimize, arg.as_ast()), 7862 is_max=True, 7863 ) 7864 7865 def minimize(self, arg): 7866 """Add objective function to minimize.""" 7867 return OptimizeObjective( 7868 self, 7869 Z3_optimize_minimize(self.ctx.ref(), self.optimize, arg.as_ast()), 7870 is_max=False, 7871 ) 7872 7873 def push(self): 7874 """create a backtracking point for added rules, facts and assertions""" 7875 Z3_optimize_push(self.ctx.ref(), self.optimize) 7876 7877 def pop(self): 7878 """restore to previously created backtracking point""" 7879 Z3_optimize_pop(self.ctx.ref(), self.optimize) 7880 7881 def check(self, *assumptions): 7882 """Check satisfiability while optimizing objective functions.""" 7883 assumptions = _get_args(assumptions) 7884 num = len(assumptions) 7885 _assumptions = (Ast * num)() 7886 for i in range(num): 7887 _assumptions[i] = assumptions[i].as_ast() 7888 return CheckSatResult(Z3_optimize_check(self.ctx.ref(), self.optimize, num, _assumptions)) 7889 7890 def reason_unknown(self): 7891 """Return a string that describes why the last `check()` returned `unknown`.""" 7892 return Z3_optimize_get_reason_unknown(self.ctx.ref(), self.optimize) 7893 7894 def model(self): 7895 """Return a model for the last check().""" 7896 try: 7897 return ModelRef(Z3_optimize_get_model(self.ctx.ref(), self.optimize), self.ctx) 7898 except Z3Exception: 7899 raise Z3Exception("model is not available") 7900 7901 def unsat_core(self): 7902 return AstVector(Z3_optimize_get_unsat_core(self.ctx.ref(), self.optimize), self.ctx) 7903 7904 def lower(self, obj): 7905 if not isinstance(obj, OptimizeObjective): 7906 raise Z3Exception("Expecting objective handle returned by maximize/minimize") 7907 return obj.lower() 7908 7909 def upper(self, obj): 7910 if not isinstance(obj, OptimizeObjective): 7911 raise Z3Exception("Expecting objective handle returned by maximize/minimize") 7912 return obj.upper() 7913 7914 def lower_values(self, obj): 7915 if not isinstance(obj, OptimizeObjective): 7916 raise Z3Exception("Expecting objective handle returned by maximize/minimize") 7917 return obj.lower_values() 7918 7919 def upper_values(self, obj): 7920 if not isinstance(obj, OptimizeObjective): 7921 raise Z3Exception("Expecting objective handle returned by maximize/minimize") 7922 return obj.upper_values() 7923 7924 def from_file(self, filename): 7925 """Parse assertions and objectives from a file""" 7926 Z3_optimize_from_file(self.ctx.ref(), self.optimize, filename) 7927 7928 def from_string(self, s): 7929 """Parse assertions and objectives from a string""" 7930 Z3_optimize_from_string(self.ctx.ref(), self.optimize, s) 7931 7932 def assertions(self): 7933 """Return an AST vector containing all added constraints.""" 7934 return AstVector(Z3_optimize_get_assertions(self.ctx.ref(), self.optimize), self.ctx) 7935 7936 def objectives(self): 7937 """returns set of objective functions""" 7938 return AstVector(Z3_optimize_get_objectives(self.ctx.ref(), self.optimize), self.ctx) 7939 7940 def __repr__(self): 7941 """Return a formatted string with all added rules and constraints.""" 7942 return self.sexpr() 7943 7944 def sexpr(self): 7945 """Return a formatted string (in Lisp-like format) with all added constraints. 7946 We say the string is in s-expression format. 7947 """ 7948 return Z3_optimize_to_string(self.ctx.ref(), self.optimize) 7949 7950 def statistics(self): 7951 """Return statistics for the last check`. 7952 """ 7953 return Statistics(Z3_optimize_get_statistics(self.ctx.ref(), self.optimize), self.ctx) 7954 7955 def set_on_model(self, on_model): 7956 """Register a callback that is invoked with every incremental improvement to 7957 objective values. The callback takes a model as argument. 7958 The life-time of the model is limited to the callback so the 7959 model has to be (deep) copied if it is to be used after the callback 7960 """ 7961 id = len(_on_models) + 41 7962 mdl = Model(self.ctx) 7963 _on_models[id] = (on_model, mdl) 7964 self._on_models_id = id 7965 Z3_optimize_register_model_eh( 7966 self.ctx.ref(), self.optimize, mdl.model, ctypes.c_void_p(id), _on_model_eh, 7967 ) 7968 7969 7970######################################### 7971# 7972# ApplyResult 7973# 7974######################################### 7975class ApplyResult(Z3PPObject): 7976 """An ApplyResult object contains the subgoals produced by a tactic when applied to a goal. 7977 It also contains model and proof converters. 7978 """ 7979 7980 def __init__(self, result, ctx): 7981 self.result = result 7982 self.ctx = ctx 7983 Z3_apply_result_inc_ref(self.ctx.ref(), self.result) 7984 7985 def __deepcopy__(self, memo={}): 7986 return ApplyResult(self.result, self.ctx) 7987 7988 def __del__(self): 7989 if self.ctx.ref() is not None: 7990 Z3_apply_result_dec_ref(self.ctx.ref(), self.result) 7991 7992 def __len__(self): 7993 """Return the number of subgoals in `self`. 7994 7995 >>> a, b = Ints('a b') 7996 >>> g = Goal() 7997 >>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b) 7998 >>> t = Tactic('split-clause') 7999 >>> r = t(g) 8000 >>> len(r) 8001 2 8002 >>> t = Then(Tactic('split-clause'), Tactic('split-clause')) 8003 >>> len(t(g)) 8004 4 8005 >>> t = Then(Tactic('split-clause'), Tactic('split-clause'), Tactic('propagate-values')) 8006 >>> len(t(g)) 8007 1 8008 """ 8009 return int(Z3_apply_result_get_num_subgoals(self.ctx.ref(), self.result)) 8010 8011 def __getitem__(self, idx): 8012 """Return one of the subgoals stored in ApplyResult object `self`. 8013 8014 >>> a, b = Ints('a b') 8015 >>> g = Goal() 8016 >>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b) 8017 >>> t = Tactic('split-clause') 8018 >>> r = t(g) 8019 >>> r[0] 8020 [a == 0, Or(b == 0, b == 1), a > b] 8021 >>> r[1] 8022 [a == 1, Or(b == 0, b == 1), a > b] 8023 """ 8024 if idx >= len(self): 8025 raise IndexError 8026 return Goal(goal=Z3_apply_result_get_subgoal(self.ctx.ref(), self.result, idx), ctx=self.ctx) 8027 8028 def __repr__(self): 8029 return obj_to_string(self) 8030 8031 def sexpr(self): 8032 """Return a textual representation of the s-expression representing the set of subgoals in `self`.""" 8033 return Z3_apply_result_to_string(self.ctx.ref(), self.result) 8034 8035 def as_expr(self): 8036 """Return a Z3 expression consisting of all subgoals. 8037 8038 >>> x = Int('x') 8039 >>> g = Goal() 8040 >>> g.add(x > 1) 8041 >>> g.add(Or(x == 2, x == 3)) 8042 >>> r = Tactic('simplify')(g) 8043 >>> r 8044 [[Not(x <= 1), Or(x == 2, x == 3)]] 8045 >>> r.as_expr() 8046 And(Not(x <= 1), Or(x == 2, x == 3)) 8047 >>> r = Tactic('split-clause')(g) 8048 >>> r 8049 [[x > 1, x == 2], [x > 1, x == 3]] 8050 >>> r.as_expr() 8051 Or(And(x > 1, x == 2), And(x > 1, x == 3)) 8052 """ 8053 sz = len(self) 8054 if sz == 0: 8055 return BoolVal(False, self.ctx) 8056 elif sz == 1: 8057 return self[0].as_expr() 8058 else: 8059 return Or([self[i].as_expr() for i in range(len(self))]) 8060 8061######################################### 8062# 8063# Tactics 8064# 8065######################################### 8066 8067 8068class Tactic: 8069 """Tactics transform, solver and/or simplify sets of constraints (Goal). 8070 A Tactic can be converted into a Solver using the method solver(). 8071 8072 Several combinators are available for creating new tactics using the built-in ones: 8073 Then(), OrElse(), FailIf(), Repeat(), When(), Cond(). 8074 """ 8075 8076 def __init__(self, tactic, ctx=None): 8077 self.ctx = _get_ctx(ctx) 8078 self.tactic = None 8079 if isinstance(tactic, TacticObj): 8080 self.tactic = tactic 8081 else: 8082 if z3_debug(): 8083 _z3_assert(isinstance(tactic, str), "tactic name expected") 8084 try: 8085 self.tactic = Z3_mk_tactic(self.ctx.ref(), str(tactic)) 8086 except Z3Exception: 8087 raise Z3Exception("unknown tactic '%s'" % tactic) 8088 Z3_tactic_inc_ref(self.ctx.ref(), self.tactic) 8089 8090 def __deepcopy__(self, memo={}): 8091 return Tactic(self.tactic, self.ctx) 8092 8093 def __del__(self): 8094 if self.tactic is not None and self.ctx.ref() is not None: 8095 Z3_tactic_dec_ref(self.ctx.ref(), self.tactic) 8096 8097 def solver(self, logFile=None): 8098 """Create a solver using the tactic `self`. 8099 8100 The solver supports the methods `push()` and `pop()`, but it 8101 will always solve each `check()` from scratch. 8102 8103 >>> t = Then('simplify', 'nlsat') 8104 >>> s = t.solver() 8105 >>> x = Real('x') 8106 >>> s.add(x**2 == 2, x > 0) 8107 >>> s.check() 8108 sat 8109 >>> s.model() 8110 [x = 1.4142135623?] 8111 """ 8112 return Solver(Z3_mk_solver_from_tactic(self.ctx.ref(), self.tactic), self.ctx, logFile) 8113 8114 def apply(self, goal, *arguments, **keywords): 8115 """Apply tactic `self` to the given goal or Z3 Boolean expression using the given options. 8116 8117 >>> x, y = Ints('x y') 8118 >>> t = Tactic('solve-eqs') 8119 >>> t.apply(And(x == 0, y >= x + 1)) 8120 [[y >= 1]] 8121 """ 8122 if z3_debug(): 8123 _z3_assert(isinstance(goal, (Goal, BoolRef)), "Z3 Goal or Boolean expressions expected") 8124 goal = _to_goal(goal) 8125 if len(arguments) > 0 or len(keywords) > 0: 8126 p = args2params(arguments, keywords, self.ctx) 8127 return ApplyResult(Z3_tactic_apply_ex(self.ctx.ref(), self.tactic, goal.goal, p.params), self.ctx) 8128 else: 8129 return ApplyResult(Z3_tactic_apply(self.ctx.ref(), self.tactic, goal.goal), self.ctx) 8130 8131 def __call__(self, goal, *arguments, **keywords): 8132 """Apply tactic `self` to the given goal or Z3 Boolean expression using the given options. 8133 8134 >>> x, y = Ints('x y') 8135 >>> t = Tactic('solve-eqs') 8136 >>> t(And(x == 0, y >= x + 1)) 8137 [[y >= 1]] 8138 """ 8139 return self.apply(goal, *arguments, **keywords) 8140 8141 def help(self): 8142 """Display a string containing a description of the available options for the `self` tactic.""" 8143 print(Z3_tactic_get_help(self.ctx.ref(), self.tactic)) 8144 8145 def param_descrs(self): 8146 """Return the parameter description set.""" 8147 return ParamDescrsRef(Z3_tactic_get_param_descrs(self.ctx.ref(), self.tactic), self.ctx) 8148 8149 8150def _to_goal(a): 8151 if isinstance(a, BoolRef): 8152 goal = Goal(ctx=a.ctx) 8153 goal.add(a) 8154 return goal 8155 else: 8156 return a 8157 8158 8159def _to_tactic(t, ctx=None): 8160 if isinstance(t, Tactic): 8161 return t 8162 else: 8163 return Tactic(t, ctx) 8164 8165 8166def _and_then(t1, t2, ctx=None): 8167 t1 = _to_tactic(t1, ctx) 8168 t2 = _to_tactic(t2, ctx) 8169 if z3_debug(): 8170 _z3_assert(t1.ctx == t2.ctx, "Context mismatch") 8171 return Tactic(Z3_tactic_and_then(t1.ctx.ref(), t1.tactic, t2.tactic), t1.ctx) 8172 8173 8174def _or_else(t1, t2, ctx=None): 8175 t1 = _to_tactic(t1, ctx) 8176 t2 = _to_tactic(t2, ctx) 8177 if z3_debug(): 8178 _z3_assert(t1.ctx == t2.ctx, "Context mismatch") 8179 return Tactic(Z3_tactic_or_else(t1.ctx.ref(), t1.tactic, t2.tactic), t1.ctx) 8180 8181 8182def AndThen(*ts, **ks): 8183 """Return a tactic that applies the tactics in `*ts` in sequence. 8184 8185 >>> x, y = Ints('x y') 8186 >>> t = AndThen(Tactic('simplify'), Tactic('solve-eqs')) 8187 >>> t(And(x == 0, y > x + 1)) 8188 [[Not(y <= 1)]] 8189 >>> t(And(x == 0, y > x + 1)).as_expr() 8190 Not(y <= 1) 8191 """ 8192 if z3_debug(): 8193 _z3_assert(len(ts) >= 2, "At least two arguments expected") 8194 ctx = ks.get("ctx", None) 8195 num = len(ts) 8196 r = ts[0] 8197 for i in range(num - 1): 8198 r = _and_then(r, ts[i + 1], ctx) 8199 return r 8200 8201 8202def Then(*ts, **ks): 8203 """Return a tactic that applies the tactics in `*ts` in sequence. Shorthand for AndThen(*ts, **ks). 8204 8205 >>> x, y = Ints('x y') 8206 >>> t = Then(Tactic('simplify'), Tactic('solve-eqs')) 8207 >>> t(And(x == 0, y > x + 1)) 8208 [[Not(y <= 1)]] 8209 >>> t(And(x == 0, y > x + 1)).as_expr() 8210 Not(y <= 1) 8211 """ 8212 return AndThen(*ts, **ks) 8213 8214 8215def OrElse(*ts, **ks): 8216 """Return a tactic that applies the tactics in `*ts` until one of them succeeds (it doesn't fail). 8217 8218 >>> x = Int('x') 8219 >>> t = OrElse(Tactic('split-clause'), Tactic('skip')) 8220 >>> # Tactic split-clause fails if there is no clause in the given goal. 8221 >>> t(x == 0) 8222 [[x == 0]] 8223 >>> t(Or(x == 0, x == 1)) 8224 [[x == 0], [x == 1]] 8225 """ 8226 if z3_debug(): 8227 _z3_assert(len(ts) >= 2, "At least two arguments expected") 8228 ctx = ks.get("ctx", None) 8229 num = len(ts) 8230 r = ts[0] 8231 for i in range(num - 1): 8232 r = _or_else(r, ts[i + 1], ctx) 8233 return r 8234 8235 8236def ParOr(*ts, **ks): 8237 """Return a tactic that applies the tactics in `*ts` in parallel until one of them succeeds (it doesn't fail). 8238 8239 >>> x = Int('x') 8240 >>> t = ParOr(Tactic('simplify'), Tactic('fail')) 8241 >>> t(x + 1 == 2) 8242 [[x == 1]] 8243 """ 8244 if z3_debug(): 8245 _z3_assert(len(ts) >= 2, "At least two arguments expected") 8246 ctx = _get_ctx(ks.get("ctx", None)) 8247 ts = [_to_tactic(t, ctx) for t in ts] 8248 sz = len(ts) 8249 _args = (TacticObj * sz)() 8250 for i in range(sz): 8251 _args[i] = ts[i].tactic 8252 return Tactic(Z3_tactic_par_or(ctx.ref(), sz, _args), ctx) 8253 8254 8255def ParThen(t1, t2, ctx=None): 8256 """Return a tactic that applies t1 and then t2 to every subgoal produced by t1. 8257 The subgoals are processed in parallel. 8258 8259 >>> x, y = Ints('x y') 8260 >>> t = ParThen(Tactic('split-clause'), Tactic('propagate-values')) 8261 >>> t(And(Or(x == 1, x == 2), y == x + 1)) 8262 [[x == 1, y == 2], [x == 2, y == 3]] 8263 """ 8264 t1 = _to_tactic(t1, ctx) 8265 t2 = _to_tactic(t2, ctx) 8266 if z3_debug(): 8267 _z3_assert(t1.ctx == t2.ctx, "Context mismatch") 8268 return Tactic(Z3_tactic_par_and_then(t1.ctx.ref(), t1.tactic, t2.tactic), t1.ctx) 8269 8270 8271def ParAndThen(t1, t2, ctx=None): 8272 """Alias for ParThen(t1, t2, ctx).""" 8273 return ParThen(t1, t2, ctx) 8274 8275 8276def With(t, *args, **keys): 8277 """Return a tactic that applies tactic `t` using the given configuration options. 8278 8279 >>> x, y = Ints('x y') 8280 >>> t = With(Tactic('simplify'), som=True) 8281 >>> t((x + 1)*(y + 2) == 0) 8282 [[2*x + y + x*y == -2]] 8283 """ 8284 ctx = keys.pop("ctx", None) 8285 t = _to_tactic(t, ctx) 8286 p = args2params(args, keys, t.ctx) 8287 return Tactic(Z3_tactic_using_params(t.ctx.ref(), t.tactic, p.params), t.ctx) 8288 8289 8290def WithParams(t, p): 8291 """Return a tactic that applies tactic `t` using the given configuration options. 8292 8293 >>> x, y = Ints('x y') 8294 >>> p = ParamsRef() 8295 >>> p.set("som", True) 8296 >>> t = WithParams(Tactic('simplify'), p) 8297 >>> t((x + 1)*(y + 2) == 0) 8298 [[2*x + y + x*y == -2]] 8299 """ 8300 t = _to_tactic(t, None) 8301 return Tactic(Z3_tactic_using_params(t.ctx.ref(), t.tactic, p.params), t.ctx) 8302 8303 8304def Repeat(t, max=4294967295, ctx=None): 8305 """Return a tactic that keeps applying `t` until the goal is not modified anymore 8306 or the maximum number of iterations `max` is reached. 8307 8308 >>> x, y = Ints('x y') 8309 >>> c = And(Or(x == 0, x == 1), Or(y == 0, y == 1), x > y) 8310 >>> t = Repeat(OrElse(Tactic('split-clause'), Tactic('skip'))) 8311 >>> r = t(c) 8312 >>> for subgoal in r: print(subgoal) 8313 [x == 0, y == 0, x > y] 8314 [x == 0, y == 1, x > y] 8315 [x == 1, y == 0, x > y] 8316 [x == 1, y == 1, x > y] 8317 >>> t = Then(t, Tactic('propagate-values')) 8318 >>> t(c) 8319 [[x == 1, y == 0]] 8320 """ 8321 t = _to_tactic(t, ctx) 8322 return Tactic(Z3_tactic_repeat(t.ctx.ref(), t.tactic, max), t.ctx) 8323 8324 8325def TryFor(t, ms, ctx=None): 8326 """Return a tactic that applies `t` to a given goal for `ms` milliseconds. 8327 8328 If `t` does not terminate in `ms` milliseconds, then it fails. 8329 """ 8330 t = _to_tactic(t, ctx) 8331 return Tactic(Z3_tactic_try_for(t.ctx.ref(), t.tactic, ms), t.ctx) 8332 8333 8334def tactics(ctx=None): 8335 """Return a list of all available tactics in Z3. 8336 8337 >>> l = tactics() 8338 >>> l.count('simplify') == 1 8339 True 8340 """ 8341 ctx = _get_ctx(ctx) 8342 return [Z3_get_tactic_name(ctx.ref(), i) for i in range(Z3_get_num_tactics(ctx.ref()))] 8343 8344 8345def tactic_description(name, ctx=None): 8346 """Return a short description for the tactic named `name`. 8347 8348 >>> d = tactic_description('simplify') 8349 """ 8350 ctx = _get_ctx(ctx) 8351 return Z3_tactic_get_descr(ctx.ref(), name) 8352 8353 8354def describe_tactics(): 8355 """Display a (tabular) description of all available tactics in Z3.""" 8356 if in_html_mode(): 8357 even = True 8358 print('<table border="1" cellpadding="2" cellspacing="0">') 8359 for t in tactics(): 8360 if even: 8361 print('<tr style="background-color:#CFCFCF">') 8362 even = False 8363 else: 8364 print("<tr>") 8365 even = True 8366 print("<td>%s</td><td>%s</td></tr>" % (t, insert_line_breaks(tactic_description(t), 40))) 8367 print("</table>") 8368 else: 8369 for t in tactics(): 8370 print("%s : %s" % (t, tactic_description(t))) 8371 8372 8373class Probe: 8374 """Probes are used to inspect a goal (aka problem) and collect information that may be used 8375 to decide which solver and/or preprocessing step will be used. 8376 """ 8377 8378 def __init__(self, probe, ctx=None): 8379 self.ctx = _get_ctx(ctx) 8380 self.probe = None 8381 if isinstance(probe, ProbeObj): 8382 self.probe = probe 8383 elif isinstance(probe, float): 8384 self.probe = Z3_probe_const(self.ctx.ref(), probe) 8385 elif _is_int(probe): 8386 self.probe = Z3_probe_const(self.ctx.ref(), float(probe)) 8387 elif isinstance(probe, bool): 8388 if probe: 8389 self.probe = Z3_probe_const(self.ctx.ref(), 1.0) 8390 else: 8391 self.probe = Z3_probe_const(self.ctx.ref(), 0.0) 8392 else: 8393 if z3_debug(): 8394 _z3_assert(isinstance(probe, str), "probe name expected") 8395 try: 8396 self.probe = Z3_mk_probe(self.ctx.ref(), probe) 8397 except Z3Exception: 8398 raise Z3Exception("unknown probe '%s'" % probe) 8399 Z3_probe_inc_ref(self.ctx.ref(), self.probe) 8400 8401 def __deepcopy__(self, memo={}): 8402 return Probe(self.probe, self.ctx) 8403 8404 def __del__(self): 8405 if self.probe is not None and self.ctx.ref() is not None: 8406 Z3_probe_dec_ref(self.ctx.ref(), self.probe) 8407 8408 def __lt__(self, other): 8409 """Return a probe that evaluates to "true" when the value returned by `self` 8410 is less than the value returned by `other`. 8411 8412 >>> p = Probe('size') < 10 8413 >>> x = Int('x') 8414 >>> g = Goal() 8415 >>> g.add(x > 0) 8416 >>> g.add(x < 10) 8417 >>> p(g) 8418 1.0 8419 """ 8420 return Probe(Z3_probe_lt(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx) 8421 8422 def __gt__(self, other): 8423 """Return a probe that evaluates to "true" when the value returned by `self` 8424 is greater than the value returned by `other`. 8425 8426 >>> p = Probe('size') > 10 8427 >>> x = Int('x') 8428 >>> g = Goal() 8429 >>> g.add(x > 0) 8430 >>> g.add(x < 10) 8431 >>> p(g) 8432 0.0 8433 """ 8434 return Probe(Z3_probe_gt(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx) 8435 8436 def __le__(self, other): 8437 """Return a probe that evaluates to "true" when the value returned by `self` 8438 is less than or equal to the value returned by `other`. 8439 8440 >>> p = Probe('size') <= 2 8441 >>> x = Int('x') 8442 >>> g = Goal() 8443 >>> g.add(x > 0) 8444 >>> g.add(x < 10) 8445 >>> p(g) 8446 1.0 8447 """ 8448 return Probe(Z3_probe_le(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx) 8449 8450 def __ge__(self, other): 8451 """Return a probe that evaluates to "true" when the value returned by `self` 8452 is greater than or equal to the value returned by `other`. 8453 8454 >>> p = Probe('size') >= 2 8455 >>> x = Int('x') 8456 >>> g = Goal() 8457 >>> g.add(x > 0) 8458 >>> g.add(x < 10) 8459 >>> p(g) 8460 1.0 8461 """ 8462 return Probe(Z3_probe_ge(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx) 8463 8464 def __eq__(self, other): 8465 """Return a probe that evaluates to "true" when the value returned by `self` 8466 is equal to the value returned by `other`. 8467 8468 >>> p = Probe('size') == 2 8469 >>> x = Int('x') 8470 >>> g = Goal() 8471 >>> g.add(x > 0) 8472 >>> g.add(x < 10) 8473 >>> p(g) 8474 1.0 8475 """ 8476 return Probe(Z3_probe_eq(self.ctx.ref(), self.probe, _to_probe(other, self.ctx).probe), self.ctx) 8477 8478 def __ne__(self, other): 8479 """Return a probe that evaluates to "true" when the value returned by `self` 8480 is not equal to the value returned by `other`. 8481 8482 >>> p = Probe('size') != 2 8483 >>> x = Int('x') 8484 >>> g = Goal() 8485 >>> g.add(x > 0) 8486 >>> g.add(x < 10) 8487 >>> p(g) 8488 0.0 8489 """ 8490 p = self.__eq__(other) 8491 return Probe(Z3_probe_not(self.ctx.ref(), p.probe), self.ctx) 8492 8493 def __call__(self, goal): 8494 """Evaluate the probe `self` in the given goal. 8495 8496 >>> p = Probe('size') 8497 >>> x = Int('x') 8498 >>> g = Goal() 8499 >>> g.add(x > 0) 8500 >>> g.add(x < 10) 8501 >>> p(g) 8502 2.0 8503 >>> g.add(x < 20) 8504 >>> p(g) 8505 3.0 8506 >>> p = Probe('num-consts') 8507 >>> p(g) 8508 1.0 8509 >>> p = Probe('is-propositional') 8510 >>> p(g) 8511 0.0 8512 >>> p = Probe('is-qflia') 8513 >>> p(g) 8514 1.0 8515 """ 8516 if z3_debug(): 8517 _z3_assert(isinstance(goal, (Goal, BoolRef)), "Z3 Goal or Boolean expression expected") 8518 goal = _to_goal(goal) 8519 return Z3_probe_apply(self.ctx.ref(), self.probe, goal.goal) 8520 8521 8522def is_probe(p): 8523 """Return `True` if `p` is a Z3 probe. 8524 8525 >>> is_probe(Int('x')) 8526 False 8527 >>> is_probe(Probe('memory')) 8528 True 8529 """ 8530 return isinstance(p, Probe) 8531 8532 8533def _to_probe(p, ctx=None): 8534 if is_probe(p): 8535 return p 8536 else: 8537 return Probe(p, ctx) 8538 8539 8540def probes(ctx=None): 8541 """Return a list of all available probes in Z3. 8542 8543 >>> l = probes() 8544 >>> l.count('memory') == 1 8545 True 8546 """ 8547 ctx = _get_ctx(ctx) 8548 return [Z3_get_probe_name(ctx.ref(), i) for i in range(Z3_get_num_probes(ctx.ref()))] 8549 8550 8551def probe_description(name, ctx=None): 8552 """Return a short description for the probe named `name`. 8553 8554 >>> d = probe_description('memory') 8555 """ 8556 ctx = _get_ctx(ctx) 8557 return Z3_probe_get_descr(ctx.ref(), name) 8558 8559 8560def describe_probes(): 8561 """Display a (tabular) description of all available probes in Z3.""" 8562 if in_html_mode(): 8563 even = True 8564 print('<table border="1" cellpadding="2" cellspacing="0">') 8565 for p in probes(): 8566 if even: 8567 print('<tr style="background-color:#CFCFCF">') 8568 even = False 8569 else: 8570 print("<tr>") 8571 even = True 8572 print("<td>%s</td><td>%s</td></tr>" % (p, insert_line_breaks(probe_description(p), 40))) 8573 print("</table>") 8574 else: 8575 for p in probes(): 8576 print("%s : %s" % (p, probe_description(p))) 8577 8578 8579def _probe_nary(f, args, ctx): 8580 if z3_debug(): 8581 _z3_assert(len(args) > 0, "At least one argument expected") 8582 num = len(args) 8583 r = _to_probe(args[0], ctx) 8584 for i in range(num - 1): 8585 r = Probe(f(ctx.ref(), r.probe, _to_probe(args[i + 1], ctx).probe), ctx) 8586 return r 8587 8588 8589def _probe_and(args, ctx): 8590 return _probe_nary(Z3_probe_and, args, ctx) 8591 8592 8593def _probe_or(args, ctx): 8594 return _probe_nary(Z3_probe_or, args, ctx) 8595 8596 8597def FailIf(p, ctx=None): 8598 """Return a tactic that fails if the probe `p` evaluates to true. 8599 Otherwise, it returns the input goal unmodified. 8600 8601 In the following example, the tactic applies 'simplify' if and only if there are 8602 more than 2 constraints in the goal. 8603 8604 >>> t = OrElse(FailIf(Probe('size') > 2), Tactic('simplify')) 8605 >>> x, y = Ints('x y') 8606 >>> g = Goal() 8607 >>> g.add(x > 0) 8608 >>> g.add(y > 0) 8609 >>> t(g) 8610 [[x > 0, y > 0]] 8611 >>> g.add(x == y + 1) 8612 >>> t(g) 8613 [[Not(x <= 0), Not(y <= 0), x == 1 + y]] 8614 """ 8615 p = _to_probe(p, ctx) 8616 return Tactic(Z3_tactic_fail_if(p.ctx.ref(), p.probe), p.ctx) 8617 8618 8619def When(p, t, ctx=None): 8620 """Return a tactic that applies tactic `t` only if probe `p` evaluates to true. 8621 Otherwise, it returns the input goal unmodified. 8622 8623 >>> t = When(Probe('size') > 2, Tactic('simplify')) 8624 >>> x, y = Ints('x y') 8625 >>> g = Goal() 8626 >>> g.add(x > 0) 8627 >>> g.add(y > 0) 8628 >>> t(g) 8629 [[x > 0, y > 0]] 8630 >>> g.add(x == y + 1) 8631 >>> t(g) 8632 [[Not(x <= 0), Not(y <= 0), x == 1 + y]] 8633 """ 8634 p = _to_probe(p, ctx) 8635 t = _to_tactic(t, ctx) 8636 return Tactic(Z3_tactic_when(t.ctx.ref(), p.probe, t.tactic), t.ctx) 8637 8638 8639def Cond(p, t1, t2, ctx=None): 8640 """Return a tactic that applies tactic `t1` to a goal if probe `p` evaluates to true, and `t2` otherwise. 8641 8642 >>> t = Cond(Probe('is-qfnra'), Tactic('qfnra'), Tactic('smt')) 8643 """ 8644 p = _to_probe(p, ctx) 8645 t1 = _to_tactic(t1, ctx) 8646 t2 = _to_tactic(t2, ctx) 8647 return Tactic(Z3_tactic_cond(t1.ctx.ref(), p.probe, t1.tactic, t2.tactic), t1.ctx) 8648 8649######################################### 8650# 8651# Utils 8652# 8653######################################### 8654 8655 8656def simplify(a, *arguments, **keywords): 8657 """Simplify the expression `a` using the given options. 8658 8659 This function has many options. Use `help_simplify` to obtain the complete list. 8660 8661 >>> x = Int('x') 8662 >>> y = Int('y') 8663 >>> simplify(x + 1 + y + x + 1) 8664 2 + 2*x + y 8665 >>> simplify((x + 1)*(y + 1), som=True) 8666 1 + x + y + x*y 8667 >>> simplify(Distinct(x, y, 1), blast_distinct=True) 8668 And(Not(x == y), Not(x == 1), Not(y == 1)) 8669 >>> simplify(And(x == 0, y == 1), elim_and=True) 8670 Not(Or(Not(x == 0), Not(y == 1))) 8671 """ 8672 if z3_debug(): 8673 _z3_assert(is_expr(a), "Z3 expression expected") 8674 if len(arguments) > 0 or len(keywords) > 0: 8675 p = args2params(arguments, keywords, a.ctx) 8676 return _to_expr_ref(Z3_simplify_ex(a.ctx_ref(), a.as_ast(), p.params), a.ctx) 8677 else: 8678 return _to_expr_ref(Z3_simplify(a.ctx_ref(), a.as_ast()), a.ctx) 8679 8680 8681def help_simplify(): 8682 """Return a string describing all options available for Z3 `simplify` procedure.""" 8683 print(Z3_simplify_get_help(main_ctx().ref())) 8684 8685 8686def simplify_param_descrs(): 8687 """Return the set of parameter descriptions for Z3 `simplify` procedure.""" 8688 return ParamDescrsRef(Z3_simplify_get_param_descrs(main_ctx().ref()), main_ctx()) 8689 8690 8691def substitute(t, *m): 8692 """Apply substitution m on t, m is a list of pairs of the form (from, to). 8693 Every occurrence in t of from is replaced with to. 8694 8695 >>> x = Int('x') 8696 >>> y = Int('y') 8697 >>> substitute(x + 1, (x, y + 1)) 8698 y + 1 + 1 8699 >>> f = Function('f', IntSort(), IntSort()) 8700 >>> substitute(f(x) + f(y), (f(x), IntVal(1)), (f(y), IntVal(1))) 8701 1 + 1 8702 """ 8703 if isinstance(m, tuple): 8704 m1 = _get_args(m) 8705 if isinstance(m1, list) and all(isinstance(p, tuple) for p in m1): 8706 m = m1 8707 if z3_debug(): 8708 _z3_assert(is_expr(t), "Z3 expression expected") 8709 _z3_assert(all([isinstance(p, tuple) and is_expr(p[0]) and is_expr(p[1]) and p[0].sort().eq( 8710 p[1].sort()) for p in m]), "Z3 invalid substitution, expression pairs expected.") 8711 num = len(m) 8712 _from = (Ast * num)() 8713 _to = (Ast * num)() 8714 for i in range(num): 8715 _from[i] = m[i][0].as_ast() 8716 _to[i] = m[i][1].as_ast() 8717 return _to_expr_ref(Z3_substitute(t.ctx.ref(), t.as_ast(), num, _from, _to), t.ctx) 8718 8719 8720def substitute_vars(t, *m): 8721 """Substitute the free variables in t with the expression in m. 8722 8723 >>> v0 = Var(0, IntSort()) 8724 >>> v1 = Var(1, IntSort()) 8725 >>> x = Int('x') 8726 >>> f = Function('f', IntSort(), IntSort(), IntSort()) 8727 >>> # replace v0 with x+1 and v1 with x 8728 >>> substitute_vars(f(v0, v1), x + 1, x) 8729 f(x + 1, x) 8730 """ 8731 if z3_debug(): 8732 _z3_assert(is_expr(t), "Z3 expression expected") 8733 _z3_assert(all([is_expr(n) for n in m]), "Z3 invalid substitution, list of expressions expected.") 8734 num = len(m) 8735 _to = (Ast * num)() 8736 for i in range(num): 8737 _to[i] = m[i].as_ast() 8738 return _to_expr_ref(Z3_substitute_vars(t.ctx.ref(), t.as_ast(), num, _to), t.ctx) 8739 8740 8741def Sum(*args): 8742 """Create the sum of the Z3 expressions. 8743 8744 >>> a, b, c = Ints('a b c') 8745 >>> Sum(a, b, c) 8746 a + b + c 8747 >>> Sum([a, b, c]) 8748 a + b + c 8749 >>> A = IntVector('a', 5) 8750 >>> Sum(A) 8751 a__0 + a__1 + a__2 + a__3 + a__4 8752 """ 8753 args = _get_args(args) 8754 if len(args) == 0: 8755 return 0 8756 ctx = _ctx_from_ast_arg_list(args) 8757 if ctx is None: 8758 return _reduce(lambda a, b: a + b, args, 0) 8759 args = _coerce_expr_list(args, ctx) 8760 if is_bv(args[0]): 8761 return _reduce(lambda a, b: a + b, args, 0) 8762 else: 8763 _args, sz = _to_ast_array(args) 8764 return ArithRef(Z3_mk_add(ctx.ref(), sz, _args), ctx) 8765 8766 8767def Product(*args): 8768 """Create the product of the Z3 expressions. 8769 8770 >>> a, b, c = Ints('a b c') 8771 >>> Product(a, b, c) 8772 a*b*c 8773 >>> Product([a, b, c]) 8774 a*b*c 8775 >>> A = IntVector('a', 5) 8776 >>> Product(A) 8777 a__0*a__1*a__2*a__3*a__4 8778 """ 8779 args = _get_args(args) 8780 if len(args) == 0: 8781 return 1 8782 ctx = _ctx_from_ast_arg_list(args) 8783 if ctx is None: 8784 return _reduce(lambda a, b: a * b, args, 1) 8785 args = _coerce_expr_list(args, ctx) 8786 if is_bv(args[0]): 8787 return _reduce(lambda a, b: a * b, args, 1) 8788 else: 8789 _args, sz = _to_ast_array(args) 8790 return ArithRef(Z3_mk_mul(ctx.ref(), sz, _args), ctx) 8791 8792 8793def AtMost(*args): 8794 """Create an at-most Pseudo-Boolean k constraint. 8795 8796 >>> a, b, c = Bools('a b c') 8797 >>> f = AtMost(a, b, c, 2) 8798 """ 8799 args = _get_args(args) 8800 if z3_debug(): 8801 _z3_assert(len(args) > 1, "Non empty list of arguments expected") 8802 ctx = _ctx_from_ast_arg_list(args) 8803 if z3_debug(): 8804 _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression") 8805 args1 = _coerce_expr_list(args[:-1], ctx) 8806 k = args[-1] 8807 _args, sz = _to_ast_array(args1) 8808 return BoolRef(Z3_mk_atmost(ctx.ref(), sz, _args, k), ctx) 8809 8810 8811def AtLeast(*args): 8812 """Create an at-most Pseudo-Boolean k constraint. 8813 8814 >>> a, b, c = Bools('a b c') 8815 >>> f = AtLeast(a, b, c, 2) 8816 """ 8817 args = _get_args(args) 8818 if z3_debug(): 8819 _z3_assert(len(args) > 1, "Non empty list of arguments expected") 8820 ctx = _ctx_from_ast_arg_list(args) 8821 if z3_debug(): 8822 _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression") 8823 args1 = _coerce_expr_list(args[:-1], ctx) 8824 k = args[-1] 8825 _args, sz = _to_ast_array(args1) 8826 return BoolRef(Z3_mk_atleast(ctx.ref(), sz, _args, k), ctx) 8827 8828 8829def _reorder_pb_arg(arg): 8830 a, b = arg 8831 if not _is_int(b) and _is_int(a): 8832 return b, a 8833 return arg 8834 8835 8836def _pb_args_coeffs(args, default_ctx=None): 8837 args = _get_args_ast_list(args) 8838 if len(args) == 0: 8839 return _get_ctx(default_ctx), 0, (Ast * 0)(), (ctypes.c_int * 0)() 8840 args = [_reorder_pb_arg(arg) for arg in args] 8841 args, coeffs = zip(*args) 8842 if z3_debug(): 8843 _z3_assert(len(args) > 0, "Non empty list of arguments expected") 8844 ctx = _ctx_from_ast_arg_list(args) 8845 if z3_debug(): 8846 _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression") 8847 args = _coerce_expr_list(args, ctx) 8848 _args, sz = _to_ast_array(args) 8849 _coeffs = (ctypes.c_int * len(coeffs))() 8850 for i in range(len(coeffs)): 8851 _z3_check_cint_overflow(coeffs[i], "coefficient") 8852 _coeffs[i] = coeffs[i] 8853 return ctx, sz, _args, _coeffs 8854 8855 8856def PbLe(args, k): 8857 """Create a Pseudo-Boolean inequality k constraint. 8858 8859 >>> a, b, c = Bools('a b c') 8860 >>> f = PbLe(((a,1),(b,3),(c,2)), 3) 8861 """ 8862 _z3_check_cint_overflow(k, "k") 8863 ctx, sz, _args, _coeffs = _pb_args_coeffs(args) 8864 return BoolRef(Z3_mk_pble(ctx.ref(), sz, _args, _coeffs, k), ctx) 8865 8866 8867def PbGe(args, k): 8868 """Create a Pseudo-Boolean inequality k constraint. 8869 8870 >>> a, b, c = Bools('a b c') 8871 >>> f = PbGe(((a,1),(b,3),(c,2)), 3) 8872 """ 8873 _z3_check_cint_overflow(k, "k") 8874 ctx, sz, _args, _coeffs = _pb_args_coeffs(args) 8875 return BoolRef(Z3_mk_pbge(ctx.ref(), sz, _args, _coeffs, k), ctx) 8876 8877 8878def PbEq(args, k, ctx=None): 8879 """Create a Pseudo-Boolean inequality k constraint. 8880 8881 >>> a, b, c = Bools('a b c') 8882 >>> f = PbEq(((a,1),(b,3),(c,2)), 3) 8883 """ 8884 _z3_check_cint_overflow(k, "k") 8885 ctx, sz, _args, _coeffs = _pb_args_coeffs(args) 8886 return BoolRef(Z3_mk_pbeq(ctx.ref(), sz, _args, _coeffs, k), ctx) 8887 8888 8889def solve(*args, **keywords): 8890 """Solve the constraints `*args`. 8891 8892 This is a simple function for creating demonstrations. It creates a solver, 8893 configure it using the options in `keywords`, adds the constraints 8894 in `args`, and invokes check. 8895 8896 >>> a = Int('a') 8897 >>> solve(a > 0, a < 2) 8898 [a = 1] 8899 """ 8900 show = keywords.pop("show", False) 8901 s = Solver() 8902 s.set(**keywords) 8903 s.add(*args) 8904 if show: 8905 print(s) 8906 r = s.check() 8907 if r == unsat: 8908 print("no solution") 8909 elif r == unknown: 8910 print("failed to solve") 8911 try: 8912 print(s.model()) 8913 except Z3Exception: 8914 return 8915 else: 8916 print(s.model()) 8917 8918 8919def solve_using(s, *args, **keywords): 8920 """Solve the constraints `*args` using solver `s`. 8921 8922 This is a simple function for creating demonstrations. It is similar to `solve`, 8923 but it uses the given solver `s`. 8924 It configures solver `s` using the options in `keywords`, adds the constraints 8925 in `args`, and invokes check. 8926 """ 8927 show = keywords.pop("show", False) 8928 if z3_debug(): 8929 _z3_assert(isinstance(s, Solver), "Solver object expected") 8930 s.set(**keywords) 8931 s.add(*args) 8932 if show: 8933 print("Problem:") 8934 print(s) 8935 r = s.check() 8936 if r == unsat: 8937 print("no solution") 8938 elif r == unknown: 8939 print("failed to solve") 8940 try: 8941 print(s.model()) 8942 except Z3Exception: 8943 return 8944 else: 8945 if show: 8946 print("Solution:") 8947 print(s.model()) 8948 8949 8950def prove(claim, show=False, **keywords): 8951 """Try to prove the given claim. 8952 8953 This is a simple function for creating demonstrations. It tries to prove 8954 `claim` by showing the negation is unsatisfiable. 8955 8956 >>> p, q = Bools('p q') 8957 >>> prove(Not(And(p, q)) == Or(Not(p), Not(q))) 8958 proved 8959 """ 8960 if z3_debug(): 8961 _z3_assert(is_bool(claim), "Z3 Boolean expression expected") 8962 s = Solver() 8963 s.set(**keywords) 8964 s.add(Not(claim)) 8965 if show: 8966 print(s) 8967 r = s.check() 8968 if r == unsat: 8969 print("proved") 8970 elif r == unknown: 8971 print("failed to prove") 8972 print(s.model()) 8973 else: 8974 print("counterexample") 8975 print(s.model()) 8976 8977 8978def _solve_html(*args, **keywords): 8979 """Version of function `solve` used in RiSE4Fun.""" 8980 show = keywords.pop("show", False) 8981 s = Solver() 8982 s.set(**keywords) 8983 s.add(*args) 8984 if show: 8985 print("<b>Problem:</b>") 8986 print(s) 8987 r = s.check() 8988 if r == unsat: 8989 print("<b>no solution</b>") 8990 elif r == unknown: 8991 print("<b>failed to solve</b>") 8992 try: 8993 print(s.model()) 8994 except Z3Exception: 8995 return 8996 else: 8997 if show: 8998 print("<b>Solution:</b>") 8999 print(s.model()) 9000 9001 9002def _solve_using_html(s, *args, **keywords): 9003 """Version of function `solve_using` used in RiSE4Fun.""" 9004 show = keywords.pop("show", False) 9005 if z3_debug(): 9006 _z3_assert(isinstance(s, Solver), "Solver object expected") 9007 s.set(**keywords) 9008 s.add(*args) 9009 if show: 9010 print("<b>Problem:</b>") 9011 print(s) 9012 r = s.check() 9013 if r == unsat: 9014 print("<b>no solution</b>") 9015 elif r == unknown: 9016 print("<b>failed to solve</b>") 9017 try: 9018 print(s.model()) 9019 except Z3Exception: 9020 return 9021 else: 9022 if show: 9023 print("<b>Solution:</b>") 9024 print(s.model()) 9025 9026 9027def _prove_html(claim, show=False, **keywords): 9028 """Version of function `prove` used in RiSE4Fun.""" 9029 if z3_debug(): 9030 _z3_assert(is_bool(claim), "Z3 Boolean expression expected") 9031 s = Solver() 9032 s.set(**keywords) 9033 s.add(Not(claim)) 9034 if show: 9035 print(s) 9036 r = s.check() 9037 if r == unsat: 9038 print("<b>proved</b>") 9039 elif r == unknown: 9040 print("<b>failed to prove</b>") 9041 print(s.model()) 9042 else: 9043 print("<b>counterexample</b>") 9044 print(s.model()) 9045 9046 9047def _dict2sarray(sorts, ctx): 9048 sz = len(sorts) 9049 _names = (Symbol * sz)() 9050 _sorts = (Sort * sz)() 9051 i = 0 9052 for k in sorts: 9053 v = sorts[k] 9054 if z3_debug(): 9055 _z3_assert(isinstance(k, str), "String expected") 9056 _z3_assert(is_sort(v), "Z3 sort expected") 9057 _names[i] = to_symbol(k, ctx) 9058 _sorts[i] = v.ast 9059 i = i + 1 9060 return sz, _names, _sorts 9061 9062 9063def _dict2darray(decls, ctx): 9064 sz = len(decls) 9065 _names = (Symbol * sz)() 9066 _decls = (FuncDecl * sz)() 9067 i = 0 9068 for k in decls: 9069 v = decls[k] 9070 if z3_debug(): 9071 _z3_assert(isinstance(k, str), "String expected") 9072 _z3_assert(is_func_decl(v) or is_const(v), "Z3 declaration or constant expected") 9073 _names[i] = to_symbol(k, ctx) 9074 if is_const(v): 9075 _decls[i] = v.decl().ast 9076 else: 9077 _decls[i] = v.ast 9078 i = i + 1 9079 return sz, _names, _decls 9080 9081 9082def parse_smt2_string(s, sorts={}, decls={}, ctx=None): 9083 """Parse a string in SMT 2.0 format using the given sorts and decls. 9084 9085 The arguments sorts and decls are Python dictionaries used to initialize 9086 the symbol table used for the SMT 2.0 parser. 9087 9088 >>> parse_smt2_string('(declare-const x Int) (assert (> x 0)) (assert (< x 10))') 9089 [x > 0, x < 10] 9090 >>> x, y = Ints('x y') 9091 >>> f = Function('f', IntSort(), IntSort()) 9092 >>> parse_smt2_string('(assert (> (+ foo (g bar)) 0))', decls={ 'foo' : x, 'bar' : y, 'g' : f}) 9093 [x + f(y) > 0] 9094 >>> parse_smt2_string('(declare-const a U) (assert (> a 0))', sorts={ 'U' : IntSort() }) 9095 [a > 0] 9096 """ 9097 ctx = _get_ctx(ctx) 9098 ssz, snames, ssorts = _dict2sarray(sorts, ctx) 9099 dsz, dnames, ddecls = _dict2darray(decls, ctx) 9100 return AstVector(Z3_parse_smtlib2_string(ctx.ref(), s, ssz, snames, ssorts, dsz, dnames, ddecls), ctx) 9101 9102 9103def parse_smt2_file(f, sorts={}, decls={}, ctx=None): 9104 """Parse a file in SMT 2.0 format using the given sorts and decls. 9105 9106 This function is similar to parse_smt2_string(). 9107 """ 9108 ctx = _get_ctx(ctx) 9109 ssz, snames, ssorts = _dict2sarray(sorts, ctx) 9110 dsz, dnames, ddecls = _dict2darray(decls, ctx) 9111 return AstVector(Z3_parse_smtlib2_file(ctx.ref(), f, ssz, snames, ssorts, dsz, dnames, ddecls), ctx) 9112 9113 9114######################################### 9115# 9116# Floating-Point Arithmetic 9117# 9118######################################### 9119 9120 9121# Global default rounding mode 9122_dflt_rounding_mode = Z3_OP_FPA_RM_TOWARD_ZERO 9123_dflt_fpsort_ebits = 11 9124_dflt_fpsort_sbits = 53 9125 9126 9127def get_default_rounding_mode(ctx=None): 9128 """Retrieves the global default rounding mode.""" 9129 global _dflt_rounding_mode 9130 if _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_ZERO: 9131 return RTZ(ctx) 9132 elif _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_NEGATIVE: 9133 return RTN(ctx) 9134 elif _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_POSITIVE: 9135 return RTP(ctx) 9136 elif _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN: 9137 return RNE(ctx) 9138 elif _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY: 9139 return RNA(ctx) 9140 9141 9142_ROUNDING_MODES = frozenset({ 9143 Z3_OP_FPA_RM_TOWARD_ZERO, 9144 Z3_OP_FPA_RM_TOWARD_NEGATIVE, 9145 Z3_OP_FPA_RM_TOWARD_POSITIVE, 9146 Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN, 9147 Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY 9148}) 9149 9150 9151def set_default_rounding_mode(rm, ctx=None): 9152 global _dflt_rounding_mode 9153 if is_fprm_value(rm): 9154 _dflt_rounding_mode = rm.decl().kind() 9155 else: 9156 _z3_assert(_dflt_rounding_mode in _ROUNDING_MODES, "illegal rounding mode") 9157 _dflt_rounding_mode = rm 9158 9159 9160def get_default_fp_sort(ctx=None): 9161 return FPSort(_dflt_fpsort_ebits, _dflt_fpsort_sbits, ctx) 9162 9163 9164def set_default_fp_sort(ebits, sbits, ctx=None): 9165 global _dflt_fpsort_ebits 9166 global _dflt_fpsort_sbits 9167 _dflt_fpsort_ebits = ebits 9168 _dflt_fpsort_sbits = sbits 9169 9170 9171def _dflt_rm(ctx=None): 9172 return get_default_rounding_mode(ctx) 9173 9174 9175def _dflt_fps(ctx=None): 9176 return get_default_fp_sort(ctx) 9177 9178 9179def _coerce_fp_expr_list(alist, ctx): 9180 first_fp_sort = None 9181 for a in alist: 9182 if is_fp(a): 9183 if first_fp_sort is None: 9184 first_fp_sort = a.sort() 9185 elif first_fp_sort == a.sort(): 9186 pass # OK, same as before 9187 else: 9188 # we saw at least 2 different float sorts; something will 9189 # throw a sort mismatch later, for now assume None. 9190 first_fp_sort = None 9191 break 9192 9193 r = [] 9194 for i in range(len(alist)): 9195 a = alist[i] 9196 is_repr = isinstance(a, str) and a.contains("2**(") and a.endswith(")") 9197 if is_repr or _is_int(a) or isinstance(a, (float, bool)): 9198 r.append(FPVal(a, None, first_fp_sort, ctx)) 9199 else: 9200 r.append(a) 9201 return _coerce_expr_list(r, ctx) 9202 9203 9204# FP Sorts 9205 9206class FPSortRef(SortRef): 9207 """Floating-point sort.""" 9208 9209 def ebits(self): 9210 """Retrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`. 9211 >>> b = FPSort(8, 24) 9212 >>> b.ebits() 9213 8 9214 """ 9215 return int(Z3_fpa_get_ebits(self.ctx_ref(), self.ast)) 9216 9217 def sbits(self): 9218 """Retrieves the number of bits reserved for the significand in the FloatingPoint sort `self`. 9219 >>> b = FPSort(8, 24) 9220 >>> b.sbits() 9221 24 9222 """ 9223 return int(Z3_fpa_get_sbits(self.ctx_ref(), self.ast)) 9224 9225 def cast(self, val): 9226 """Try to cast `val` as a floating-point expression. 9227 >>> b = FPSort(8, 24) 9228 >>> b.cast(1.0) 9229 1 9230 >>> b.cast(1.0).sexpr() 9231 '(fp #b0 #x7f #b00000000000000000000000)' 9232 """ 9233 if is_expr(val): 9234 if z3_debug(): 9235 _z3_assert(self.ctx == val.ctx, "Context mismatch") 9236 return val 9237 else: 9238 return FPVal(val, None, self, self.ctx) 9239 9240 9241def Float16(ctx=None): 9242 """Floating-point 16-bit (half) sort.""" 9243 ctx = _get_ctx(ctx) 9244 return FPSortRef(Z3_mk_fpa_sort_16(ctx.ref()), ctx) 9245 9246 9247def FloatHalf(ctx=None): 9248 """Floating-point 16-bit (half) sort.""" 9249 ctx = _get_ctx(ctx) 9250 return FPSortRef(Z3_mk_fpa_sort_half(ctx.ref()), ctx) 9251 9252 9253def Float32(ctx=None): 9254 """Floating-point 32-bit (single) sort.""" 9255 ctx = _get_ctx(ctx) 9256 return FPSortRef(Z3_mk_fpa_sort_32(ctx.ref()), ctx) 9257 9258 9259def FloatSingle(ctx=None): 9260 """Floating-point 32-bit (single) sort.""" 9261 ctx = _get_ctx(ctx) 9262 return FPSortRef(Z3_mk_fpa_sort_single(ctx.ref()), ctx) 9263 9264 9265def Float64(ctx=None): 9266 """Floating-point 64-bit (double) sort.""" 9267 ctx = _get_ctx(ctx) 9268 return FPSortRef(Z3_mk_fpa_sort_64(ctx.ref()), ctx) 9269 9270 9271def FloatDouble(ctx=None): 9272 """Floating-point 64-bit (double) sort.""" 9273 ctx = _get_ctx(ctx) 9274 return FPSortRef(Z3_mk_fpa_sort_double(ctx.ref()), ctx) 9275 9276 9277def Float128(ctx=None): 9278 """Floating-point 128-bit (quadruple) sort.""" 9279 ctx = _get_ctx(ctx) 9280 return FPSortRef(Z3_mk_fpa_sort_128(ctx.ref()), ctx) 9281 9282 9283def FloatQuadruple(ctx=None): 9284 """Floating-point 128-bit (quadruple) sort.""" 9285 ctx = _get_ctx(ctx) 9286 return FPSortRef(Z3_mk_fpa_sort_quadruple(ctx.ref()), ctx) 9287 9288 9289class FPRMSortRef(SortRef): 9290 """"Floating-point rounding mode sort.""" 9291 9292 9293def is_fp_sort(s): 9294 """Return True if `s` is a Z3 floating-point sort. 9295 9296 >>> is_fp_sort(FPSort(8, 24)) 9297 True 9298 >>> is_fp_sort(IntSort()) 9299 False 9300 """ 9301 return isinstance(s, FPSortRef) 9302 9303 9304def is_fprm_sort(s): 9305 """Return True if `s` is a Z3 floating-point rounding mode sort. 9306 9307 >>> is_fprm_sort(FPSort(8, 24)) 9308 False 9309 >>> is_fprm_sort(RNE().sort()) 9310 True 9311 """ 9312 return isinstance(s, FPRMSortRef) 9313 9314# FP Expressions 9315 9316 9317class FPRef(ExprRef): 9318 """Floating-point expressions.""" 9319 9320 def sort(self): 9321 """Return the sort of the floating-point expression `self`. 9322 9323 >>> x = FP('1.0', FPSort(8, 24)) 9324 >>> x.sort() 9325 FPSort(8, 24) 9326 >>> x.sort() == FPSort(8, 24) 9327 True 9328 """ 9329 return FPSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) 9330 9331 def ebits(self): 9332 """Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`. 9333 >>> b = FPSort(8, 24) 9334 >>> b.ebits() 9335 8 9336 """ 9337 return self.sort().ebits() 9338 9339 def sbits(self): 9340 """Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`. 9341 >>> b = FPSort(8, 24) 9342 >>> b.sbits() 9343 24 9344 """ 9345 return self.sort().sbits() 9346 9347 def as_string(self): 9348 """Return a Z3 floating point expression as a Python string.""" 9349 return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) 9350 9351 def __le__(self, other): 9352 return fpLEQ(self, other, self.ctx) 9353 9354 def __lt__(self, other): 9355 return fpLT(self, other, self.ctx) 9356 9357 def __ge__(self, other): 9358 return fpGEQ(self, other, self.ctx) 9359 9360 def __gt__(self, other): 9361 return fpGT(self, other, self.ctx) 9362 9363 def __add__(self, other): 9364 """Create the Z3 expression `self + other`. 9365 9366 >>> x = FP('x', FPSort(8, 24)) 9367 >>> y = FP('y', FPSort(8, 24)) 9368 >>> x + y 9369 x + y 9370 >>> (x + y).sort() 9371 FPSort(8, 24) 9372 """ 9373 [a, b] = _coerce_fp_expr_list([self, other], self.ctx) 9374 return fpAdd(_dflt_rm(), a, b, self.ctx) 9375 9376 def __radd__(self, other): 9377 """Create the Z3 expression `other + self`. 9378 9379 >>> x = FP('x', FPSort(8, 24)) 9380 >>> 10 + x 9381 1.25*(2**3) + x 9382 """ 9383 [a, b] = _coerce_fp_expr_list([other, self], self.ctx) 9384 return fpAdd(_dflt_rm(), a, b, self.ctx) 9385 9386 def __sub__(self, other): 9387 """Create the Z3 expression `self - other`. 9388 9389 >>> x = FP('x', FPSort(8, 24)) 9390 >>> y = FP('y', FPSort(8, 24)) 9391 >>> x - y 9392 x - y 9393 >>> (x - y).sort() 9394 FPSort(8, 24) 9395 """ 9396 [a, b] = _coerce_fp_expr_list([self, other], self.ctx) 9397 return fpSub(_dflt_rm(), a, b, self.ctx) 9398 9399 def __rsub__(self, other): 9400 """Create the Z3 expression `other - self`. 9401 9402 >>> x = FP('x', FPSort(8, 24)) 9403 >>> 10 - x 9404 1.25*(2**3) - x 9405 """ 9406 [a, b] = _coerce_fp_expr_list([other, self], self.ctx) 9407 return fpSub(_dflt_rm(), a, b, self.ctx) 9408 9409 def __mul__(self, other): 9410 """Create the Z3 expression `self * other`. 9411 9412 >>> x = FP('x', FPSort(8, 24)) 9413 >>> y = FP('y', FPSort(8, 24)) 9414 >>> x * y 9415 x * y 9416 >>> (x * y).sort() 9417 FPSort(8, 24) 9418 >>> 10 * y 9419 1.25*(2**3) * y 9420 """ 9421 [a, b] = _coerce_fp_expr_list([self, other], self.ctx) 9422 return fpMul(_dflt_rm(), a, b, self.ctx) 9423 9424 def __rmul__(self, other): 9425 """Create the Z3 expression `other * self`. 9426 9427 >>> x = FP('x', FPSort(8, 24)) 9428 >>> y = FP('y', FPSort(8, 24)) 9429 >>> x * y 9430 x * y 9431 >>> x * 10 9432 x * 1.25*(2**3) 9433 """ 9434 [a, b] = _coerce_fp_expr_list([other, self], self.ctx) 9435 return fpMul(_dflt_rm(), a, b, self.ctx) 9436 9437 def __pos__(self): 9438 """Create the Z3 expression `+self`.""" 9439 return self 9440 9441 def __neg__(self): 9442 """Create the Z3 expression `-self`. 9443 9444 >>> x = FP('x', Float32()) 9445 >>> -x 9446 -x 9447 """ 9448 return fpNeg(self) 9449 9450 def __div__(self, other): 9451 """Create the Z3 expression `self / other`. 9452 9453 >>> x = FP('x', FPSort(8, 24)) 9454 >>> y = FP('y', FPSort(8, 24)) 9455 >>> x / y 9456 x / y 9457 >>> (x / y).sort() 9458 FPSort(8, 24) 9459 >>> 10 / y 9460 1.25*(2**3) / y 9461 """ 9462 [a, b] = _coerce_fp_expr_list([self, other], self.ctx) 9463 return fpDiv(_dflt_rm(), a, b, self.ctx) 9464 9465 def __rdiv__(self, other): 9466 """Create the Z3 expression `other / self`. 9467 9468 >>> x = FP('x', FPSort(8, 24)) 9469 >>> y = FP('y', FPSort(8, 24)) 9470 >>> x / y 9471 x / y 9472 >>> x / 10 9473 x / 1.25*(2**3) 9474 """ 9475 [a, b] = _coerce_fp_expr_list([other, self], self.ctx) 9476 return fpDiv(_dflt_rm(), a, b, self.ctx) 9477 9478 def __truediv__(self, other): 9479 """Create the Z3 expression division `self / other`.""" 9480 return self.__div__(other) 9481 9482 def __rtruediv__(self, other): 9483 """Create the Z3 expression division `other / self`.""" 9484 return self.__rdiv__(other) 9485 9486 def __mod__(self, other): 9487 """Create the Z3 expression mod `self % other`.""" 9488 return fpRem(self, other) 9489 9490 def __rmod__(self, other): 9491 """Create the Z3 expression mod `other % self`.""" 9492 return fpRem(other, self) 9493 9494 9495class FPRMRef(ExprRef): 9496 """Floating-point rounding mode expressions""" 9497 9498 def as_string(self): 9499 """Return a Z3 floating point expression as a Python string.""" 9500 return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) 9501 9502 9503def RoundNearestTiesToEven(ctx=None): 9504 ctx = _get_ctx(ctx) 9505 return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx) 9506 9507 9508def RNE(ctx=None): 9509 ctx = _get_ctx(ctx) 9510 return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx) 9511 9512 9513def RoundNearestTiesToAway(ctx=None): 9514 ctx = _get_ctx(ctx) 9515 return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx) 9516 9517 9518def RNA(ctx=None): 9519 ctx = _get_ctx(ctx) 9520 return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx) 9521 9522 9523def RoundTowardPositive(ctx=None): 9524 ctx = _get_ctx(ctx) 9525 return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx) 9526 9527 9528def RTP(ctx=None): 9529 ctx = _get_ctx(ctx) 9530 return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx) 9531 9532 9533def RoundTowardNegative(ctx=None): 9534 ctx = _get_ctx(ctx) 9535 return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx) 9536 9537 9538def RTN(ctx=None): 9539 ctx = _get_ctx(ctx) 9540 return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx) 9541 9542 9543def RoundTowardZero(ctx=None): 9544 ctx = _get_ctx(ctx) 9545 return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx) 9546 9547 9548def RTZ(ctx=None): 9549 ctx = _get_ctx(ctx) 9550 return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx) 9551 9552 9553def is_fprm(a): 9554 """Return `True` if `a` is a Z3 floating-point rounding mode expression. 9555 9556 >>> rm = RNE() 9557 >>> is_fprm(rm) 9558 True 9559 >>> rm = 1.0 9560 >>> is_fprm(rm) 9561 False 9562 """ 9563 return isinstance(a, FPRMRef) 9564 9565 9566def is_fprm_value(a): 9567 """Return `True` if `a` is a Z3 floating-point rounding mode numeral value.""" 9568 return is_fprm(a) and _is_numeral(a.ctx, a.ast) 9569 9570# FP Numerals 9571 9572 9573class FPNumRef(FPRef): 9574 """The sign of the numeral. 9575 9576 >>> x = FPVal(+1.0, FPSort(8, 24)) 9577 >>> x.sign() 9578 False 9579 >>> x = FPVal(-1.0, FPSort(8, 24)) 9580 >>> x.sign() 9581 True 9582 """ 9583 9584 def sign(self): 9585 num = (ctypes.c_int)() 9586 nsign = Z3_fpa_get_numeral_sign(self.ctx.ref(), self.as_ast(), byref(num)) 9587 if nsign is False: 9588 raise Z3Exception("error retrieving the sign of a numeral.") 9589 return num.value != 0 9590 9591 """The sign of a floating-point numeral as a bit-vector expression. 9592 9593 Remark: NaN's are invalid arguments. 9594 """ 9595 9596 def sign_as_bv(self): 9597 return BitVecNumRef(Z3_fpa_get_numeral_sign_bv(self.ctx.ref(), self.as_ast()), self.ctx) 9598 9599 """The significand of the numeral. 9600 9601 >>> x = FPVal(2.5, FPSort(8, 24)) 9602 >>> x.significand() 9603 1.25 9604 """ 9605 9606 def significand(self): 9607 return Z3_fpa_get_numeral_significand_string(self.ctx.ref(), self.as_ast()) 9608 9609 """The significand of the numeral as a long. 9610 9611 >>> x = FPVal(2.5, FPSort(8, 24)) 9612 >>> x.significand_as_long() 9613 1.25 9614 """ 9615 9616 def significand_as_long(self): 9617 ptr = (ctypes.c_ulonglong * 1)() 9618 if not Z3_fpa_get_numeral_significand_uint64(self.ctx.ref(), self.as_ast(), ptr): 9619 raise Z3Exception("error retrieving the significand of a numeral.") 9620 return ptr[0] 9621 9622 """The significand of the numeral as a bit-vector expression. 9623 9624 Remark: NaN are invalid arguments. 9625 """ 9626 9627 def significand_as_bv(self): 9628 return BitVecNumRef(Z3_fpa_get_numeral_significand_bv(self.ctx.ref(), self.as_ast()), self.ctx) 9629 9630 """The exponent of the numeral. 9631 9632 >>> x = FPVal(2.5, FPSort(8, 24)) 9633 >>> x.exponent() 9634 1 9635 """ 9636 9637 def exponent(self, biased=True): 9638 return Z3_fpa_get_numeral_exponent_string(self.ctx.ref(), self.as_ast(), biased) 9639 9640 """The exponent of the numeral as a long. 9641 9642 >>> x = FPVal(2.5, FPSort(8, 24)) 9643 >>> x.exponent_as_long() 9644 1 9645 """ 9646 9647 def exponent_as_long(self, biased=True): 9648 ptr = (ctypes.c_longlong * 1)() 9649 if not Z3_fpa_get_numeral_exponent_int64(self.ctx.ref(), self.as_ast(), ptr, biased): 9650 raise Z3Exception("error retrieving the exponent of a numeral.") 9651 return ptr[0] 9652 9653 """The exponent of the numeral as a bit-vector expression. 9654 9655 Remark: NaNs are invalid arguments. 9656 """ 9657 9658 def exponent_as_bv(self, biased=True): 9659 return BitVecNumRef(Z3_fpa_get_numeral_exponent_bv(self.ctx.ref(), self.as_ast(), biased), self.ctx) 9660 9661 """Indicates whether the numeral is a NaN.""" 9662 9663 def isNaN(self): 9664 return Z3_fpa_is_numeral_nan(self.ctx.ref(), self.as_ast()) 9665 9666 """Indicates whether the numeral is +oo or -oo.""" 9667 9668 def isInf(self): 9669 return Z3_fpa_is_numeral_inf(self.ctx.ref(), self.as_ast()) 9670 9671 """Indicates whether the numeral is +zero or -zero.""" 9672 9673 def isZero(self): 9674 return Z3_fpa_is_numeral_zero(self.ctx.ref(), self.as_ast()) 9675 9676 """Indicates whether the numeral is normal.""" 9677 9678 def isNormal(self): 9679 return Z3_fpa_is_numeral_normal(self.ctx.ref(), self.as_ast()) 9680 9681 """Indicates whether the numeral is subnormal.""" 9682 9683 def isSubnormal(self): 9684 return Z3_fpa_is_numeral_subnormal(self.ctx.ref(), self.as_ast()) 9685 9686 """Indicates whether the numeral is positive.""" 9687 9688 def isPositive(self): 9689 return Z3_fpa_is_numeral_positive(self.ctx.ref(), self.as_ast()) 9690 9691 """Indicates whether the numeral is negative.""" 9692 9693 def isNegative(self): 9694 return Z3_fpa_is_numeral_negative(self.ctx.ref(), self.as_ast()) 9695 9696 """ 9697 The string representation of the numeral. 9698 9699 >>> x = FPVal(20, FPSort(8, 24)) 9700 >>> x.as_string() 9701 1.25*(2**4) 9702 """ 9703 9704 def as_string(self): 9705 s = Z3_get_numeral_string(self.ctx.ref(), self.as_ast()) 9706 return ("FPVal(%s, %s)" % (s, self.sort())) 9707 9708 9709def is_fp(a): 9710 """Return `True` if `a` is a Z3 floating-point expression. 9711 9712 >>> b = FP('b', FPSort(8, 24)) 9713 >>> is_fp(b) 9714 True 9715 >>> is_fp(b + 1.0) 9716 True 9717 >>> is_fp(Int('x')) 9718 False 9719 """ 9720 return isinstance(a, FPRef) 9721 9722 9723def is_fp_value(a): 9724 """Return `True` if `a` is a Z3 floating-point numeral value. 9725 9726 >>> b = FP('b', FPSort(8, 24)) 9727 >>> is_fp_value(b) 9728 False 9729 >>> b = FPVal(1.0, FPSort(8, 24)) 9730 >>> b 9731 1 9732 >>> is_fp_value(b) 9733 True 9734 """ 9735 return is_fp(a) and _is_numeral(a.ctx, a.ast) 9736 9737 9738def FPSort(ebits, sbits, ctx=None): 9739 """Return a Z3 floating-point sort of the given sizes. If `ctx=None`, then the global context is used. 9740 9741 >>> Single = FPSort(8, 24) 9742 >>> Double = FPSort(11, 53) 9743 >>> Single 9744 FPSort(8, 24) 9745 >>> x = Const('x', Single) 9746 >>> eq(x, FP('x', FPSort(8, 24))) 9747 True 9748 """ 9749 ctx = _get_ctx(ctx) 9750 return FPSortRef(Z3_mk_fpa_sort(ctx.ref(), ebits, sbits), ctx) 9751 9752 9753def _to_float_str(val, exp=0): 9754 if isinstance(val, float): 9755 if math.isnan(val): 9756 res = "NaN" 9757 elif val == 0.0: 9758 sone = math.copysign(1.0, val) 9759 if sone < 0.0: 9760 return "-0.0" 9761 else: 9762 return "+0.0" 9763 elif val == float("+inf"): 9764 res = "+oo" 9765 elif val == float("-inf"): 9766 res = "-oo" 9767 else: 9768 v = val.as_integer_ratio() 9769 num = v[0] 9770 den = v[1] 9771 rvs = str(num) + "/" + str(den) 9772 res = rvs + "p" + _to_int_str(exp) 9773 elif isinstance(val, bool): 9774 if val: 9775 res = "1.0" 9776 else: 9777 res = "0.0" 9778 elif _is_int(val): 9779 res = str(val) 9780 elif isinstance(val, str): 9781 inx = val.find("*(2**") 9782 if inx == -1: 9783 res = val 9784 elif val[-1] == ")": 9785 res = val[0:inx] 9786 exp = str(int(val[inx + 5:-1]) + int(exp)) 9787 else: 9788 _z3_assert(False, "String does not have floating-point numeral form.") 9789 elif z3_debug(): 9790 _z3_assert(False, "Python value cannot be used to create floating-point numerals.") 9791 if exp == 0: 9792 return res 9793 else: 9794 return res + "p" + exp 9795 9796 9797def fpNaN(s): 9798 """Create a Z3 floating-point NaN term. 9799 9800 >>> s = FPSort(8, 24) 9801 >>> set_fpa_pretty(True) 9802 >>> fpNaN(s) 9803 NaN 9804 >>> pb = get_fpa_pretty() 9805 >>> set_fpa_pretty(False) 9806 >>> fpNaN(s) 9807 fpNaN(FPSort(8, 24)) 9808 >>> set_fpa_pretty(pb) 9809 """ 9810 _z3_assert(isinstance(s, FPSortRef), "sort mismatch") 9811 return FPNumRef(Z3_mk_fpa_nan(s.ctx_ref(), s.ast), s.ctx) 9812 9813 9814def fpPlusInfinity(s): 9815 """Create a Z3 floating-point +oo term. 9816 9817 >>> s = FPSort(8, 24) 9818 >>> pb = get_fpa_pretty() 9819 >>> set_fpa_pretty(True) 9820 >>> fpPlusInfinity(s) 9821 +oo 9822 >>> set_fpa_pretty(False) 9823 >>> fpPlusInfinity(s) 9824 fpPlusInfinity(FPSort(8, 24)) 9825 >>> set_fpa_pretty(pb) 9826 """ 9827 _z3_assert(isinstance(s, FPSortRef), "sort mismatch") 9828 return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, False), s.ctx) 9829 9830 9831def fpMinusInfinity(s): 9832 """Create a Z3 floating-point -oo term.""" 9833 _z3_assert(isinstance(s, FPSortRef), "sort mismatch") 9834 return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, True), s.ctx) 9835 9836 9837def fpInfinity(s, negative): 9838 """Create a Z3 floating-point +oo or -oo term.""" 9839 _z3_assert(isinstance(s, FPSortRef), "sort mismatch") 9840 _z3_assert(isinstance(negative, bool), "expected Boolean flag") 9841 return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, negative), s.ctx) 9842 9843 9844def fpPlusZero(s): 9845 """Create a Z3 floating-point +0.0 term.""" 9846 _z3_assert(isinstance(s, FPSortRef), "sort mismatch") 9847 return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, False), s.ctx) 9848 9849 9850def fpMinusZero(s): 9851 """Create a Z3 floating-point -0.0 term.""" 9852 _z3_assert(isinstance(s, FPSortRef), "sort mismatch") 9853 return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, True), s.ctx) 9854 9855 9856def fpZero(s, negative): 9857 """Create a Z3 floating-point +0.0 or -0.0 term.""" 9858 _z3_assert(isinstance(s, FPSortRef), "sort mismatch") 9859 _z3_assert(isinstance(negative, bool), "expected Boolean flag") 9860 return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, negative), s.ctx) 9861 9862 9863def FPVal(sig, exp=None, fps=None, ctx=None): 9864 """Return a floating-point value of value `val` and sort `fps`. 9865 If `ctx=None`, then the global context is used. 9866 9867 >>> v = FPVal(20.0, FPSort(8, 24)) 9868 >>> v 9869 1.25*(2**4) 9870 >>> print("0x%.8x" % v.exponent_as_long(False)) 9871 0x00000004 9872 >>> v = FPVal(2.25, FPSort(8, 24)) 9873 >>> v 9874 1.125*(2**1) 9875 >>> v = FPVal(-2.25, FPSort(8, 24)) 9876 >>> v 9877 -1.125*(2**1) 9878 >>> FPVal(-0.0, FPSort(8, 24)) 9879 -0.0 9880 >>> FPVal(0.0, FPSort(8, 24)) 9881 +0.0 9882 >>> FPVal(+0.0, FPSort(8, 24)) 9883 +0.0 9884 """ 9885 ctx = _get_ctx(ctx) 9886 if is_fp_sort(exp): 9887 fps = exp 9888 exp = None 9889 elif fps is None: 9890 fps = _dflt_fps(ctx) 9891 _z3_assert(is_fp_sort(fps), "sort mismatch") 9892 if exp is None: 9893 exp = 0 9894 val = _to_float_str(sig) 9895 if val == "NaN" or val == "nan": 9896 return fpNaN(fps) 9897 elif val == "-0.0": 9898 return fpMinusZero(fps) 9899 elif val == "0.0" or val == "+0.0": 9900 return fpPlusZero(fps) 9901 elif val == "+oo" or val == "+inf" or val == "+Inf": 9902 return fpPlusInfinity(fps) 9903 elif val == "-oo" or val == "-inf" or val == "-Inf": 9904 return fpMinusInfinity(fps) 9905 else: 9906 return FPNumRef(Z3_mk_numeral(ctx.ref(), val, fps.ast), ctx) 9907 9908 9909def FP(name, fpsort, ctx=None): 9910 """Return a floating-point constant named `name`. 9911 `fpsort` is the floating-point sort. 9912 If `ctx=None`, then the global context is used. 9913 9914 >>> x = FP('x', FPSort(8, 24)) 9915 >>> is_fp(x) 9916 True 9917 >>> x.ebits() 9918 8 9919 >>> x.sort() 9920 FPSort(8, 24) 9921 >>> word = FPSort(8, 24) 9922 >>> x2 = FP('x', word) 9923 >>> eq(x, x2) 9924 True 9925 """ 9926 if isinstance(fpsort, FPSortRef) and ctx is None: 9927 ctx = fpsort.ctx 9928 else: 9929 ctx = _get_ctx(ctx) 9930 return FPRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), fpsort.ast), ctx) 9931 9932 9933def FPs(names, fpsort, ctx=None): 9934 """Return an array of floating-point constants. 9935 9936 >>> x, y, z = FPs('x y z', FPSort(8, 24)) 9937 >>> x.sort() 9938 FPSort(8, 24) 9939 >>> x.sbits() 9940 24 9941 >>> x.ebits() 9942 8 9943 >>> fpMul(RNE(), fpAdd(RNE(), x, y), z) 9944 fpMul(RNE(), fpAdd(RNE(), x, y), z) 9945 """ 9946 ctx = _get_ctx(ctx) 9947 if isinstance(names, str): 9948 names = names.split(" ") 9949 return [FP(name, fpsort, ctx) for name in names] 9950 9951 9952def fpAbs(a, ctx=None): 9953 """Create a Z3 floating-point absolute value expression. 9954 9955 >>> s = FPSort(8, 24) 9956 >>> rm = RNE() 9957 >>> x = FPVal(1.0, s) 9958 >>> fpAbs(x) 9959 fpAbs(1) 9960 >>> y = FPVal(-20.0, s) 9961 >>> y 9962 -1.25*(2**4) 9963 >>> fpAbs(y) 9964 fpAbs(-1.25*(2**4)) 9965 >>> fpAbs(-1.25*(2**4)) 9966 fpAbs(-1.25*(2**4)) 9967 >>> fpAbs(x).sort() 9968 FPSort(8, 24) 9969 """ 9970 ctx = _get_ctx(ctx) 9971 [a] = _coerce_fp_expr_list([a], ctx) 9972 return FPRef(Z3_mk_fpa_abs(ctx.ref(), a.as_ast()), ctx) 9973 9974 9975def fpNeg(a, ctx=None): 9976 """Create a Z3 floating-point addition expression. 9977 9978 >>> s = FPSort(8, 24) 9979 >>> rm = RNE() 9980 >>> x = FP('x', s) 9981 >>> fpNeg(x) 9982 -x 9983 >>> fpNeg(x).sort() 9984 FPSort(8, 24) 9985 """ 9986 ctx = _get_ctx(ctx) 9987 [a] = _coerce_fp_expr_list([a], ctx) 9988 return FPRef(Z3_mk_fpa_neg(ctx.ref(), a.as_ast()), ctx) 9989 9990 9991def _mk_fp_unary(f, rm, a, ctx): 9992 ctx = _get_ctx(ctx) 9993 [a] = _coerce_fp_expr_list([a], ctx) 9994 if z3_debug(): 9995 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") 9996 _z3_assert(is_fp(a), "Second argument must be a Z3 floating-point expression") 9997 return FPRef(f(ctx.ref(), rm.as_ast(), a.as_ast()), ctx) 9998 9999 10000def _mk_fp_unary_pred(f, a, ctx): 10001 ctx = _get_ctx(ctx) 10002 [a] = _coerce_fp_expr_list([a], ctx) 10003 if z3_debug(): 10004 _z3_assert(is_fp(a), "First argument must be a Z3 floating-point expression") 10005 return BoolRef(f(ctx.ref(), a.as_ast()), ctx) 10006 10007 10008def _mk_fp_bin(f, rm, a, b, ctx): 10009 ctx = _get_ctx(ctx) 10010 [a, b] = _coerce_fp_expr_list([a, b], ctx) 10011 if z3_debug(): 10012 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") 10013 _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression") 10014 return FPRef(f(ctx.ref(), rm.as_ast(), a.as_ast(), b.as_ast()), ctx) 10015 10016 10017def _mk_fp_bin_norm(f, a, b, ctx): 10018 ctx = _get_ctx(ctx) 10019 [a, b] = _coerce_fp_expr_list([a, b], ctx) 10020 if z3_debug(): 10021 _z3_assert(is_fp(a) or is_fp(b), "First or second argument must be a Z3 floating-point expression") 10022 return FPRef(f(ctx.ref(), a.as_ast(), b.as_ast()), ctx) 10023 10024 10025def _mk_fp_bin_pred(f, a, b, ctx): 10026 ctx = _get_ctx(ctx) 10027 [a, b] = _coerce_fp_expr_list([a, b], ctx) 10028 if z3_debug(): 10029 _z3_assert(is_fp(a) or is_fp(b), "First or second argument must be a Z3 floating-point expression") 10030 return BoolRef(f(ctx.ref(), a.as_ast(), b.as_ast()), ctx) 10031 10032 10033def _mk_fp_tern(f, rm, a, b, c, ctx): 10034 ctx = _get_ctx(ctx) 10035 [a, b, c] = _coerce_fp_expr_list([a, b, c], ctx) 10036 if z3_debug(): 10037 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") 10038 _z3_assert(is_fp(a) or is_fp(b) or is_fp( 10039 c), "Second, third or fourth argument must be a Z3 floating-point expression") 10040 return FPRef(f(ctx.ref(), rm.as_ast(), a.as_ast(), b.as_ast(), c.as_ast()), ctx) 10041 10042 10043def fpAdd(rm, a, b, ctx=None): 10044 """Create a Z3 floating-point addition expression. 10045 10046 >>> s = FPSort(8, 24) 10047 >>> rm = RNE() 10048 >>> x = FP('x', s) 10049 >>> y = FP('y', s) 10050 >>> fpAdd(rm, x, y) 10051 fpAdd(RNE(), x, y) 10052 >>> fpAdd(RTZ(), x, y) # default rounding mode is RTZ 10053 x + y 10054 >>> fpAdd(rm, x, y).sort() 10055 FPSort(8, 24) 10056 """ 10057 return _mk_fp_bin(Z3_mk_fpa_add, rm, a, b, ctx) 10058 10059 10060def fpSub(rm, a, b, ctx=None): 10061 """Create a Z3 floating-point subtraction expression. 10062 10063 >>> s = FPSort(8, 24) 10064 >>> rm = RNE() 10065 >>> x = FP('x', s) 10066 >>> y = FP('y', s) 10067 >>> fpSub(rm, x, y) 10068 fpSub(RNE(), x, y) 10069 >>> fpSub(rm, x, y).sort() 10070 FPSort(8, 24) 10071 """ 10072 return _mk_fp_bin(Z3_mk_fpa_sub, rm, a, b, ctx) 10073 10074 10075def fpMul(rm, a, b, ctx=None): 10076 """Create a Z3 floating-point multiplication expression. 10077 10078 >>> s = FPSort(8, 24) 10079 >>> rm = RNE() 10080 >>> x = FP('x', s) 10081 >>> y = FP('y', s) 10082 >>> fpMul(rm, x, y) 10083 fpMul(RNE(), x, y) 10084 >>> fpMul(rm, x, y).sort() 10085 FPSort(8, 24) 10086 """ 10087 return _mk_fp_bin(Z3_mk_fpa_mul, rm, a, b, ctx) 10088 10089 10090def fpDiv(rm, a, b, ctx=None): 10091 """Create a Z3 floating-point division expression. 10092 10093 >>> s = FPSort(8, 24) 10094 >>> rm = RNE() 10095 >>> x = FP('x', s) 10096 >>> y = FP('y', s) 10097 >>> fpDiv(rm, x, y) 10098 fpDiv(RNE(), x, y) 10099 >>> fpDiv(rm, x, y).sort() 10100 FPSort(8, 24) 10101 """ 10102 return _mk_fp_bin(Z3_mk_fpa_div, rm, a, b, ctx) 10103 10104 10105def fpRem(a, b, ctx=None): 10106 """Create a Z3 floating-point remainder expression. 10107 10108 >>> s = FPSort(8, 24) 10109 >>> x = FP('x', s) 10110 >>> y = FP('y', s) 10111 >>> fpRem(x, y) 10112 fpRem(x, y) 10113 >>> fpRem(x, y).sort() 10114 FPSort(8, 24) 10115 """ 10116 return _mk_fp_bin_norm(Z3_mk_fpa_rem, a, b, ctx) 10117 10118 10119def fpMin(a, b, ctx=None): 10120 """Create a Z3 floating-point minimum expression. 10121 10122 >>> s = FPSort(8, 24) 10123 >>> rm = RNE() 10124 >>> x = FP('x', s) 10125 >>> y = FP('y', s) 10126 >>> fpMin(x, y) 10127 fpMin(x, y) 10128 >>> fpMin(x, y).sort() 10129 FPSort(8, 24) 10130 """ 10131 return _mk_fp_bin_norm(Z3_mk_fpa_min, a, b, ctx) 10132 10133 10134def fpMax(a, b, ctx=None): 10135 """Create a Z3 floating-point maximum expression. 10136 10137 >>> s = FPSort(8, 24) 10138 >>> rm = RNE() 10139 >>> x = FP('x', s) 10140 >>> y = FP('y', s) 10141 >>> fpMax(x, y) 10142 fpMax(x, y) 10143 >>> fpMax(x, y).sort() 10144 FPSort(8, 24) 10145 """ 10146 return _mk_fp_bin_norm(Z3_mk_fpa_max, a, b, ctx) 10147 10148 10149def fpFMA(rm, a, b, c, ctx=None): 10150 """Create a Z3 floating-point fused multiply-add expression. 10151 """ 10152 return _mk_fp_tern(Z3_mk_fpa_fma, rm, a, b, c, ctx) 10153 10154 10155def fpSqrt(rm, a, ctx=None): 10156 """Create a Z3 floating-point square root expression. 10157 """ 10158 return _mk_fp_unary(Z3_mk_fpa_sqrt, rm, a, ctx) 10159 10160 10161def fpRoundToIntegral(rm, a, ctx=None): 10162 """Create a Z3 floating-point roundToIntegral expression. 10163 """ 10164 return _mk_fp_unary(Z3_mk_fpa_round_to_integral, rm, a, ctx) 10165 10166 10167def fpIsNaN(a, ctx=None): 10168 """Create a Z3 floating-point isNaN expression. 10169 10170 >>> s = FPSort(8, 24) 10171 >>> x = FP('x', s) 10172 >>> y = FP('y', s) 10173 >>> fpIsNaN(x) 10174 fpIsNaN(x) 10175 """ 10176 return _mk_fp_unary_pred(Z3_mk_fpa_is_nan, a, ctx) 10177 10178 10179def fpIsInf(a, ctx=None): 10180 """Create a Z3 floating-point isInfinite expression. 10181 10182 >>> s = FPSort(8, 24) 10183 >>> x = FP('x', s) 10184 >>> fpIsInf(x) 10185 fpIsInf(x) 10186 """ 10187 return _mk_fp_unary_pred(Z3_mk_fpa_is_infinite, a, ctx) 10188 10189 10190def fpIsZero(a, ctx=None): 10191 """Create a Z3 floating-point isZero expression. 10192 """ 10193 return _mk_fp_unary_pred(Z3_mk_fpa_is_zero, a, ctx) 10194 10195 10196def fpIsNormal(a, ctx=None): 10197 """Create a Z3 floating-point isNormal expression. 10198 """ 10199 return _mk_fp_unary_pred(Z3_mk_fpa_is_normal, a, ctx) 10200 10201 10202def fpIsSubnormal(a, ctx=None): 10203 """Create a Z3 floating-point isSubnormal expression. 10204 """ 10205 return _mk_fp_unary_pred(Z3_mk_fpa_is_subnormal, a, ctx) 10206 10207 10208def fpIsNegative(a, ctx=None): 10209 """Create a Z3 floating-point isNegative expression. 10210 """ 10211 return _mk_fp_unary_pred(Z3_mk_fpa_is_negative, a, ctx) 10212 10213 10214def fpIsPositive(a, ctx=None): 10215 """Create a Z3 floating-point isPositive expression. 10216 """ 10217 return _mk_fp_unary_pred(Z3_mk_fpa_is_positive, a, ctx) 10218 10219 10220def _check_fp_args(a, b): 10221 if z3_debug(): 10222 _z3_assert(is_fp(a) or is_fp(b), "First or second argument must be a Z3 floating-point expression") 10223 10224 10225def fpLT(a, b, ctx=None): 10226 """Create the Z3 floating-point expression `other < self`. 10227 10228 >>> x, y = FPs('x y', FPSort(8, 24)) 10229 >>> fpLT(x, y) 10230 x < y 10231 >>> (x < y).sexpr() 10232 '(fp.lt x y)' 10233 """ 10234 return _mk_fp_bin_pred(Z3_mk_fpa_lt, a, b, ctx) 10235 10236 10237def fpLEQ(a, b, ctx=None): 10238 """Create the Z3 floating-point expression `other <= self`. 10239 10240 >>> x, y = FPs('x y', FPSort(8, 24)) 10241 >>> fpLEQ(x, y) 10242 x <= y 10243 >>> (x <= y).sexpr() 10244 '(fp.leq x y)' 10245 """ 10246 return _mk_fp_bin_pred(Z3_mk_fpa_leq, a, b, ctx) 10247 10248 10249def fpGT(a, b, ctx=None): 10250 """Create the Z3 floating-point expression `other > self`. 10251 10252 >>> x, y = FPs('x y', FPSort(8, 24)) 10253 >>> fpGT(x, y) 10254 x > y 10255 >>> (x > y).sexpr() 10256 '(fp.gt x y)' 10257 """ 10258 return _mk_fp_bin_pred(Z3_mk_fpa_gt, a, b, ctx) 10259 10260 10261def fpGEQ(a, b, ctx=None): 10262 """Create the Z3 floating-point expression `other >= self`. 10263 10264 >>> x, y = FPs('x y', FPSort(8, 24)) 10265 >>> fpGEQ(x, y) 10266 x >= y 10267 >>> (x >= y).sexpr() 10268 '(fp.geq x y)' 10269 """ 10270 return _mk_fp_bin_pred(Z3_mk_fpa_geq, a, b, ctx) 10271 10272 10273def fpEQ(a, b, ctx=None): 10274 """Create the Z3 floating-point expression `fpEQ(other, self)`. 10275 10276 >>> x, y = FPs('x y', FPSort(8, 24)) 10277 >>> fpEQ(x, y) 10278 fpEQ(x, y) 10279 >>> fpEQ(x, y).sexpr() 10280 '(fp.eq x y)' 10281 """ 10282 return _mk_fp_bin_pred(Z3_mk_fpa_eq, a, b, ctx) 10283 10284 10285def fpNEQ(a, b, ctx=None): 10286 """Create the Z3 floating-point expression `Not(fpEQ(other, self))`. 10287 10288 >>> x, y = FPs('x y', FPSort(8, 24)) 10289 >>> fpNEQ(x, y) 10290 Not(fpEQ(x, y)) 10291 >>> (x != y).sexpr() 10292 '(distinct x y)' 10293 """ 10294 return Not(fpEQ(a, b, ctx)) 10295 10296 10297def fpFP(sgn, exp, sig, ctx=None): 10298 """Create the Z3 floating-point value `fpFP(sgn, sig, exp)` from the three bit-vectors sgn, sig, and exp. 10299 10300 >>> s = FPSort(8, 24) 10301 >>> x = fpFP(BitVecVal(1, 1), BitVecVal(2**7-1, 8), BitVecVal(2**22, 23)) 10302 >>> print(x) 10303 fpFP(1, 127, 4194304) 10304 >>> xv = FPVal(-1.5, s) 10305 >>> print(xv) 10306 -1.5 10307 >>> slvr = Solver() 10308 >>> slvr.add(fpEQ(x, xv)) 10309 >>> slvr.check() 10310 sat 10311 >>> xv = FPVal(+1.5, s) 10312 >>> print(xv) 10313 1.5 10314 >>> slvr = Solver() 10315 >>> slvr.add(fpEQ(x, xv)) 10316 >>> slvr.check() 10317 unsat 10318 """ 10319 _z3_assert(is_bv(sgn) and is_bv(exp) and is_bv(sig), "sort mismatch") 10320 _z3_assert(sgn.sort().size() == 1, "sort mismatch") 10321 ctx = _get_ctx(ctx) 10322 _z3_assert(ctx == sgn.ctx == exp.ctx == sig.ctx, "context mismatch") 10323 return FPRef(Z3_mk_fpa_fp(ctx.ref(), sgn.ast, exp.ast, sig.ast), ctx) 10324 10325 10326def fpToFP(a1, a2=None, a3=None, ctx=None): 10327 """Create a Z3 floating-point conversion expression from other term sorts 10328 to floating-point. 10329 10330 From a bit-vector term in IEEE 754-2008 format: 10331 >>> x = FPVal(1.0, Float32()) 10332 >>> x_bv = fpToIEEEBV(x) 10333 >>> simplify(fpToFP(x_bv, Float32())) 10334 1 10335 10336 From a floating-point term with different precision: 10337 >>> x = FPVal(1.0, Float32()) 10338 >>> x_db = fpToFP(RNE(), x, Float64()) 10339 >>> x_db.sort() 10340 FPSort(11, 53) 10341 10342 From a real term: 10343 >>> x_r = RealVal(1.5) 10344 >>> simplify(fpToFP(RNE(), x_r, Float32())) 10345 1.5 10346 10347 From a signed bit-vector term: 10348 >>> x_signed = BitVecVal(-5, BitVecSort(32)) 10349 >>> simplify(fpToFP(RNE(), x_signed, Float32())) 10350 -1.25*(2**2) 10351 """ 10352 ctx = _get_ctx(ctx) 10353 if is_bv(a1) and is_fp_sort(a2): 10354 return FPRef(Z3_mk_fpa_to_fp_bv(ctx.ref(), a1.ast, a2.ast), ctx) 10355 elif is_fprm(a1) and is_fp(a2) and is_fp_sort(a3): 10356 return FPRef(Z3_mk_fpa_to_fp_float(ctx.ref(), a1.ast, a2.ast, a3.ast), ctx) 10357 elif is_fprm(a1) and is_real(a2) and is_fp_sort(a3): 10358 return FPRef(Z3_mk_fpa_to_fp_real(ctx.ref(), a1.ast, a2.ast, a3.ast), ctx) 10359 elif is_fprm(a1) and is_bv(a2) and is_fp_sort(a3): 10360 return FPRef(Z3_mk_fpa_to_fp_signed(ctx.ref(), a1.ast, a2.ast, a3.ast), ctx) 10361 else: 10362 raise Z3Exception("Unsupported combination of arguments for conversion to floating-point term.") 10363 10364 10365def fpBVToFP(v, sort, ctx=None): 10366 """Create a Z3 floating-point conversion expression that represents the 10367 conversion from a bit-vector term to a floating-point term. 10368 10369 >>> x_bv = BitVecVal(0x3F800000, 32) 10370 >>> x_fp = fpBVToFP(x_bv, Float32()) 10371 >>> x_fp 10372 fpToFP(1065353216) 10373 >>> simplify(x_fp) 10374 1 10375 """ 10376 _z3_assert(is_bv(v), "First argument must be a Z3 bit-vector expression") 10377 _z3_assert(is_fp_sort(sort), "Second argument must be a Z3 floating-point sort.") 10378 ctx = _get_ctx(ctx) 10379 return FPRef(Z3_mk_fpa_to_fp_bv(ctx.ref(), v.ast, sort.ast), ctx) 10380 10381 10382def fpFPToFP(rm, v, sort, ctx=None): 10383 """Create a Z3 floating-point conversion expression that represents the 10384 conversion from a floating-point term to a floating-point term of different precision. 10385 10386 >>> x_sgl = FPVal(1.0, Float32()) 10387 >>> x_dbl = fpFPToFP(RNE(), x_sgl, Float64()) 10388 >>> x_dbl 10389 fpToFP(RNE(), 1) 10390 >>> simplify(x_dbl) 10391 1 10392 >>> x_dbl.sort() 10393 FPSort(11, 53) 10394 """ 10395 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression.") 10396 _z3_assert(is_fp(v), "Second argument must be a Z3 floating-point expression.") 10397 _z3_assert(is_fp_sort(sort), "Third argument must be a Z3 floating-point sort.") 10398 ctx = _get_ctx(ctx) 10399 return FPRef(Z3_mk_fpa_to_fp_float(ctx.ref(), rm.ast, v.ast, sort.ast), ctx) 10400 10401 10402def fpRealToFP(rm, v, sort, ctx=None): 10403 """Create a Z3 floating-point conversion expression that represents the 10404 conversion from a real term to a floating-point term. 10405 10406 >>> x_r = RealVal(1.5) 10407 >>> x_fp = fpRealToFP(RNE(), x_r, Float32()) 10408 >>> x_fp 10409 fpToFP(RNE(), 3/2) 10410 >>> simplify(x_fp) 10411 1.5 10412 """ 10413 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression.") 10414 _z3_assert(is_real(v), "Second argument must be a Z3 expression or real sort.") 10415 _z3_assert(is_fp_sort(sort), "Third argument must be a Z3 floating-point sort.") 10416 ctx = _get_ctx(ctx) 10417 return FPRef(Z3_mk_fpa_to_fp_real(ctx.ref(), rm.ast, v.ast, sort.ast), ctx) 10418 10419 10420def fpSignedToFP(rm, v, sort, ctx=None): 10421 """Create a Z3 floating-point conversion expression that represents the 10422 conversion from a signed bit-vector term (encoding an integer) to a floating-point term. 10423 10424 >>> x_signed = BitVecVal(-5, BitVecSort(32)) 10425 >>> x_fp = fpSignedToFP(RNE(), x_signed, Float32()) 10426 >>> x_fp 10427 fpToFP(RNE(), 4294967291) 10428 >>> simplify(x_fp) 10429 -1.25*(2**2) 10430 """ 10431 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression.") 10432 _z3_assert(is_bv(v), "Second argument must be a Z3 bit-vector expression") 10433 _z3_assert(is_fp_sort(sort), "Third argument must be a Z3 floating-point sort.") 10434 ctx = _get_ctx(ctx) 10435 return FPRef(Z3_mk_fpa_to_fp_signed(ctx.ref(), rm.ast, v.ast, sort.ast), ctx) 10436 10437 10438def fpUnsignedToFP(rm, v, sort, ctx=None): 10439 """Create a Z3 floating-point conversion expression that represents the 10440 conversion from an unsigned bit-vector term (encoding an integer) to a floating-point term. 10441 10442 >>> x_signed = BitVecVal(-5, BitVecSort(32)) 10443 >>> x_fp = fpUnsignedToFP(RNE(), x_signed, Float32()) 10444 >>> x_fp 10445 fpToFPUnsigned(RNE(), 4294967291) 10446 >>> simplify(x_fp) 10447 1*(2**32) 10448 """ 10449 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression.") 10450 _z3_assert(is_bv(v), "Second argument must be a Z3 bit-vector expression") 10451 _z3_assert(is_fp_sort(sort), "Third argument must be a Z3 floating-point sort.") 10452 ctx = _get_ctx(ctx) 10453 return FPRef(Z3_mk_fpa_to_fp_unsigned(ctx.ref(), rm.ast, v.ast, sort.ast), ctx) 10454 10455 10456def fpToFPUnsigned(rm, x, s, ctx=None): 10457 """Create a Z3 floating-point conversion expression, from unsigned bit-vector to floating-point expression.""" 10458 if z3_debug(): 10459 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") 10460 _z3_assert(is_bv(x), "Second argument must be a Z3 bit-vector expression") 10461 _z3_assert(is_fp_sort(s), "Third argument must be Z3 floating-point sort") 10462 ctx = _get_ctx(ctx) 10463 return FPRef(Z3_mk_fpa_to_fp_unsigned(ctx.ref(), rm.ast, x.ast, s.ast), ctx) 10464 10465 10466def fpToSBV(rm, x, s, ctx=None): 10467 """Create a Z3 floating-point conversion expression, from floating-point expression to signed bit-vector. 10468 10469 >>> x = FP('x', FPSort(8, 24)) 10470 >>> y = fpToSBV(RTZ(), x, BitVecSort(32)) 10471 >>> print(is_fp(x)) 10472 True 10473 >>> print(is_bv(y)) 10474 True 10475 >>> print(is_fp(y)) 10476 False 10477 >>> print(is_bv(x)) 10478 False 10479 """ 10480 if z3_debug(): 10481 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") 10482 _z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression") 10483 _z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort") 10484 ctx = _get_ctx(ctx) 10485 return BitVecRef(Z3_mk_fpa_to_sbv(ctx.ref(), rm.ast, x.ast, s.size()), ctx) 10486 10487 10488def fpToUBV(rm, x, s, ctx=None): 10489 """Create a Z3 floating-point conversion expression, from floating-point expression to unsigned bit-vector. 10490 10491 >>> x = FP('x', FPSort(8, 24)) 10492 >>> y = fpToUBV(RTZ(), x, BitVecSort(32)) 10493 >>> print(is_fp(x)) 10494 True 10495 >>> print(is_bv(y)) 10496 True 10497 >>> print(is_fp(y)) 10498 False 10499 >>> print(is_bv(x)) 10500 False 10501 """ 10502 if z3_debug(): 10503 _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") 10504 _z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression") 10505 _z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort") 10506 ctx = _get_ctx(ctx) 10507 return BitVecRef(Z3_mk_fpa_to_ubv(ctx.ref(), rm.ast, x.ast, s.size()), ctx) 10508 10509 10510def fpToReal(x, ctx=None): 10511 """Create a Z3 floating-point conversion expression, from floating-point expression to real. 10512 10513 >>> x = FP('x', FPSort(8, 24)) 10514 >>> y = fpToReal(x) 10515 >>> print(is_fp(x)) 10516 True 10517 >>> print(is_real(y)) 10518 True 10519 >>> print(is_fp(y)) 10520 False 10521 >>> print(is_real(x)) 10522 False 10523 """ 10524 if z3_debug(): 10525 _z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression") 10526 ctx = _get_ctx(ctx) 10527 return ArithRef(Z3_mk_fpa_to_real(ctx.ref(), x.ast), ctx) 10528 10529 10530def fpToIEEEBV(x, ctx=None): 10531 """\brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. 10532 10533 The size of the resulting bit-vector is automatically determined. 10534 10535 Note that IEEE 754-2008 allows multiple different representations of NaN. This conversion 10536 knows only one NaN and it will always produce the same bit-vector representation of 10537 that NaN. 10538 10539 >>> x = FP('x', FPSort(8, 24)) 10540 >>> y = fpToIEEEBV(x) 10541 >>> print(is_fp(x)) 10542 True 10543 >>> print(is_bv(y)) 10544 True 10545 >>> print(is_fp(y)) 10546 False 10547 >>> print(is_bv(x)) 10548 False 10549 """ 10550 if z3_debug(): 10551 _z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression") 10552 ctx = _get_ctx(ctx) 10553 return BitVecRef(Z3_mk_fpa_to_ieee_bv(ctx.ref(), x.ast), ctx) 10554 10555 10556######################################### 10557# 10558# Strings, Sequences and Regular expressions 10559# 10560######################################### 10561 10562class SeqSortRef(SortRef): 10563 """Sequence sort.""" 10564 10565 def is_string(self): 10566 """Determine if sort is a string 10567 >>> s = StringSort() 10568 >>> s.is_string() 10569 True 10570 >>> s = SeqSort(IntSort()) 10571 >>> s.is_string() 10572 False 10573 """ 10574 return Z3_is_string_sort(self.ctx_ref(), self.ast) 10575 10576 def basis(self): 10577 return _to_sort_ref(Z3_get_seq_sort_basis(self.ctx_ref(), self.ast), self.ctx) 10578 10579class CharSortRef(SortRef): 10580 """Character sort.""" 10581 10582 10583 10584def StringSort(ctx=None): 10585 """Create a string sort 10586 >>> s = StringSort() 10587 >>> print(s) 10588 String 10589 """ 10590 ctx = _get_ctx(ctx) 10591 return SeqSortRef(Z3_mk_string_sort(ctx.ref()), ctx) 10592 10593def CharSort(ctx=None): 10594 """Create a character sort 10595 >>> ch = CharSort() 10596 >>> print(ch) 10597 Char 10598 """ 10599 ctx = _get_ctx(ctx) 10600 return CharSortRef(Z3_mk_char_sort(ctx.ref()), ctx) 10601 10602 10603def SeqSort(s): 10604 """Create a sequence sort over elements provided in the argument 10605 >>> s = SeqSort(IntSort()) 10606 >>> s == Unit(IntVal(1)).sort() 10607 True 10608 """ 10609 return SeqSortRef(Z3_mk_seq_sort(s.ctx_ref(), s.ast), s.ctx) 10610 10611 10612class SeqRef(ExprRef): 10613 """Sequence expression.""" 10614 10615 def sort(self): 10616 return SeqSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) 10617 10618 def __add__(self, other): 10619 return Concat(self, other) 10620 10621 def __radd__(self, other): 10622 return Concat(other, self) 10623 10624 def __getitem__(self, i): 10625 if _is_int(i): 10626 i = IntVal(i, self.ctx) 10627 return _to_expr_ref(Z3_mk_seq_nth(self.ctx_ref(), self.as_ast(), i.as_ast()), self.ctx) 10628 10629 def at(self, i): 10630 if _is_int(i): 10631 i = IntVal(i, self.ctx) 10632 return SeqRef(Z3_mk_seq_at(self.ctx_ref(), self.as_ast(), i.as_ast()), self.ctx) 10633 10634 def is_string(self): 10635 return Z3_is_string_sort(self.ctx_ref(), Z3_get_sort(self.ctx_ref(), self.as_ast())) 10636 10637 def is_string_value(self): 10638 return Z3_is_string(self.ctx_ref(), self.as_ast()) 10639 10640 def as_string(self): 10641 """Return a string representation of sequence expression.""" 10642 if self.is_string_value(): 10643 string_length = ctypes.c_uint() 10644 chars = Z3_get_lstring(self.ctx_ref(), self.as_ast(), byref(string_length)) 10645 return string_at(chars, size=string_length.value).decode("latin-1") 10646 return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) 10647 10648 def __le__(self, other): 10649 return SeqRef(Z3_mk_str_le(self.ctx_ref(), self.as_ast(), other.as_ast()), self.ctx) 10650 10651 def __lt__(self, other): 10652 return SeqRef(Z3_mk_str_lt(self.ctx_ref(), self.as_ast(), other.as_ast()), self.ctx) 10653 10654 def __ge__(self, other): 10655 return SeqRef(Z3_mk_str_le(self.ctx_ref(), other.as_ast(), self.as_ast()), self.ctx) 10656 10657 def __gt__(self, other): 10658 return SeqRef(Z3_mk_str_lt(self.ctx_ref(), other.as_ast(), self.as_ast()), self.ctx) 10659 10660 10661def _coerce_seq(s, ctx=None): 10662 if isinstance(s, str): 10663 ctx = _get_ctx(ctx) 10664 s = StringVal(s, ctx) 10665 if not is_expr(s): 10666 raise Z3Exception("Non-expression passed as a sequence") 10667 if not is_seq(s): 10668 raise Z3Exception("Non-sequence passed as a sequence") 10669 return s 10670 10671 10672def _get_ctx2(a, b, ctx=None): 10673 if is_expr(a): 10674 return a.ctx 10675 if is_expr(b): 10676 return b.ctx 10677 if ctx is None: 10678 ctx = main_ctx() 10679 return ctx 10680 10681 10682def is_seq(a): 10683 """Return `True` if `a` is a Z3 sequence expression. 10684 >>> print (is_seq(Unit(IntVal(0)))) 10685 True 10686 >>> print (is_seq(StringVal("abc"))) 10687 True 10688 """ 10689 return isinstance(a, SeqRef) 10690 10691 10692def is_string(a): 10693 """Return `True` if `a` is a Z3 string expression. 10694 >>> print (is_string(StringVal("ab"))) 10695 True 10696 """ 10697 return isinstance(a, SeqRef) and a.is_string() 10698 10699 10700def is_string_value(a): 10701 """return 'True' if 'a' is a Z3 string constant expression. 10702 >>> print (is_string_value(StringVal("a"))) 10703 True 10704 >>> print (is_string_value(StringVal("a") + StringVal("b"))) 10705 False 10706 """ 10707 return isinstance(a, SeqRef) and a.is_string_value() 10708 10709def StringVal(s, ctx=None): 10710 """create a string expression""" 10711 s = "".join(str(ch) if 32 <= ord(ch) and ord(ch) < 127 else "\\u{%x}" % (ord(ch)) for ch in s) 10712 ctx = _get_ctx(ctx) 10713 return SeqRef(Z3_mk_string(ctx.ref(), s), ctx) 10714 10715 10716def String(name, ctx=None): 10717 """Return a string constant named `name`. If `ctx=None`, then the global context is used. 10718 10719 >>> x = String('x') 10720 """ 10721 ctx = _get_ctx(ctx) 10722 return SeqRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), StringSort(ctx).ast), ctx) 10723 10724 10725def Strings(names, ctx=None): 10726 """Return a tuple of String constants. """ 10727 ctx = _get_ctx(ctx) 10728 if isinstance(names, str): 10729 names = names.split(" ") 10730 return [String(name, ctx) for name in names] 10731 10732 10733def SubString(s, offset, length): 10734 """Extract substring or subsequence starting at offset""" 10735 return Extract(s, offset, length) 10736 10737 10738def SubSeq(s, offset, length): 10739 """Extract substring or subsequence starting at offset""" 10740 return Extract(s, offset, length) 10741 10742 10743def Empty(s): 10744 """Create the empty sequence of the given sort 10745 >>> e = Empty(StringSort()) 10746 >>> e2 = StringVal("") 10747 >>> print(e.eq(e2)) 10748 True 10749 >>> e3 = Empty(SeqSort(IntSort())) 10750 >>> print(e3) 10751 Empty(Seq(Int)) 10752 >>> e4 = Empty(ReSort(SeqSort(IntSort()))) 10753 >>> print(e4) 10754 Empty(ReSort(Seq(Int))) 10755 """ 10756 if isinstance(s, SeqSortRef): 10757 return SeqRef(Z3_mk_seq_empty(s.ctx_ref(), s.ast), s.ctx) 10758 if isinstance(s, ReSortRef): 10759 return ReRef(Z3_mk_re_empty(s.ctx_ref(), s.ast), s.ctx) 10760 raise Z3Exception("Non-sequence, non-regular expression sort passed to Empty") 10761 10762 10763def Full(s): 10764 """Create the regular expression that accepts the universal language 10765 >>> e = Full(ReSort(SeqSort(IntSort()))) 10766 >>> print(e) 10767 Full(ReSort(Seq(Int))) 10768 >>> e1 = Full(ReSort(StringSort())) 10769 >>> print(e1) 10770 Full(ReSort(String)) 10771 """ 10772 if isinstance(s, ReSortRef): 10773 return ReRef(Z3_mk_re_full(s.ctx_ref(), s.ast), s.ctx) 10774 raise Z3Exception("Non-sequence, non-regular expression sort passed to Full") 10775 10776 10777def Unit(a): 10778 """Create a singleton sequence""" 10779 return SeqRef(Z3_mk_seq_unit(a.ctx_ref(), a.as_ast()), a.ctx) 10780 10781 10782def PrefixOf(a, b): 10783 """Check if 'a' is a prefix of 'b' 10784 >>> s1 = PrefixOf("ab", "abc") 10785 >>> simplify(s1) 10786 True 10787 >>> s2 = PrefixOf("bc", "abc") 10788 >>> simplify(s2) 10789 False 10790 """ 10791 ctx = _get_ctx2(a, b) 10792 a = _coerce_seq(a, ctx) 10793 b = _coerce_seq(b, ctx) 10794 return BoolRef(Z3_mk_seq_prefix(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 10795 10796 10797def SuffixOf(a, b): 10798 """Check if 'a' is a suffix of 'b' 10799 >>> s1 = SuffixOf("ab", "abc") 10800 >>> simplify(s1) 10801 False 10802 >>> s2 = SuffixOf("bc", "abc") 10803 >>> simplify(s2) 10804 True 10805 """ 10806 ctx = _get_ctx2(a, b) 10807 a = _coerce_seq(a, ctx) 10808 b = _coerce_seq(b, ctx) 10809 return BoolRef(Z3_mk_seq_suffix(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 10810 10811 10812def Contains(a, b): 10813 """Check if 'a' contains 'b' 10814 >>> s1 = Contains("abc", "ab") 10815 >>> simplify(s1) 10816 True 10817 >>> s2 = Contains("abc", "bc") 10818 >>> simplify(s2) 10819 True 10820 >>> x, y, z = Strings('x y z') 10821 >>> s3 = Contains(Concat(x,y,z), y) 10822 >>> simplify(s3) 10823 True 10824 """ 10825 ctx = _get_ctx2(a, b) 10826 a = _coerce_seq(a, ctx) 10827 b = _coerce_seq(b, ctx) 10828 return BoolRef(Z3_mk_seq_contains(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) 10829 10830 10831def Replace(s, src, dst): 10832 """Replace the first occurrence of 'src' by 'dst' in 's' 10833 >>> r = Replace("aaa", "a", "b") 10834 >>> simplify(r) 10835 "baa" 10836 """ 10837 ctx = _get_ctx2(dst, s) 10838 if ctx is None and is_expr(src): 10839 ctx = src.ctx 10840 src = _coerce_seq(src, ctx) 10841 dst = _coerce_seq(dst, ctx) 10842 s = _coerce_seq(s, ctx) 10843 return SeqRef(Z3_mk_seq_replace(src.ctx_ref(), s.as_ast(), src.as_ast(), dst.as_ast()), s.ctx) 10844 10845 10846def IndexOf(s, substr, offset=None): 10847 """Retrieve the index of substring within a string starting at a specified offset. 10848 >>> simplify(IndexOf("abcabc", "bc", 0)) 10849 1 10850 >>> simplify(IndexOf("abcabc", "bc", 2)) 10851 4 10852 """ 10853 if offset is None: 10854 offset = IntVal(0) 10855 ctx = None 10856 if is_expr(offset): 10857 ctx = offset.ctx 10858 ctx = _get_ctx2(s, substr, ctx) 10859 s = _coerce_seq(s, ctx) 10860 substr = _coerce_seq(substr, ctx) 10861 if _is_int(offset): 10862 offset = IntVal(offset, ctx) 10863 return ArithRef(Z3_mk_seq_index(s.ctx_ref(), s.as_ast(), substr.as_ast(), offset.as_ast()), s.ctx) 10864 10865 10866def LastIndexOf(s, substr): 10867 """Retrieve the last index of substring within a string""" 10868 ctx = None 10869 ctx = _get_ctx2(s, substr, ctx) 10870 s = _coerce_seq(s, ctx) 10871 substr = _coerce_seq(substr, ctx) 10872 return ArithRef(Z3_mk_seq_last_index(s.ctx_ref(), s.as_ast(), substr.as_ast()), s.ctx) 10873 10874 10875def Length(s): 10876 """Obtain the length of a sequence 's' 10877 >>> l = Length(StringVal("abc")) 10878 >>> simplify(l) 10879 3 10880 """ 10881 s = _coerce_seq(s) 10882 return ArithRef(Z3_mk_seq_length(s.ctx_ref(), s.as_ast()), s.ctx) 10883 10884 10885def StrToInt(s): 10886 """Convert string expression to integer 10887 >>> a = StrToInt("1") 10888 >>> simplify(1 == a) 10889 True 10890 >>> b = StrToInt("2") 10891 >>> simplify(1 == b) 10892 False 10893 >>> c = StrToInt(IntToStr(2)) 10894 >>> simplify(1 == c) 10895 False 10896 """ 10897 s = _coerce_seq(s) 10898 return ArithRef(Z3_mk_str_to_int(s.ctx_ref(), s.as_ast()), s.ctx) 10899 10900 10901def IntToStr(s): 10902 """Convert integer expression to string""" 10903 if not is_expr(s): 10904 s = _py2expr(s) 10905 return SeqRef(Z3_mk_int_to_str(s.ctx_ref(), s.as_ast()), s.ctx) 10906 10907 10908def Re(s, ctx=None): 10909 """The regular expression that accepts sequence 's' 10910 >>> s1 = Re("ab") 10911 >>> s2 = Re(StringVal("ab")) 10912 >>> s3 = Re(Unit(BoolVal(True))) 10913 """ 10914 s = _coerce_seq(s, ctx) 10915 return ReRef(Z3_mk_seq_to_re(s.ctx_ref(), s.as_ast()), s.ctx) 10916 10917 10918# Regular expressions 10919 10920class ReSortRef(SortRef): 10921 """Regular expression sort.""" 10922 10923 def basis(self): 10924 return _to_sort_ref(Z3_get_re_sort_basis(self.ctx_ref(), self.ast), self.ctx) 10925 10926 10927def ReSort(s): 10928 if is_ast(s): 10929 return ReSortRef(Z3_mk_re_sort(s.ctx.ref(), s.ast), s.ctx) 10930 if s is None or isinstance(s, Context): 10931 ctx = _get_ctx(s) 10932 return ReSortRef(Z3_mk_re_sort(ctx.ref(), Z3_mk_string_sort(ctx.ref())), s.ctx) 10933 raise Z3Exception("Regular expression sort constructor expects either a string or a context or no argument") 10934 10935 10936class ReRef(ExprRef): 10937 """Regular expressions.""" 10938 10939 def __add__(self, other): 10940 return Union(self, other) 10941 10942 10943def is_re(s): 10944 return isinstance(s, ReRef) 10945 10946 10947def InRe(s, re): 10948 """Create regular expression membership test 10949 >>> re = Union(Re("a"),Re("b")) 10950 >>> print (simplify(InRe("a", re))) 10951 True 10952 >>> print (simplify(InRe("b", re))) 10953 True 10954 >>> print (simplify(InRe("c", re))) 10955 False 10956 """ 10957 s = _coerce_seq(s, re.ctx) 10958 return BoolRef(Z3_mk_seq_in_re(s.ctx_ref(), s.as_ast(), re.as_ast()), s.ctx) 10959 10960 10961def Union(*args): 10962 """Create union of regular expressions. 10963 >>> re = Union(Re("a"), Re("b"), Re("c")) 10964 >>> print (simplify(InRe("d", re))) 10965 False 10966 """ 10967 args = _get_args(args) 10968 sz = len(args) 10969 if z3_debug(): 10970 _z3_assert(sz > 0, "At least one argument expected.") 10971 _z3_assert(all([is_re(a) for a in args]), "All arguments must be regular expressions.") 10972 if sz == 1: 10973 return args[0] 10974 ctx = args[0].ctx 10975 v = (Ast * sz)() 10976 for i in range(sz): 10977 v[i] = args[i].as_ast() 10978 return ReRef(Z3_mk_re_union(ctx.ref(), sz, v), ctx) 10979 10980 10981def Intersect(*args): 10982 """Create intersection of regular expressions. 10983 >>> re = Intersect(Re("a"), Re("b"), Re("c")) 10984 """ 10985 args = _get_args(args) 10986 sz = len(args) 10987 if z3_debug(): 10988 _z3_assert(sz > 0, "At least one argument expected.") 10989 _z3_assert(all([is_re(a) for a in args]), "All arguments must be regular expressions.") 10990 if sz == 1: 10991 return args[0] 10992 ctx = args[0].ctx 10993 v = (Ast * sz)() 10994 for i in range(sz): 10995 v[i] = args[i].as_ast() 10996 return ReRef(Z3_mk_re_intersect(ctx.ref(), sz, v), ctx) 10997 10998 10999def Plus(re): 11000 """Create the regular expression accepting one or more repetitions of argument. 11001 >>> re = Plus(Re("a")) 11002 >>> print(simplify(InRe("aa", re))) 11003 True 11004 >>> print(simplify(InRe("ab", re))) 11005 False 11006 >>> print(simplify(InRe("", re))) 11007 False 11008 """ 11009 return ReRef(Z3_mk_re_plus(re.ctx_ref(), re.as_ast()), re.ctx) 11010 11011 11012def Option(re): 11013 """Create the regular expression that optionally accepts the argument. 11014 >>> re = Option(Re("a")) 11015 >>> print(simplify(InRe("a", re))) 11016 True 11017 >>> print(simplify(InRe("", re))) 11018 True 11019 >>> print(simplify(InRe("aa", re))) 11020 False 11021 """ 11022 return ReRef(Z3_mk_re_option(re.ctx_ref(), re.as_ast()), re.ctx) 11023 11024 11025def Complement(re): 11026 """Create the complement regular expression.""" 11027 return ReRef(Z3_mk_re_complement(re.ctx_ref(), re.as_ast()), re.ctx) 11028 11029 11030def Star(re): 11031 """Create the regular expression accepting zero or more repetitions of argument. 11032 >>> re = Star(Re("a")) 11033 >>> print(simplify(InRe("aa", re))) 11034 True 11035 >>> print(simplify(InRe("ab", re))) 11036 False 11037 >>> print(simplify(InRe("", re))) 11038 True 11039 """ 11040 return ReRef(Z3_mk_re_star(re.ctx_ref(), re.as_ast()), re.ctx) 11041 11042 11043def Loop(re, lo, hi=0): 11044 """Create the regular expression accepting between a lower and upper bound repetitions 11045 >>> re = Loop(Re("a"), 1, 3) 11046 >>> print(simplify(InRe("aa", re))) 11047 True 11048 >>> print(simplify(InRe("aaaa", re))) 11049 False 11050 >>> print(simplify(InRe("", re))) 11051 False 11052 """ 11053 return ReRef(Z3_mk_re_loop(re.ctx_ref(), re.as_ast(), lo, hi), re.ctx) 11054 11055 11056def Range(lo, hi, ctx=None): 11057 """Create the range regular expression over two sequences of length 1 11058 >>> range = Range("a","z") 11059 >>> print(simplify(InRe("b", range))) 11060 True 11061 >>> print(simplify(InRe("bb", range))) 11062 False 11063 """ 11064 lo = _coerce_seq(lo, ctx) 11065 hi = _coerce_seq(hi, ctx) 11066 return ReRef(Z3_mk_re_range(lo.ctx_ref(), lo.ast, hi.ast), lo.ctx) 11067 11068def AllChar(regex_sort, ctx=None): 11069 """Create a regular expression that accepts all single character strings 11070 """ 11071 return ReRef(Z3_mk_re_allchar(regex_sort.ctx_ref(), regex_sort.ast), regex_sort.ctx) 11072 11073# Special Relations 11074 11075 11076def PartialOrder(a, index): 11077 return FuncDeclRef(Z3_mk_partial_order(a.ctx_ref(), a.ast, index), a.ctx) 11078 11079 11080def LinearOrder(a, index): 11081 return FuncDeclRef(Z3_mk_linear_order(a.ctx_ref(), a.ast, index), a.ctx) 11082 11083 11084def TreeOrder(a, index): 11085 return FuncDeclRef(Z3_mk_tree_order(a.ctx_ref(), a.ast, index), a.ctx) 11086 11087 11088def PiecewiseLinearOrder(a, index): 11089 return FuncDeclRef(Z3_mk_piecewise_linear_order(a.ctx_ref(), a.ast, index), a.ctx) 11090 11091 11092def TransitiveClosure(f): 11093 """Given a binary relation R, such that the two arguments have the same sort 11094 create the transitive closure relation R+. 11095 The transitive closure R+ is a new relation. 11096 """ 11097 return FuncDeclRef(Z3_mk_transitive_closure(f.ctx_ref(), f.ast), f.ctx) 11098 11099 11100class PropClosures: 11101 def __init__(self): 11102 self.bases = {} 11103 self.lock = None 11104 11105 def set_threaded(self): 11106 if self.lock is None: 11107 import threading 11108 self.lock = threading.Lock() 11109 11110 def get(self, ctx): 11111 if self.lock: 11112 with self.lock: 11113 r = self.bases[ctx] 11114 else: 11115 r = self.bases[ctx] 11116 return r 11117 11118 def set(self, ctx, r): 11119 if self.lock: 11120 with self.lock: 11121 self.bases[ctx] = r 11122 else: 11123 self.bases[ctx] = r 11124 11125 def insert(self, r): 11126 if self.lock: 11127 with self.lock: 11128 id = len(self.bases) + 3 11129 self.bases[id] = r 11130 else: 11131 id = len(self.bases) + 3 11132 self.bases[id] = r 11133 return id 11134 11135 11136_prop_closures = None 11137 11138 11139def ensure_prop_closures(): 11140 global _prop_closures 11141 if _prop_closures is None: 11142 _prop_closures = PropClosures() 11143 11144 11145def user_prop_push(ctx): 11146 _prop_closures.get(ctx).push() 11147 11148 11149def user_prop_pop(ctx, num_scopes): 11150 _prop_closures.get(ctx).pop(num_scopes) 11151 11152 11153def user_prop_fresh(id, ctx): 11154 _prop_closures.set_threaded() 11155 prop = _prop_closures.get(id) 11156 new_prop = prop.fresh() 11157 _prop_closures.set(new_prop.id, new_prop) 11158 return ctypes.c_void_p(new_prop.id) 11159 11160 11161def user_prop_fixed(ctx, cb, id, value): 11162 prop = _prop_closures.get(ctx) 11163 prop.cb = cb 11164 prop.fixed(id, _to_expr_ref(ctypes.c_void_p(value), prop.ctx())) 11165 prop.cb = None 11166 11167 11168def user_prop_final(ctx, cb): 11169 prop = _prop_closures.get(ctx) 11170 prop.cb = cb 11171 prop.final() 11172 prop.cb = None 11173 11174 11175def user_prop_eq(ctx, cb, x, y): 11176 prop = _prop_closures.get(ctx) 11177 prop.cb = cb 11178 prop.eq(x, y) 11179 prop.cb = None 11180 11181 11182def user_prop_diseq(ctx, cb, x, y): 11183 prop = _prop_closures.get(ctx) 11184 prop.cb = cb 11185 prop.diseq(x, y) 11186 prop.cb = None 11187 11188 11189_user_prop_push = push_eh_type(user_prop_push) 11190_user_prop_pop = pop_eh_type(user_prop_pop) 11191_user_prop_fresh = fresh_eh_type(user_prop_fresh) 11192_user_prop_fixed = fixed_eh_type(user_prop_fixed) 11193_user_prop_final = final_eh_type(user_prop_final) 11194_user_prop_eq = eq_eh_type(user_prop_eq) 11195_user_prop_diseq = eq_eh_type(user_prop_diseq) 11196 11197 11198class UserPropagateBase: 11199 11200 # 11201 # Either solver is set or ctx is set. 11202 # Propagators that are created throuh callbacks 11203 # to "fresh" inherit the context of that is supplied 11204 # as argument to the callback. 11205 # This context should not be deleted. It is owned by the solver. 11206 # 11207 def __init__(self, s, ctx=None): 11208 assert s is None or ctx is None 11209 ensure_prop_closures() 11210 self.solver = s 11211 self._ctx = None 11212 self.cb = None 11213 self.id = _prop_closures.insert(self) 11214 self.fixed = None 11215 self.final = None 11216 self.eq = None 11217 self.diseq = None 11218 if ctx: 11219 # TBD fresh is broken: ctx is not of the right type when we reach here. 11220 self._ctx = Context() 11221 #Z3_del_context(self._ctx.ctx) 11222 #self._ctx.ctx = ctx 11223 #self._ctx.eh = Z3_set_error_handler(ctx, z3_error_handler) 11224 #Z3_set_ast_print_mode(ctx, Z3_PRINT_SMTLIB2_COMPLIANT) 11225 if s: 11226 Z3_solver_propagate_init(self.ctx_ref(), 11227 s.solver, 11228 ctypes.c_void_p(self.id), 11229 _user_prop_push, 11230 _user_prop_pop, 11231 _user_prop_fresh) 11232 11233 def __del__(self): 11234 if self._ctx: 11235 self._ctx.ctx = None 11236 11237 def ctx(self): 11238 if self._ctx: 11239 return self._ctx 11240 else: 11241 return self.solver.ctx 11242 11243 def ctx_ref(self): 11244 return self.ctx().ref() 11245 11246 def add_fixed(self, fixed): 11247 assert not self.fixed 11248 assert not self._ctx 11249 Z3_solver_propagate_fixed(self.ctx_ref(), self.solver.solver, _user_prop_fixed) 11250 self.fixed = fixed 11251 11252 def add_final(self, final): 11253 assert not self.final 11254 assert not self._ctx 11255 Z3_solver_propagate_final(self.ctx_ref(), self.solver.solver, _user_prop_final) 11256 self.final = final 11257 11258 def add_eq(self, eq): 11259 assert not self.eq 11260 assert not self._ctx 11261 Z3_solver_propagate_eq(self.ctx_ref(), self.solver.solver, _user_prop_eq) 11262 self.eq = eq 11263 11264 def add_diseq(self, diseq): 11265 assert not self.diseq 11266 assert not self._ctx 11267 Z3_solver_propagate_diseq(self.ctx_ref(), self.solver.solver, _user_prop_diseq) 11268 self.diseq = diseq 11269 11270 def push(self): 11271 raise Z3Exception("push needs to be overwritten") 11272 11273 def pop(self, num_scopes): 11274 raise Z3Exception("pop needs to be overwritten") 11275 11276 def fresh(self): 11277 raise Z3Exception("fresh needs to be overwritten") 11278 11279 def add(self, e): 11280 assert self.solver 11281 assert not self._ctx 11282 return Z3_solver_propagate_register(self.ctx_ref(), self.solver.solver, e.ast) 11283 11284 # 11285 # Propagation can only be invoked as during a fixed or final callback. 11286 # 11287 def propagate(self, e, ids, eqs=[]): 11288 num_fixed = len(ids) 11289 _ids = (ctypes.c_uint * num_fixed)() 11290 for i in range(num_fixed): 11291 _ids[i] = ids[i] 11292 num_eqs = len(eqs) 11293 _lhs = (ctypes.c_uint * num_eqs)() 11294 _rhs = (ctypes.c_uint * num_eqs)() 11295 for i in range(num_eqs): 11296 _lhs[i] = eqs[i][0] 11297 _rhs[i] = eqs[i][1] 11298 Z3_solver_propagate_consequence(e.ctx.ref(), ctypes.c_void_p( 11299 self.cb), num_fixed, _ids, num_eqs, _lhs, _rhs, e.ast) 11300 11301 def conflict(self, ids): 11302 self.propagate(BoolVal(False, self.ctx()), ids, eqs=[]) 11303