o
    3Ih(                     @   sL   d Z ddlmZmZmZmZ ddlmZ dd Zdd Z	dd	 Z
d
d ZdS )z%Module for differentiation using CSE.    )cseMatrix
Derivative
MatrixBase)iterablec                    sN   fdddd t |   fdd| D } fdd|D }||fS )a  
    This function is designed to postprocess the output of a common subexpression
    elimination (CSE) operation. Specifically, it removes any CSE replacement
    symbols from the arguments of ``Derivative`` terms in the expression. This
    is necessary to ensure that the forward Jacobian function correctly handles
    derivative terms.

    Parameters
    ==========

    replacements : list of (Symbol, expression) pairs
        Replacement symbols and relative common subexpressions that have been
        replaced during a CSE operation.

    reduced_expressions : list of SymPy expressions
        The reduced expressions with all the replacements from the
        replacements list above.

    Returns
    =======

    processed_replacements : list of (Symbol, expression) pairs
        Processed replacement list, in the same format of the
        ``replacements`` input list.

    processed_reduced : list of SymPy expressions
        Processed reduced list, in the same format of the
        ``reduced_expressions`` input list.
    c                    s>   t | tr
|  S | js| S  fdd| jD }| j| S )Nc                       g | ]}| qS  r   ).0arg	repl_dicttraverser   X/home/air/sanwanet/gpt-api/venv/lib/python3.10/site-packages/sympy/simplify/_cse_diff.py
<listcomp>+       zA_remove_cse_from_derivative.<locals>.traverse.<locals>.<listcomp>)
isinstancer   argsfunc)noder   new_args)replace_allr   r   r   r   &   s   


z-_remove_cse_from_derivative.<locals>.traversec                    s4   | }	 |j } fdd|D }|s	 |S ||}q)NTc                    s   i | ]}| v r| | qS r   r   )r	   kr   r   r   
<dictcomp>2   s    zD_remove_cse_from_derivative.<locals>.replace_all.<locals>.<dictcomp>)free_symbolsxreplace)r   r   resultr   symbols_dictr   r   r   r   .   s   
z0_remove_cse_from_derivative.<locals>.replace_allc                    s   g | ]\}}|| fqS r   r   )r	   rep_symsub_expr   r   r   r   9   s    z/_remove_cse_from_derivative.<locals>.<listcomp>c                    s&   g | ]}|  fd d|D qS )c                    r   r   r   )r	   expr   r   r   r   >   r   z:_remove_cse_from_derivative.<locals>.<listcomp>.<listcomp>)	__class__)r	   red_expr   r   r   r   =   s    )dict)replacementsreduced_expressionsprocessed_replacementsprocessed_reducedr   )r   r   r   r   _remove_cse_from_derivative   s   
r(   c              
      sH  t |d tstd|d jd dks!|d jd dks!tdts)tdt ts2tjd dksDjd dksDtdt| |\} }| rWttt|  \n	tg tg t	t	t	|d }}}|d j
|| fddt|d D }| sg |gg fS t|| fd	dtd
d |d D D }tfddD td| fddtD }td|D ]Etd fddtd D }	td| fddtD }
|	j r|	||
}t||}qt||
}q|||}|d 
|g}| |fS )a|  
    Core function to compute the Jacobian of an input Matrix of expressions
    through forward accumulation. Takes directly the output of a CSE operation
    (replacements and reduced_expr), and an iterable of variables (wrt) with
    respect to which to differentiate the reduced expression and returns the
    reduced Jacobian matrix and the ``replacements`` list.

    The function also returns a list of precomputed free symbols for each
    subexpression, which are useful in the substitution process.

    Parameters
    ==========

    replacements : list of (Symbol, expression) pairs
        Replacement symbols and relative common subexpressions that have been
        replaced during a CSE operation.

    reduced_expr : list of SymPy expressions
        The reduced expressions with all the replacements from the
        replacements list above.

    wrt : iterable
        Iterable of expressions with respect to which to compute the
        Jacobian matrix.

    Returns
    =======

    replacements : list of (Symbol, expression) pairs
        Replacement symbols and relative common subexpressions that have been
        replaced during a CSE operation. Compared to the input replacement list,
        the output one doesn't contain replacement symbols inside
        ``Derivative``'s arguments.

    jacobian : list of SymPy expressions
        The list only contains one element, which is the Jacobian matrix with
        elements in reduced form (replacement symbols are present).

    precomputed_fs: list
        List of sets, which store the free symbols present in each sub-expression.
        Useful in the substitution process.
    r   z``expr`` must be of matrix type   z)``expr`` must be a row or a column matrixz(``wrt`` must be an iterable of variablesz(``wrt`` must be a row or a column matrixc                    s>   i | ]\}}t D ]\}}||  d kr
