3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00

Fix some PEP-8 violations in Python code (#5295)

* reformat python code using autopep8

* manually wrap some too long lines and adjust some checks

* run autopep8 in aggressive mode

* run autopep8 in very aggressive mode

* manually reformat z3types.py

* unify: use double quotes

* use sys.version_info instead of sys.version

* drop accidentally commited src/util/z3_version.h
This commit is contained in:
Gram 2021-05-23 19:27:55 +02:00 committed by GitHub
parent f1545b04d2
commit 3d8865d925
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 1669 additions and 910 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
############################################ ############################################
# Copyright (c) 2012 Microsoft Corporation # Copyright (c) 2012 Microsoft Corporation
# #
# Z3 Python interface for Z3 numerals # Z3 Python interface for Z3 numerals
# #
# Author: Leonardo de Moura (leonardo) # Author: Leonardo de Moura (leonardo)
@ -12,18 +12,20 @@ from fractions import Fraction
from .z3 import _get_ctx from .z3 import _get_ctx
def _to_numeral(num, ctx=None): def _to_numeral(num, ctx=None):
if isinstance(num, Numeral): if isinstance(num, Numeral):
return num return num
else: else:
return Numeral(num, ctx) return Numeral(num, ctx)
class Numeral: class Numeral:
""" """
A Z3 numeral can be used to perform computations over arbitrary A Z3 numeral can be used to perform computations over arbitrary
precision integers, rationals and real algebraic numbers. precision integers, rationals and real algebraic numbers.
It also automatically converts python numeric values. It also automatically converts python numeric values.
>>> Numeral(2) >>> Numeral(2)
2 2
>>> Numeral("3/2") + 1 >>> Numeral("3/2") + 1
@ -35,9 +37,9 @@ class Numeral:
>>> Numeral(Sqrt(2)) + Numeral(Sqrt(3)) >>> Numeral(Sqrt(2)) + Numeral(Sqrt(3))
3.1462643699? 3.1462643699?
Z3 numerals can be used to perform computations with Z3 numerals can be used to perform computations with
values in a Z3 model. values in a Z3 model.
>>> s = Solver() >>> s = Solver()
>>> x = Real('x') >>> x = Real('x')
>>> s.add(x*x == 2) >>> s.add(x*x == 2)
@ -49,34 +51,34 @@ class Numeral:
1.4142135623? 1.4142135623?
>>> m[x] + 1 >>> m[x] + 1
1.4142135623? + 1 1.4142135623? + 1
The previous result is a Z3 expression. The previous result is a Z3 expression.
>>> (m[x] + 1).sexpr() >>> (m[x] + 1).sexpr()
'(+ (root-obj (+ (^ x 2) (- 2)) 2) 1.0)' '(+ (root-obj (+ (^ x 2) (- 2)) 2) 1.0)'
>>> Numeral(m[x]) + 1 >>> Numeral(m[x]) + 1
2.4142135623? 2.4142135623?
>>> Numeral(m[x]).is_pos() >>> Numeral(m[x]).is_pos()
True True
>>> Numeral(m[x])**2 >>> Numeral(m[x])**2
2 2
We can also isolate the roots of polynomials. We can also isolate the roots of polynomials.
>>> x0, x1, x2 = RealVarVector(3) >>> x0, x1, x2 = RealVarVector(3)
>>> r0 = isolate_roots(x0**5 - x0 - 1) >>> r0 = isolate_roots(x0**5 - x0 - 1)
>>> r0 >>> r0
[1.1673039782?] [1.1673039782?]
In the following example, we are isolating the roots In the following example, we are isolating the roots
of a univariate polynomial (on x1) obtained after substituting of a univariate polynomial (on x1) obtained after substituting
x0 -> r0[0] x0 -> r0[0]
>>> r1 = isolate_roots(x1**2 - x0 + 1, [ r0[0] ]) >>> r1 = isolate_roots(x1**2 - x0 + 1, [ r0[0] ])
>>> r1 >>> r1
[-0.4090280898?, 0.4090280898?] [-0.4090280898?, 0.4090280898?]
Similarly, in the next example we isolate the roots of Similarly, in the next example we isolate the roots of
a univariate polynomial (on x2) obtained after substituting a univariate polynomial (on x2) obtained after substituting
x0 -> r0[0] and x1 -> r1[0] x0 -> r0[0] and x1 -> r1[0]
@ -85,10 +87,11 @@ class Numeral:
[2.8538479564?] [2.8538479564?]
""" """
def __init__(self, num, ctx=None): def __init__(self, num, ctx=None):
if isinstance(num, Ast): if isinstance(num, Ast):
self.ast = num self.ast = num
self.ctx = _get_ctx(ctx) self.ctx = _get_ctx(ctx)
elif isinstance(num, RatNumRef) or isinstance(num, AlgebraicNumRef): elif isinstance(num, RatNumRef) or isinstance(num, AlgebraicNumRef):
self.ast = num.ast self.ast = num.ast
self.ctx = num.ctx self.ctx = num.ctx
@ -102,13 +105,13 @@ class Numeral:
self.ctx = v.ctx self.ctx = v.ctx
Z3_inc_ref(self.ctx_ref(), self.as_ast()) Z3_inc_ref(self.ctx_ref(), self.as_ast())
assert Z3_algebraic_is_value(self.ctx_ref(), self.ast) assert Z3_algebraic_is_value(self.ctx_ref(), self.ast)
def __del__(self): def __del__(self):
Z3_dec_ref(self.ctx_ref(), self.as_ast()) Z3_dec_ref(self.ctx_ref(), self.as_ast())
def is_integer(self): def is_integer(self):
""" Return True if the numeral is integer. """ Return True if the numeral is integer.
>>> Numeral(2).is_integer() >>> Numeral(2).is_integer()
True True
>>> (Numeral(Sqrt(2)) * Numeral(Sqrt(2))).is_integer() >>> (Numeral(Sqrt(2)) * Numeral(Sqrt(2))).is_integer()
@ -129,13 +132,13 @@ class Numeral:
True True
>>> Numeral(Sqrt(2)).is_rational() >>> Numeral(Sqrt(2)).is_rational()
False False
""" """
return Z3_get_ast_kind(self.ctx_ref(), self.as_ast()) == Z3_NUMERAL_AST return Z3_get_ast_kind(self.ctx_ref(), self.as_ast()) == Z3_NUMERAL_AST
def denominator(self): def denominator(self):
""" Return the denominator if `self` is rational. """ Return the denominator if `self` is rational.
>>> Numeral("2/3").denominator() >>> Numeral("2/3").denominator()
3 3
""" """
@ -144,14 +147,13 @@ class Numeral:
def numerator(self): def numerator(self):
""" Return the numerator if `self` is rational. """ Return the numerator if `self` is rational.
>>> Numeral("2/3").numerator() >>> Numeral("2/3").numerator()
2 2
""" """
assert(self.is_rational()) assert(self.is_rational())
return Numeral(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx) return Numeral(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx)
def is_irrational(self): def is_irrational(self):
""" Return True if the numeral is irrational. """ Return True if the numeral is irrational.
@ -169,7 +171,7 @@ class Numeral:
""" """
assert(self.is_integer()) assert(self.is_integer())
if sys.version_info[0] >= 3: if sys.version_info.major >= 3:
return int(Z3_get_numeral_string(self.ctx_ref(), self.as_ast())) return int(Z3_get_numeral_string(self.ctx_ref(), self.as_ast()))
else: else:
return long(Z3_get_numeral_string(self.ctx_ref(), self.as_ast())) return long(Z3_get_numeral_string(self.ctx_ref(), self.as_ast()))
@ -183,9 +185,9 @@ class Numeral:
return Fraction(self.numerator().as_long(), self.denominator().as_long()) return Fraction(self.numerator().as_long(), self.denominator().as_long())
def approx(self, precision=10): def approx(self, precision=10):
"""Return a numeral that approximates the numeral `self`. """Return a numeral that approximates the numeral `self`.
The result `r` is such that |r - self| <= 1/10^precision The result `r` is such that |r - self| <= 1/10^precision
If `self` is rational, then the result is `self`. If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2) >>> x = Numeral(2).root(2)
@ -199,9 +201,9 @@ class Numeral:
return self.upper(precision) return self.upper(precision)
def upper(self, precision=10): def upper(self, precision=10):
"""Return a upper bound that approximates the numeral `self`. """Return a upper bound that approximates the numeral `self`.
The result `r` is such that r - self <= 1/10^precision The result `r` is such that r - self <= 1/10^precision
If `self` is rational, then the result is `self`. If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2) >>> x = Numeral(2).root(2)
@ -218,9 +220,9 @@ class Numeral:
return Numeral(Z3_get_algebraic_number_upper(self.ctx_ref(), self.as_ast(), precision), self.ctx) return Numeral(Z3_get_algebraic_number_upper(self.ctx_ref(), self.as_ast(), precision), self.ctx)
def lower(self, precision=10): def lower(self, precision=10):
"""Return a lower bound that approximates the numeral `self`. """Return a lower bound that approximates the numeral `self`.
The result `r` is such that self - r <= 1/10^precision The result `r` is such that self - r <= 1/10^precision
If `self` is rational, then the result is `self`. If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2) >>> x = Numeral(2).root(2)
@ -236,7 +238,7 @@ class Numeral:
def sign(self): def sign(self):
""" Return the sign of the numeral. """ Return the sign of the numeral.
>>> Numeral(2).sign() >>> Numeral(2).sign()
1 1
>>> Numeral(-3).sign() >>> Numeral(-3).sign()
@ -245,10 +247,10 @@ class Numeral:
0 0
""" """
return Z3_algebraic_sign(self.ctx_ref(), self.ast) return Z3_algebraic_sign(self.ctx_ref(), self.ast)
def is_pos(self): def is_pos(self):
""" Return True if the numeral is positive. """ Return True if the numeral is positive.
>>> Numeral(2).is_pos() >>> Numeral(2).is_pos()
True True
>>> Numeral(-3).is_pos() >>> Numeral(-3).is_pos()
@ -260,7 +262,7 @@ class Numeral:
def is_neg(self): def is_neg(self):
""" Return True if the numeral is negative. """ Return True if the numeral is negative.
>>> Numeral(2).is_neg() >>> Numeral(2).is_neg()
False False
>>> Numeral(-3).is_neg() >>> Numeral(-3).is_neg()
@ -272,7 +274,7 @@ class Numeral:
def is_zero(self): def is_zero(self):
""" Return True if the numeral is zero. """ Return True if the numeral is zero.
>>> Numeral(2).is_zero() >>> Numeral(2).is_zero()
False False
>>> Numeral(-3).is_zero() >>> Numeral(-3).is_zero()
@ -353,7 +355,7 @@ class Numeral:
def __rdiv__(self, other): def __rdiv__(self, other):
""" Return the numeral `other / self`. """ Return the numeral `other / self`.
>>> 3 / Numeral(2) >>> 3 / Numeral(2)
3/2 3/2
>>> 3 / Numeral(2).root(2) >>> 3 / Numeral(2).root(2)
2.1213203435? 2.1213203435?
@ -388,7 +390,7 @@ class Numeral:
3 3
""" """
return Numeral(Z3_algebraic_power(self.ctx_ref(), self.ast, k), self.ctx) return Numeral(Z3_algebraic_power(self.ctx_ref(), self.ast, k), self.ctx)
def __pow__(self, k): def __pow__(self, k):
""" Return the numeral `self^k`. """ Return the numeral `self^k`.
@ -415,7 +417,7 @@ class Numeral:
def __rlt__(self, other): def __rlt__(self, other):
""" Return True if `other < self`. """ Return True if `other < self`.
>>> 2 < Numeral(Sqrt(2)) >>> 2 < Numeral(Sqrt(2))
False False
""" """
return self > other return self > other
@ -440,7 +442,6 @@ class Numeral:
""" """
return self < other return self < other
def __le__(self, other): def __le__(self, other):
""" Return True if `self <= other`. """ Return True if `self <= other`.
@ -456,7 +457,7 @@ class Numeral:
def __rle__(self, other): def __rle__(self, other):
""" Return True if `other <= self`. """ Return True if `other <= self`.
>>> 2 <= Numeral(Sqrt(2)) >>> 2 <= Numeral(Sqrt(2))
False False
""" """
return self >= other return self >= other
@ -523,13 +524,14 @@ class Numeral:
def ctx_ref(self): def ctx_ref(self):
return self.ctx.ref() return self.ctx.ref()
def eval_sign_at(p, vs): def eval_sign_at(p, vs):
""" """
Evaluate the sign of the polynomial `p` at `vs`. `p` is a Z3 Evaluate the sign of the polynomial `p` at `vs`. `p` is a Z3
Expression containing arithmetic operators: +, -, *, ^k where k is Expression containing arithmetic operators: +, -, *, ^k where k is
an integer; and free variables x that is_var(x) is True. Moreover, an integer; and free variables x that is_var(x) is True. Moreover,
all variables must be real. all variables must be real.
The result is 1 if the polynomial is positive at the given point, The result is 1 if the polynomial is positive at the given point,
-1 if negative, and 0 if zero. -1 if negative, and 0 if zero.
@ -547,15 +549,16 @@ def eval_sign_at(p, vs):
_vs[i] = vs[i].ast _vs[i] = vs[i].ast
return Z3_algebraic_eval(p.ctx_ref(), p.as_ast(), num, _vs) return Z3_algebraic_eval(p.ctx_ref(), p.as_ast(), num, _vs)
def isolate_roots(p, vs=[]): def isolate_roots(p, vs=[]):
""" """
Given a multivariate polynomial p(x_0, ..., x_{n-1}, x_n), returns the Given a multivariate polynomial p(x_0, ..., x_{n-1}, x_n), returns the
roots of the univariate polynomial p(vs[0], ..., vs[len(vs)-1], x_n). roots of the univariate polynomial p(vs[0], ..., vs[len(vs)-1], x_n).
Remarks: Remarks:
* p is a Z3 expression that contains only arithmetic terms and free variables. * p is a Z3 expression that contains only arithmetic terms and free variables.
* forall i in [0, n) vs is a numeral. * forall i in [0, n) vs is a numeral.
The result is a list of numerals The result is a list of numerals
>>> x0 = RealVar(0) >>> x0 = RealVar(0)
@ -573,5 +576,4 @@ def isolate_roots(p, vs=[]):
for i in range(num): for i in range(num):
_vs[i] = vs[i].ast _vs[i] = vs[i].ast
_roots = AstVector(Z3_algebraic_roots(p.ctx_ref(), p.as_ast(), num, _vs), p.ctx) _roots = AstVector(Z3_algebraic_roots(p.ctx_ref(), p.as_ast(), num, _vs), p.ctx)
return [ Numeral(r) for r in _roots ] return [Numeral(r) for r in _roots]

