U
    9%eG-                     @   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/Darija-Ai-API/env/lib/python3.8/site-packages/sympy/codegen/rewriting.py__init__@   s    zOptimization.__init__c                 G   s   t || jdd S )N)keyr   )sortedr    )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)r'   r    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   rA   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_AddrD   r#   r#   r$   r:      r;   vwnc                 C   s   | j S r   rH   rD   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(   rH   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   )rN   r   ).0tr#   r#   r$   	<genexpr>   s     z<lambda>.<locals>.<genexpr>)rN   r   r(   rI   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(   rU   rP   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	   rZ   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   )rI   rO   r#   r#   r$   r:      r;   z,FuncMinusOneOptim.__init__.<locals>.<lambda>c                    s   |   |    S r   )Z	count_opsrR   rS   func_m_1weightr#   r$   r:      r;   rT   )r/   r%   replace_in_Addfuncrc   opportunistic)r"   rf   rc   rg   r3   rb   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   rM   argr#   r#   r$   r:      r;   z4FuncMinusOneOptim._group_Add_terms.<locals>.<lambda>Tbinaryc                    s   |   jS r   )hasrf   rh   r"   r#   r$   r:      r;   )r   r(   sum)r"   addnumbersZnon_numnumsumterms_with_funcotherr#   rm   r$   _group_Add_terms   s    z"FuncMinusOneOptim._group_Add_termsc                    s4    |\}}}|dkr|S g g  }}|D ]}|jrt|j fdddd\}}	t|dkr|t|	dkr||d |	d  }}	qd}	n|j jkr|tj }}	nd}	|	dk	r|	jrt	|	t	| kr j
rt|	| 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   )rf   rh   rm   r#   r$   r:      r;   z2FuncMinusOneOptim.replace_in_Add.<locals>.<lambda>Trj   r   N)rt   Zis_Mulr   r(   rX   rf   r   ZOnerH   r   rg   absappendrc   )r"   rP   rq   rr   Zother_non_num_termsZsubstitutedZ	untouchedZ	with_funcrf   ZcoeffZdo_substituter#   rm   r$   re      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%   rt   re   r7   r8   r#   r#   r3   r$   r`      s
   & r`   c                 C   s
   t | tS r   )rN   r   rO   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   rw   rh   r#   r#   r$   r:     r;   rQ   r   )r   r5   r   _ur   rZ   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?   r@   r   Z
is_Integerru   rO   rz   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   r@   rA   r#   r#   r$   r:   C  s    ()r.   )r|   rz   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_MatMulrX   r(   Z
is_Inverseshaperi   rN   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(   ri   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_drx   _v_wZ_nZ	sinc_opt1Z	sinc_opt2Z	sinc_optsZlog2_optZlog2const_optZlogsumexp_2terms_optr`   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    )
  *[


+
 ,