U
    ZÊ¹jA-  ã                   @   sî  d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
mZ ddlmZmZ ddlmZmZmZ dd	lmZmZ dd
lmZmZmZmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z"m#Z# ddl$m%Z%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z, G dd„ dƒZ-G dd„ de-ƒZ.dd„ Z/e.dd„ dd„ ƒZ0eddd„ gd�Z1edd d„ gd�Z2ed!ƒZ3ed"ƒZ4ed#d$d„ gd�Z5e.ee4ƒe4 ee4ƒƒZ6e.ee5e4 ƒe4 e5ee5e4 ƒ ƒZ7e6e7fZ8e.e3ee4ƒ ed%ƒ e3ee4ƒ d&d„ d'�Z9e.ed%ƒee4ƒ ee4ƒƒZ:e.d(d„ d)d„ ƒZ;G d*d+„ d+e.ƒZ<e<e
eƒZ=e<ee%ƒZ>e<e e&ƒZ?e.d,d„ d-d„ ƒZ@d.d„ d/œd0d1„ZAd2d3„ ZBd4d5„ ZCe.eBeCƒZDe.ee
e3ƒe
e4ƒ ƒe"e3e4ƒƒZEe.ee d%e3ƒe d%e4ƒ ƒe#e3e4ƒed%ƒ ƒZFe=e@e0e9e:fZGeGeEeFf e8 ZHe>e?fZId6S )7aø  
Classes and functions useful for rewriting expressions for optimized code
generation. Some languages (or standards thereof), e.g. C99, offer specialized
math functions for better performance and/or precision.

Using the ``optimize`` function in this module, together with a collection of
rules (represented as instances of ``Optimization``), one can rewrite the
expressions for this purpose::

    >>> from sympy import Symbol, exp, log
    >>> from sympy.codegen.rewriting import optimize, optims_c99
    >>> x = Symbol('x')
    >>> optimize(3*exp(2*x) - 3, optims_c99)
    3*expm1(2*x)
    >>> optimize(exp(2*x) - 1 - exp(-33), optims_c99)
    expm1(2*x) - exp(-33)
    >>> optimize(log(3*x + 3), optims_c99)
    log1p(x) + log(3)
    >>> optimize(log(2*x + 3), optims_c99)
    log(2*x + 3)

The ``optims_c99`` imported above is tuple containing the following instances
(which may be imported from ``sympy.codegen.rewriting``):

- ``expm1_opt``
- ``log1p_opt``
- ``exp2_opt``
- ``log2_opt``
- ``log2const_opt``


é    )Ú
expand_log)ÚS)ÚWild)Úsign)ÚexpÚlog)ÚMaxÚMin)ÚcosÚsinÚsinc)ÚQÚask)Úlog1pÚlog2Úexp2Úexpm1)ÚMatrixSolve)ÚUnevaluatedExpr)ÚPow)Ú	logaddexpÚ
logaddexp2)Úcosm1Úpowm1)ÚMul)ÚMatrixSymbol)Úsiftc                   @   s"   e Zd ZdZddd„Zdd„ ZdS )	ÚOptimizationzí Abstract base class for rewriting optimization.

    Subclasses should implement ``__call__`` taking an expression
    as argument.

    Parameters
    ==========
    cost_function : callable returning number
    priority : number

    Né   c                 C   s   || _ || _d S ©N)Úcost_functionÚpriority)Úselfr    r!   © r#   úV/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/codegen/rewriting.pyÚ__init__@   s    zOptimization.__init__c                 G   s   t || jd�S )N)Úkey)Úminr    )r"   Úargsr#   r#   r$   ÚcheapestD   s    zOptimization.cheapest)Nr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r%   r)   r#   r#   r#   r$   r   4   s   
