o
    ¨"`Er  ã                   @   sú  d Z ddlmZ ddlmZmZ dd„ ZG dd„ deƒZdSdd„Z	dTdd„Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ ddfdd„ ddfdd„ ddfd d„ d!dfd"d„ d#dfd$d„ d%dfd&d„ d'dfd(d„ d)dfd*d„ d+dfd,d„ d-dfd.d„ d/dfd0d„ d1dfd2d„ d3dfd4d„ d5dfd6d„ d7dfd8d„ d9dfd:d„ d;dfd<d„ d=dfd>d„ d?dfd@d„ dAdfdBd„ dCdfdDd„ dEdfdFd„ dGdfdHd„ dIdfdJd„ dKdfdLd„ dMdfdNd„ dOdfgZg dd	ddfdPdQ„Ze	e_	e
e_
ee_edRkrûddlZe ¡  dS dS )Uzs
Implements the PSLQ algorithm for integer relation detection,
and derivative algorithms for constant recognition.
é   )Úxrange)Ú	int_typesÚ
sqrt_fixedc                 C   s   | d|d >  |? |> S ©Nr   © )ÚxÚprecr   r   ú7/usr/lib/python3/dist-packages/mpmath/identification.pyÚround_fixed
   s   r
   c                   @   s   e Zd ZdS )ÚIdentificationMethodsN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r	   r      s    r   Néè  éd   Fc           "         s	  t |ƒ}|dk rtdƒ‚ˆj‰ˆdk rtdƒ‚|r&ˆtd|ƒ dk r&tdƒ tˆd ƒ}|du r9ˆ d¡|  }nˆ |¡}d	}ˆ|7 ‰|rQtd