View file

@ -1,6 +1,6 @@
############################################ ############################################
# Copyright (c) 2012 Microsoft Corporation # Copyright (c) 2012 Microsoft Corporation
# #
# Z3 Python interface for Z3 polynomials # Z3 Python interface for Z3 polynomials
# #
# Author: Leonardo de Moura (leonardo) # Author: Leonardo de Moura (leonardo)
@ -8,16 +8,17 @@
from .z3 import * from .z3 import *
def subresultants(p, q, x): def subresultants(p, q, x):
""" """
Return the non-constant subresultants of 'p' and 'q' with respect to the "variable" 'x'. Return the non-constant subresultants of 'p' and 'q' with respect to the "variable" 'x'.
'p', 'q' and 'x' are Z3 expressions where 'p' and 'q' are arithmetic terms. 'p', 'q' and 'x' are Z3 expressions where 'p' and 'q' are arithmetic terms.
Note that, any subterm that cannot be viewed as a polynomial is assumed to be a variable. Note that, any subterm that cannot be viewed as a polynomial is assumed to be a variable.
Example: f(a) is a considered to be a variable b in the polynomial Example: f(a) is a considered to be a variable b in the polynomial
f(a)*f(a) + 2*f(a) + 1
f(a)*f(a) + 2*f(a) + 1
>>> x, y = Reals('x y') >>> x, y = Reals('x y')
>>> subresultants(2*x + y, 3*x - 2*y + 2, x) >>> subresultants(2*x + y, 3*x - 2*y + 2, x)
[-7*y + 4] [-7*y + 4]
@ -29,6 +30,7 @@ def subresultants(p, q, x):
""" """
return AstVector(Z3_polynomial_subresultants(p.ctx_ref(), p.as_ast(), q.as_ast(), x.as_ast()), p.ctx) return AstVector(Z3_polynomial_subresultants(p.ctx_ref(), p.as_ast(), q.as_ast(), x.as_ast()), p.ctx)
if __name__ == "__main__": if __name__ == "__main__":
import doctest import doctest
if doctest.testmod().failed: if doctest.testmod().failed:

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
############################################ ############################################
# Copyright (c) 2013 Microsoft Corporation # Copyright (c) 2013 Microsoft Corporation
# #
# Z3 Python interface for Z3 Real Closed Fields # Z3 Python interface for Z3 Real Closed Fields
# that may contain # that may contain
# - computable transcendentals # - computable transcendentals
# - infinitesimals # - infinitesimals
# - algebraic extensions # - algebraic extensions
@ -14,42 +14,48 @@ from .z3core import *
from .z3printer import * from .z3printer import *
from fractions import Fraction from fractions import Fraction
def _to_rcfnum(num, ctx=None): def _to_rcfnum(num, ctx=None):
if isinstance(num, RCFNum): if isinstance(num, RCFNum):
return num return num
else: else:
return RCFNum(num, ctx) return RCFNum(num, ctx)
def Pi(ctx=None): def Pi(ctx=None):
ctx = z3.get_ctx(ctx) ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_pi(ctx.ref()), ctx) return RCFNum(Z3_rcf_mk_pi(ctx.ref()), ctx)
def E(ctx=None): def E(ctx=None):
ctx = z3.get_ctx(ctx) ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_e(ctx.ref()), ctx) return RCFNum(Z3_rcf_mk_e(ctx.ref()), ctx)
def MkInfinitesimal(name="eps", ctx=None): def MkInfinitesimal(name="eps", ctx=None):
# Todo: remove parameter name. # Todo: remove parameter name.
# For now, we keep it for backward compatibility. # For now, we keep it for backward compatibility.
ctx = z3.get_ctx(ctx) ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_infinitesimal(ctx.ref()), ctx) return RCFNum(Z3_rcf_mk_infinitesimal(ctx.ref()), ctx)
def MkRoots(p, ctx=None): def MkRoots(p, ctx=None):
ctx = z3.get_ctx(ctx) ctx = z3.get_ctx(ctx)
num = len(p) num = len(p)
_tmp = [] _tmp = []
_as = (RCFNumObj * num)() _as = (RCFNumObj * num)()
_rs = (RCFNumObj * num)() _rs = (RCFNumObj * num)()
for i in range(num): for i in range(num):
_a = _to_rcfnum(p[i], ctx) _a = _to_rcfnum(p[i], ctx)
_tmp.append(_a) # prevent GC _tmp.append(_a) # prevent GC
_as[i] = _a.num _as[i] = _a.num
nr = Z3_rcf_mk_roots(ctx.ref(), num, _as, _rs) nr = Z3_rcf_mk_roots(ctx.ref(), num, _as, _rs)
r = [] r = []
for i in range(nr): for i in range(nr):
r.append(RCFNum(_rs[i], ctx)) r.append(RCFNum(_rs[i], ctx))
return r return r
class RCFNum: class RCFNum:
def __init__(self, num, ctx=None): def __init__(self, num, ctx=None):
# TODO: add support for converting AST numeral values into RCFNum # TODO: add support for converting AST numeral values into RCFNum
@ -65,7 +71,7 @@ class RCFNum:
def ctx_ref(self): def ctx_ref(self):
return self.ctx.ref() return self.ctx.ref()
def __repr__(self): def __repr__(self):
return Z3_rcf_num_to_string(self.ctx_ref(), self.num, False, in_html_mode()) return Z3_rcf_num_to_string(self.ctx_ref(), self.num, False, in_html_mode())
@ -112,10 +118,10 @@ class RCFNum:
def __pow__(self, k): def __pow__(self, k):
return self.power(k) return self.power(k)
def decimal(self, prec=5): def decimal(self, prec=5):
return Z3_rcf_num_to_decimal_string(self.ctx_ref(), self.num, prec) return Z3_rcf_num_to_decimal_string(self.ctx_ref(), self.num, prec)
def __lt__(self, other): def __lt__(self, other):
v = _to_rcfnum(other, self.ctx) v = _to_rcfnum(other, self.ctx)
return Z3_rcf_lt(self.ctx_ref(), self.num, v.num) return Z3_rcf_lt(self.ctx_ref(), self.num, v.num)

