
    gEr                        d Z ddlmZ ddlmZmZ d Z G d de          ZdJdZ	dKdZ
d Zd Zd Zd Zd ddfd ddfd ddfd ddfd ddfd ddfd ddfd  d!dfd" d#dfd$ d%dfd& d'dfd( d)dfd* d+dfd, d-dfd. d/dfd0 d1dfd2 d3dfd4 d5dfd6 d7dfd8 d9dfd: d;dfd< d=dfd> d?dfd@ dAdfdB dCdfdD dEdfdF dGdfgZg ddd
d
fdHZe	e_	        e
e_
        ee_        edIk    rddlZ ej                     dS dS )Lzs
Implements the PSLQ algorithm for integer relation detection,
and derivative algorithms for constant recognition.
   )xrange)	int_types
sqrt_fixedc                 $    | d|dz
  z  z   |z	  |z  S Nr    )xprecs     Q/var/www/html/ai-engine/env/lib/python3.11/site-packages/mpmath/identification.pyround_fixedr   
   s    !d1f+4'D00    c                       e Zd ZdS )IdentificationMethodsN)__name__
__module____qualname__r   r   r   r   r      s        Dr   r   N  d   Fc                 b   "#$ t          |          }|dk     rt          d           j        $$dk     rt          d          |r&$t          d|          z  dk     rt	          d           t          $dz            }|                     d          | z  }n                     |          }d	}$|z  $|r't	          d
$                     |          fz              	                    |$          }|sJ dg $fd|D             z   }t          d |dd         D                       }	|	st          d          |	|dz  k     r|rt	          d           dS t          d$z  dz  $          }
i }i "i }t          d|dz             D ]4#t          d|dz             D ]}#|k    $z  x|#|f<   "#|f<   d|#|f<   5dgdg|z  z   }t          d|dz             D ]>}d}t          ||dz             D ]}|||         dz  $z	  z  }t          |$          ||<   ?|d         }|dd         }t          d|dz             D ]$}||         $z  |z  ||<   ||         $z  |z  ||<   %t          d|dz             D ]#t          #dz   |          D ]	}d|#|f<   
#|dz
  k    r,|#         r|#dz            $z  |#         z  |##f<   nd|##f<   t          d#          D ]=}||         ||dz            z  }|r|#          ||         z  $z  |z  |#|f<   6d|#|f<   >t          d|dz             D ]#t          #dz
  dd          D ]}|||f         r't          |#|f         $z  |||f         z  $          }n4||         ||#         z  $z	  z   ||<   t          d|dz             D ]"}|#|f         ||||f         z  $z	  z
  |#|f<   #t          d|dz             D ]B}|#|f         ||||f         z  $z	  z
  |#|f<   "||f         |"|#f         z  $z	  z   "||f<   Cیt          |          D ]V}d}d}t          d|          D ]4#|##f         }|
#z  t          |          z  $#dz
  z  z	  }||k    r#}|}5||dz            ||         c||<   ||dz   <   t          d|dz             D ]'#||dz   #f         ||#f         c||#f<   ||dz   #f<   (t          d|dz             D ]'#||dz   #f         ||#f         c||#f<   ||dz   #f<   (t          d|dz             D ]'#"#|dz   f         "#|f         c"#|f<   "#|dz   f<   (||dz
  k    rt          |||f         dz  |||dz   f         dz  z   $z	  $          }|s n|||f         $z  |z  }|||dz   f         $z  |z  }t          ||dz             D ]C#|#|f         }|#|dz   f         }||z  ||z  z   $z	  |#|f<   | |z  ||z  z   $z	  |#|dz   f<   Dt          |dz   |dz             D ]
