o
    ohA-                     @   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#   k/var/www/html/construction_image-detection-poc/venv/lib/python3.10/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di | || _|| _d S )Nr#   )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u 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      | j S r   )r!   )optr#   r#   r$   <lambda>       zoptimize.<locals>.<lambda>T)r&   reverseN)sortedr    r)   )r6   optimizationsoptimnew_exprr#   r#   r$   optimizeq   s   
rB   c                 C   s   | j o| jdkS )N   )is_Powbasepr#   r#   r$   r;          r;   c                 C   s
   t | jS r   )r   r   rF   r#   r#   r$   r;         
 dc                 C   r9   r   )is_Dummyxr#   r#   r$   r;      r<   )
propertiesuc                 C   s   | j  o| j S r   )	is_numberis_AddrL   r#   r#   r$   r;      rH   vwnc                 C   r9   r   rP   rL   r#   r#   r$   r;      r<   rC   c                 C   s   |  dd S )Nc                 S   s*   | j r| jjpt| ttfo| jd j S )Nr   )rD   r   is_negative
isinstancer   r   r(   rP   er#   r#   r$   r;      s   <lambda>.<locals>.<lambda>)countr6   r#   r#   r$   r;      s    r    c                 C   sD   t | to!| jd jo!t| jd jdko!tdd | jd jD S )Nr   rC   c                 s   s    | ]}t |tV  qd S r   )rW   r   ).0tr#   r#   r$   	<genexpr>   s    z<lambda>.<locals>.<genexpr>)rW   r   r(   rQ   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      g | ]}|j d  qS r   r(   r^   rY   r#   r#   r$   
<listcomp>       z<lambda>.<locals>.<listcomp>r   c                 S   re   rf   rg   rh   r#   r#   r$   ri      rj   )r   r(   r   r   r	   rc   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   r9   r   )rQ   rX   r#   r#   r$   r;      r<   z,FuncMinusOneOptim.__init__.<locals>.<lambda>c                    s   |   |    S r   )	count_opsr[   r\   func_m_1weightr#   r$   r;      rj   r]   )r/   r%   replace_in_Addfuncro   opportunistic)r"   rr   ro   rs   r3   rn   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   r9   r   rU   argr#   r#   r$   r;      r<   z4FuncMinusOneOptim._group_Add_terms.<locals>.<lambda>Tbinaryc                    s   |   jS r   )hasrr   rt   r"   r#   r$   r;          )r   r(   sum)r"   addnumbersnon_numnumsumterms_with_funcotherr#   ry   r$   _group_Add_terms   s   
z"FuncMinusOneOptim._group_Add_termsc                    s2    |\}}}|dkr|S g g }}|D ]v}|jrAt|j fdddd\}}	t|dkr>t|	dkr>|d |	d }}	nd}	n|j jkrN|tj}}	nd}	|	dur|	jrt	|	t	| kr j
rnt|	| t|k }
n|	| dk}
|
r||	7 }||	 j|j   q|| q|j|g|||R  S )z1 passed as second argument to Basic.replace(...) r   c                    s   | j  j kS r   )rr   rt   ry   r#   r$   r;      rz   z2FuncMinusOneOptim.replace_in_Add.<locals>.<lambda>Trv   r   N)r   is_Mulr   r(   ra   rr   r   OnerP   r   rs   absappendro   )r"   rY   r   r   other_non_num_termssubstituted	untouched	with_funcrr   coeffdo_substituter#   ry   r$   rq      s.   
 z FuncMinusOneOptim.replace_in_Addc                    s(   t  |}t  | }| ||S r   )r/   r7   factorr)   )r"   r6   alt1alt2r3   r#   r$   r7     s   zFuncMinusOneOptim.__call__)T)	r*   r+   r,   r-   r%   r   rq   r7   r8   r#   r#   r3   r$   rk      s    & rk   c                 C   s
   t | tS r   )rW   r   rX   r#   r#   r$   r;     rI   c                 C   s(   t | tdd ttd ttS )Nc                 S   s   t |  S r   )r   r   rt   r#   r#   r$   r;     rz   rZ   r   )r   r5   r   _ur   rc   r#   r#   r$   r;     s    c                 C   r9   r   )	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   )rD   rE   r   
is_Integerr   rX   r   limitr#   r$   r;   B  s   & 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   rE   rF   r#   r#   r$   r;   C  s   (")r.   )r   r   r#   r   r$   create_expand_pow_optimization  s   #r   c                 C   sZ   | j r+t| jdkr+| j\}}|jr+|jd dkr+|j}t|tr+tt	t
|jS dS )NrC   r   F)	is_MatMulra   r(   
is_Inverseshaperu   rW   r   boolr   r   fullrankr6   leftrightinv_argr#   r#   r$   _matinv_predicateI  s   

r   c                 C   s   | j \}}|j}t||S r   )r(   ru   r   r   r#   r#   r$   _matinv_transformT  s   

r   N)Jr-   sympy.core.functionr   sympy.core.singletonr   sympy.core.symbolr   $sympy.functions.elementary.complexesr   &sympy.functions.elementary.exponentialr   r   (sympy.functions.elementary.miscellaneousr   r	   (sympy.functions.elementary.trigonometricr
   r   r   sympy.assumptionsr   r   sympy.codegen.cfunctionsr   r   r   r   sympy.codegen.matrix_nodesr   sympy.core.exprr   sympy.core.powerr   sympy.codegen.numpy_nodesr   r   sympy.codegen.scipy_nodesr   r   sympy.core.mulr   "sympy.matrices.expressions.matexprr   sympy.utilities.iterablesr   r   r.   rB   exp2_opt_dr   _v_w_n	sinc_opt1	sinc_opt2	sinc_optslog2_optlog2const_optlogsumexp_2terms_optrk   	expm1_opt	cosm1_opt	powm1_opt	log1p_optr   r   r   
matinv_optlogaddexp_optlogaddexp2_opt
optims_c99optims_numpyoptims_scipyr#   r#   r#   r$   <module>   sx     )*
[

+
 ,