View file

@ -1,6 +1,6 @@
############################################ ############################################
# Copyright (c) 2012 Microsoft Corporation # Copyright (c) 2012 Microsoft Corporation
# #
# Z3 Python interface # Z3 Python interface
# #
# Author: Leonardo de Moura (leonardo) # Author: Leonardo de Moura (leonardo)
@ -8,123 +8,234 @@
import ctypes import ctypes
class Z3Exception(Exception): class Z3Exception(Exception):
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
def __str__(self): def __str__(self):
return str(self.value) return str(self.value)
class ContextObj(ctypes.c_void_p): class ContextObj(ctypes.c_void_p):
def __init__(self, context): self._as_parameter_ = context def __init__(self, context):
def from_param(obj): return obj self._as_parameter_ = context
def from_param(obj):
return obj
class Config(ctypes.c_void_p): class Config(ctypes.c_void_p):
def __init__(self, config): self._as_parameter_ = config def __init__(self, config):
def from_param(obj): return obj self._as_parameter_ = config
def from_param(obj):
return obj
class Symbol(ctypes.c_void_p): class Symbol(ctypes.c_void_p):
def __init__(self, symbol): self._as_parameter_ = symbol def __init__(self, symbol):
def from_param(obj): return obj self._as_parameter_ = symbol
def from_param(obj):
return obj
class Sort(ctypes.c_void_p): class Sort(ctypes.c_void_p):
def __init__(self, sort): self._as_parameter_ = sort def __init__(self, sort):
def from_param(obj): return obj self._as_parameter_ = sort
def from_param(obj):
return obj
class FuncDecl(ctypes.c_void_p): class FuncDecl(ctypes.c_void_p):
def __init__(self, decl): self._as_parameter_ = decl def __init__(self, decl):
def from_param(obj): return obj self._as_parameter_ = decl
def from_param(obj):
return obj
class Ast(ctypes.c_void_p): class Ast(ctypes.c_void_p):
def __init__(self, ast): self._as_parameter_ = ast def __init__(self, ast):
def from_param(obj): return obj self._as_parameter_ = ast
def from_param(obj):
return obj
class Pattern(ctypes.c_void_p): class Pattern(ctypes.c_void_p):
def __init__(self, pattern): self._as_parameter_ = pattern def __init__(self, pattern):
def from_param(obj): return obj self._as_parameter_ = pattern
def from_param(obj):
return obj
class Model(ctypes.c_void_p): class Model(ctypes.c_void_p):
def __init__(self, model): self._as_parameter_ = model def __init__(self, model):
def from_param(obj): return obj self._as_parameter_ = model
def from_param(obj):
return obj
class Literals(ctypes.c_void_p): class Literals(ctypes.c_void_p):
def __init__(self, literals): self._as_parameter_ = literals def __init__(self, literals):
def from_param(obj): return obj self._as_parameter_ = literals
def from_param(obj):
return obj
class Constructor(ctypes.c_void_p): class Constructor(ctypes.c_void_p):
def __init__(self, constructor): self._as_parameter_ = constructor def __init__(self, constructor):
def from_param(obj): return obj self._as_parameter_ = constructor
def from_param(obj):
return obj
class ConstructorList(ctypes.c_void_p): class ConstructorList(ctypes.c_void_p):
def __init__(self, constructor_list): self._as_parameter_ = constructor_list def __init__(self, constructor_list):
def from_param(obj): return obj self._as_parameter_ = constructor_list
def from_param(obj):
return obj
class GoalObj(ctypes.c_void_p): class GoalObj(ctypes.c_void_p):
def __init__(self, goal): self._as_parameter_ = goal def __init__(self, goal):
def from_param(obj): return obj self._as_parameter_ = goal
def from_param(obj):
return obj
class TacticObj(ctypes.c_void_p): class TacticObj(ctypes.c_void_p):
def __init__(self, tactic): self._as_parameter_ = tactic def __init__(self, tactic):
def from_param(obj): return obj self._as_parameter_ = tactic
def from_param(obj):
return obj
class ProbeObj(ctypes.c_void_p): class ProbeObj(ctypes.c_void_p):
def __init__(self, probe): self._as_parameter_ = probe def __init__(self, probe):
def from_param(obj): return obj self._as_parameter_ = probe
def from_param(obj):
return obj
class ApplyResultObj(ctypes.c_void_p): class ApplyResultObj(ctypes.c_void_p):
def __init__(self, obj): self._as_parameter_ = obj def __init__(self, obj):
def from_param(obj): return obj self._as_parameter_ = obj
def from_param(obj):
return obj
class StatsObj(ctypes.c_void_p): class StatsObj(ctypes.c_void_p):
def __init__(self, statistics): self._as_parameter_ = statistics def __init__(self, statistics):
def from_param(obj): return obj self._as_parameter_ = statistics
def from_param(obj):
return obj
class SolverObj(ctypes.c_void_p): class SolverObj(ctypes.c_void_p):
def __init__(self, solver): self._as_parameter_ = solver def __init__(self, solver):
def from_param(obj): return obj self._as_parameter_ = solver
def from_param(obj):
return obj
class SolverCallbackObj(ctypes.c_void_p): class SolverCallbackObj(ctypes.c_void_p):
def __init__(self, solver): self._as_parameter_ = solver def __init__(self, solver):
def from_param(obj): return obj self._as_parameter_ = solver
def from_param(obj):
return obj
class FixedpointObj(ctypes.c_void_p): class FixedpointObj(ctypes.c_void_p):
def __init__(self, fixedpoint): self._as_parameter_ = fixedpoint def __init__(self, fixedpoint):
def from_param(obj): return obj self._as_parameter_ = fixedpoint
def from_param(obj):
return obj
class OptimizeObj(ctypes.c_void_p): class OptimizeObj(ctypes.c_void_p):
def __init__(self, optimize): self._as_parameter_ = optimize def __init__(self, optimize):
def from_param(obj): return obj self._as_parameter_ = optimize
def from_param(obj):
return obj
class ModelObj(ctypes.c_void_p): class ModelObj(ctypes.c_void_p):
def __init__(self, model): self._as_parameter_ = model def __init__(self, model):
def from_param(obj): return obj self._as_parameter_ = model
def from_param(obj):
return obj
class AstVectorObj(ctypes.c_void_p): class AstVectorObj(ctypes.c_void_p):
def __init__(self, vector): self._as_parameter_ = vector def __init__(self, vector):
def from_param(obj): return obj self._as_parameter_ = vector
def from_param(obj):
return obj
class AstMapObj(ctypes.c_void_p): class AstMapObj(ctypes.c_void_p):
def __init__(self, ast_map): self._as_parameter_ = ast_map def __init__(self, ast_map):
def from_param(obj): return obj self._as_parameter_ = ast_map
def from_param(obj):
return obj
class Params(ctypes.c_void_p): class Params(ctypes.c_void_p):
def __init__(self, params): self._as_parameter_ = params def __init__(self, params):
def from_param(obj): return obj self._as_parameter_ = params
def from_param(obj):
return obj
class ParamDescrs(ctypes.c_void_p): class ParamDescrs(ctypes.c_void_p):
def __init__(self, paramdescrs): self._as_parameter_ = paramdescrs def __init__(self, paramdescrs):
def from_param(obj): return obj self._as_parameter_ = paramdescrs
def from_param(obj):
return obj
class FuncInterpObj(ctypes.c_void_p): class FuncInterpObj(ctypes.c_void_p):
def __init__(self, f): self._as_parameter_ = f def __init__(self, f):
def from_param(obj): return obj self._as_parameter_ = f
def from_param(obj):
return obj
class FuncEntryObj(ctypes.c_void_p): class FuncEntryObj(ctypes.c_void_p):
def __init__(self, e): self._as_parameter_ = e def __init__(self, e):
def from_param(obj): return obj self._as_parameter_ = e
def from_param(obj):
return obj
class RCFNumObj(ctypes.c_void_p): class RCFNumObj(ctypes.c_void_p):
def __init__(self, e): self._as_parameter_ = e def __init__(self, e):
def from_param(obj): return obj self._as_parameter_ = e
def from_param(obj):
return obj

