{fErdZddlmZddlmZmZdZGddeZdId Z dJd Z d Z d Z dZ dZdddfdddfdddfdddfdddfdddfdddfdd dfd!d"dfd#d$dfd%d&dfd'd(dfd)d*dfd+d,dfd-d.dfd/d0dfd1d2dfd3d4dfd5d6dfd7d8dfd9d:dfd;ddfd?d@dfdAdBdfdCdDdfdEdFdfgZgddd d fdGZe e_ e e_ ee_edHk(rddlZej&yy)Kzs Implements the PSLQ algorithm for integer relation detection, and derivative algorithms for constant recognition. )xrange) int_types sqrt_fixedc$|d|dz zz|z |zSNr)xprecs ^/var/lib/jenkins/workspace/mettalog/venv/lib/python3.12/site-packages/mpmath/identification.py round_fixedr s !d1f+ 4 'D 00c eZdZy)IdentificationMethodsN)__name__ __module__ __qualname__rr r rr sr rNFc t|}|dkr td|j}|dkr td|r|td|zdkr t dt |dz}||j d| z}n|j|}d } || z }|rt d ||j|fz|j||}|sJdg|D cgc]#} |j|j | |%c} z}td |d dD} | s td | |dzkr|r t dytd|zdz|} i} i}i}td |d zD]1}td |d zD]}||k(|zx| ||f<|||f<d|||f<3dgdg|zz}td |d zD]5}d}t||d zD]}|||dz|z z }t||||<7|d }|dd}td |d zD]}|||z|z||<|||z|z||< td |d zD]}t|d z|D] }d|||f< ||d z kr#||r||d z|z||z|||f<nd|||f<td |D]1}||||d zz}|r|| ||z|z|z|||f<+d|||f<3td|d zD]}t|d z ddD]}|||frt|||f|z|||fz|}n(|||||z|z z||<td |d zD]}|||f||||fz|z z |||f<td |d zD]6}| ||f|| ||fz|z z | ||f<|||f||||fz|z z|||f<8t|D]}d}d}td |D]-}|||f}| |zt|z||d z zz }||kDs*|}|}/||d z||c||<||d z<td |d zD]!}||d z|f|||fc|||f<||d z|f<#td |d zD]!}| |d z|f| ||fc| ||f<| |d z|f<#td |d zD]!}|||d zf|||fc|||f<|||d zf<#||dz krt|||fdz|||d zfdzz|z |}|sn|||f|z|z}|||d zf|z|z}t||d zD]=}|||f}|||d zf} ||z|| zz|z |||f<| |z|| zz|z |||d zf<?t|d z|d zD]}tt|d z |d zddD]} t|||f|z|||fz|}|||||z|z z||<td |d zD]}|||f||||fz|z z |||f<td |d zD]6}| ||f|| ||fz|z z | ||f<|||f||||fz|z z|||f<8||z}!td |d zD]}t||}"|"|krtd |d zDcgc]}t t|||f||z !}#}td|#D|kr>|r6t d|||j|"|j d|zz d fz|#ccSt|"|!}!td|j#D}$|$rd d|zz|$z|z }%|%dz}%n |j$}%|r7t d|||j|!|j d|zz d |%fz|%|k\sn|rt d|fzt d%zycc} w#t $rYHwxYwcc}w)a Given a vector of real numbers `x = [x_0, x_1, ..., x_n]`, ``pslq(x)`` uses the PSLQ algorithm to find a list of integers `[c_0, c_1, ..., c_n]` such that .. math :: |c_1 x_1 + c_2 x_2 + ... + c_n x_n| < \mathrm{tol} and such that `\max |c_k| < \mathrm{maxcoeff}`. If no such vector exists, :func:`~mpmath.pslq` returns ``None``. The tolerance defaults to 3/4 of the working precision. **Examples** Find rational approximations for `\pi`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> pslq([-1, pi], tol=0.01) [22, 7] >>> pslq([-1, pi], tol=0.001) [355, 113] >>> mpf(22)/7; mpf(355)/113; +pi 3.14285714285714 3.14159292035398 3.14159265358979 Pi is not a rational number with denominator less than 1000:: >>> pslq([-1, pi]) >>> To within the standard precision, it can however be approximated by at least one rational number with denominator less than `10^{12}`:: >>> p, q = pslq([-1, pi], maxcoeff=10**12) >>> print(p); print(q) 238410049439 75888275702 >>> mpf(p)/q 3.14159265358979 The PSLQ algorithm can be applied to long vectors. For example, we can investigate the rational (in)dependence of integer square roots:: >>> mp.dps = 30 >>> pslq([sqrt(n) for n in range(2, 5+1)]) >>> >>> pslq([sqrt(n) for n in range(2, 6+1)]) >>> >>> pslq([sqrt(n) for n in range(2, 8+1)]) [2, 0, 0, 0, 0, 0, -1] **Machin formulas** A famous formula for `\pi` is Machin's, .. math :: \frac{\pi}{4} = 4 \operatorname{acot} 5 - \operatorname{acot} 239 There are actually infinitely many formulas of this type. Two others are .. math :: \frac{\pi}{4} = \operatorname{acot} 1 \frac{\pi}{4} = 12 \operatorname{acot} 49 + 32 \operatorname{acot} 57 + 5 \operatorname{acot} 239 + 12 \operatorname{acot} 110443 We can easily verify the formulas using the PSLQ algorithm:: >>> mp.dps = 30 >>> pslq([pi/4, acot(1)]) [1, -1] >>> pslq([pi/4, acot(5), acot(239)]) [1, -4, 1] >>> pslq([pi/4, acot(49), acot(57), acot(239), acot(110443)]) [1, -12, -32, 5, -12] We could try to generate a custom Machin-like formula by running the PSLQ algorithm with a few inverse cotangent values, for example acot(2), acot(3) ... acot(10). Unfortunately, there is a linear dependence among these values, resulting in only that dependence being detected, with a zero coefficient for `\pi`:: >>> pslq([pi] + [acot(n) for n in range(2,11)]) [0, 1, -1, 0, 0, 0, -1, 0, 0, 0] We get better luck by removing linearly dependent terms:: >>> pslq([pi] + [acot(n) for n in range(2,11) if n not in (3, 5)]) [1, -8, 0, 0, 4, 0, 0, 0] In other words, we found the following formula:: >>> 8*acot(2) - 4*acot(7) 3.14159265358979323846264338328 >>> +pi 3.14159265358979323846264338328 **Algorithm** This is a fairly direct translation to Python of the pseudocode given by David Bailey, "The PSLQ Integer Relation Algorithm": http://www.cecm.sfu.ca/organics/papers/bailey/paper/html/node3.html The present implementation uses fixed-point instead of floating-point arithmetic, since this is significantly (about 7x) faster. zn cannot be less than 25zprec cannot be less than 53z*Warning: precision for PSLQ may be too lowg?N<zPSLQ using prec %i and tol %sc32K|]}t|ywNabs).0xxs r zpslq..s'2s2w'rz)PSLQ requires a vector of nonzero numbersdz#STOPPING: (one number is too small)c32K|]}t|ywrr)rvs r rzpslq..s+!s1v+r z'FOUND relation at iter %i/%i, error: %sc32K|]}t|ywrr)rhs r rzpslq..'s1c!f1r z%i/%i: Error: %8s Norm: %szCANCELLING after step %i/%i.z2Could not find an integer relation. Norm bound: %s)len ValueErrorr maxprintintmpfconvertnstrto_fixedminrrranger rZeroDivisionErrorvaluesinf)&ctxr tolmaxcoeffmaxstepsverbosenr targetextraxkminxgABHijsktysjj1REPmszmaxr)szt0t1t2t3t4best_errerrvecrecnormnorms& r pslqr[s f AA1u233 88D by67743q8#a' :;  F {ggajF7#kk# EEMD -sxx}0EEF ,,sD !C J3 A>b#,,swwr{D1>>A '12' 'D DEE c3h  7 8AtGa<&A A A AAqs^1Q3A !tn ,AacFQqsVAacF  !qA Aqs^ 1Q3A !A$'T/ "A !T"!  !A !A Aqs^! "!! "!Aqs^!QAAacF !8tAaC&D.QqT1!A#!A#q!AQ4!A#;DaD51:,t3!A#!A# Aqs^!Q#A1v1Q34!AaC& 8$?Q41QqT6T>*AaDAqs^1Q31QqsV8t#34!A#$Aqs^1Q31QqsV8t#34!A#1Q31QqsV8t#34!A#$$X q!A!A#AQ$Q-T1Q3Z0BEz 1vqt !a!f!A#A1QqSU8QqsV 0!A#!A#a%!A#A1QqSU8QqsV 0!A#!A#a%!A#A1QqsU8QqsV 0!A#!AaC% A:QqsVQY1QqS514t;TBBAaC&D.R'BAacE(d"r)BAqs^qsVq1uXR%2+$.!A#CF2b5LT1!AaC% $ !QqS!AC!QqSM1b1#QqsVt^a!f$1Q3Aad)CSya! !s;q1vt4<=+s++h6G (CHHS3771:t;K5KQ,OPQRJ3)H 1ahhj11 1T6]w.47D SLD77D  1hCGGAJ4D)Da H$OP Q 8  [\ ,X>? BTIJ c?H)(s(]4"]9$^ 9 ^ ^ c |j|}|dkr td|dk(rddgS|jdg}td|dzD]5}|j||z|j|fi|}|-|dddcSy)a ``findpoly(x, n)`` returns the coefficients of an integer polynomial `P` of degree at most `n` such that `P(x) \approx 0`. If no polynomial having `x` as a root can be found, :func:`~mpmath.findpoly` returns ``None``. :func:`~mpmath.findpoly` works by successively calling :func:`~mpmath.pslq` with the vectors `[1, x]`, `[1, x, x^2]`, `[1, x, x^2, x^3]`, ..., `[1, x, x^2, .., x^n]` as input. Keyword arguments given to :func:`~mpmath.findpoly` are forwarded verbatim to :func:`~mpmath.pslq`. In particular, you can specify a tolerance for `P(x)` with ``tol`` and a maximum permitted coefficient size with ``maxcoeff``. For large values of `n`, it is recommended to run :func:`~mpmath.findpoly` at high precision; preferably 50 digits or more. **Examples** By default (degree `n = 1`), :func:`~mpmath.findpoly` simply finds a linear polynomial with a rational root:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> findpoly(0.7) [-10, 7] The generated coefficient list is valid input to ``polyval`` and ``polyroots``:: >>> nprint(polyval(findpoly(phi, 2), phi), 1) -2.0e-16 >>> for r in polyroots(findpoly(phi, 2)): ... print(r) ... -0.618033988749895 1.61803398874989 Numbers of the form `m + n \sqrt p` for integers `(m, n, p)` are solutions to quadratic equations. As we find here, `1+\sqrt 2` is a root of the polynomial `x^2 - 2x - 1`:: >>> findpoly(1+sqrt(2), 2) [1, -2, -1] >>> findroot(lambda x: x**2 - 2*x - 1, 1) 2.4142135623731 Despite only containing square roots, the following number results in a polynomial of degree 4:: >>> findpoly(sqrt(2)+sqrt(3), 4) [1, 0, -10, 0, 1] In fact, `x^4 - 10x^2 + 1` is the *minimal polynomial* of `r = \sqrt 2 + \sqrt 3`, meaning that a rational polynomial of lower degree having `r` as a root does not exist. Given sufficient precision, :func:`~mpmath.findpoly` will usually find the correct minimal polynomial of a given algebraic number. **Non-algebraic numbers** If :func:`~mpmath.findpoly` fails to find a polynomial with given coefficient size and tolerance constraints, that means no such polynomial exists. We can verify that `\pi` is not an algebraic number of degree 3 with coefficients less than 1000:: >>> mp.dps = 15 >>> findpoly(pi, 3) >>> It is always possible to find an algebraic approximation of a number using one (or several) of the following methods: 1. Increasing the permitted degree 2. Allowing larger coefficients 3. Reducing the tolerance One example of each method is shown below:: >>> mp.dps = 15 >>> findpoly(pi, 4) [95, -545, 863, -183, -298] >>> findpoly(pi, 3, maxcoeff=10000) [836, -1734, -2658, -457] >>> findpoly(pi, 3, tol=1e-7) [-4, 22, -29, -2] It is unknown whether Euler's constant is transcendental (or even irrational). We can use :func:`~mpmath.findpoly` to check that if is an algebraic number, its minimal polynomial must have degree at least 7 and a coefficient of magnitude at least 1000000:: >>> mp.dps = 200 >>> findpoly(euler, 6, maxcoeff=10**6, tol=1e-100, maxsteps=1000) >>> Note that the high precision and strict tolerance is necessary for such high-degree runs, since otherwise unwanted low-accuracy approximations will be detected. It may also be necessary to set maxsteps high to prevent a premature exit (before the coefficient bound has been reached). Running with ``verbose=True`` to get an idea what is happening can be useful. rzn cannot be less than 1r$Nr%)r/r+r4appendr[)r8r r=kwargsxsrFas r findpolyra7sR  A1u233Av1v ''!*B 1QqS\ !Q$ CHHR "6 " =TrT7N r cV||}}|r |||z}}|r |dk7r ||z}||z}|dk(r|S||fSrr)pqr rKs r fracgcdresN aqA !a%1 Av a aAv a4Kr cz|d}|dd}g}tt|D]r}||}|s t| |}||d}|dk(rd}nd|z}t|tr|dkDrt ||z}nd|z|z}nd|z|z}|j |tdj|}d |vsd|vrd |zd z}|xsd S) Nr$r1*z(%s)z(%s/%s)z + +()0)r4r*re isinstancerstrr]join) r constantsrdrHrFrczcsterms r pslqstringrvs !A !"A A 3q6] aD 1 A1aBSy2X!Y'q5Q"$"(1*!2$!A + HHTN  1 A ax3!8 !GcM 8Or c|d}|dd}g}g}tt|D]}||}|s t| |}||d}t|tr;t |dk(r|} n|dt |} ||g|dkj | k|dt |dd|dd} ||g|ddkj | dj|}dj|}|r |r d|d |dS|r|S|rd |zSy) Nr$rz**z**(/rlrirkz)/(z1/(%s))r4r*rernrrr]rp) rqrrrdnumdenrFrcrsrtrJs r prodstringr{s !A !"A C C 3q6] aD 1 A1aB!Y'q6Q;B02CF$;c1Q3''*%'QqTAaD9c1Q46"**1- ((3-C ((3-C s#s33 3J 8c> !sr c|dkr | | | }}}| |j|dzd|z|zz zd|zz }| |j|dzd|z|zz z d|zz }t||z t||z kr4|rd| d|dzd|z|zz dd|zd}|Sdd |z|zd d|zd}|S|rd| d |dzd|z|zz dd|zd}|Sd d |z|zd d|zd}|S) Nr$rr"z((z+sqrt(z))/rlz(sqrt(z)/z-sqrt(z(-sqrt()sqrtr)r8rJr`bcu1u2rHs r quadraticstringrs(1uA2qbA! "SXXad1Q3q5j ! !AaC (B "SXXad1Q3q5j ! !AaC (B 2a4y3r!t9 A2ad1Q3q5j1=q H &(d1fQqS1q H A2ad1Q3q5j1=q H ')!tAvac2q Hr c ||zSrrr8r rs r r1Q3r z$y/$cr$c ||z Srrrs r rrrr z$c*$yc ||z Srrrs r rrrr z$c/$yc||zdzSNrrrs r rr AaC!8r z sqrt($y)/$cc||z dzSrrrs r rrrr z $c*sqrt($y)c||z dzSrrrs r rrrr z $c/sqrt($y)c||dzzSrrrs r rr 1QT6r zsqrt($y)/sqrt($c)c|dz|z Srrrs r rrs 1a46r zsqrt($c)*sqrt($y)c||dzz Srrrs r rrrr zsqrt($c)/sqrt($y)c*|j||zSrr~rs r rr388AaC=r z$y**2/$cc*|j||z Srrrs r rrrr z$c*$y**2c*|j||z Srrrs r rrrr z$c/$y**2c*||j|zSrrrs r rr1SXXa[=r z $y**2/$c**2c*|j||z Srrrs r rrs388A;q=r z $c**2*$y**2c*||j|z Srrrs r rrrr z $c**2/$y**2c*|j||zSrexprs r rr3771Q3>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> identify(phi) '((1+sqrt(5))/2)' :func:`~mpmath.identify` can identify simple algebraic numbers and simple combinations of given base constants, as well as certain basic transformations thereof. More specifically, :func:`~mpmath.identify` looks for the following: 1. Fractions 2. Quadratic algebraic numbers 3. Rational linear combinations of the base constants 4. Any of the above after first transforming `x` into `f(x)` where `f(x)` is `1/x`, `\sqrt x`, `x^2`, `\log x` or `\exp x`, either directly or with `x` or `f(x)` multiplied or divided by one of the base constants 5. Products of fractional powers of the base constants and small integers Base constants can be given as a list of strings representing mpmath expressions (:func:`~mpmath.identify` will ``eval`` the strings to numerical values and use the original strings for the output), or as a dict of formula:value pairs. In order not to produce spurious results, :func:`~mpmath.identify` should be used with high precision; preferably 50 digits or more. **Examples** Simple identifications can be performed safely at standard precision. Here the default recognition of rational, algebraic, and exp/log of algebraic numbers is demonstrated:: >>> mp.dps = 15 >>> identify(0.22222222222222222) '(2/9)' >>> identify(1.9662210973805663) 'sqrt(((24+sqrt(48))/8))' >>> identify(4.1132503787829275) 'exp((sqrt(8)/2))' >>> identify(0.881373587019543) 'log(((2+sqrt(8))/2))' By default, :func:`~mpmath.identify` does not recognize `\pi`. At standard precision it finds a not too useful approximation. At slightly increased precision, this approximation is no longer accurate enough and :func:`~mpmath.identify` more correctly returns ``None``:: >>> identify(pi) '(2**(176/117)*3**(20/117)*5**(35/39))/(7**(92/117))' >>> mp.dps = 30 >>> identify(pi) >>> Numbers such as `\pi`, and simple combinations of user-defined constants, can be identified if they are provided explicitly:: >>> identify(3*pi-2*e, ['pi', 'e']) '(3*pi + (-2)*e)' Here is an example using a dict of constants. Note that the constants need not be "atomic"; :func:`~mpmath.identify` can just as well express the given number in terms of expressions given by formulas:: >>> identify(pi+e, {'a':pi+2, 'b':2*e}) '((-2) + 1*a + (1/2)*b)' Next, we attempt some identifications with a set of base constants. It is necessary to increase the precision a bit. >>> mp.dps = 50 >>> base = ['sqrt(2)','pi','log(2)'] >>> identify(0.25, base) '(1/4)' >>> identify(3*pi + 2*sqrt(2) + 5*log(2)/7, base) '(2*sqrt(2) + 3*pi + (5/7)*log(2))' >>> identify(exp(pi+2), base) 'exp((2 + 1*pi))' >>> identify(1/(3+sqrt(2)), base) '((3/7) + (-1/7)*sqrt(2))' >>> identify(sqrt(2)/(3*pi+4), base) 'sqrt(2)/(4 + 3*pi)' >>> identify(5**(mpf(1)/3)*pi*log(2)**2, base) '5**(1/3)*pi*log(2)**2' An example of an erroneous solution being found when too low precision is used:: >>> mp.dps = 15 >>> identify(1/(3*pi-4*e+sqrt(8)), ['pi', 'e', 'sqrt(2)']) '((11/25) + (-158/75)*pi + (76/75)*e + (44/15)*sqrt(2))' >>> mp.dps = 50 >>> identify(1/(3*pi-4*e+sqrt(8)), ['pi', 'e', 'sqrt(2)']) '1/(3*pi + (-4)*e + 2*sqrt(2))' **Finding approximate solutions** The tolerance ``tol`` defaults to 3/4 of the working precision. Lowering the tolerance is useful for finding approximate matches. We can for example try to generate approximations for pi:: >>> mp.dps = 15 >>> identify(pi, tol=1e-2) '(22/7)' >>> identify(pi, tol=1e-3) '(355/113)' >>> identify(pi, tol=1e-10) '(5**(339/269))/(2**(64/269)*3**(13/269)*7**(92/269))' With ``full=True``, and by supplying a few base constants, ``identify`` can generate almost endless lists of approximations for any number (the output below has been truncated to show only the first few):: >>> for p in identify(pi, ['e', 'catalan'], tol=1e-5, full=True): ... print(p) ... # doctest: +ELLIPSIS e/log((6 + (-4/3)*e)) (3**3*5*e*catalan**2)/(2*7**2) sqrt(((-13) + 1*e + 22*catalan)) log(((-6) + 24*e + 4*catalan)/e) exp(catalan*((-1/5) + (8/15)*e)) catalan*(6 + (-6)*e + 15*catalan) sqrt((5 + 26*e + (-3)*catalan))/e e*sqrt(((-27) + 2*e + 25*catalan)) log(((-1) + (-11)*e + 59*catalan)) ((3/20) + (21/20)*e + (3/20)*catalan) ... The numerical values are roughly as close to `\pi` as permitted by the specified tolerance: >>> e/log(6-4*e/3) 3.14157719846001 >>> 135*e*catalan**2/98 3.14166950419369 >>> sqrt(e-13+22*catalan) 3.14158000062992 >>> log(24*e-6+4*catalan)-1 3.14158791577159 **Symbolic processing** The output formula can be evaluated as a Python expression. Note however that if fractions (like '2/3') are present in the formula, Python's :func:`~mpmath.eval()` may erroneously perform integer division. Note also that the output is not necessarily in the algebraically simplest form:: >>> identify(sqrt(2)) '(sqrt(8)/2)' As a solution to both problems, consider using SymPy's :func:`~mpmath.sympify` to convert the formula into a symbolic expression. SymPy can be used to pretty-print or further simplify the formula symbolically:: >>> from sympy import sympify # doctest: +SKIP >>> sympify(identify(sqrt(2))) # doctest: +SKIP 2**(1/2) Sometimes :func:`~mpmath.identify` can simplify an expression further than a symbolic algorithm:: >>> from sympy import simplify # doctest: +SKIP >>> x = sympify('-1/(-3/2+(1/2)*5**(1/2))*(3/2-1/2*5**(1/2))**(1/2)') # doctest: +SKIP >>> x # doctest: +SKIP (3/2 - 5**(1/2)/2)**(-1/2) >>> x = simplify(x) # doctest: +SKIP >>> x # doctest: +SKIP 2/(6 - 2*5**(1/2))**(1/2) >>> mp.dps = 30 # doctest: +SKIP >>> x = sympify(identify(x.evalf(30))) # doctest: +SKIP >>> x # doctest: +SKIP 1/2 + 5**(1/2)/2 (In fact, this functionality is available directly in SymPy as the function :func:`~mpmath.nsimplify`, which is essentially a wrapper for :func:`~mpmath.identify`.) **Miscellaneous issues and limitations** The input `x` must be a real number. All base constants must be positive real numbers and must not be rationals or rational linear combinations of each other. The worst-case computation time grows quickly with the number of base constants. Already with 3 or 4 base constants, :func:`~mpmath.identify` may require several seconds to finish. To search for relations among a large number of constants, you should consider using :func:`~mpmath.pslq` directly. The extended transformations are applied to x, not the constants separately. As a result, ``identify`` will for example be able to recognize ``exp(2*pi+3)`` with ``pi`` given as a base constant, but not ``2*exp(pi)+3``. It will be able to recognize the latter if ``exp(pi)`` is given explicitly as a base constant. cDr td|j|y)NzFound: )r-r])rH solutionsr<s r addsolutionzidentify..addsolutions E)Q'r r$rmNz-(%s)gffffff?c3:K|]}|t|fywr)getattr)rnamer8s r rzidentify..sL4dGC$56Lsrrgrc32K|]}t|ywrrruws r rzidentify..s$9SW$9r r#z/$cz$yrhz$c.)rr#rc 3K|]@}tjjj|z dByw)rN)boolrar)rrFr`r8s r rzidentify..8s6PQtCLL366!9).<s 5RR 5r )key)r/identifyepsrndictsorteditemsdireval transformsrr[r,rvoner*rreplacer-sumr]rror{) r8r rrr9r:fullr<rsolrHMrr' namespacercvalueftftnredrcnrJr`rqrdaabbccilogslogsrFrs ` ` ` @r rrsjI  A Av 1ullA2y#xwG ;J '*+!GAI+ +S=  ggclggslA i &=CIOODU=VW q#''!*d+WIWL3s8LLI:CDQ$q),a0DID  I6=D%66ggaj#&')3 # CEArrSy3q A1v1}A !i8!88#qAAA}$9q$9!9Q!>1Q4q),HHcggq!Q$/a8=SVq[QqT!"JBB3r73r73r73q8+C"R;9%3, D!,44UB?A D!,44T2>AAIaL0c 9#@ AvDAqP%PP SVVAYN+-22q3q6"2T9 HHcffQi[$#7QAaD#77a @ =S 51 55:qt  1d+ , ! , iS))S,XE 7 9>3#7s* O6O 8O O O#O!& O& __main__)Nrr!F)r)__doc__ libmp.backendrlibmprrr objectrr[rarervr{rrrrdoctesttestmodrr r rs "(1 F dL sj 0".  "###]A.]A.]A..2.2.2 *a0 *a0 *a0 -3 -3 -3q1q1q1q1q1q1 a0 a0 a0 a0 a0 a07 < "td ob "!)!) zGOOr