ˆˆ |¡f ƒ ˆ 	|ˆ¡}|s[J ‚dg‡‡fdd„|D ƒ }t
dd„ |dd… D ƒƒ}	|	s{tdƒ‚|	|d k r‰|r‡tdƒ dS tdˆ> d ˆƒ}
i }i ‰ i }td|d ƒD ]"‰td|d ƒD ]}ˆ|kˆ>  |ˆ|f< ˆ ˆ|f< d|ˆ|f< q¨qŸdgdg|  }td|d ƒD ]}d}t||d ƒD ]}||| d ˆ? 7 }qÜt|ˆƒ||< qÑ|d }|dd… }td|d ƒD ]}|| ˆ> | ||< || ˆ> | ||< qtd|d ƒD ]f‰tˆd |ƒD ]	}d|ˆ|f< q*ˆ|d krW|ˆ rQ|ˆd  ˆ> |ˆ  |ˆˆf< nd|ˆˆf< tdˆƒD ])}|| ||d   }|r~|ˆ  ||  ˆ> | |ˆ|f< q\d|ˆ|f< q\q!td|d ƒD ]Š‰tˆd ddƒD ]~}|||f r´t|ˆ|f ˆ> |||f  ˆƒ}nq™|| ||ˆ  ˆ?  ||< td|d ƒD ]}|ˆ|f ||||f  ˆ?  |ˆ|f< qËtd|d ƒD ]+}|ˆ|f ||||f  ˆ?  |ˆ|f< ˆ ||f |ˆ |ˆf  ˆ?  ˆ ||f< qêq™qt|ƒD ]P}d}d}td|ƒD ] ‰|ˆˆf }|
ˆ t|ƒ ˆˆd  ? }||krIˆ}|}q*||d  || ||< ||d < td|d ƒD ]‰||d ˆf ||ˆf ||ˆf< ||d ˆf< qctd|d ƒD ]‰||d ˆf ||ˆf ||ˆf< ||d ˆf< q‡td|d ƒD ]‰ˆ ˆ|d f ˆ ˆ|f ˆ ˆ|f< ˆ ˆ|d f< q«||d kr:t|||f d |||d f d  ˆ? ˆƒ}|sì n„|||f ˆ> | }|||d f ˆ> | }t||d ƒD ]0‰|ˆ|f }|ˆ|d f }|| ||  ˆ? |ˆ|f< | | ||  ˆ? |ˆ|d f< q	t|d |d ƒD ]“‰tt
ˆd |d ƒddƒD ]‚}zt|ˆ|f ˆ> |||f  ˆƒ}W n tyr   Y  ncw || ||ˆ  ˆ?  ||< td|d ƒD ]}|ˆ|f ||||f  ˆ?  |ˆ|f< qˆtd|d ƒD ]+}|ˆ|f ||||f  ˆ?  |ˆ|f< ˆ ||f |ˆ |ˆf  ˆ?  ˆ ||f< q§qRqC|ˆ> }td|d ƒD ]L‰t|ˆ ƒ}||k r(‡ ‡‡fdd„td|d ƒD ƒ}tdd„ |D ƒƒ|k r(|r"td||ˆ |ˆ d¡ˆ  d¡f ƒ |    S t
||ƒ}qâtdd„ | ¡ D ƒƒ} | rLddˆ > |  ˆ? }!|!d }!nˆj}!|rgtd||ˆ |ˆ d¡ˆ  d¡|!f ƒ |!|krn nq|rtd||f ƒ td|! ƒ 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 2é5   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                    s   g | ]}ˆ   ˆ  |¡ˆ¡‘qS r   )Úto_fixedÚmpf)Ú.0Zxk)Úctxr   r   r	   Ú
<listcomp>¤   ó    zpslq.<locals>.<listcomp>c                 s   ó    | ]}t |ƒV  qd S ©N©Úabs)r   Zxxr   r   r	   Ú	<genexpr>§   ó   € zpslq.<locals>.<genexpr>r   z)PSLQ requires a vector of nonzero numbersr   z#STOPPING: (one number is too small)é   é   é    éÿÿÿÿc                    s&   g | ]}t tˆ |ˆf ˆƒˆ? ƒ‘qS r   )Úintr
   )r   Új)ÚBÚir   r   r	   r     s   & c                 s   r   r   r   )r   Úvr   r   r	   r     r    z'FOUND relation at iter %i/%i, error: %sc                 s   r   r   r   )r   Úhr   r   r	   r   '  r    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   ZconvertZnstrr   Úminr   r   Úranger
   r   ÚZeroDivisionErrorÚvaluesÚinf)"r   r   ÚtolÚmaxcoeffZmaxstepsÚverboseÚnÚtargetZextraZminxÚgÚAÚHr&   ÚsÚkÚtÚyZsjj1ZREPÚmZszmaxr*   ZszZt0Út1Út2Zt3Zt4Zbest_errÚerrZvecZrecnormZnormr   )r'   r   r(   r   r	   Úpslq   s  s
 þ
"&û$,(,þö
€"HHH.&&ÿ,(,þ€	
ÿÿ
 ÿ
ÿrD   c                 K   sˆ   |   |¡}|dk rtdƒ‚|dkrddgS |   d¡g}td|d ƒD ]}| || ¡ | j|fi |¤Ž}|durA|ddd…   S q"d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   r,   r0   ÚappendrD   )r   r   r7   ÚkwargsZxsr(   Úar   r   r	   Úfindpoly7  s   
iÿýrH   c                 C   sL   | |}}|r||| }}|s|dkr| | } || }|dkr"| S | |fS r   r   )ÚpÚqr   r?   r   r   r	   Úfracgcd¬  s   
ÿrK   c           	      C   sÖ   | d }| dd … } g }t t| ƒƒD ]A}| | }|rSt| |ƒ}|| d }|dkr-d}nd| }t|tƒrH|dkrAt|ƒ| }nd| | }nd| | }| |¡ qd |¡}d	|v sad|v rgd
| d }|pjdS )Nr#   r   Ú1Ú Ú*z(%s)z(%s/%s)z + ú+ú(ú)Ú0)r0   r+   rK   Ú
isinstancer   ÚstrrE   Újoin)	ÚrÚ	constantsrJ   r<   r(   rI   ÚzÚcsZtermr   r   r	   Ú
pslqstring·  s*   

€
rZ   c           
      C   s
  | d }| dd … } g }g }t t| ƒƒD ]P}| | }|rdt| |ƒ}|| d }t|tƒrJt|ƒdkr6|}	nd|t|ƒf }	||g|dk   |	¡ qd|t|d ƒ|d f }	||g|d dk   |	¡ qd |¡}d |¡}|ry|ryd||f S |r}|S |rƒd| S d S )Nr#   r   z%s**%sz%s**(%s/%s)rN   z	(%s)/(%s)z1/(%s))r0   r+   rK   rS   r   r   rE   rU   )