r   c                       s(   e Zd ZdZ‡ fdd„Zdd„ Z‡  ZS )ÚReplaceOptimaÕ   Rewriting optimization calling replace on expressions.

    Explanation
    ===========

    The instance can be used as a function on expressions for which
    it will apply the ``replace`` method (see
    :meth:`sympy.core.basic.Basic.replace`).

    Parameters
    ==========

    query :
        First argument passed to replace.
    value :
        Second argument passed to replace.

    Examples
    ========

    >>> from sympy import Symbol
    >>> from sympy.codegen.rewriting import ReplaceOptim
    >>> from sympy.codegen.cfunctions import exp2
    >>> x = Symbol('x')
    >>> exp2_opt = ReplaceOptim(lambda p: p.is_Pow and p.base == 2,
    ...     lambda p: exp2(p.exp))
    >>> exp2_opt(2**x)
    exp2(x)

    c                    s   t ƒ jf |Ž || _|| _d S r   )Úsuperr%   ÚqueryÚvalue)r"   r0   r1   Úkwargs©Ú	__class__r#   r$   r%   h   s    zReplaceOptim.__init__c                 C   s   |  | j| j¡S r   )Úreplacer0   r1   )r"   Úexprr#   r#   r$   Ú__call__m   s    zReplaceOptim.__call__)r*   r+   r,   r-   r%   r7   Ú__classcell__r#   r#   r3   r$   r.   H   s   r.   c                 C   s@   t |dd„ dd�D ](}|| ƒ}|jdkr.|} q| | |¡} q| S )aë   Apply optimizations to an expression.

    Parameters
    ==========

    expr : expression
    optimizations : iterable of ``Optimization`` instances
        The optimizations will be sorted with respect to ``priority`` (highest first).

    Examples
    ========

    >>> from sympy import log, Symbol
    >>> from sympy.codegen.rewriting import optims_c99, optimize
    >>> x = Symbol('x')
    >>> optimize(log(x+3)/log(2) + log(x**2 + 1), optims_c99)
    log1p(x**2) + log2(x + 3)

    c                 S   s   | j S r   )r!   )Úoptr#   r#   r$   Ú<lambda>†   ó    zoptimize.<locals>.<lambda>T)r&   ÚreverseN)Úsortedr    r)   )r6   ZoptimizationsZoptimZnew_exprr#   r#   r$   Úoptimizeq   s    
r>   c                 C   s   | j o| jdkS )Né   )Úis_PowÚbase©Úpr#   r#   r$   r:   �   r;   r:   c                 C   s
   t | jƒS r   )r   r   rB   r#   r#   r$   r:   ‘   r;   Údc                 C   s   | j S r   )Zis_Dummy©Úxr#   r#   r$   r:   •   r;   )Ú