||f q
qS r   	enumeratediff)r	   irjw)
diff_valuewrtr   r   r      s    z)_forward_jacobian_cse.<locals>.<dictcomp>c                    sJ   i | ]!\}\}}t D ]\}}||v r||  d kr||f qqS r*   r+   )r	   r.   r/   fsr0   s)r2   r   r   r   r      s    
c                 S   s   g | ]}||j fqS r   r   )r	   r/   r   r   r   r      r   z)_forward_jacobian_cse.<locals>.<listcomp>c                    s   g | ]}|j  @ qS r   r6   )r	   r5   )rep_sym_setr   r   r      r   c                    s0   i | ]\}}d   |  d krd |f qS r*   r-   r	   r0   r1   )r2   sub_exprr   r   r          c                    s@   i | ]}|  v r  |   d krd |f qS r*   r8   r	   r0   )r2   r.   precomputed_fsr   r:   r   r   r      s
    c                    s0   i | ]\}}  |  d krd |f qS r*   r8   r9   )r2   r.   r:   r   r   r      r;   )r   r   	TypeErrorshaper   r   r(   mapziplenr!   from_dokr,   setrange_repnnzmultiplyaddvstack)r$   reduced_exprr3   l_subl_wrtl_redf1f2c_matrix	bi_matrix	ai_matrix	ci_matrixjacobianr   )r2   r.   r=   r   r7   r:   r3   r   _forward_jacobian_cseE   s\   ,$
 
		 
rV   c                 C   s(   t | \}}t|||\}}}|||fS )au  
    Function to compute the Jacobian of an input Matrix of expressions through
    forward accumulation. Takes a sympy Matrix of expressions (expr) as input
    and an iterable of variables (wrt) with respect to which to compute the
    Jacobian matrix. The matrix is returned in reduced form (containing
    replacement symbols) along with the ``replacements`` list.

    The function also returns a list of precomputed free symbols for each
    subexpression, which are useful in the substitution process.

    Parameters
    ==========

    expr : Matrix
        The vector to be differentiated.

    wrt : iterable
        The vector with respect to which to perform the differentiation.
        Can be a matrix or an iterable of variables.

    Returns
    =======

    replacements : list of (Symbol, expression) pairs
        Replacement symbols and relative common subexpressions that have been
        replaced during a CSE operation. The output replacement list doesn't
        contain replacement symbols inside ``Derivative``'s arguments.

    jacobian : list of SymPy expressions
        The list only contains one element, which is the Jacobian matrix with
        elements in reduced form (replacement symbols are present).

    precomputed_fs: list
        List of sets, which store the free symbols present in each
        sub-expression. Useful in the substitution process.
    )r   rV   )exprr3   r$   rK   rU   r=   r   r   r   !_forward_jacobian_norm_in_cse_out   s   &
rX   c                    s   t | \}}|rttt| \}}ntg }t|||\}}}|s%|d S t| t|D ]\}}	 fdd|	D }
 ||  |
 || < q-|d  S )a2  
    Function to compute the Jacobian of an input Matrix of expressions through
    forward accumulation. Takes a sympy Matrix of expressions (expr) as input
    and an iterable of variables (wrt) with respect to which to compute the
    Jacobian matrix.

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

    Expressions often contain repeated subexpressions. Using a tree structure,
    these subexpressions are duplicated and differentiated multiple times,
    leading to inefficiency.

    Instead, if a data structure called a directed acyclic graph (DAG) is used
    then each of these repeated subexpressions will only exist a single time.
    This function uses a combination of representing the expression as a DAG and
    a forward accumulation algorithm (repeated application of the chain rule
    symbolically) to more efficiently calculate the Jacobian matrix of a target
    expression ``expr`` with respect to an expression or set of expressions
    ``wrt``.

    Note that this function is intended to improve performance when
    differentiating large expressions that contain many common subexpressions.
    For small and simple expressions it is likely less performant than using
    SymPy's standard differentiation functions and methods.

    Parameters
    ==========

    expr : Matrix
        The vector to be differentiated.

    wrt : iterable
        The vector with respect to which to do the differentiation.
        Can be a matrix or an iterable of variables.

    See Also
    ========

    Direct Acyclic Graph : https://en.wikipedia.org/wiki/Directed_acyclic_graph
    r   c                    s   i | ]}| | qS r   r   r<   sub_repr   r   r      r   z%_forward_jacobian.<locals>.<dictcomp>)r   r@   r   rA   rV   r#   r,   r   )rW   r3   r$   rK   r   _rU   r=   r.   iksub_dictr   rY   r   _forward_jacobian   s   +r^   N)__doc__sympyr   r   r   r   sympy.utilities.iterablesr   r(   rV   rX   r^   r   r   r   r   <module>   s    >w,