rV   rW   rJ   ZnumZdenr(   rI   rX   rY   r>   r   r   r	   Ú
prodstringÏ  s*   
€

r[   c                 C   s  |dk r| | | }}}| |   |d d| |  ¡ d|  }| |   |d d| |  ¡ d|  }t|| ƒt|| ƒk rg|rYd| |d d| |  d| f }|S dd| | d| f }|S |r}d| |d d| |  d| f }|S dd| | d| f }|S )	Nr#   r   r!   z((%s+sqrt(%s))/%s)z(sqrt(%s)/%s)éüÿÿÿz((%s-sqrt(%s))/%s)z(-sqrt(%s)/%s))Úsqrtr   )r   r>   rG   ÚbÚcZu1Zu2r<   r   r   r	   Úquadraticstringæ  s   (((ü(þÿr`   c                 C   s   || S r   r   ©r   r   r_   r   r   r	   Ú<lambda>÷  ó    rb   z$y/$cr#   c                 C   s   || S r   r   ra   r   r   r	   rb   ø  rc   z$c*$yc                 C   s   || S r   r   ra   r   r   r	   rb   ù  rc   z$c/$yc                 C   s   || d S ©Nr   r   ra   r   r   r	   rb   ú  ó    zsqrt($y)/$cc                 C   s   || d S rd   r   ra   r   r   r	   rb   û  re   z$c*sqrt($y)c                 C   s   || d S rd   r   ra   r   r   r	   rb   ü  re   z$c/sqrt($y)c                 C   s   ||d  S rd   r   ra   r   r   r	   rb   ý  re   zsqrt($y)/sqrt($c)c                 C   s   |d | S rd   r   ra   r   r   r	   rb   þ  re   zsqrt($c)*sqrt($y)c                 C   s   ||d  S rd   r   ra   r   r   r	   rb   ÿ  re   zsqrt($c)/sqrt($y)c                 C   ó   |   || ¡S r   ©r]   ra   r   r   r	   rb      ó    z$y**2/$cc                 C   ó   |   || ¡S r   rg   ra   r   r   r	   rb     rh   z$c*$y**2c                 C   ó   |   || ¡S r   rg   ra   r   r   r	   rb     rh   z$c/$y**2c                 C   ó   ||   |¡ S r   rg   ra   r   r   r	   rb     rh   z$y**2/$c**2c                 C   ó   |   |¡| S r   rg   ra   r   r   r	   rb     rh   z$c**2*$y**2c                 C   ó   ||   |¡ S r   rg   ra   r   r   r	   rb     rh   z$c**2/$y**2c                 C   rf   r   ©Zexpra   r   r   r	   rb     rh   z
log($y)/$cc                 C   ri   r   rn   ra   r   r   r	   rb     rh   z
$c*log($y)c                 C   rj   r   rn   ra   r   r   r	   rb     rh   z
$c/log($y)c                 C   rk   r   rn   ra   r   r   r	   rb   	  rh   z
log($y/$c)c                 C   rl   r   rn   ra   r   r   r	   rb   
  rh   z