propertiesÚuc                 C   s   | j  o| j S r   )Ú	is_numberÚis_AddrE   r#   r#   r$   r:   –   r;   ÚvÚwÚnc                 C   s   | j S r   ©rI   rE   r#   r#   r$   r:   ™   r;   r?   c                 C   s   |   dd„ ¡S )Nc                 S   s*   | j r| jjp(t| ttfƒo(| jd j S )Nr   )r@   r   Zis_negativeÚ
isinstancer   r   r(   rI   ©Úer#   r#   r$   r:   ¤   s    ú<lambda>.<locals>.<lambda>)Úcount©r6   r#   r#   r$   r:   £   s   ÿ©r    c                 C   sD   t | tƒoB| jd joBt| jd jƒdkoBtdd„ | jd jD ƒƒS )Nr   r?   c                 s   s   | ]}t |tƒV  qd S r   )rO   r   )Ú.0Útr#   r#   r$   Ú	<genexpr>°   s     z<lambda>.<locals>.<genexpr>)rO   r   r(   rJ   ÚlenÚall©Úlr#   r#   r$   r:   ­   s
   

ÿþc                 C   s<   t dd„ | jd jD ƒŽ tttdd„ | jd jD ƒŽ ƒƒ S )Nc                 S   s   g | ]}|j d  ‘qS ©r   ©r(   ©rV   rQ   r#   r#   r$   Ú
<listcomp>²   s     z<lambda>.<locals>.<listcomp>r   c                 S   s   g | ]}|j d  ‘qS r]   r^   r_   r#   r#   r$   r`   ³   s     )r   r(   r   r   r	   r[   r#   r#   r$   r:   ±   s     ÿc                       s>   e Zd ZdZd‡ fdd„	Zdd„ Zdd„ Z‡ fd	d
„Z‡  ZS )ÚFuncMinusOneOptimaí  Specialization of ReplaceOptim for functions evaluating "f(x) - 1".

    Explanation
    ===========

    Numerical functions which go toward one as x go toward zero is often best
    implemented by a dedicated function in order to avoid catastrophic
    cancellation. One such example is ``expm1(x)`` in the C standard library
    which evaluates ``exp(x) - 1``. Such functions preserves many more
    significant digits when its argument is much smaller than one, compared
    to subtracting one afterwards.

    Parameters
    ==========

    func :
        The function which is subtracted by one.
    func_m_1 :
        The specialized function evaluating ``func(x) - 1``.
    opportunistic : bool
        When ``True``, apply the transformation as long as the magnitude of the
        remaining number terms decreases. When ``False``, only apply the
        transformation if it completely eliminates the number term.

    Examples
    ========

    >>> from sympy import symbols, exp
    >>> from sympy.codegen.rewriting import FuncMinusOneOptim
    >>> from sympy.codegen.cfunctions import expm1
    >>> x, y = symbols('x y')
    >>> expm1_opt = FuncMinusOneOptim(exp, expm1)
    >>> expm1_opt(exp(x) + 2*exp(5*y) - 3)
    expm1(x) + 2*expm1(5*y)


    Tc                    s<   d‰t ƒ jdd„ | j‡ ‡fdd„d� || _ˆ | _|| _d S )Né
   c                 S   s   | j S r   )rJ   rP   r#   r#   r$   r:   á   r;   z,FuncMinusOneOptim.__init__.<locals>.<lambda>c                    s   |   ¡ ˆ|  ˆ ¡  S r   )Z	count_opsrS   rT   ©Úfunc_m_1Úweightr#   r$   r:   â   r;   rU   )r/   r%   Úreplace_in_AddÚfuncrd   Úopportunistic)r"   rg   rd   rh   r3   rc   r$   r%   ß   s    ÿzFuncMinusOneOptim.__init__c                    sD   t |jdd„ dd�\}}t|ƒ}t |‡ fdd„dd�\}}|||fS )Nc                 S   s   | j S r   rN   ©Úargr#   r#   r$   r:   è   r;   z4FuncMinusOneOptim._group_Add_terms.<locals>.<lambda>T©Úbinaryc                    s   |   ˆ j¡S r   )Úhasrg   ri   ©r"   r#   r$   r:   ê   r;   )r   r(   Úsum)r"   ÚaddÚnumbersZnon_numÚnumsumÚterms_with_funcÚotherr#   rn   r$   Ú_group_Add_termsç   s    z"FuncMinusOneOptim._group_Add_termsc                    s4  ˆ   |¡\}}}|dkr|S g g  }}|D ]ô}|jr‚t|j‡ fdd„dd�\}}	t|ƒdkr|t|	ƒdkr||d |	d  }}	q d}	n|jˆ jkrœ|tj }}	nd}	|	dk	�r|	j�rt	|	ƒt	|ƒ k�rˆ j
