
    [hEr                        S r SSKJr  SSKJrJr  S r " S S\5      rSIS
 jr	SJS jr
S rS rS rS rS SS4S SS4S SS4S SS4S SS4S SS4S SS4S S S4S! S"S4S# S$S4S% S&S4S' S(S4S) S*S4S+ S,S4S- S.S4S/ S0S4S1 S2S4S3 S4S4S5 S6S4S7 S8S4S9 S:S4S; S<S4S= S>S4S? S@S4SA SBS4SC SDS4SE SFS4/r/ SSS	S	4SG jr\	\l	        \
\l
        \\l        \SH:X  a  SSKr\R&                  " 5         gg)Kzs
Implements the PSLQ algorithm for integer relation detection,
and derivative algorithms for constant recognition.
   )xrange)	int_types
sqrt_fixedc                 $    U SUS-
  -  -   U-	  U-  $ Nr    )xprecs     M/var/www/auris/envauris/lib/python3.13/site-packages/mpmath/identification.pyround_fixedr   
   s    !d1f+4'D00    c                       \ rS rSrSrg)IdentificationMethods   r   N)__name__
__module____qualname____firstlineno____static_attributes__r   r   r   r   r      s    r   r   N  Fc                    [        U5      nUS:  a  [        S5      eU R                  nUS:  a  [        S5      eU(       a  U[        SU5      -  S:  a  [	        S5        [        US-  5      nUc  U R                  S5      U* -  nOU R                  U5      nS	n	Xy-  nU(       a  [	        S
XpR                  U5      4-  5        U R                  X'5      nU(       d   eS/U V
s/ s H#  oR                  U R                  U
5      U5      PM%     sn
-   n[        S USS  5       5      nU(       d  [        S5      eXS-  :  a  U(       a  [	        S5        g[        SU-  S-  U5      n0 n0 n0 n[        SUS-   5       H4  n[        SUS-   5       H  nUU:H  U-  =UUU4'   UUU4'   SUUU4'   M      M6     S/S/U-  -   n[        SUS-   5       H8  nSn[        UUS-   5       H  nUUU   S-  U-	  -  nM     [        UU5      UU'   M:     US   nUSS n[        SUS-   5       H  nUU   U-  U-  UU'   UU   U-  U-  UU'   M!     [        SUS-   5       H  n[        US-   U5       H
  nSUUU4'   M     UUS-
  ::  a(  UU   (       a  UUS-      U-  UU   -  UUU4'   OSUUU4'   [        SU5       H8  nUU   UUS-      -  nU(       a  UU   * UU   -  U-  U-  UUU4'   M1  SUUU4'   M:     M     [        SUS-   5       H  n[        US-
  SS5       H  nUUU4   (       a  [        UUU4   U-  UUU4   -  U5      nOM.  UU   UUU   -  U-	  -   UU'   [        SUS-   5       H  nUUU4   UUUU4   -  U-	  -
  UUU4'   M     [        SUS-   5       H7  nUUU4   UUUU4   -  U-	  -
  UUU4'   UUU4   UUUU4   -  U-	  -   UUU4'   M9     M     M     [        U5       GH  nSnSn[        SU5       H0  nUUU4   nUU-  [        U5      -  UUS-
  -  -	  nUU:  d  M,  UnUnM2     UUS-      UU   sUU'   UUS-   '   [        SUS-   5       H"  nUUS-   U4   UUU4   sUUU4'   UUS-   U4'   M$     [        SUS-   5       H"  nUUS-   U4   UUU4   sUUU4'   UUS-   U4'   M$     [        SUS-   5       H"  nUUUS-   4   UUU4   sUUU4'   UUUS-   4'   M$     UUS-
  ::  a  [        UUU4   S-  UUUS-   4   S-  -   U-	  U5      nU(       d    GOUUU4   U-  U-  nUUUS-   4   U-  U-  n[        UUS-   5       H>  nUUU4   nUUUS-   4   n UU-  UU -  -   U-	  UUU4'   U* U-  UU -  -   U-	  UUUS-   4'   M@     [        US-   US-   5       H  n[        [        US-
  US-   5      SS5       H  n [        UUU4   U-  UUU4   -  U5      nUU   UUU   -  U-	  -   UU'   [        SUS-   5       H  nUUU4   UUUU4   -  U-	  -
  UUU4'   M     [        SUS-   5       H7  nUUU4   UUUU4   -  U-	  -
  UUU4'   UUU4   UUUU4   -  U-	  -   UUU4'   M9     M     M     X7-  n![        SUS-   5       H  n[        UU   5      n"U"U:  a  [        SUS-   5       Vs/ s H   n[        [        UUU4   U5      U-	  5      PM"     n#n[        S U# 5       5      U:  aB  U(       a5  [	        SUX@R                  U"U R                  S5      U-  -  S5      4-  5        U#s  s  $ [        U"U!5      n!M     [        S UR#                  5        5       5      n$U$(       a  SSU-  -  U$-  U-	  n%U%S-  n%OU R$                  n%U(       a6  [	        SUX@R                  U!U R                  S5      U-  -  S5      U%4-  5        U%U:  d  GM    O   U(       a  [	        SWU4-  5        [	        SW%-  5        gs  sn
f ! [          a       GMm  f = fs  snf )az  
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.
   zn cannot be less than 25   zprec cannot be less than 53   z*Warning: precision for PSLQ may be too lowg      ?N<   zPSLQ using prec %i and tol %sc              3   8   #    U  H  n[        U5      v   M     g 7fNabs).0xxs     r   	<genexpr>pslq.<locals>.<genexpr>   s     '2s2ww   r   z)PSLQ requires a vector of nonzero numbersd   z#STOPPING: (one number is too small)          c              3   8   #    U  H  n[        U5      v   M     g 7fr   r   )r    vs     r   r"   r#     s     +s!s1vvsr$   z'FOUND relation at iter %i/%i, error: %sc              3   8   #    U  H  n[        U5      v   M     g 7fr   r   )r    hs     r   r"   r#   '  s     1jc!ffjr$   z%i/%i:  Error: %8s   Norm: %szCANCELLING after step %i/%i.z2Could not find an integer relation. Norm bound: %s)len
ValueErrorr
   maxprintintmpfconvertnstrto_fixedminr   r   ranger   r   ZeroDivisionErrorvaluesinf)&ctxr	   tolmaxcoeffmaxstepsverbosenr
   targetextraxkminxgABHijsktysjj1REPmszmaxr-   szt0t1t2t3t4best_errerrvecrecnormnorms&                                         r   pslqr_      s	   f 	AA1u233 88Dby67743q8#a':;F
{ggajF7#kk#EMD-xx}0EEF
,,s
!CJ3 
A>Ab,,swwr{D1A>>A '12''DDEE3h78AtGa<&A
A
A
A Aqs^1Q3A !tn,AacFQqsVAacF   
 
!qAAqs^1Q3A!A$'T/"A  !T"!	 
 	
!A	!AAqs^!"!!"!  Aqs^!QAAacF  !8tAaC&D.QqT1!A#!A#q!AQ4!A#;DaD51:,t3!A#!A#   Aqs^!Q#A1v1Q34!AaC& 8$? Q41QqT6T>*AaDAqs^1Q31QqsV8t#34!A# $Aqs^1Q31QqsV8t#34!A#1Q31QqsV8t#34!A# $ $  Xq!A!A#AQ$Q-T1Q3Z0BEz  1vqt!a!f!A#A1QqSU8QqsV 0!A#!A#a%!A#A1QqSU8QqsV 0!A#!A#a%!A#A1QqsU8QqsV 0!A#!AaC%A:QqsVQY1QqS514t;TBB AaC&D.R'BAacE(d"r)BAqs^qsVq1uXR%2+$.!A#CF2b5LT1!AaC%	 $ !QqS!AC!QqSM1b1#QqsVt^a!f$<dCA t!A$4/0!1Q3AqsVq1Q3x4'78AacF (1Q3AqsVq1Q3x4'78AacFqsVq1Q3x4'78AacF ( 2 "& >1Q3Aad)CSy a! CDs;q1vt4<=  +s++h6G (HHS3771:t;K5KQ,OPQ RJ3)H    1ahhj111T6]w.47DSLD77D1hCGGAJ4D)Da H$OP Q8[ \ ,X>?BTIJc ?H ) (s   "*_/:_4''`4
`	`	c                    U R                  U5      nUS:  a  [        S5      eUS:X  a  SS/$ U R                  S5      /n[        SUS-   5       H6  nUR                  X-  5        U R                  " U40 UD6nUc  M.  USSS2   s  $    g)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.
r   zn cannot be less than 1r(   Nr)   )r3   r/   r8   appendr_   )r<   r	   rA   kwargsxsrJ   as          r   findpolyre   7  s    R 	
A1u233Av1v
''!*B1QqS\
		!$HHR"6"=TrT7N	 r   c                 b    Xp2U(       a  X2U-  p2U(       a  M  US:w  a  X-  n X-  nUS:X  a  U $ X4$ r   r   )pqr	   rO   s       r   fracgcdri     sB    q
a%1 !Av		Av4Kr   c                    U S   nU SS  n / n[        [        U 5      5       H~  nX   nU(       d  M  [        U* U5      nX   S   nUS:X  a  SnOSU-   n[        U[        5      (       a  US:  a  [        U5      U-   nOSU-  U-   nOSU-  U-   nUR                  U5        M     SR                  U5      nS	U;   d  SU;   a  S
U-   S-   nU=(       d    S$ )Nr(   r   1 *z(%s)z(%s/%s)z + +()0)r8   r.   ri   
isinstancer   strra   join)	r	constantsrh   rL   rJ   rg   zcsterms	            r   
pslqstringrz     s    	!A	!"A
A3q6]D11AaBSy2X!Y''q5Q"$"(1*!2$!A+HHTN  	

1A
ax3!8!GcM8Or   c                 N   U S   nU SS  n / n/ n[        [        U 5      5       H  nX   nU(       d  M  [        U* U5      nX   S   n[        U[        5      (       a>  [        U5      S:X  a  Un	OU< S[        U5      < 3n	X4/US:     R                  U	5        Mw  U< S[        US   5      < SUS   < S3n	X4/US   S:     R                  U	5        M     SR                  U5      nSR                  U5      nU(       a  U(       a  SU< S	U< S3$ U(       a  U$ U(       a  S
U-  $ g )Nr(   r   z**z**(/rp   rm   ro   z)/(z1/(%s))r8   r.   ri   rr   r   r   ra   rt   )
ru   rv   rh   numdenrJ   rg   rw   rx   rN   s
             r   
prodstringr     s   	!A	!"A
C
C3q6]D11AaB!Y''q6Q;B02CF$;1Q3''*%'QqTAaD91Q46"**1-  ((3-C
((3-C
s#s33
3J
8c>!sr   c                    US:  a  U* U* U* pCnU* U R                  US-  SU-  U-  -
  5      -   SU-  -  nU* U R                  US-  SU-  U-  -
  5      -
  SU-  -  n[        XQ-
  5      [        Xa-
  5      :  a?  U(       a!  SU* < SUS-  SU-  U-  -
  < SSU-  < S3nU$ SS	U-  U-  < S
SU-  < S3n U$ U(       a!  SU* < SUS-  SU-  U-  -
  < SSU-  < S3nU$ SS	U-  U-  < S
SU-  < S3nU$ )Nr(   r   r&   z((z+sqrt(z))/rp   z(sqrt(z)/z-sqrt(z(-sqrt()sqrtr   )r<   rN   rd   bcu1u2rL   s           r   quadraticstringr     s"   1uA2qbA"SXXad1Q3q5j!
!AaC	(B"SXXad1Q3q5j!
!AaC	(B
24y3rt9A2ad1Q3q5j1=q
 H &(d1fQqS1q H A2ad1Q3q5j1=qH ')!tAvac2qHr   c                 
    X-  $ r   r   r<   r	   r   s      r   <lambda>r         13r   z$y/$cr(   c                 
    X-  $ r   r   r   s      r   r   r     r   r   z$c*$yc                 
    X!-  $ r   r   r   s      r   r   r     r   r   z$c/$yc                     X-  S-  $ Nr   r   r   s      r   r   r     
    AC!8r   zsqrt($y)/$cc                     X-  S-  $ r   r   r   s      r   r   r     r   r   z$c*sqrt($y)c                     X!-  S-  $ r   r   r   s      r   r   r     r   r   z$c/sqrt($y)c                     X!S-  -  $ r   r   r   s      r   r   r     
    1T6r   zsqrt($y)/sqrt($c)c                     US-  U-  $ r   r   r   s      r   r   r     s    1a46r   zsqrt($c)*sqrt($y)c                     X!S-  -  $ r   r   r   s      r   r   r     r   r   zsqrt($c)/sqrt($y)c                 (    U R                  X-  5      $ r   r   r   s      r   r   r          388AC=r   z$y**2/$cc                 (    U R                  X-  5      $ r   r   r   s      r   r   r     r   r   z$c*$y**2c                 (    U R                  X!-  5      $ r   r   r   s      r   r   r     r   r   z$c/$y**2c                 (    X R                  U5      -  $ r   r   r   s      r   r   r         1XXa[=r   z$y**2/$c**2c                 *    U R                  U5      U-  $ r   r   r   s      r   r   r     s    388A;q=r   z$c**2*$y**2c                 (    X R                  U5      -  $ r   r   r   s      r   r   r     r   r   z$c**2/$y**2c                 (    U R                  X-  5      $ r   expr   s      r   r   r         37713<r   z
log($y)/$cc                 (    U R                  X-  5      $ r   r   r   s      r   r   r     r   r   z
$c*log($y)c                 (    U R                  X!-  5      $ r   r   r   s      r   r   r     r   r   z
$c/log($y)c                 (    X R                  U5      -  $ r   r   r   s      r   r   r   	      1WWQZ<r   z
log($y/$c)c                 *    U R                  U5      U-  $ r   r   r   s      r   r   r   
  s    3771:a<r   z
log($c*$y)c                 (    X R                  U5      -  $ r   r   r   s      r   r   r     r   r   z
log($c/$y)c                 (    U R                  X-  5      $ r   lnr   s      r   r   r         366!#;r   z
exp($y)/$cc                 (    U R                  X-  5      $ r   r   r   s      r   r   r     r   r   z
$c*exp($y)c                 (    U R                  X!-  5      $ r   r   r   s      r   r   r     r   r   z
$c/exp($y)c                 (    X R                  U5      -  $ r   r   r   s      r   r   r         1VVAY;r   z
exp($y/$c)c                 *    U R                  U5      U-  $ r   r   r   s      r   r   r     s    366!9Q;r   z
exp($c*$y)c                 (    X R                  U5      -  $ r   r   r   s      r   r   r     r   r   z
exp($c/$y)c           
        ^ ^^^ / mUU4S jnT R                  U5      nUS:X  a  U(       a  S/$ gUS:  a<  T R                  U* X#XET5      nUc  U$ U(       a  U V	s/ s H  n	SU	-  PM
     sn	$ SU-  $ U(       a  T R                  U5      nOT R                  S-  nUn
U(       a  [        U[        5      (       a?  [        UR                  5       5       VVs/ s H  u  pT R                  U5      U4PM     nnnO>[	        U 4S j[        T 5       5       5      nU Vs/ s H  n[        X5      U4PM     nnO/ nSU VVs/ s H  u  pUPM	     snn;  a  T R                  S5      S	4/U-   n[         GH  u  nnnU GH  u  nnU(       a  US	:X  a  M  U" T UU5      n[        U5      U
S
-  :  d  [        U5      U:  a  MC  T R                  U/U Vs/ s H  nUS   PM
     sn-   X:5      nSn	Ub-  [        S U 5       5      U
::  a  US   (       a  [        UU5      n	OT R                  T R                  UUS
-  /X:5      nUbZ  [        U5      S:X  aK  US
   (       aA  Uu  nnn[        [        U5      [        U5      [        U5      5      U
::  a  [!        T UUUU5      n	U	(       ai  US	:X  a)  SU;   a#  UR#                  SU	5      R#                  SS5      n	O"UR#                  SU	5      R#                  SU5      n	U" U	5        U(       d	  TS   s  s  $ T(       d  GM  [%        S5        GM     GM     US:w  a  / SQn/ nU HE  u  mn	['        UU 4S jU 5       5      (       a  M#  UR)                  T R+                  T5      U	45        MG     U Vs/ s H  nT R+                  U5      [-        U5      4PM!     snU-   nT R                  T R+                  U5      /U Vs/ s H  nUS   PM
     sn-   X:5      nUb>  [        S U 5       5      U
::  a(  US   (       a  U" [/        UU5      5        U(       d  TS   $ U(       a  [        T[        S9$ gs  sn	f s  snnf s  snf s  snnf s  snf s  snf s  snf )a  
Given a real number `x`, ``identify(x)`` attempts to find an exact
formula for `x`. This formula is returned as a string. If no match
is found, ``None`` is returned. With ``full=True``, a list of
matching formulas is returned.

As a simple example, :func:`~mpmath.identify` will find an algebraic
formula for the golden ratio::

    >>> 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.

c                 N   > T(       a  [        SU 5        TR                  U 5        g )NzFound: )r1   ra   )rL   	solutionsr@   s    r   addsolutionidentify.<locals>.addsolution  s    E)Q'r   r(   rq   Nz-(%s)gffffff?c              3   >   >#    U  H  o[        TU5      4v   M     g 7fr   )getattr)r    namer<   s     r   r"   identify.<locals>.<genexpr>  s     L84GC$568s   r   rk   r   c              3   8   #    U  H  n[        U5      v   M     g 7fr   r   r    uws     r   r"   r     s     $9qSWWqr$   r'   z/$cz$yrl   z$c.)r   r'   r      c           	   3      >#    U  HA  n[        TR                  TR                  T5      TR                  U5      -  S 5      5      v   MC     g7f)r   N)boolre   r   )r    rJ   rd   r<   s     r   r"   r   8  s9     P%QtCLL366!9)<Q?@@%s   A	Ac              3   8   #    U  H  n[        U5      v   M     g 7fr   r   r   s     r   r"   r   <  s      51RR1r$   )key)r3   identifyepsrr   dictsorteditemsdireval
transformsr   r_   r0   rz   oner.   r   replacer1   sumra   r   rs   r   ) r<   r	   rv   r=   r>   fullr@   r   solrL   Mr   r+   	namespacerg   valueftftnredr   cnrN   rd   ru   rh   aabbccilogslogsrJ   r   s    `     `               `        @r   r   r     s   j I 	
A 	Av1ullA2yxwG;J'*+s!GAIs++S= 
ggclggslAi&&=CIOODU=VW=V	#''!*d+=VIWIL3s8LLI:CD)Q$q,a0)IDI	 	I6I=DI66ggaj#&')3	 #
CEArrSy3qA1v1}A!i8i!i88#AAA}$9q$9!9Q!>1Q4q), HHcggq!Q$/8=SVq[QqT!"JBB3r73r73r73q8+C"R;9%3,D!,44UB?AD!,44T2>AAIaL0wc
9  #@ 	AvDAqP%PPPSVVAYN+  -22Eq3q6"E2T9HHcffQi[$#7$QAaD$#77@=S 51 55:qt
1d+,	!,iS))S , X E
 7  9> 3#7s*   P;Q Q;QQ?&QQ
__main__)Nr   r%   F)r   )__doc__libmp.backendr   libmpr   r   r   objectr   r_   re   ri   rz   r   r   r   r   r   doctesttestmodr   r   r   <module>r      s  
 " (1	F 	dL	sj	0"." ###]A.]A.]A..2.2.2 *a0 *a0 *a0 -3 -3 -3q1q1q1q1q1q1a0a0a0a0a0a07
<  "tdob	 "  !)  !)   zOO r   