View file

@ -1,21 +1,22 @@
############################################ ############################################
# Copyright (c) 2012 Microsoft Corporation # Copyright (c) 2012 Microsoft Corporation
# #
# Z3 Python interface # Z3 Python interface
# #
# Authors: Leonardo de Moura (leonardo) # Authors: Leonardo de Moura (leonardo)
# ThanhVu (Vu) Nguyen <tnguyen@cs.unm.edu> # ThanhVu (Vu) Nguyen <tnguyen@cs.unm.edu>
############################################ ############################################
""" """
Usage: Usage:
import common_z3 as CM_Z3 import common_z3 as CM_Z3
""" """
import ctypes import ctypes
from .z3 import * from .z3 import *
def vset(seq, idfun=None, as_list=True): def vset(seq, idfun=None, as_list=True):
# This functions preserves the order of arguments while removing duplicates. # This functions preserves the order of arguments while removing duplicates.
# This function is from https://code.google.com/p/common-python-vu/source/browse/vu_common.py # This function is from https://code.google.com/p/common-python-vu/source/browse/vu_common.py
# (Thanhu's personal code). It has been copied here to avoid a dependency on vu_common.py. # (Thanhu's personal code). It has been copied here to avoid a dependency on vu_common.py.
""" """
@ -24,36 +25,36 @@ def vset(seq, idfun=None, as_list=True):
>>> vset([[11,2],1, [10,['9',1]],2, 1, [11,2],[3,3],[10,99],1,[10,['9',1]]],idfun=repr) >>> vset([[11,2],1, [10,['9',1]],2, 1, [11,2],[3,3],[10,99],1,[10,['9',1]]],idfun=repr)
[[11, 2], 1, [10, ['9', 1]], 2, [3, 3], [10, 99]] [[11, 2], 1, [10, ['9', 1]], 2, [3, 3], [10, 99]]
""" """
def _uniq_normal(seq): def _uniq_normal(seq):
d_ = {} d_ = {}
for s in seq: for s in seq:
if s not in d_: if s not in d_:
d_[s] = None d_[s] = None
yield s yield s
def _uniq_idfun(seq,idfun): def _uniq_idfun(seq, idfun):
d_ = {} d_ = {}
for s in seq: for s in seq:
h_ = idfun(s) h_ = idfun(s)
if h_ not in d_: if h_ not in d_:
d_[h_] = None d_[h_] = None
yield s yield s
if idfun is None: if idfun is None:
res = _uniq_normal(seq) res = _uniq_normal(seq)
else: else:
res = _uniq_idfun(seq,idfun) res = _uniq_idfun(seq, idfun)
return list(res) if as_list else res return list(res) if as_list else res
def get_z3_version(as_str=False): def get_z3_version(as_str=False):
major = ctypes.c_uint(0) major = ctypes.c_uint(0)
minor = ctypes.c_uint(0) minor = ctypes.c_uint(0)
build = ctypes.c_uint(0) build = ctypes.c_uint(0)
rev = ctypes.c_uint(0) rev = ctypes.c_uint(0)
Z3_get_version(major,minor, build, rev) Z3_get_version(major, minor, build, rev)
rs = map(int, (major.value, minor.value, build.value, rev.value)) rs = map(int, (major.value, minor.value, build.value, rev.value))
if as_str: if as_str:
return "{}.{}.{}.{}".format(*rs) return "{}.{}.{}.{}".format(*rs)
@ -64,9 +65,9 @@ def get_z3_version(as_str=False):
def ehash(v): def ehash(v):
""" """
Returns a 'stronger' hash value than the default hash() method. Returns a 'stronger' hash value than the default hash() method.
The result from hash() is not enough to distinguish between 2 The result from hash() is not enough to distinguish between 2
z3 expressions in some cases. z3 expressions in some cases.
Note: the following doctests will fail with Python 2.x as the Note: the following doctests will fail with Python 2.x as the
default formatting doesn't match that of 3.x. default formatting doesn't match that of 3.x.
>>> x1 = Bool('x'); x2 = Bool('x'); x3 = Int('x') >>> x1 = Bool('x'); x2 = Bool('x'); x3 = Int('x')
@ -74,7 +75,7 @@ def ehash(v):
783810685 783810685 783810685 783810685 783810685 783810685
>>> print(ehash(x1), ehash(x2), ehash(x3)) >>> print(ehash(x1), ehash(x2), ehash(x3))
x_783810685_1 x_783810685_1 x_783810685_2 x_783810685_1 x_783810685_1 x_783810685_2
""" """
if z3_debug(): if z3_debug():
assert is_expr(v) assert is_expr(v)
@ -83,10 +84,11 @@ def ehash(v):
""" """
In Z3, variables are called *uninterpreted* consts and In Z3, variables are called *uninterpreted* consts and
variables are *interpreted* consts. variables are *interpreted* consts.
""" """
def is_expr_var(v): def is_expr_var(v):
""" """
EXAMPLES: EXAMPLES:
@ -111,7 +113,8 @@ def is_expr_var(v):
True True
""" """
return is_const(v) and v.decl().kind()==Z3_OP_UNINTERPRETED return is_const(v) and v.decl().kind() == Z3_OP_UNINTERPRETED
def is_expr_val(v): def is_expr_val(v):
""" """
@ -135,13 +138,11 @@ def is_expr_val(v):
False False
>>> is_expr_val(SafetyInjection) >>> is_expr_val(SafetyInjection)
False False
""" """
return is_const(v) and v.decl().kind()!=Z3_OP_UNINTERPRETED return is_const(v) and v.decl().kind() != Z3_OP_UNINTERPRETED
def get_vars(f, rs=None):
def get_vars(f, rs = None):
""" """
>>> x,y = Ints('x y') >>> x,y = Ints('x y')
>>> a,b = Bools('a b') >>> a,b = Bools('a b')
@ -151,15 +152,15 @@ def get_vars(f, rs = None):
""" """
if rs is None: if rs is None:
rs = [] rs = []
if z3_debug(): if z3_debug():
assert is_expr(f) assert is_expr(f)
if is_const(f): if is_const(f):
if is_expr_val(f): if is_expr_val(f):
return rs return rs
else: #variable else: # variable
return vset(rs + [f],str) return vset(rs + [f], str)
else: else:
for f_ in f.children(): for f_ in f.children():
@ -168,7 +169,6 @@ def get_vars(f, rs = None):
return vset(rs, str) return vset(rs, str)
def mk_var(name, vsort): def mk_var(name, vsort):
if vsort.kind() == Z3_INT_SORT: if vsort.kind() == Z3_INT_SORT:
v = Int(name) v = Int(name)
@ -179,13 +179,12 @@ def mk_var(name, vsort):
elif vsort.kind() == Z3_DATATYPE_SORT: elif vsort.kind() == Z3_DATATYPE_SORT:
v = Const(name, vsort) v = Const(name, vsort)
else: else:
raise TypeError('Cannot handle this sort (s: %sid: %d)' %(vsort,vsort.kind())) raise TypeError("Cannot handle this sort (s: %sid: %d)" % (vsort, vsort.kind()))
return v return v
def prove(claim, assume=None, verbose=0):
def prove(claim,assume=None,verbose=0):
""" """
>>> r,m = prove(BoolVal(True),verbose=0); r,model_str(m,as_str=False) >>> r,m = prove(BoolVal(True),verbose=0); r,model_str(m,as_str=False)
(True, None) (True, None)
@ -204,11 +203,11 @@ def prove(claim,assume=None,verbose=0):
AssertionError: Assumption is always False! AssertionError: Assumption is always False!
>>> r,m = prove(Implies(x,x),assume=y,verbose=2); r,model_str(m,as_str=False) >>> r,m = prove(Implies(x,x),assume=y,verbose=2); r,model_str(m,as_str=False)
assume: assume:
y y
claim: claim:
Implies(x, x) Implies(x, x)
to_prove: to_prove:
Implies(y, Implies(x, x)) Implies(y, Implies(x, x))
(True, None) (True, None)
@ -236,52 +235,52 @@ def prove(claim,assume=None,verbose=0):
to_prove = claim to_prove = claim
if assume: if assume:
if z3_debug(): if z3_debug():
is_proved,_ = prove(Not(assume)) is_proved, _ = prove(Not(assume))
def _f(): def _f():
emsg = "Assumption is always False!" emsg = "Assumption is always False!"
if verbose >= 2: if verbose >= 2:
emsg = "{}\n{}".format(assume,emsg) emsg = "{}\n{}".format(assume, emsg)
return emsg return emsg
assert is_proved==False, _f() assert is_proved == False, _f()
to_prove = Implies(assume,to_prove) to_prove = Implies(assume, to_prove)
if verbose >= 2: if verbose >= 2:
print('assume: ') print("assume: ")
print(assume) print(assume)
print('claim: ') print("claim: ")
print(claim) print(claim)
print('to_prove: ') print("to_prove: ")
print(to_prove) print(to_prove)
f = Not(to_prove) f = Not(to_prove)
models = get_models(f,k=1) models = get_models(f, k=1)
if models is None: #unknown if models is None: # unknown
print('E: cannot solve !') print("E: cannot solve !")
return None, None return None, None
elif models == False: #unsat elif models == False: # unsat
return True,None return True, None
else: #sat else: # sat
if z3_debug(): if z3_debug():
assert isinstance(models,list) assert isinstance(models, list)
if models: if models:
return False, models[0] #the first counterexample return False, models[0] # the first counterexample
else: else:
return False, [] #infinite counterexample,models return False, [] # infinite counterexample,models
def get_models(f,k):
def get_models(f, k):
""" """
Returns the first k models satisfiying f. Returns the first k models satisfiying f.
If f is not satisfiable, returns False. If f is not satisfiable, returns False.
If f cannot be solved, returns None If f cannot be solved, returns None
If f is satisfiable, returns the first k models If f is satisfiable, returns the first k models
Note that if f is a tautology, e.g.\ True, then the result is [] Note that if f is a tautology, e.g.\\ True, then the result is []
Based on http://stackoverflow.com/questions/11867611/z3py-checking-all-solutions-for-equation Based on http://stackoverflow.com/questions/11867611/z3py-checking-all-solutions-for-equation
EXAMPLES: EXAMPLES:
@ -314,7 +313,7 @@ def get_models(f,k):
if z3_debug(): if z3_debug():
assert is_expr(f) assert is_expr(f)
assert k >= 1 assert k >= 1
s = Solver() s = Solver()
s.add(f) s.add(f)
@ -323,16 +322,14 @@ def get_models(f,k):
while s.check() == sat and i < k: while s.check() == sat and i < k:
i = i + 1 i = i + 1
m = s.model() m = s.model()
if not m: #if m == [] if not m: # if m == []
break break
models.append(m) models.append(m)
# create new constraint to block the current model
#create new constraint to block the current model
block = Not(And([v() == m[v] for v in m])) block = Not(And([v() == m[v] for v in m]))
s.add(block) s.add(block)
if s.check() == unknown: if s.check() == unknown:
return None return None
elif s.check() == unsat and i == 0: elif s.check() == unsat and i == 0:
@ -340,7 +337,8 @@ def get_models(f,k):
else: else:
return models return models
def is_tautology(claim,verbose=0):
def is_tautology(claim, verbose=0):
""" """
>>> is_tautology(Implies(Bool('x'),Bool('x'))) >>> is_tautology(Implies(Bool('x'),Bool('x')))
True True
@ -355,38 +353,38 @@ def is_tautology(claim,verbose=0):
False False
""" """
return prove(claim=claim,assume=None,verbose=verbose)[0] return prove(claim=claim, assume=None, verbose=verbose)[0]
def is_contradiction(claim,verbose=0): def is_contradiction(claim, verbose=0):
""" """
>>> x,y=Bools('x y') >>> x,y=Bools('x y')
>>> is_contradiction(BoolVal(False)) >>> is_contradiction(BoolVal(False))
True True
>>> is_contradiction(BoolVal(True)) >>> is_contradiction(BoolVal(True))
False False
>>> is_contradiction(x) >>> is_contradiction(x)
False False
>>> is_contradiction(Implies(x,y)) >>> is_contradiction(Implies(x,y))
False False
>>> is_contradiction(Implies(x,x)) >>> is_contradiction(Implies(x,x))
False False
>>> is_contradiction(And(x,Not(x))) >>> is_contradiction(And(x,Not(x)))
True True
""" """
return prove(claim=Not(claim),assume=None,verbose=verbose)[0] return prove(claim=Not(claim), assume=None, verbose=verbose)[0]
def exact_one_model(f): def exact_one_model(f):
""" """
return True if f has exactly 1 model, False otherwise. return True if f has exactly 1 model, False otherwise.
EXAMPLES: EXAMPLES:
>>> x, y = Ints('x y') >>> x, y = Ints('x y')
@ -403,30 +401,29 @@ def exact_one_model(f):
False False
""" """
models = get_models(f,k=2) models = get_models(f, k=2)
if isinstance(models,list): if isinstance(models, list):
return len(models)==1 return len(models) == 1
else: else:
return False return False
def myBinOp(op,*L):
def myBinOp(op, *L):
""" """
>>> myAnd(*[Bool('x'),Bool('y')]) >>> myAnd(*[Bool('x'),Bool('y')])
And(x, y) And(x, y)
>>> myAnd(*[Bool('x'),None]) >>> myAnd(*[Bool('x'),None])
x x
>>> myAnd(*[Bool('x')]) >>> myAnd(*[Bool('x')])
x x
>>> myAnd(*[]) >>> myAnd(*[])
>>> myAnd(Bool('x'),Bool('y')) >>> myAnd(Bool('x'),Bool('y'))
And(x, y) And(x, y)
>>> myAnd(*[Bool('x'),Bool('y')]) >>> myAnd(*[Bool('x'),Bool('y')])
And(x, y) And(x, y)
@ -435,7 +432,7 @@ def myBinOp(op,*L):
>>> myAnd((Bool('x'),Bool('y'))) >>> myAnd((Bool('x'),Bool('y')))
And(x, y) And(x, y)
>>> myAnd(*[Bool('x'),Bool('y'),True]) >>> myAnd(*[Bool('x'),Bool('y'),True])
Traceback (most recent call last): Traceback (most recent call last):
... ...
@ -444,59 +441,62 @@ def myBinOp(op,*L):
if z3_debug(): if z3_debug():
assert op == Z3_OP_OR or op == Z3_OP_AND or op == Z3_OP_IMPLIES assert op == Z3_OP_OR or op == Z3_OP_AND or op == Z3_OP_IMPLIES
if len(L)==1 and (isinstance(L[0],list) or isinstance(L[0],tuple)): if len(L) == 1 and (isinstance(L[0], list) or isinstance(L[0], tuple)):
L = L[0] L = L[0]
if z3_debug(): if z3_debug():
assert all(not isinstance(l,bool) for l in L) assert all(not isinstance(l, bool) for l in L)
L = [l for l in L if is_expr(l)] L = [l for l in L if is_expr(l)]
if L: if L:
if len(L)==1: if len(L) == 1:
return L[0] return L[0]
if op == Z3_OP_OR: if op == Z3_OP_OR:
return Or(L) return Or(L)
if op == Z3_OP_AND: if op == Z3_OP_AND:
return And(L) return And(L)
return Implies(L[0],L[1]) return Implies(L[0], L[1])
else: else:
return None return None
def myAnd(*L): def myAnd(*L):
return myBinOp(Z3_OP_AND,*L) return myBinOp(Z3_OP_AND, *L)
def myOr(*L): def myOr(*L):
return myBinOp(Z3_OP_OR,*L) return myBinOp(Z3_OP_OR, *L)
def myImplies(a,b):
return myBinOp(Z3_OP_IMPLIES,[a,b])
Iff = lambda f: And(Implies(f[0],f[1]),Implies(f[1],f[0])) def myImplies(a, b):
return myBinOp(Z3_OP_IMPLIES, [a, b])
def model_str(m,as_str=True):
def Iff(f):
return And(Implies(f[0], f[1]), Implies(f[1], f[0]))
def model_str(m, as_str=True):
""" """
Returned a 'sorted' model (so that it's easier to see) Returned a 'sorted' model (so that it's easier to see)
The model is sorted by its key, The model is sorted by its key,
e.g. if the model is y = 3 , x = 10, then the result is e.g. if the model is y = 3 , x = 10, then the result is
x = 10, y = 3 x = 10, y = 3
EXAMPLES: EXAMPLES:
see doctest exampels from function prove() see doctest exampels from function prove()
""" """
if z3_debug(): if z3_debug():
assert m is None or m == [] or isinstance(m,ModelRef) assert m is None or m == [] or isinstance(m, ModelRef)
if m : if m:
vs = [(v,m[v]) for v in m] vs = [(v, m[v]) for v in m]
vs = sorted(vs,key=lambda a,_: str(a)) vs = sorted(vs, key=lambda a, _: str(a))
if as_str: if as_str:
return '\n'.join(['{} = {}'.format(k,v) for (k,v) in vs]) return "\n".join(["{} = {}".format(k, v) for (k, v) in vs])
else: else:
return vs return vs
else: else:
return str(m) if as_str else m return str(m) if as_str else m