rât|	| ƒt|ƒk }
n|	| dk}
|
�r||	7 }| |	ˆ j|jŽ  ¡ q*| |¡ q*|j|f|||žŽ S )z1 passed as second argument to Basic.replace(...) r   c                    s   | j ˆ j kS r   )rg   ri   rn   r#   r$   r:   õ   r;   z2FuncMinusOneOptim.replace_in_Add.<locals>.<lambda>Trk   r   N)ru   Zis_Mulr   r(   rY   rg   r   ZOnerI   r   rh   ÚabsÚappendrd   )r"   rQ   rr   rs   Zother_non_num_termsZsubstitutedZ	untouchedZ	with_funcrg   ZcoeffZdo_substituter#   rn   r$   rf   í   s.    
&z FuncMinusOneOptim.replace_in_Addc                    s(   t ƒ  |¡}t ƒ  | ¡ ¡}|  ||¡S r   )r/   r7   Úfactorr)   )r"   r6   Zalt1Zalt2r3   r#   r$   r7     s    zFuncMinusOneOptim.__call__)T)	r*   r+   r,   r-   r%   ru   rf   r7   r8   r#   r#   r3   r$   ra   ¸   s
   & ra   c                 C   s
   t | tƒS r   )rO   r   rP   r#   r#   r$   r:     r;   c                 C   s(   t |  tdd„ ¡ƒ ttd ƒttƒ¡S )Nc                 S   s   t |  ¡ ƒS r   )r   rx   ri   r#   r#   r$   r:     r;   rR   r   )r   r5   r   Ú_ur   r[   r#   r#   r$   r:     s    ÿ
 þc                 C   s   | j S r   )Z	is_symbol)Úbr#   r#   r$   r:     r;   )Úbase_reqc                   s   t ‡ ‡fdd„dd„ ƒS )a   Creates an instance of :class:`ReplaceOptim` for expanding ``Pow``.

    Explanation
    ===========

    The requirements for expansions are that the base needs to be a symbol
    and the exponent needs to be an Integer (and be less than or equal to
    ``limit``).

    Parameters
    ==========

    limit : int
         The highest power which is expanded into multiplication.
    base_req : function returning bool
         Requirement on base for expansion to happen, default is to return
         the ``is_symbol`` attribute of the base.

    Examples
    ========

    >>> from sympy import Symbol, sin
    >>> from sympy.codegen.rewriting import create_expand_pow_optimization
    >>> x = Symbol('x')
    >>> expand_opt = create_expand_pow_optimization(3)
    >>> expand_opt(x**5 + x**3)
    x**5 + x*x*x
    >>> expand_opt(x**5 + x**3 + sin(x)**3)
    x**5 + sin(x)**3 + x*x*x
    >>> opt2 = create_expand_pow_optimization(3, base_req=lambda b: not b.is_Function)
    >>> opt2((x+1)**2 + sin(x)**2)
    sin(x)**2 + (x + 1)*(x + 1)

    c                    s&   | j o$ˆ | jƒo$| jjo$t| jƒˆkS r   )r@   rA   r   Z
is_Integerrv   rP   ©r{   Úlimitr#   r$   r:   B  r;   z0create_expand_pow_optimization.<locals>.<lambda>c                 S   sJ   | j dkr(tt| jg| j 
  ddiŽƒS dtt| jg| j   ddiŽƒ S )Nr   ÚevaluateFr   )r   r   r   rA   rB   r#   r#   r$   r:   C  s    ()r.   )r}   r{   r#   r|   r$   Úcreate_expand_pow_optimization  s    #þr   c                 C   sZ   | j rVt| jƒdkrV| j\}}|jrV|jd dkrV|j}t|tƒrVtt	t
 |j¡ƒƒS dS )Nr?   r   F)Z	is_MatMulrY   r(   Z
is_InverseÚshaperj   rO   r   Úboolr   r   Zfullrank©r6   ÚleftÚrightZinv_argr#   r#   r$   Ú_matinv_predicateI  s    

r…   c                 C   s   | j \}}|j}t||ƒS r   )r(   rj   r   r‚   r#   r#   r$   Ú_matinv_transformT  s    
r†   N)Jr-   Zsympy.core.functionr   Zsympy.core.singletonr   Zsympy.core.symbolr   Z$sympy.functions.elementary.complexesr   Z&sympy.functions.elementary.exponentialr   r   Z(sympy.functions.elementary.miscellaneousr   r	   Z(sympy.functions.elementary.trigonometricr
   r   r   Zsympy.assumptionsr   r   Zsympy.codegen.cfunctionsr   r   r   r   Zsympy.codegen.matrix_nodesr   Zsympy.core.exprr   Zsympy.core.powerr   Zsympy.codegen.numpy_nodesr   r   Zsympy.codegen.scipy_nodesr   r   Zsympy.core.mulr   Z"sympy.matrices.expressions.matexprr   Zsympy.utilities.iterablesr   r   r.   r>   Zexp2_optZ_dry   Ú_vÚ_wZ_nZ	sinc_opt1Z	sinc_opt2Z	sinc_optsZlog2_optZlog2const_optZlogsumexp_2terms_optra   Z	expm1_optZ	cosm1_optZ	powm1_optZ	log1p_optr   r…   r†   Z
matinv_optZlogaddexp_optZlogaddexp2_optZ
optims_c99Zoptims_numpyZoptims_scipyr#   r#   r#   r$   Ú<module>   sz    )þ
 ÿ ÿ*û[


þ+
 ,