U t`>@s`ddlTddlTddlTddlmZddlmZdddZGdd d Zd d Zgfd d Z dS))*)Fraction)_get_ctxNcCst|tr|St||SdSN) isinstanceNumeral)numctxr src/api/python/z3/z3num.py _to_numerals r c@sxeZdZdZd\ddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ d]ddZ d^ddZd_ddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zd.d/Zd0d1Zd2d3Zd4d5Zd6d7Zd8d9Zd:d;Zdd?Z!d@dAZ"dBdCZ#dDdEZ$dFdGZ%dHdIZ&dJdKZ'dLdMZ(dNdOZ)dPdQZ*dRdSZ+dTdUZ,dVdWZ-dXdYZ.dZd[Z/dS)`ra  A Z3 numeral can be used to perform computations over arbitrary precision integers, rationals and real algebraic numbers. It also automatically converts python numeric values. >>> Numeral(2) 2 >>> Numeral("3/2") + 1 5/2 >>> Numeral(Sqrt(2)) 1.4142135623? >>> Numeral(Sqrt(2)) + 2 3.4142135623? >>> Numeral(Sqrt(2)) + Numeral(Sqrt(3)) 3.1462643699? Z3 numerals can be used to perform computations with values in a Z3 model. >>> s = Solver() >>> x = Real('x') >>> s.add(x*x == 2) >>> s.add(x > 0) >>> s.check() sat >>> m = s.model() >>> m[x] 1.4142135623? >>> m[x] + 1 1.4142135623? + 1 The previous result is a Z3 expression. >>> (m[x] + 1).sexpr() '(+ (root-obj (+ (^ x 2) (- 2)) 2) 1.0)' >>> Numeral(m[x]) + 1 2.4142135623? >>> Numeral(m[x]).is_pos() True >>> Numeral(m[x])**2 2 We can also isolate the roots of polynomials. >>> x0, x1, x2 = RealVarVector(3) >>> r0 = isolate_roots(x0**5 - x0 - 1) >>> r0 [1.1673039782?] In the following example, we are isolating the roots of a univariate polynomial (on x1) obtained after substituting x0 -> r0[0] >>> r1 = isolate_roots(x1**2 - x0 + 1, [ r0[0] ]) >>> r1 [-0.4090280898?, 0.4090280898?] Similarly, in the next example we isolate the roots of a univariate polynomial (on x2) obtained after substituting x0 -> r0[0] and x1 -> r1[0] >>> isolate_roots(x1*x2 + x0, [ r0[0], r1[0] ]) [2.8538479564?] NcCst|tr||_t||_ndt|ts0t|trB|j|_|j|_n>t|trft|}|j|_|j|_nt ||}|j|_|j|_t | | t | |jstdSr)rAstastrr RatNumRefAlgebraicNumRefZArithRefZsimplifyZRealVal Z3_inc_refctx_refas_astZ3_algebraic_is_valueAssertionError)selfr r rvr r r __init__[s      zNumeral.__init__cCst||dSr) Z3_dec_refrrrr r r __del__mszNumeral.__del__cCs|o|dkS)a Return True if the numeral is integer. >>> Numeral(2).is_integer() True >>> (Numeral(Sqrt(2)) * Numeral(Sqrt(2))).is_integer() True >>> Numeral(Sqrt(2)).is_integer() False >>> Numeral("2/3").is_integer() False r) is_rational denominatorrr r r is_integerps zNumeral.is_integercCst||tkS)z Return True if the numeral is rational. >>> Numeral(2).is_rational() True >>> Numeral("2/3").is_rational() True >>> Numeral(Sqrt(2)).is_rational() False )Z3_get_ast_kindrrZZ3_NUMERAL_ASTrr r r r~s zNumeral.is_rationalcCs&|s ttt|||jS)zk Return the denominator if `self` is rational. >>> Numeral("2/3").denominator() 3 )rrrZ3_get_denominatorrrr rr r r rs zNumeral.denominatorcCs&|s ttt|||jS)zg Return the numerator if `self` is rational. >>> Numeral("2/3").numerator() 2 )rrrZ3_get_numeratorrrr rr r r numerators zNumeral.numeratorcCs | S)z Return True if the numeral is irrational. >>> Numeral(2).is_irrational() False >>> Numeral("2/3").is_irrational() False >>> Numeral(Sqrt(2)).is_irrational() True )rrr r r is_irrationals zNumeral.is_irrationalcCsH|s ttjjdkr.tt||St t||SdS)zB Return a numeral (that is an integer) as a Python long. N) r rsys version_infomajorintZ3_get_numeral_stringrrlongrr r r as_longs  zNumeral.as_longcCs&|s tt||S)z Return a numeral (that is a rational) as a Python Fraction. >>> Numeral("1/5").as_fraction() Fraction(1, 5) )rrrr$r-rrr r r as_fractions zNumeral.as_fraction cCs ||S)aReturn a numeral that approximates the numeral `self`. The result `r` is such that |r - self| <= 1/10^precision If `self` is rational, then the result is `self`. >>> x = Numeral(2).root(2) >>> x.approx(20) 6838717160008073720548335/4835703278458516698824704 >>> x.approx(5) 2965821/2097152 >>> Numeral(2).approx(10) 2 )upperrZ precisionr r r approxszNumeral.approxcCs,|r |Stt||||jSdS)aReturn a upper bound that approximates the numeral `self`. The result `r` is such that r - self <= 1/10^precision If `self` is rational, then the result is `self`. >>> x = Numeral(2).root(2) >>> x.upper(20) 6838717160008073720548335/4835703278458516698824704 >>> x.upper(5) 2965821/2097152 >>> Numeral(2).upper(10) 2 N)rrZ3_get_algebraic_number_upperrrr r1r r r r0sz Numeral.uppercCs,|r |Stt||||jSdS)afReturn a lower bound that approximates the numeral `self`. The result `r` is such that self - r <= 1/10^precision If `self` is rational, then the result is `self`. >>> x = Numeral(2).root(2) >>> x.lower(20) 1709679290002018430137083/1208925819614629174706176 >>> Numeral("2/3").lower(10) 2/3 N)rrZ3_get_algebraic_number_lowerrrr r1r r r lowers z Numeral.lowercCst||jS)z Return the sign of the numeral. >>> Numeral(2).sign() 1 >>> Numeral(-3).sign() -1 >>> Numeral(0).sign() 0 )Z3_algebraic_signrrrr r r signs z Numeral.signcCst||jS)z Return True if the numeral is positive. >>> Numeral(2).is_pos() True >>> Numeral(-3).is_pos() False >>> Numeral(0).is_pos() False )Z3_algebraic_is_posrrrr r r is_poss zNumeral.is_poscCst||jS)z Return True if the numeral is negative. >>> Numeral(2).is_neg() False >>> Numeral(-3).is_neg() True >>> Numeral(0).is_neg() False )Z3_algebraic_is_negrrrr r r is_negs zNumeral.is_negcCst||jS)a? Return True if the numeral is zero. >>> Numeral(2).is_zero() False >>> Numeral(-3).is_zero() False >>> Numeral(0).is_zero() True >>> sqrt2 = Numeral(2).root(2) >>> sqrt2.is_zero() False >>> (sqrt2 - sqrt2).is_zero() True )Z3_algebraic_is_zerorrrr r r is_zeroszNumeral.is_zerocCs$tt||jt||jj|jS)z Return the numeral `self + other`. >>> Numeral(2) + 3 5 >>> Numeral(2) + Numeral(4) 6 >>> Numeral("2/3") + 1 5/3 rZ3_algebraic_addrrr r rotherr r r __add__$s zNumeral.__add__cCs$tt||jt||jj|jS)zR Return the numeral `other + self`. >>> 3 + Numeral(2) 5 r>r@r r r __radd__0szNumeral.__radd__cCs$tt||jt||jj|jS)zS Return the numeral `self - other`. >>> Numeral(2) - 3 -1 )rZ3_algebraic_subrrr r r@r r r __sub__8szNumeral.__sub__cCs$tt|t||jj|j|jS)zR Return the numeral `other - self`. >>> 3 - Numeral(2) 1 )rrDrr r rr@r r r __rsub__@szNumeral.__rsub__cCs$tt||jt||jj|jS)zQ Return the numeral `self * other`. >>> Numeral(2) * 3 6 rZ3_algebraic_mulrrr r r@r r r __mul__HszNumeral.__mul__cCs$tt||jt||jj|jS)zP Return the numeral `other * mul`. >>> 3 * Numeral(2) 6 rGr@r r r __rmul__OszNumeral.__rmul__cCs$tt||jt||jj|jS)z Return the numeral `self / other`. >>> Numeral(2) / 3 2/3 >>> Numeral(2).root(2) / 3 0.4714045207? >>> Numeral(Sqrt(2)) / Numeral(Sqrt(3)) 0.8164965809? )rZ3_algebraic_divrrr r r@r r r __div__Vs zNumeral.__div__cCs ||Sr)rLr@r r r __truediv__aszNumeral.__truediv__cCs$tt|t||jj|j|jS)z Return the numeral `other / self`. >>> 3 / Numeral(2) 3/2 >>> 3 / Numeral(2).root(2) 2.1213203435? )rrKrr r rr@r r r __rdiv__dszNumeral.__rdiv__cCs ||Sr)rNr@r r r __rtruediv__mszNumeral.__rtruediv__cCstt||j||jS)a' Return the numeral `self^(1/k)`. >>> sqrt2 = Numeral(2).root(2) >>> sqrt2 1.4142135623? >>> sqrt2 * sqrt2 2 >>> sqrt2 * 2 + 1 3.8284271247? >>> (sqrt2 * 2 + 1).sexpr() '(root-obj (+ (^ x 2) (* (- 2) x) (- 7)) 2)' )rZ3_algebraic_rootrrr rkr r r rootps z Numeral.rootcCstt||j||jS)z Return the numeral `self^k`. >>> sqrt3 = Numeral(3).root(2) >>> sqrt3 1.7320508075? >>> sqrt3.power(2) 3 )rZ3_algebraic_powerrrr rQr r r powers z Numeral.powercCs ||S)z Return the numeral `self^k`. >>> sqrt3 = Numeral(3).root(2) >>> sqrt3 1.7320508075? >>> sqrt3**2 3 )rUrQr r r __pow__s zNumeral.__pow__cCst||jt||jjS)z Return True if `self < other`. >>> Numeral(Sqrt(2)) < 2 True >>> Numeral(Sqrt(3)) < Numeral(Sqrt(2)) False >>> Numeral(Sqrt(2)) < Numeral(Sqrt(2)) False )Z3_algebraic_ltrrr r r@r r r __lt__s zNumeral.__lt__cCs||kS)zX Return True if `other < self`. >>> 2 < Numeral(Sqrt(2)) False r r@r r r __rlt__szNumeral.__rlt__cCst||jt||jjS)z Return True if `self > other`. >>> Numeral(Sqrt(2)) > 2 False >>> Numeral(Sqrt(3)) > Numeral(Sqrt(2)) True >>> Numeral(Sqrt(2)) > Numeral(Sqrt(2)) False )Z3_algebraic_gtrrr r r@r r r __gt__s zNumeral.__gt__cCs||kS)zW Return True if `other > self`. >>> 2 > Numeral(Sqrt(2)) True r r@r r r __rgt__szNumeral.__rgt__cCst||jt||jjS)z Return True if `self <= other`. >>> Numeral(Sqrt(2)) <= 2 True >>> Numeral(Sqrt(3)) <= Numeral(Sqrt(2)) False >>> Numeral(Sqrt(2)) <= Numeral(Sqrt(2)) True )Z3_algebraic_lerrr r r@r r r __le__s zNumeral.__le__cCs||kS)zZ Return True if `other <= self`. >>> 2 <= Numeral(Sqrt(2)) False r r@r r r __rle__szNumeral.__rle__cCst||jt||jjS)z Return True if `self >= other`. >>> Numeral(Sqrt(2)) >= 2 False >>> Numeral(Sqrt(3)) >= Numeral(Sqrt(2)) True >>> Numeral(Sqrt(2)) >= Numeral(Sqrt(2)) True )Z3_algebraic_gerrr r r@r r r __ge__s zNumeral.__ge__cCs||kS)zY Return True if `other >= self`. >>> 2 >= Numeral(Sqrt(2)) True r r@r r r __rge__szNumeral.__rge__cCst||jt||jjS)z Return True if `self == other`. >>> Numeral(Sqrt(2)) == 2 False >>> Numeral(Sqrt(3)) == Numeral(Sqrt(2)) False >>> Numeral(Sqrt(2)) == Numeral(Sqrt(2)) True )Z3_algebraic_eqrrr r r@r r r __eq__s zNumeral.__eq__cCst||jt||jjS)z Return True if `self != other`. >>> Numeral(Sqrt(2)) != 2 True >>> Numeral(Sqrt(3)) != Numeral(Sqrt(2)) True >>> Numeral(Sqrt(2)) != Numeral(Sqrt(2)) False )Z3_algebraic_neqrrr r r@r r r __ne__s zNumeral.__ne__cCs8t||jr"tt|j|jStt|j|jSdSr)Z3_is_numeral_astrrstrrr rrr r r __str__szNumeral.__str__cCs|Sr)rirr r r __repr__szNumeral.__repr__cCst||Sr)Z3_ast_to_stringrrrr r r sexprsz Numeral.sexprcCs|jSr)rrr r r r szNumeral.as_astcCs |jSr)r refrr r r r szNumeral.ctx_ref)N)r/)r/)r/)0__name__ __module__ __qualname____doc__rrr rrr$r%r-r.r2r0r5r7r9r;r=rBrCrErFrIrJrLrMrNrOrSrUrVrXrYr[r\r^r_rarbrdrfrirjrlrrr r r r rsZC                       rcCsDt|}t|}t|D]}||j||<qt||||S)ax Evaluate the sign of the polynomial `p` at `vs`. `p` is a Z3 Expression containing arithmetic operators: +, -, *, ^k where k is an integer; and free variables x that is_var(x) is True. Moreover, all variables must be real. The result is 1 if the polynomial is positive at the given point, -1 if negative, and 0 if zero. >>> x0, x1, x2 = RealVarVector(3) >>> eval_sign_at(x0**2 + x1*x2 + 1, (Numeral(0), Numeral(1), Numeral(2))) 1 >>> eval_sign_at(x0**2 - 2, [ Numeral(Sqrt(2)) ]) 0 >>> eval_sign_at((x0 + x1)*(x0 + x2), (Numeral(0), Numeral(Sqrt(2)), Numeral(Sqrt(3)))) 1 )lenrrangerZ3_algebraic_evalrr)pvsr _vsir r r eval_sign_ats   rycCsZt|}t|}t|D]}||j||<qtt|||||j}dd|DS)a 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). Remarks: * p is a Z3 expression that contains only arithmetic terms and free variables. * forall i in [0, n) vs is a numeral. The result is a list of numerals >>> x0 = RealVar(0) >>> isolate_roots(x0**5 - x0 - 1) [1.1673039782?] >>> x1 = RealVar(1) >>> isolate_roots(x0**2 - x1**4 - 1, [ Numeral(Sqrt(3)) ]) [-1.1892071150?, 1.1892071150?] >>> x2 = RealVar(2) >>> isolate_roots(x2**2 + x0 - x1, [ Numeral(Sqrt(3)), Numeral(Sqrt(2)) ]) [] cSsg|] }t|qSr )r).0rr r r Csz!isolate_roots..) rrrrsrZ AstVectorZ3_algebraic_rootsrrr )rurvr rwrxZ_rootsr r r isolate_roots)s   r})N) z3Zz3coreZ z3printerZ fractionsrrr rryr}r r r r s   |