log($c*$y)c                 C   rm   r   rn   ra   r   r   r	   rb     rh   z
log($c/$y)c                 C   rf   r   ©Úlnra   r   r   r	   rb     rh   z
exp($y)/$cc                 C   ri   r   ro   ra   r   r   r	   rb     rh   z
$c*exp($y)c                 C   rj   r   ro   ra   r   r   r	   rb     rh   z
$c/exp($y)c                 C   rk   r   ro   ra   r   r   r	   rb     rh   z
exp($y/$c)c                 C   rl   r   ro   ra   r   r   r	   rb     rh   z
exp($c*$y)c                 C   rm   r   ro   ra   r   r   r	   rb     rh   z
exp($c/$y)c                    s  g ‰‡‡fdd„}ˆ  |¡}|dkr|rdgS dS |dk r;ˆ | ||||ˆ¡}|du r.|S |r7dd„ |D ƒS d| S |rCˆ  |¡}nˆjd	 }|}	|rvt|tƒr_‡fd
d„t| ¡ ƒD ƒ}nt‡fdd„tˆƒD ƒƒ‰‡fdd„|D ƒ}ng }ddd„ |D ƒvr‹ˆ  d¡dfg| }tD ]Ä\}
}}|D ]¼\}}|rŸ|dkrŸq”|
ˆ||ƒ}t	|ƒ|	d ks³t	|ƒ|k r´q”ˆ 
|gdd„ |D ƒ ||	¡}d}|durÞtdd„ |D ƒƒ|	krÞ|d rÞt||ƒ}n:ˆ 
ˆj||d g||	¡}|durt|ƒdkr|d r|\}}}tt	|ƒt	|ƒt	|ƒƒ|	krtˆ||||ƒ}|rI|dkr0d|v r0| d|¡ dd¡}n
| d|¡ d|¡}||ƒ |sIˆd     S ˆrPtdƒ q”q|dkr½g d¢}g }|D ]\‰ }t‡ ‡fdd„|D ƒƒsz| ˆ ˆ ¡|f¡ q_‡fdd„|D ƒ| }ˆ 
ˆ |¡gdd„ |D ƒ ||	¡}|dur½tdd„ |D ƒƒ|	kr½|d r½|t||ƒƒ |s½ˆd S |rÆtˆtd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                    s   ˆrt d| ƒ ˆ  | ¡ d S )NzFound: )r.   rE   )r<   )Ú	solutionsr6   r   r	   Úaddsolutionë  s   zidentify.<locals>.addsolutionr#   rR   Nc                 S   s   g | ]}d | ‘qS )ú-(%s)r   )r   r<   r   r   r	   r   ú  ó    zidentify.<locals>.<listcomp>rs   gffffffæ?c                    s   g | ]\}}ˆ   |¡|f‘qS r   )r   )r   Únamer)   ©r   r   r	   r     r   c                 3   s    | ]
}|t ˆ |ƒfV  qd S r   )Úgetattr)r   ru   rv   r   r	   r     s   € zidentify.<locals>.<genexpr>c                    s   g | ]	}t |ˆ ƒ|f‘qS r   )Úeval)r   rI   )Ú	namespacer   r	   r   	  s    r   c                 S   s   g | ]\}}|‘qS r   r   )r   ru   Úvaluer   r   r	   r     rt   rL   r   c                 S   ó   g | ]}|d  ‘qS ©r#   r   ©r   rG   r   r   r	   r     rt   c                 s   r   r   r   ©r   Zuwr   r   r	   r     r    r"   z/$cz$yrM   z$cÚ.)r   r"   r   é   c                 3   s0    | ]}t ˆ ˆ ˆ ¡ˆ |¡ d ¡ƒV  qdS )r   N)ÚboolrH   rp   ©r   r(   )rG   r   r   r	   r   8  s   €. c                    s   g | ]}ˆ   |¡t|ƒf‘qS r   )rp   rT   r‚   rv   r   r	   r   :  r   c                 S   r{   r|   r   r}   r   r   r	   r   ;  rt   c                 s   r   r   r   r~   r   r   r	   r   <  r    )Úkey)r   ÚidentifyZepsrS   ÚdictÚsortedÚitemsÚdirÚ
transformsr   rD   r-   rZ   Zoner+   r`   Úreplacer.   ÚsumrE   rp   r[   )r   r   rW   r4   r5   Zfullr6   rr   ZsolÚMZftZftnZredr_   Zcnr>   rV   r<   rJ   ZaaZbbZccZilogsZlogsr   )rG   r   ry   rq   r6   r	   r„     s†    V



&"
€ä
€$,r„   Ú__main__)Nr   r   F)r   )Ú__doc__Zlibmp.backendr   Zlibmpr   r   r
   Úobjectr   rD   rH   rK   rZ   r[   r`   r‰   r„   r   ZdoctestZtestmodr   r   r   r	   Ú<module>   sj    
  
(uå
ÿ  3þ