� H�gEr����dZddlmZddlmZmZd�ZGd�de��ZdJd �Z dKd �Z d �Z d�Z d�Z d�Zd�ddfd�ddfd�ddfd�ddfd�ddfd�ddfd�ddfd �d!dfd"�d#dfd$�d%dfd&�d'dfd(�d)dfd*�d+dfd,�d-dfd.�d/dfd0�d1dfd2�d3dfd4�d5dfd6�d7dfd8�d9dfd:�d;dfd<�d=dfd>�d?dfd@�dAdfdB�dCdfdD�dEdfdF�dGdfgZgddd d fdH�Ze e_ e e_ ee_edIkrddlZej��dSdS)Lzs Implements the PSLQ algorithm for integer relation detection, and derivative algorithms for constant recognition. �)�xrange)� int_types� sqrt_fixedc�$�|d|dz zz|z |zS�Nr�)�x�precs �e/home/asafur/pinokio/api/open-webui.git/app/env/lib/python3.11/site-packages/mpmath/identification.py� round_fixedr s�� �!�d�1�f�+� �4� '�D� 0�0�c��eZdZdS)�IdentificationMethodsN)�__name__� __module__� __qualname__rr r rr s�������Dr rN���dFc �b��"�#�$�t|��}|dkrtd����j�$�$dkrtd���|r&�$td|��zdkrt d��t �$dz��}|���d��| z}n��|��}d }�$|z �$|r't d �$��|��fz���� |�$��}|sJ�dg��$fd �|D��z}td �|d d�D����} | std���| |dzkr|rt d��dStd�$zdz�$��} i} i�"i} td |d z��D]4�#td |d z��D]} �#| k�$zx| �#| f<�"�#| f<d| �#| f<��5dgdg|zz}td |d z��D]>}d}t||d z��D]} ||| dz�$z z }�t|�$��||<�?|d }|dd�}td |d z��D]$}||�$z|z||<||�$z|z||<�%td |d z��D]��#t�#d z|��D] } d| �#| f<� �#|d z kr,|�#r|�#d z�$z|�#z| �#�#f<nd| �#�#f<td �#��D]=} || || d zz}|r|�# || z�$z|z| �#| f<�6d| �#| f<�>��td|d z��D]�#t�#d z dd��D]�} | | | fr't| �#| f�$z| | | fz�$��}n�4|| ||�#z�$z z|| <td | d z��D]"}| �#|f|| | |fz�$z z | �#|f<�#td |d z��D]B}| �#|f|| | |fz�$z z | �#|f<�"|| f|�"|�#fz�$z z�"|| f<�C�ی�t|��D�]V}d}d}td |��D]4�#| �#�#f}| �#zt|��z�$�#d z zz }||kr�#}|}�5||d z||c||<||d z<td |d z��D]'�#| |d z�#f| |�#fc| |�#f<| |d z�#f<�(td |d z��D]'�#| |d z�#f| |�#fc| |�#f<| |d z�#f<�(td |d z��D]'�#�"�#|d zf�"�#|fc�"�#|f<�"�#|d zf<�(||dz kr�t| ||fdz| ||d zfdzz�$z �$��}|s�n| ||f�$z|z}| ||d zf�$z|z}t||d z��D]C�#| �#|f}| �#|d zf}||z||zz�$z | �#|f<| |z||zz�$z | �#|d zf<�Dt|d z|d z��D�] �#tt�#d z |d z��dd��D]�} t| �#| f�$z| | | fz�$��}n#t $rYn�wxYw|| ||�#z�$z z|| <td | d z��D]"}| �#|f|| | |fz�$z z | �#|f<�#td |d z��D]B}| �#|f|| | |fz�$z z | �#|f<�"|| f|�"|�#fz�$z z�"|| f<�C��� |�$z}td |d z��D]��#t|�#��}||kr��"�#�$fd�td |d z��D��}td�|D����|krJ|rBt d||��|��d���$zz d ��fz��|ccSt||��}��td�| ���D����} | rd d�$zz| z�$z }!|!dz}!n�j}!|rCt d||��|��d���$zz d ��|!fz��|!|krn��X|r&t d||fz��t d|!z��dS)a� Given a vector of real numbers `x = [x_0, x_1, ..., x_n]`, ``pslq(x)`` uses the PSLQ algorithm to find a list of integers `[c_0, c_1, ..., c_n]` such that .. math :: |c_1 x_1 + c_2 x_2 + ... + c_n x_n| < \mathrm{tol} and such that `\max |c_k| < \mathrm{maxcoeff}`. If no such vector exists, :func:`~mpmath.pslq` returns ``None``. The tolerance defaults to 3/4 of the working precision. **Examples** Find rational approximations for `\pi`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> pslq([-1, pi], tol=0.01) [22, 7] >>> pslq([-1, pi], tol=0.001) [355, 113] >>> mpf(22)/7; mpf(355)/113; +pi 3.14285714285714 3.14159292035398 3.14159265358979 Pi is not a rational number with denominator less than 1000:: >>> pslq([-1, pi]) >>> To within the standard precision, it can however be approximated by at least one rational number with denominator less than `10^{12}`:: >>> p, q = pslq([-1, pi], maxcoeff=10**12) >>> print(p); print(q) 238410049439 75888275702 >>> mpf(p)/q 3.14159265358979 The PSLQ algorithm can be applied to long vectors. For example, we can investigate the rational (in)dependence of integer square roots:: >>> mp.dps = 30 >>> pslq([sqrt(n) for n in range(2, 5+1)]) >>> >>> pslq([sqrt(n) for n in range(2, 6+1)]) >>> >>> pslq([sqrt(n) for n in range(2, 8+1)]) [2, 0, 0, 0, 0, 0, -1] **Machin formulas** A famous formula for `\pi` is Machin's, .. math :: \frac{\pi}{4} = 4 \operatorname{acot} 5 - \operatorname{acot} 239 There are actually infinitely many formulas of this type. Two others are .. math :: \frac{\pi}{4} = \operatorname{acot} 1 \frac{\pi}{4} = 12 \operatorname{acot} 49 + 32 \operatorname{acot} 57 + 5 \operatorname{acot} 239 + 12 \operatorname{acot} 110443 We can easily verify the formulas using the PSLQ algorithm:: >>> mp.dps = 30 >>> pslq([pi/4, acot(1)]) [1, -1] >>> pslq([pi/4, acot(5), acot(239)]) [1, -4, 1] >>> pslq([pi/4, acot(49), acot(57), acot(239), acot(110443)]) [1, -12, -32, 5, -12] We could try to generate a custom Machin-like formula by running the PSLQ algorithm with a few inverse cotangent values, for example acot(2), acot(3) ... acot(10). Unfortunately, there is a linear dependence among these values, resulting in only that dependence being detected, with a zero coefficient for `\pi`:: >>> pslq([pi] + [acot(n) for n in range(2,11)]) [0, 1, -1, 0, 0, 0, -1, 0, 0, 0] We get better luck by removing linearly dependent terms:: >>> pslq([pi] + [acot(n) for n in range(2,11) if n not in (3, 5)]) [1, -8, 0, 0, 4, 0, 0, 0] In other words, we found the following formula:: >>> 8*acot(2) - 4*acot(7) 3.14159265358979323846264338328 >>> +pi 3.14159265358979323846264338328 **Algorithm** This is a fairly direct translation to Python of the pseudocode given by David Bailey, "The PSLQ Integer Relation Algorithm": http://www.cecm.sfu.ca/organics/papers/bailey/paper/html/node3.html The present implementation uses fixed-point instead of floating-point arithmetic, since this is significantly (about 7x) faster. �zn cannot be less than 2�5zprec cannot be less than 53�z*Warning: precision for PSLQ may be too lowg�?N�<zPSLQ using prec %i and tol %sc�b��g|]+}����|�������,Sr)�to_fixed�mpf)�.0�xk�ctxr s ��r � <listcomp>zpslq.<locals>.<listcomp>�s1���>�>�>�b�#�,�,�s�w�w�r�{�{�D�1�1�>�>�>r c3�4K�|]}t|��V��dS�N��abs)r�xxs r � <genexpr>zpslq.<locals>.<genexpr>�s(����'�'�2�s�2�w�w�'�'�'�'�'�'r rz)PSLQ requires a vector of nonzero numbersrz#STOPPING: (one number is too small)��������c �`��g|]*}tt�|�f����z ����+Sr)�intr )r�j�B�ir s ���r r zpslq.<locals>.<listcomp>sD������!�s�;�q��1��v�t�4�4��<�=�=���r c3�4K�|]}t|��V��dSr"r#)r�vs r r&zpslq.<locals>.<genexpr>s(����+�+�!�s�1�v�v�+�+�+�+�+�+r z'FOUND relation at iter %i/%i, error: %sc3�4K�|]}t|��V��dSr"r#)r�hs r r&zpslq.<locals>.<genexpr>'s(����1�1��c�!�f�f�1�1�1�1�1�1r z%i/%i: Error: %8s Norm: %szCANCELLING after step %i/%i.z2Could not find an integer relation. Norm bound: %s)�len� ValueErrorr �max�printr,r�convert�nstrr�minrr�ranger r$�ZeroDivisionError�values�inf)%rr �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��1�u�u��2�3�3�3� �8�D� �b�y�y��6�7�7�7��<�4�3�q��8�8�#�a�'�'� �:�;�;�;� ���� � �F� �{��g�g�a�j�j�F�7�#����k�k�#���� �E��E�M�D��G� �-��s�x�x��}�}�0E�E�F�F�F� �,�,�s�D� !� !�C� �J�J�3� ��>�>�>�>�>�A�>�>�>�>�A� �'�'��1�2�2��'�'�'� '� '�D� �F��D�E�E�E� �c�3�h��� � 9� �7� 8� 8� 8��t��A�t�G�a�<��&�&�A� �A� �A� �A��A�q��s�^�^������1�Q�3��� � �A� �!�t��n� ,�A�a��c�F�Q�q��s�V��A�a��c�F�F� � ��!��q���A� �A�q��s�^�^�#�#�� ����1�Q�3��� #� #�A� �!�A�$��'�T�/� "�A�A��!�T�"�"��!��� �!��A� �!�!�!��A� �A�q��s�^�^�#�#���!��� ��"��!���!��� ��"��!��� �A�q��s�^�^� � ����!��Q��� � �A��A�a��c�F�F� ��!��8�8���t� ��A�a�C�&�D�.�Q�q�T�1��!�A�#�����!�A�#���q�!��� � �A��Q�4��!�A�#��;�D�� ��a�D�5��1��:��,�t�3��!�A�#�����!�A�#���  ��A�q��s�^�^� 5� 5����!��Q��#�#� 5� 5�A���1��v� ���1�Q�3��4��!�A�a�C�&� 8�$�?�?�����Q�4�1�Q�q�T�6�T�>�*�A�a�D��A�q��s�^�^� 5� 5���1�Q�3��1�Q�q��s�V�8�t�#3�4��!�A�#����A�q��s�^�^� 5� 5���1�Q�3��1�Q�q��s�V�8�t�#3�4��!�A�#���1�Q�3��1�Q�q��s�V�8�t�#3�4��!�A�#��� 5� 5��X���M�M�� �����q�!��� � �A��!�A�#��A��Q�$��Q���-�T�1�Q�3�Z�0�B��E�z�z��������1��v�q��t� ��!��a��!��f���!�A�#���C�C�A�1�Q�q�S��U�8�Q�q��s�V� 0��!�A�#���!�A�#�a�%�����!�A�#���C�C�A�1�Q�q�S��U�8�Q�q��s�V� 0��!�A�#���!�A�#�a�%�����!�A�#���C�C�A�1�Q�q��s�U�8�Q�q��s�V� 0��!�A�#���!�A�a�C�%��� ��A��:�:��Q�q��s�V�Q�Y��1�Q�q�S�5��1��4�t�;�T�B�B�B�� ����A�a�C�&�D�.�R�'�B��A�a��c�E�(�d�"�r�)�B��A�q��s�^�^� 2� 2���q��s�V���q��1��u�X���R�%��2��+�$�.��!�A�#���C��F�2�b�5�L�T�1��!�A�a�C�%�����!��Q�q�S�!�!� 9� 9�A��C��!��Q�q�S�M�M�1�b�1�1� 9� 9���#�Q�q��s�V�t�^�a��!��f�$<�d�C�C�A�A��(�����E�E�������t��!�A�$��4�/�0��!����1�Q�3���9�9�A��q��s�V�q��1�Q�3��x�4�'7�8�A�a��c�F�F���1�Q�3���9�9�A��q��s�V�q��1�Q�3��x�4�'7�8�A�a��c�F��q��s�V�q��1�Q�3��x�4�'7�8�A�a��c�F�F�9���T�>����1�Q�3��� *� *�A��a��d�)�)�C��S�y�y��������a��!�� � ������+�+�s�+�+�+�+�+�h�6�6��R��G� �(�C�H�H�S�3�7�7�1�:�:�t�;K�5K�Q�,O�,O�P�Q�R�R�R��J�J�J�J�J��3��)�)�H�H��1�1�a�h�h�j�j�1�1�1�1�1�� � ��1�T�6�]�w�.�4�7�D� �S�L�D�D��7�D� � Q� �1��h�����C�G�G�A�J�J��4D�)D�a� H� H�$�O�P� Q� Q� Q� �8� � � �E� ��K� �,��X��>�?�?�?� �B�T�I�J�J�J� �4s�&Y(�( Y6 �5Y6 c �0�|�|��}|dkrtd���|dkrddgS|�d��g}td|dz��D]7}|�||z��|j|fi|��}|� |ddd�cS�8dS)a� ``findpoly(x, n)`` returns the coefficients of an integer polynomial `P` of degree at most `n` such that `P(x) \approx 0`. If no polynomial having `x` as a root can be found, :func:`~mpmath.findpoly` returns ``None``. :func:`~mpmath.findpoly` works by successively calling :func:`~mpmath.pslq` with the vectors `[1, x]`, `[1, x, x^2]`, `[1, x, x^2, x^3]`, ..., `[1, x, x^2, .., x^n]` as input. Keyword arguments given to :func:`~mpmath.findpoly` are forwarded verbatim to :func:`~mpmath.pslq`. In particular, you can specify a tolerance for `P(x)` with ``tol`` and a maximum permitted coefficient size with ``maxcoeff``. For large values of `n`, it is recommended to run :func:`~mpmath.findpoly` at high precision; preferably 50 digits or more. **Examples** By default (degree `n = 1`), :func:`~mpmath.findpoly` simply finds a linear polynomial with a rational root:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> findpoly(0.7) [-10, 7] The generated coefficient list is valid input to ``polyval`` and ``polyroots``:: >>> nprint(polyval(findpoly(phi, 2), phi), 1) -2.0e-16 >>> for r in polyroots(findpoly(phi, 2)): ... print(r) ... -0.618033988749895 1.61803398874989 Numbers of the form `m + n \sqrt p` for integers `(m, n, p)` are solutions to quadratic equations. As we find here, `1+\sqrt 2` is a root of the polynomial `x^2 - 2x - 1`:: >>> findpoly(1+sqrt(2), 2) [1, -2, -1] >>> findroot(lambda x: x**2 - 2*x - 1, 1) 2.4142135623731 Despite only containing square roots, the following number results in a polynomial of degree 4:: >>> findpoly(sqrt(2)+sqrt(3), 4) [1, 0, -10, 0, 1] In fact, `x^4 - 10x^2 + 1` is the *minimal polynomial* of `r = \sqrt 2 + \sqrt 3`, meaning that a rational polynomial of lower degree having `r` as a root does not exist. Given sufficient precision, :func:`~mpmath.findpoly` will usually find the correct minimal polynomial of a given algebraic number. **Non-algebraic numbers** If :func:`~mpmath.findpoly` fails to find a polynomial with given coefficient size and tolerance constraints, that means no such polynomial exists. We can verify that `\pi` is not an algebraic number of degree 3 with coefficients less than 1000:: >>> mp.dps = 15 >>> findpoly(pi, 3) >>> It is always possible to find an algebraic approximation of a number using one (or several) of the following methods: 1. Increasing the permitted degree 2. Allowing larger coefficients 3. Reducing the tolerance One example of each method is shown below:: >>> mp.dps = 15 >>> findpoly(pi, 4) [95, -545, 863, -183, -298] >>> findpoly(pi, 3, maxcoeff=10000) [836, -1734, -2658, -457] >>> findpoly(pi, 3, tol=1e-7) [-4, 22, -29, -2] It is unknown whether Euler's constant is transcendental (or even irrational). We can use :func:`~mpmath.findpoly` to check that if is an algebraic number, its minimal polynomial must have degree at least 7 and a coefficient of magnitude at least 1000000:: >>> mp.dps = 200 >>> findpoly(euler, 6, maxcoeff=10**6, tol=1e-100, maxsteps=1000) >>> Note that the high precision and strict tolerance is necessary for such high-degree runs, since otherwise unwanted low-accuracy approximations will be detected. It may also be necessary to set maxsteps high to prevent a premature exit (before the coefficient bound has been reached). Running with ``verbose=True`` to get an idea what is happening can be useful. rzn cannot be less than 1r)Nr*)rr5r;�appendr])rr rC�kwargs�xsr/�as r �findpolyrc7s���R ���� � �A��1�u�u��2�3�3�3��A�v�v��1�v� � �'�'�!�*�*��B� �1�Q�q�S�\�\���� � � �!�Q�$���� �C�H�R� "� "�6� "� "�� �=��T�T�r�T�7�N�N�N� ��r c�X�||}}|r |||z}}|� |dkr ||z}||z}|dkr|S||fSrr)�p�qr rMs r �fracgcdrg�s\�� �a�q�A� ���!�a�%�1�� ���A�v�v� �a��� �a����A�v�v��� �a�4�Kr c���|d}|dd�}g}tt|����D]�}||}|r�t| |��}||d}|dkrd}nd|z}t|t��r"|dkrt |��|z}nd|z|z}nd|z|z}|�|����d�|��}d |vsd|vrd |zd z}|pd S) Nr)r�1��*z(%s)z(%s/%s)z + �+�(�)�0)r;r4rg� isinstancer�strr_�join) �r� constantsrfrJr/re�z�cs�terms r � pslqstringrx�s �� �!��A� �!�"�"��A� �A� �3�q�6�6�]�]���� �a�D�� � ����1� � �A��1��a��B��S�y�y�����2�X���!�Y�'�'� ,��q�5�5��Q���"��$�$�"(�1�*��!2�$�$�!�A� ��+�� �H�H�T�N�N�N�� � � �1� � �A� �a�x�x�3�!�8�8� �!�G�c�M�� �8��Or c��|d}|dd�}g}g}tt|����D]�}||}|r�t| |��}||d}t|t��rLt |��dkr|} n|�dt |����} ||g|dk�| ����|�dt |d���d|d�d�} ||g|ddk�| ����d�|��}d�|��}|r |r d|�d |�d�S|r|S|rd |zSdS) Nr)rz**z**(�/rnrkrmz)/(z1/(%s))r;r4rgrprr$r_rr) rsrtrf�num�denr/rerurvrLs r � prodstringr}�ss�� �!��A� �!�"�"��A� �C� �C� �3�q�6�6�]�]� .� .�� �a�D�� � .����1� � �A��1��a��B��!�Y�'�'� .��q�6�6�Q�;�;�B���02���C��F�F�F�$;���c��1�Q�3��'�'��*�*�*�*�%'�R�R��Q�q�T�����A�a�D�D�D�9���c��1�Q�4��6�"�*�*�1�-�-�-�� �(�(�3�-�-�C� �(�(�3�-�-�C� �3�s�3�3�#�#�#�s�s�s�3�3� ��3�J� �!�8�c�>� !�!�!r c���|dkr | | | }}}| |�|dzd|z|zz ��zd|zz }| |�|dzd|z|zz ��z d|zz }t||z ��t||z ��kr2|rd| �d|dzd|z|zz �dd|z�d�}nDdd |z|z�d d|z�d�}n1|rd| �d |dzd|z|zz �dd|z�d�}nd d |z|z�d d|z�d�}|S) Nr)rr'z((z+sqrt(z))/rnz(sqrt(�����z)/z-sqrt(z(-sqrt()�sqrtr$)rrLrb�b�c�u1�u2rJs r �quadraticstringr��sd���1�u�u���A�2�q�b�A�!�� �"�S�X�X�a��d�1�Q�3�q�5�j� !� !� !�A�a�C� (�B� �"�S�X�X�a��d�1�Q�3�q�5�j� !� !� !�A�a�C� (�B� �2�a�4�y�y�3�r�!�t�9�9��� � 2� 2�A�2�2�2�a��d�1�Q�3�q�5�j�j�j��1����=�q�q� 2�&(��d�1�f�f�f�Q�q�S�S�S�1�q�q� � 3� 3�A�2�2�2�a��d�1�Q�3�q�5�j�j�j��1����=�q�q� 3�')�!�t�A�v�v�v�a��c�c�c�2�q� �Hr c� �||zSr"r�rr r�s r �<lambda>r��� ��1�Q�3�r z$y/$cr)c� �||z Sr"rr�s r r�r��r�r z$c*$yc� �||z Sr"rr�s r r�r��r�r z$c/$yc��||zdzS�Nrrr�s r r�r�����A�a�C�!�8�r z sqrt($y)/$cc��||z dzSr�rr�s r r�r��r�r z $c*sqrt($y)c��||z dzSr�rr�s r r�r��r�r z $c/sqrt($y)c��||dzzSr�rr�s r r�r�����1�Q��T�6�r zsqrt($y)/sqrt($c)c��|dz|z Sr�rr�s r r�r��s��1�a�4��6�r zsqrt($c)*sqrt($y)c��||dzz Sr�rr�s r r�r��r�r zsqrt($c)/sqrt($y)c�2�|�||z��Sr"�r�r�s r r�r����3�8�8�A�a�C�=�=�r z$y**2/$cc�2�|�||z ��Sr"r�r�s r r�r�r�r z$c*$y**2c�2�|�||z ��Sr"r�r�s r r�r�r�r z$c/$y**2c�2�||�|��zSr"r�r�s r r�r����1�S�X�X�a�[�[�=�r z $y**2/$c**2c�2�|�|��|z Sr"r�r�s r r�r�s��3�8�8�A�;�;�q�=�r z $c**2*$y**2c�2�||�|��z Sr"r�r�s r r�r�r�r z $c**2/$y**2c�2�|�||z��Sr"��expr�s r r�r����3�7�7�1�Q�3�<�<�r z log($y)/$cc�2�|�||z ��Sr"r�r�s r r�r�r�r z $c*log($y)c�2�|�||z ��Sr"r�r�s r r�r�r�r z $c/log($y)c�2�||�|��zSr"r�r�s r r�r� ���1�S�W�W�Q�Z�Z�<�r z log($y/$c)c�2�|�|��|z Sr"r�r�s r r�r� s��3�7�7�1�:�:�a�<�r z log($c*$y)c�2�||�|��z Sr"r�r�s r r�r� r�r z log($c/$y)c�2�|�||z��Sr"��lnr�s r r�r� ���3�6�6�!�A�#�;�;�r z exp($y)/$cc�2�|�||z ��Sr"r�r�s r r�r� r�r z $c*exp($y)c�2�|�||z ��Sr"r�r�s r r�r�r�r z $c/exp($y)c�2�||�|��zSr"r�r�s r r�r����1�S�V�V�A�Y�Y�;�r z exp($y/$c)c�2�|�|��|z Sr"r�r�s r r�r�s��3�6�6�!�9�9�Q�;�r z exp($c*$y)c�2�||�|��z Sr"r�r�s r r�r�r�r z exp($c/$y)c �$������g���fd�}��|��}|dkr|rdgSdS|dkr2��| ||||���}|�|S|r d�|D��Sd|zS|r��|��}n �jdz}|} |rzt|t��r.�fd�t |�����D��}n9t �fd �t���D������fd �|D��}ng}d d �|D��vr��d ��d fg|z}tD�]�\} } } |D�]�\} }| r|d kr�| �|| ��}t|��| dzkst|��|kr�F�� |gd�|D��z|| ��}d}|�6td�|D����| kr|drt||��}n��� �j ||dzg|| ��}|�pt|��dkr]|drU|\}}}tt|��t|��t|����| krt�||||��}|rx|d kr/d| vr+| �d|���dd��}n*| �d|���d|��}||��|s �dccS�rt#d����Ɛ��|d kr�gd�}g}|D]K\�}t%��fd�|D����s*|������|f���L�fd�|D��|z}�� ��|��gd�|D��z|| ��}|�Htd�|D����| kr+|dr#|t+||����|s�dS|rt �t���SdS)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���rtd|����|��dS)NzFound: )r7r_)rJ� solutionsrBs ��r � addsolutionzidentify.<locals>.addsolution�s2��� �'�E�)�Q�'�'�'���������r r)roNc��g|]}d|z��S)�-(%s)r)rrJs r r zidentify.<locals>.<listcomp>�s��+�+�+�!�G�A�I�+�+�+r r�gffffff�?c�D��g|]\}}��|��|f��Sr)r)r�namer1rs �r r zidentify.<locals>.<listcomp>s,���W�W�W� ��q�#�'�'�!�*�*�d�+�W�W�Wr c3�<�K�|]}|t�|��fV��dSr")�getattr)rr�rs �r r&zidentify.<locals>.<genexpr>s2�����L�L�4�d�G�C��$5�$5�6�L�L�L�L�L�Lr c�4��g|]}t|���|f��Sr)�eval)rre� namespaces �r r zidentify.<locals>.<listcomp> s(���D�D�D�Q�$�q�)�,�,�a�0�D�D�Dr rc��g|]\}}|��Srr)rr��values r r zidentify.<locals>.<listcomp>s��6�6�6�=�D�%��6�6�6r rirc��g|] }|d�� S�r)r�rrbs r r zidentify.<locals>.<listcomp>s��8�8�8���!��8�8�8r c3�4K�|]}t|��V��dSr"r#�r�uws r r&zidentify.<locals>.<genexpr>s(����$9�$9��S��W�W�$9�$9�$9�$9�$9�$9r r(z/$cz$yrjz$c�.)rr(r�c 3��K�|]P}t���������|��z d����V��QdS)rN)�boolrcr�)rr/rbrs ��r r&zidentify.<locals>.<genexpr>8sR�����P�P�Q�t�C�L�L�������3�6�6�!�9�9�)<�Q�?�?�@�@�P�P�P�P�P�Pr c�X��g|]&}��|��t|��f��'Sr)r�rq)rr/rs �r r zidentify.<locals>.<listcomp>:s.���2�2�2�q�������3�q�6�6�"�2�2�2r c��g|] }|d�� Sr�rr�s r r zidentify.<locals>.<listcomp>;s��#7�#7�#7�Q�A�a�D�#7�#7�#7r c3�4K�|]}t|��V��dSr"r#r�s r r&zidentify.<locals>.<genexpr><s(���� 5� 5�R��R��� 5� 5� 5� 5� 5� 5r )�key)r�identify�epsrp�dict�sorted�items�dir� transformsr$r]r6rx�oner4r��replacer7�sumr_r�r})rr rtr?r@�fullrBr��sol�M�ft�ftn�redr��cnrLrsrJrf�aa�bb�cc�ilogs�logsrbr�r�s` ` @@@r r�r�s��������j�I������� ���� � �A� �A�v�v� � �������1�u�u��l�l�A�2�y�#�x��w�G�G�� �;��J� � !�+�+�s�+�+�+� +��S�=� � ���g�g�c�l�l����g�s�l���A��� �i�� &� &� E�W�W�W�W�V�I�O�O�DU�DU�=V�=V�W�W�W�I�I��L�L�L�L�3�s�8�8�L�L�L�L�L�I�D�D�D�D�)�D�D�D�I�I�� � �6�6�I�6�6�6�6�6��g�g�a�j�j�#�&�'�)�3� �#��� ��C��� � �E�A�r�� �r�S�y�y����3�q�� � �A��1�v�v��1��}�}��A���� � �����!��8�8�i�8�8�8�8�#�q�A�A�A��A��}��$9�$9�q�$9�$9�$9�!9�!9�Q�!>�!>�1�Q�4�!>��q�)�,�,����H�H�c�g�q�!�Q�$�/��a�8�8���=�S��V�V�q�[�[�Q�q�T�[�!"�J�B��B��3�r�7�7�3�r�7�7�3�r�7�7�3�3�q�8�8�+�C��"�R��;�;��� 1���9�9�%�3�,�,�� � �D�!�,�,�4�4�U�B�?�?�A�A�� � �D�!�,�,�4�4�T�2�>�>�A�� �A�����0�I�a�L�0�0�0�0�0�� ��c� � � ��9 �> �A�v�v�� � ����� ,� ,�D�A�q��P�P�P�P�P�%�P�P�P�P�P� ,�� � �S�V�V�A�Y�Y��N�+�+�+��2�2�2�2�E�2�2�2�T�9�� �H�H�c�f�f�Q�i�i�[�#7�#7�$�#7�#7�#7�7��a� @� @�� �=�S� 5� 5�1� 5� 5� 5�5�5��:�:�q��t�:� �K� �1�d�+�+� ,� ,� ,�� ,� �!� �,� ���i�S�)�)�)�)��tr �__main__)NrrF)r)�__doc__� libmp.backendr�libmprrr �objectrr]rcrgrxr}r�r�r�r�doctest�testmodrr 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�0�7� �< "�t�d�� �o�o�o�o�b "���!)���!)��� �z����N�N�N��G�O�������r
Memory