#t          t          #dz
  |dz             dd          D ]}	 t          |#|f         $z  |||f         z  $          }n# t           $ r Y  nw xY w||         ||#         z  $z	  z   ||<   t          d|dz             D ]"}|#|f         ||||f         z  $z	  z
  |#|f<   #t          d|dz             D ]B}|#|f         ||||f         z  $z	  z
  |#|f<   "||f         |"|#f         z  $z	  z   "||f<   C|$z  }t          d|dz             D ]#t          |#                   }||k     r"#$fdt          d|dz             D             }t          d |D                       |k     rJ|rBt	          d||                     |                     d          $z  z  d          fz             |c c S t          ||          }t          d |                                D                       } | rdd$z  z  | z  $z	  }!|!dz  }!n j        }!|rCt	          d||                     |                     d          $z  z  d          |!fz             |!|k    r nX|r&t	          d||fz             t	          d|!z             dS )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.
       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                 b    g | ]+}                                         |                    ,S r   )to_fixedmpf).0xkctxr
   s     r   
<listcomp>zpslq.<locals>.<listcomp>   s1    >>>b#,,swwr{{D11>>>r   c              3   4   K   | ]}t          |          V  d S Nabs)r   xxs     r   	<genexpr>zpslq.<locals>.<genexpr>   s(      ''2s2ww''''''r   r   z)PSLQ requires a vector of nonzero numbersr   z#STOPPING: (one number is too small)          c           	      `    g | ]*}t          t          |f                   z	            +S r   )intr   )r   jBir
   s     r   r    zpslq.<locals>.<listcomp>  sD       !s;q1vt44<==   r   c              3   4   K   | ]}t          |          V  d S r"   r#   )r   vs     r   r&   zpslq.<locals>.<genexpr>  s(      ++!s1vv++++++r   z'FOUND relation at iter %i/%i, error: %sc              3   4   K   | ]}t          |          V  d S r"   r#   )r   hs     r   r&   zpslq.<locals>.<genexpr>'  s(      11c!ff111111r   z%i/%i:  Error: %8s   Norm: %szCANCELLING after step %i/%i.z2Could not find an integer relation. Norm bound: %s)len
ValueErrorr
   maxprintr,   r   convertnstrr   minr   r   ranger   r$   ZeroDivisionErrorvaluesinf)%r   r	   tolmaxcoeffmaxstepsverbosentargetextraminxgAHr-   sktysjj1REPmszmaxr3   szt0t1t2t3t4best_errerrvecrecnormnormr.   r/   r
   s%   `                                 @@@r   pslqr]      sp   f 	AA1uu2333 8Dbyy6777 <43q88#a'':;;;F
{ggajjF7#kk#EEMD G-sxx}}0EEFFF
,,sD
!
!CJJJ 
>>>>>A>>>>A ''122'''''D FDEEEc3h 	97888tAtGa<&&A
A
A
A Aqs^^  1Q3 	 	A !tn,AacFQqsVAacFF	 
!qAAqs^^ # #1Q3 	# 	#A!A$'T/"AA!T""!	!A	!!!AAqs^^ # #!"!!"!Aqs^^  !Q 	 	AAacFF!88t AaC&D.QqT1!A#!A#q! 	 	AQ4!A#;D aD51:,t3!A#!A#	 Aqs^^ 5 5!Q## 	5 	5A1v 1Q34!AaC& 8$?? Q41QqT6T>*AaDAqs^^ 5 51Q31QqsV8t#34!A#Aqs^^ 5 51Q31QqsV8t#34!A#1Q31QqsV8t#34!A#5	5 X M Mq! 	 	A!A#AQ$Q-T1Q3Z0BEzz1vqt!a!f!A#CCA1QqSU8QqsV 0!A#!A#a%!A#CCA1QqSU8QqsV 0!A#!A#a%!A#CCA1QqsU8QqsV 0!A#!AaC%A::QqsVQY1QqS514t;TBBB  AaC&D.R'BAacE(d"r)BAqs^^ 2 2qsVq1uXR%2+$.!A#CF2b5LT1!AaC%!QqS!! 	9 	9AC!QqSMM1b11 9 9#QqsVt^a!f$<dCCAA(   EEt!A$4/0!1Q3 9 9AqsVq1Q3x4'78AacFF1Q3 9 9AqsVq1Q3x4'78AacFqsVq1Q3x4'78AacFF9 T>1Q3 	* 	*Aad))CSyy     a!  ++s+++++h66 RG (CHHS3771::t;K5KQ,O,OPQ R R RJJJJJ3))HH 11ahhjj11111 	1T6]w.47DSLDD7D 	Q1hCGGAJJ4D)Da H H$OP Q Q Q8E  K,X>???BTIJJJ4s   &Y((
Y6	5Y6	c                 0   |                      |          }|dk     rt          d          |dk    rddgS |                      d          g}t          d|dz             D ]7}|                    ||z              | j        |fi |}||ddd         c S 8dS )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*   )r   r5   r;   appendr]   )r   r	   rC   kwargsxsr/   as          r   findpolyrc   7  s    R 	

A1uu2333Avv1v
''!**B1QqS\\  
		!Q$CHR""6""=TTrT7NNN  r   c                 X    | |}}|r	|||z  }}|	|dk    r
| |z  } ||z  }|dk    r| S | |fS r   r   )pqr	   rM   s       r   fracgcdrg     s\    aqA
 !a%1  Avv	a	aAvva4Kr   c                    | d         }| dd          } g }t          t          |                     D ]}| |         }|rt          | |          }||         d         }|dk    rd}nd|z   }t          |t                    r"|dk    rt          |          |z   }nd|z  |z   }nd|z  |z   }|                    |           d                    |          }d	|v sd|v rd
|z   dz   }|pdS )Nr)   r   1 *z(%s)z(%s/%s)z + +()0)r;   r4   rg   
isinstancer   strr_   join)	r	constantsrf   rJ   r/   re   zcsterms	            r   
pslqstringrx     s   	!A	!""A
A3q66]]  aD 	1A1aBSyy2X!Y'' ,q55Q"$$"(1*!2$$!A+HHTNNN

1A
axx3!88!GcM8Or   c                    | d         }| dd          } g }g }t          t          |                     D ]}| |         }|rt          | |          }||         d         }t          |t                    rLt          |          dk    r|}	n|dt          |          }	||g|dk                                  |	           |dt          |d                   d|d         d}	||g|d         dk                                  |	           d                    |          }d                    |          }|r|r	d|d	|dS |r|S |rd
|z  S d S )Nr)   r   z**z**(/rn   rk   rm   z)/(z1/(%s))r;   r4   rg   rp   r   r$   r_   rr   )
rs   rt   rf   numdenr/   re   ru   rv   rL   s
             r   
prodstringr}     ss   	!A	!""A
C
C3q66]] . .aD 		.1A1aB!Y'' .q66Q;;B02CFFF$;c1Q3''****%'RRQqTAaDDD9c1Q46"**1---
((3--C
((3--C
3s33###sss33
3J
!8c>!!!r   c                    |dk     r	| | | }}}| |                      |dz  d|z  |z  z
            z   d|z  z  }| |                      |dz  d|z  |z  z
            z
  d|z  z  }t          ||z
            t          ||z
            k     r2|rd| d|dz  d|z  |z  z
  dd|z  d}nDdd	|z  |z  d
d|z  d}n1|rd| d|dz  d|z  |z  z
  dd|z  d}ndd	|z  |z  d
d|z  d}|S )Nr)   r   r'   z((z+sqrt(z))/rn   z(sqrt(z)/z-sqrt(z(-sqrt()sqrtr$   )r   rL   rb   bcu1u2rJ   s           r   quadraticstringr     sd   1uuA2qbA!"SXXad1Q3q5j!!
!AaC	(B"SXXad1Q3q5j!!
!AaC	(B
2a4yy3r!t99 	2 	2A222ad1Q3q5jjj1=qq 	2&(d1fffQqSSS1qq 	3 	3A222ad1Q3q5jjj1=qq 	3')!tAvvvaccc2qHr   c                     ||z  S r"   r   r   r	   r   s      r   <lambda>r     
    1Q3 r   z$y/$cr)   c                     ||z  S r"   r   r   s      r   r   r     r   r   z$c*$yc                     ||z  S r"   r   r   s      r   r   r     r   r   z$c/$yc                     ||z  dz  S Nr   r   r   s      r   r   r         AaC!8 r   zsqrt($y)/$cc                     ||z  dz  S r   r   r   s      r   r   r     r   r   z$c*sqrt($y)c                     ||z  dz  S r   r   r   s      r   r   r     r   r   z$c/sqrt($y)c                     ||dz  z  S r   r   r   s      r   r   r         1QT6 r   zsqrt($y)/sqrt($c)c                     |dz  |z  S r   r   r   s      r   r   r     s    1a46 r   zsqrt($c)*sqrt($y)c                     ||dz  z  S r   r   r   s      r   r   r     r   r   zsqrt($c)/sqrt($y)c                 2    |                      ||z            S r"   r   r   s      r   r   r          388AaC== r   z$y**2/$cc                 2    |                      ||z            S r"   r   r   s      r   r   r     r   r   z$c*$y**2c                 2    |                      ||z            S r"   r   r   s      r   r   r     r   r   z$c/$y**2c                 2    ||                      |          z  S r"   r   r   s      r   r   r         1SXXa[[= r   z$y**2/$c**2c                 2    |                      |          |z  S r"   r   r   s      r   r   r     s    388A;;q= r   z$c**2*$y**2c                 2    ||                      |          z  S r"   r   r   s      r   r   r     r   r   z$c**2/$y**2c                 2    |                      ||z            S r"   expr   s      r   r   r         3771Q3<< r   z
log($y)/$cc                 2    |                      ||z            S r"   r   r   s      r   r   r     r   r   z
$c*log($y)c                 2    |                      ||z            S r"   r   r   s      r   r   r     r   r   z
$c/log($y)c                 2    ||                      |          z  S r"   r   r   s      r   r   r   	      1SWWQZZ< r   z
log($y/$c)c                 2    |                      |          |z  S r"   r   r   s      r   r   r   
  s    3771::a< r   z
log($c*$y)c                 2    ||                      |          z  S r"   r   r   s      r   r   r     r   r   z
log($c/$y)c                 2    |                      ||z            S r"   lnr   s      r   r   r         366!A#;; r   z
exp($y)/$cc                 2    |                      ||z            S r"   r   r   s      r   r   r     r   r   z
$c*exp($y)c                 2    |                      ||z            S r"   r   r   s      r   r   r     r   r   z
$c/exp($y)c                 2    ||                      |          z  S r"   r   r   s      r   r   r         1SVVAYY; r   z
exp($y/$c)c                 2    |                      |          |z  S r"   r   r   s      r   r   r     s    366!99Q; r   z
exp($c*$y)c                 2    ||                      |          z  S r"   r   r   s      r   r   r     r   r   z
exp($c/$y)c           	      $    g fd}                      |          }|dk    r|rdgS dS |dk     r2                     | ||||          }||S |rd |D             S d|z  S |r                      |          }n
 j        dz  }|}	|rzt          |t                    r. fdt          |                                          D             }n9t	           fd	t                     D                       fd
|D             }ng }dd |D             vr                      d          dfg|z   }t          D ]\  }
}}|D ]\  }}|r|dk    r |
 ||          }t          |          |	dz  k    st          |          |k     rF 
                    |gd |D             z   ||	          }d}|6t          d |D                       |	k    r|d         rt          ||          }n 
                     j        ||dz  g||	          }|pt          |          dk    r]|d         rU|\  }}}t          t          |          t          |          t          |                    |	k    rt           ||||          }|rx|dk    r/d|v r+|                    d|                              dd          }n*|                    d|                              d|          } ||           |sd         c c S rt#          d           Ɛ|dk    rg d}g }|D ]K\  }t%           fd|D                       s*|                                                   |f           L fd|D             |z   } 
                                         |          gd |D             z   ||	          }|Ht          d |D                       |	k    r+|d         r# |t+          ||                     |sd         S |rt          t                    S dS )an  
    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                 V    rt          d|                                |            d S )NzFound: )r7   r_   )rJ   	solutionsrB   s    r   addsolutionzidentify.<locals>.addsolution  s2    'E)Q'''r   r)   ro   Nc                     g | ]}d |z  S )-(%s)r   )r   rJ   s     r   r    zidentify.<locals>.<listcomp>  s    +++!GAI+++r   r   gffffff?c                 D    g | ]\  }}                     |          |fS r   )r   )r   namer1   r   s      r   r    zidentify.<locals>.<listcomp>  s,    WWW	q#''!**d+WWWr   c              3   <   K   | ]}|t          |          fV  d S r"   )getattr)r   r   r   s     r   r&   zidentify.<locals>.<genexpr>  s2      LL4dGC$5$56LLLLLLr   c                 4    g | ]}t          |          |fS r   )eval)r   re   	namespaces     r   r    zidentify.<locals>.<listcomp>	  s(    DDDQ$q),,a0DDDr   r   c                     g | ]\  }}|S r   r   )r   r   values      r   r    zidentify.<locals>.<listcomp>  s    666=D%666r   ri   r   c                     g | ]
}|d          S r)   r   r   rb   s     r   r    zidentify.<locals>.<listcomp>  s    888!888r   c              3   4   K   | ]}t          |          V  d S r"   r#   r   uws     r   r&   zidentify.<locals>.<genexpr>  s(      $9$9SWW$9$9$9$9$9$9r   r(   z/$cz$yrj   z$c.)r   r(   r      c           	   3      K   | ]P}t                                                                                |          z  d                     V  QdS )r   N)boolrc   r   )r   r/   rb   r   s     r   r&   zidentify.<locals>.<genexpr>8  sR      PPQtCLL366!99)<Q??@@PPPPPPr   c                 X    g | ]&}                     |          t          |          f'S r   )r   rq   )r   r/   r   s     r   r    zidentify.<locals>.<listcomp>:  s.    222q3q66"222r   c                     g | ]
}|d          S r   r   r   s     r   r    zidentify.<locals>.<listcomp>;  s    #7#7#7QAaD#7#7#7r   c              3   4   K   | ]}t          |          V  d S r"   r#   r   s     r   r&   zidentify.<locals>.<genexpr><  s(       5 5RR 5 5 5 5 5 5r   )key)r   identifyepsrp   dictsorteditemsdir
transformsr$   r]   r6   rx   oner4   r   replacer7   sumr_   r   r}   )r   r	   rt   r?   r@   fullrB   r   solMftftnredr   cnrL   rs   rJ   rf   aabbccilogslogsrb   r   r   s   `     `                 @@@r   r   r     s   j I      	

A 	Avv 	1uullA2y#xwGG;J 	!++s++++S= 
 ggcllgslA i&& 	EWWWWVIOODUDU=V=VWWWIILLLL3s88LLLLLIDDDD)DDDII	 	66I66666ggajj#&')3	 #  C 	 	EAr rSyy3qA1vv1}}A!88i8888#qAAAA}$9$9q$9$9$9!9!9Q!>!>1Q4!>q),, HHcgq!Q$/a88=SVVq[[QqT[!"JBB3r773r773r7733q88+C"R;; 199%3,,D!,,44UB??AAD!,,44T2>>AA0IaL00000 c


9	> 	Avv		 	, 	,DAqPPPPP%PPPPP ,SVVAYYN+++2222E222T9HHcffQii[#7#7$#7#7#77a@@=S 5 51 5 5 555::qt:K
1d++,,,,	!, iS))))tr   __main__)Nr   r   F)r   )__doc__libmp.backendr   libmpr   r   r   objectr   r]   rc   rg   rx   r}   r   r   r   r   doctesttestmodr   r   r   <module>r      s   
 " ! ! ! ! ! ( ( ( ( ( ( ( (1 1 1	 	 	 	 	F 	 	 	d d d dL	s s s 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 o o ob	 "  !)  !)   zNNNGO r   