
    \hNz                        S r SSKJr  SSKJrJrJrJrJr  SSK	J
r
Jr  SSKJr  SSKJr  SSKJr  SSKJrJr  SS	KJrJrJrJrJr  SS
KJrJrJrJrJ r J!r!  SSK"J#r#  SSK$J%r%  SSK&J'r'J(r(J)r)J*r*  SSK+J,r,  \,RZ                  \,R\                  4\S4/r/S r0S r1S r2S r3S r4 " S S5      r5 " S S5      r6S r7SS jr8S S jr9  S!S jr:S r;g)"z2Tools for doing common subexpression elimination.
    )defaultdict)BasicMulAddPowsympify)Tuple
OrderedSet)factor_terms)S)ordered)symbolsSymbol)
MatrixBaseMatrixImmutableMatrixSparseMatrixImmutableSparseMatrix)
MatrixExprMatrixSymbolMatMulMatAddMatPowInverse)MatrixElement)RootOf)numbered_symbolssifttopological_sortiterable   )cse_optsNc                 ,   [        U 5      n / n[        U 5       HB  u  nu  p4[        U 5       H+  u  nu  pgX7R                  ;   d  M  UR                  X%45        M-     MD     [	        [        [        U 5      5      U45       Vs/ s H  oU   PM	     sn$ s  snf )a  Sort replacements ``r`` so (k1, v1) appears before (k2, v2)
if k2 is in v1's free symbols. This orders items in the
way that cse returns its results (hence, in order to use the
replacements in a substitution option it would make sense
to reverse the order).

Examples
========

>>> from sympy.simplify.cse_main import reps_toposort
>>> from sympy.abc import x, y
>>> from sympy import Eq
>>> for l, r in reps_toposort([(x, y + 1), (y, 2)]):
...     print(Eq(l, r))
...
Eq(y, 2)
Eq(x, y + 1)

)r   	enumeratefree_symbolsappendr   rangelen)	rEc1k1v1c2k2v2is	            O/var/www/auris/envauris/lib/python3.13/site-packages/sympy/simplify/cse_main.pyreps_toposortr3   +   s    ( 	
A
A!!HR%aLLB__$"" ) % +E#a&M1+=>?>QaD>???s    Bc                     [        US 5      nXS    Vs/ s H  o3R                  PM     sn-   n US   n[        U 5      U/$ s  snf )ao  Move expressions that are in the form (symbol, expr) out of the
expressions and sort them into the replacements using the reps_toposort.

Examples
========

>>> from sympy.simplify.cse_main import cse_separate
>>> from sympy.abc import x, y, z
>>> from sympy import cos, exp, cse, Eq, symbols
>>> x0, x1 = symbols('x:2')
>>> eq = (x + 1 + exp((x + 1)/(y + 1)) + cos(y + 1))
>>> cse([eq, Eq(x, z + 1), z - 2], postprocess=cse_separate) in [
... [[(x0, y + 1), (x, z + 1), (x1, x + 1)],
...  [x1 + exp(x1/x0) + cos(x0), z - 2]],
... [[(x1, y + 1), (x, z + 1), (x0, x + 1)],
...  [x0 + exp(x0/x1) + cos(x1), z - 2]]]
...
True
c                 T    U R                   =(       a    U R                  R                  $ N)is_Equalitylhs	is_Symbol)ws    r2   <lambda>cse_separate.<locals>.<lambda>\   s    !--;AEEOO;    TF)r   argsr3   )r)   edr:   s       r2   cse_separaterA   H   sL    ( 	Q;<A	tW%WVVW%%A	%A!a   &s   Ac                   ^^	^
 U (       d  X4$ [        U 6 u  mm
[        S[        U5      -  5      n[        U5      n[        T5      m[	        T5      m	[        T
5      m
[        [        U5      5       Vs/ s H  oAU   X4   4PM     nn[        [        UU	U
U4S jS96 u  p[        U5      nT
U-  m
/ n[        T
5      S-
  nUS:  a  T
R                  5       nT	UR                  -  nU(       a/  UR                  [        U[        S9 Vs/ s H  oS4PM     sn5        U[        U 5      :  a"  UR                  UR                  5       U45        OUR                  TU   U45        T	U-  m	US-  nUS:  a  M  UR                  5         XR4$ s  snf s  snf )a  
Return tuples giving ``(a, b)`` where ``a`` is a symbol and ``b`` is
either an expression or None. The value of None is used when a
symbol is no longer needed for subsequent expressions.

Use of such output can reduce the memory footprint of lambdified
expressions that contain large, repeated subexpressions.

Examples
========

>>> from sympy import cse
>>> from sympy.simplify.cse_main import cse_release_variables
>>> from sympy.abc import x, y
>>> eqs = [(x + y - 1)**2, x, x + y, (x + y)/(2*x + 1) + (x + y - 1)**2, (2*x + 1)**(x + y)]
>>> defs, rvs = cse_release_variables(*cse(eqs))
>>> for i in defs:
...   print(i)
...
(x0, x + y)
(x1, (x0 - 1)**2)
(x2, 2*x + 1)
(_3, x0/x2 + x1)
(_4, x2**x0)
(x2, None)
(_0, x1)
(x1, None)
(_2, x0)
(x0, None)
(_1, x)
>>> print(rvs)
(_0, _1, _2, _3, _4)
z_:%dc                 R   > [        UU4S jU S   R                  T-   5       5      * $ )Nc              3   h   >#    U  H'  nTTR                  U5         R                  5       v   M)     g 7fr6   )index	count_ops).0r1   pss     r2   	<genexpr>:cse_release_variables.<locals>.<lambda>.<locals>.<genexpr>   s0      -+A QWWQZ=2244+s   /2r   )sumr%   )xin_userH   rI   s    r2   r;   'cse_release_variables.<locals>.<lambda>   s+    s -1""V+- - -r=   keyr!   r   N)zipr   r(   listsetr'   sortedpopr%   extendstrr&   reverse)r)   r?   esymssymsr1   rv_pcrI   rN   rH   s           `@@r2   cse_release_variablesr_   b   sn   D t7DAqFSVO$E;DQAVFQA"'A-0-QA$-A06!-. /GA :DFA	BA
A
q&UUWR__$II&*<=*<Q4y*<=>A;IItxxz2&'IIqtRj!!	Q q& JJL9) 	1 >s   2FF
c                 6    U H  u  p#Uc  M
  U" U 5      n M     U $ )aL  Preprocess an expression to optimize for common subexpression
elimination.

Parameters
==========

expr : SymPy expression
    The target expression to optimize.
optimizations : list of (callable, callable) pairs
    The (preprocessor, postprocessor) pairs.

Returns
=======

expr : SymPy expression
    The transformed expression.
 exproptimizationspreposts       r2   preprocess_for_cserg      s%    $ #	?t9D # Kr=   c                 H    [        U5       H  u  p#Uc  M
  U" U 5      n M     U $ )a  Postprocess an expression after common subexpression elimination to
return the expression to canonical SymPy form.

Parameters
==========

expr : SymPy expression
    The target expression to transform.
optimizations : list of (callable, callable) pairs, optional
    The (preprocessor, postprocessor) pairs.  The postprocessors will be
    applied in reversed order to undo the effects of the preprocessors
    correctly.

Returns
=======

expr : SymPy expression
    The transformed expression.
)reversedrb   s       r2   postprocess_for_cserj      s+    ( m,	:D - Kr=   c                   J    \ rS rSrSrS rS rS rS rSS jr	SS	 jr
S
 rSrg)FuncArgTracker   zq
A class which manages a mapping from functions to arguments and an inverse
mapping from arguments to functions.
c                 T   0 U l         / U l        / U l        / U l        [	        U5       H}  u  p#[        5       nUR                   HC  nU R                  U5      nUR                  U5        U R                  U   R                  U5        ME     U R                  R                  U5        M     g r6   )
value_numbersvalue_number_to_valuearg_to_funcsetfunc_to_argsetr$   r
   r>   get_or_add_value_numberaddr&   )selffuncsfunc_ifuncfunc_argsetfunc_arg
arg_numbers          r2   __init__FuncArgTracker.__init__   s      %'" ! %e,LF$,K II!99(C

+##J/33F; &
 &&{3 -r=   c                 \    [        U5       Vs/ s H  o R                  U   PM     sn$ s  snf )zP
Return the list of arguments in sorted order according to their value
numbers.
)rU   rp   )ru   argsetargns      r2   get_args_in_value_order&FuncArgTracker.get_args_in_value_order   s*    
 >DF^L^T**40^LLLs   )c                     [        U R                  5      nU R                  R                  X5      nX2:X  a>  U R                  R	                  U5        U R
                  R	                  [        5       5        U$ )z1
Return the value number for the given argument.
)r(   ro   
setdefaultrp   r&   rq   r
   )ru   valuenvaluesvalue_numbers       r2   rs   &FuncArgTracker.get_or_add_value_number   s`     d(()))44UD"&&--e4&&z|4r=   c                 l    U R                   U    H!  nU R                  U   R                  U5        M#     g)zC
Remove the function func_i from the argument to function mapping.
N)rr   rq   remove)ru   rw   args      r2   stop_arg_tracking FuncArgTracker.stop_arg_tracking  s2     &&v.C$++F3 /r=   c                    [        S 5      nU(       d  U$ U Vs/ s H  o@R                  U   PM     nn[        U[        S9nU H%  nXgL a  M	  U H  nX:  d  M
  X8==   S-  ss'   M     M'     [	        Xc/[        S9u  n	n
U	 H   nX8   S:  a  M  X;   d  M  X8==   S-  ss'   M"     UR                  5        VVs0 s H  u  pUS:  d  M  X_M     snn$ s  snf s  snnf )zReturn a dict whose keys are function numbers. The entries of the dict are
the number of arguments said function has in common with
``argset``. Entries have at least 2 items in common.  All keys have
value at least ``min_func_i``.
c                      g)Nr   ra   ra   r=   r2   r;   :FuncArgTracker.get_common_arg_candidates.<locals>.<lambda>  s    r=   rP   r!      )r   rq   maxr(   rU   items)ru   r   
min_func_i	count_mapr   funcsetslargest_funcsetfuncsetrw   smaller_funcs_containerlarger_funcs_containerkvs                r2   get_common_arg_candidates(FuncArgTracker.get_common_arg_candidates  s      	*	8>?'',? hC0G)!'%*% "   $*!-$	!	 	 .F  1$/!Q&! . "+!2=!2a1f!2==9 @8 >s   C8CCNc                     [        U5      n[        S U R                  [        U5          5       5      nUb  XB-  nU H  nX@R                  U   -  nM     U$ )z
Return a set of functions each of which whose argument list contains
``argset``, optionally filtered only to contain functions in
``restrict_to_funcset``.
c              3   $   #    U  H  ov   M     g 7fr6   ra   )rG   fis     r2   rJ   7FuncArgTracker.get_subset_candidates.<locals>.<genexpr>>  s      :82B8s   )iterr
   rq   next)ru   r   restrict_to_funcsetiargindicesr   s         r2   get_subset_candidates$FuncArgTracker.get_subset_candidates6  sg     F| :,,T$Z8: : **GC**3//G  r=   c                 R   [        U5      nU R                  U   nXC-
   H!  nU R                  U   R                  U5        M#     X4-
   H!  nU R                  U   R	                  U5        M#     U R                  U   R                  5         U R                  U   R                  U5        g)z0
Update a function with a new set of arguments.
N)r
   rr   rq   r   rt   clearupdate)ru   rw   
new_argsetnew_argsold_argsdeleted_arg	added_args          r2   update_func_argset!FuncArgTracker.update_func_argsetI  s     j)&&v.#.K,33F; /!,I	*..v6 - 	F#))+F#**84r=   )rq   rr   rp   ro   )r   r6   )__name__
__module____qualname____firstlineno____doc__r|   r   rs   r   r   r   r   __static_attributes__ra   r=   r2   rl   rl      s,    
4(M	4&>P&5r=   rl   c                   :    \ rS rSrS rS rS r\S 5       r\r	Sr
g)UnevaluatediY  c                     Xl         X l        g r6   rx   r>   )ru   rx   r>   s      r2   r|   Unevaluated.__init__[  s    		r=   c                 z    SR                  U R                  SR                  S U R                   5       5      5      $ )NzUneval<{}>({})z, c              3   8   #    U  H  n[        U5      v   M     g 7fr6   )rX   )rG   as     r2   rJ   &Unevaluated.__str__.<locals>.<genexpr>a  s     $?YSVVYs   )formatrx   joinr>   ru   s    r2   __str__Unevaluated.__str___  s3    &&		499$?TYY$??A 	Ar=   c                 :    U R                   " U R                  SS06$ )NevaluateFr   r   s    r2   as_unevaluated_basic Unevaluated.as_unevaluated_basicc  s    yy$))4e44r=   c                     [        5       R                  " U R                   Vs/ s H  oR                  PM     sn6 $ s  snf r6   )rT   unionr>   r%   )ru   r   s     r2   r%   Unevaluated.free_symbolsf  s+    u{{TYY?Y^^Y?@@?s   <)r>   rx   N)r   r   r   r   r|   r   r   propertyr%   __repr__r   ra   r=   r2   r   r   Y  s/    A5 A A Hr=   r   c           	        ^ [        US S9n[        U5      n[        5       n[        [	        U5      5       GH.  nUR                  UR                  U   US-   S9m[        [        TR                  5       U4S jS95      nU(       Ga  UR                  SS9nUR                  U   R                  UR                  U   5      n[	        U5      S::  a  MS  UR                  U   R                  U5      n	U	(       a[  [        XR                  U5      5      n
UR                  U
5      nUR                  XY[        U/5      -  5        UR                  U5        OUR                  X   5      nUR                  U   R                  U5      nUR                  X|[        U/5      -  5        UR                  U5        UR!                  X5       HP  nUR                  U   R                  U5      nUR                  X[        U/5      -  5        UR                  U5        MR     U(       a  GM  XT;   a-  [        U UR                  UR                  U   5      5      X!U   '   UR#                  U5        GM1     g)	a/  
Recognize and extract common subexpressions of function arguments within a
set of function calls. For instance, for the following function calls::

    x + z + y
    sin(x + y)

this will extract a common subexpression of `x + y`::

    w = x + y
    w + z
    sin(w)

The function we work with is assumed to be associative and commutative.

Parameters
==========

func_class: class
    The function class (e.g. Add, Mul)
funcs: list of functions
    A list of function calls.
opt_subs: dict
    A dictionary of substitutions which this function may update.
c                 ,    [        U R                  5      $ r6   )r(   r>   )fs    r2   r;   #match_common_args.<locals>.<lambda>  s    AFFr=   rP   r!   )r   c                    > TU    U 4$ r6   ra   )r   common_arg_candidates_countss    r2   r;   r     s    ;A>Br=   F)lastN)rU   rl   r
   r'   r(   r   rr   keysrV   intersection
differencer   r   rs   r   rt   r   r   )
func_classrv   opt_subsarg_trackerchangedr1   common_arg_candidatesjcom_argsdiff_icom_funccom_func_numberdiff_jr   diff_kr   s                  @r2   match_common_argsr   m  sG   : 534E 'KlG3u:'2'L'L**1-!a% (M (A$
 !+6,113B,D !E $%))u)5A"11!4AA..q13H 8}! 
 !//2==hGF&"$G$G$QS"-"E"Eh"O..q:FW;X2XYA #."E"Eeh"O //2==hGF**1z?BS7T.TUKKN 665$33A6AA(K..q:FW;X2XYA	5K $#V <!,Z33K4N4Nq4QR"TH1X 	%%a(s r=   c                   ^^^^^^ 0 m[        5       m[        5       m[        5       m[        5       mUUUUUU4S jmU  H(  n[        U[        [        45      (       d  M   T" U5        M*     T Vs/ s H(  nUR
                  S   T;   d  M  X3R
                  S   4PM*     nn[        [        TU45      5       H2  nTR                  UR
                  S   UR
                  S   5      TU'   M4     [        5       nT H  nUR                  SS9u  pxU(       d  M  UR                  " U6 n	U(       ad  U	S:X  a  UR                  " U6 n
OI[        U[        5      (       a  UR                  " U	/UQ7SS06n
OUR                  XR                  " U6 SS9n
U
TU'   [        U5      S:  d  M  UR                  U	5        M     [        [        TT5        [        [         UT5        T$ s  snf )a  Find optimization opportunities in Adds, Muls, Pows and negative
coefficient Muls.

Parameters
==========

exprs : list of SymPy expressions
    The expressions to optimize.
order : string, 'none' or 'canonical'
    The order by which Mul and Add arguments are processed. For large
    expressions where speed is a concern, use the setting order='none'.

Returns
=======

opt_subs : dictionary of expression substitutions
    The expression substitutions which can be useful to optimize CSE.

Examples
========

>>> from sympy.simplify.cse_main import opt_cse
>>> from sympy.abc import x
>>> opt_subs = opt_cse([x**-2])
>>> k, v = list(opt_subs.keys())[0], list(opt_subs.values())[0]
>>> print((k, v.as_unevaluated_basic()))
(x**(-2), 1/(x**2))
c                   > [        U [        [        45      (       d  g U R                  (       d  U R                  (       a  g [        U 5      (       a  [        [        TU 5      5        g U T	;   a  U $ T	R                  U 5        [        [        TU R                  5      5        [        U [        5      (       d  U R                  5       (       ay  [        U [        5      (       a  [        S U R                   5       6 nOU * nUR                  (       d6  [        [        [        R                  U45      TU '   T	R                  U5        Un [        U [        [         45      (       a=  [#        U R                  5      S:X  a  TR                  U 5        g TR                  U 5        g [        U [        [$        45      (       a=  [#        U R                  5      S:X  a  TR                  U 5        g TR                  U 5        g [        U [&        5      (       a  g [        U [(        [*        45      (       aM  U R,                  U R.                  p2UR                  5       (       a   [        [(        [)        X#* 5      S45      TU '   g g g )Nc              3   &   #    U  H  o* v   M	     g 7fr6   ra   )rG   r1   s     r2   rJ   .opt_cse.<locals>._find_opts.<locals>.<genexpr>  s      7YYs   r!   )
isinstancer   r   is_Atomis_Orderr    rS   maprt   r>   r   could_extract_minus_signr   r   r   NegativeOner   r(   r   r   r   r   baseexp)
rc   neg_exprr   r   
_find_optsaddscollapsible_subexpmulsr   seen_subexps
       r2   r   opt_cse.<locals>._find_opts  s   $ 455<<4==D>>Z&';KSTYY'($
++0M0M0O0O $$$ 7TYY 78 5##!,S1==(2K!L)dS&M**499~""&&t,sFm,,499~""&&t,g&&sFm,,		488#++--!,S3tT?B2G!H . -r=   r   F)csetr!   r   )r   )r
   rT   r   r   r   r>   ri   r   getargs_cncrx   r   r(   rt   r   r   r   )exprsorderr?   rI   edgescommutative_mulsmr^   ncc_mulnew_objr   r   r   r   r   r   s              @@@@@@r2   opt_cser    s   : H<D<D%K3I 3Ij a%-..qM 
 &8 1%7q	// a^%7E 1&(:E'BCDll166!9affQi8 E "|


&1FFAJEA:ffbkG!!V,,"#&&"D"De"D"#&&e&"L%1vz $$U+   c4*c+X6O51s   .G	Gc                 |  ^^^^^^	^
^^^^ Tc  0 m[        5       m[        5       m[        5       m
UU
UUUU4S jmU  H"  n[        U[        5      (       d  M  T" U5        M$     U
4S jT 5       m/ m0 mU	UUUUUU4S jm	/ nU  H4  n[        U[        5      (       a	  T	" U5      nOUnUR                  U5        M6     TU4$ )a  Perform raw CSE on expression tree, taking opt_subs into account.

Parameters
==========

exprs : list of SymPy expressions
    The expressions to reduce.
symbols : infinite iterator yielding unique Symbols
    The symbols used to label the common subexpressions which are pulled
    out.
opt_subs : dictionary of expression substitutions
    The expressions to be substituted before any CSE action is performed.
order : string, 'none' or 'canonical'
    The order by which Mul and Add arguments are processed. For large
    expressions where speed is a concern, use the setting order='none'.
ignore : iterable of Symbols
    Substitutions containing any Symbol from ``ignore`` will be ignored.
c                 l  > [        U [        [        45      (       d  g [        U [        5      (       a  g [        U [        5      (       aj  U R                  (       d,  U R
                  (       d  [        U [        [        45      (       a-  U R                  (       a  TR                  U R                  5        g [        U 5      (       a  U nOZU T;   a,  T H  nX R                  ;   d  M    O   TR                  U 5        g TR                  U 5        U T;   a  TU    n U R                  n[        [        TU5      5        g r6   )r   r   r   r   r   r   r   r   r9   rt   namer    r%   r>   rS   r   )	rc   r>   ign_find_repeatedexcluded_symbolsignorer   r   to_eliminates	      r2   r   tree_cse.<locals>._find_repeatedd  s    $ 455dF##dE""4,!>??~~ $$TYY/D>>D {"!C/// " !$$T*OOD!x~99DS&'r=   c              3   J   >#    U  H  oR                   T;  d  M  Uv   M     g 7fr6   )r
  )rG   _r  s     r2   rJ   tree_cse.<locals>.<genexpr>  s     D'QVV3C%Cqq's   #	#c                   > [        U [        [        45      (       d  U $ U R                  (       d  U $ [	        U 5      (       a1  U R                   Vs/ s H  nT	" U5      PM     nnU R
                  " U6 $ U T;   a  TU    $ U nU T
;   a  T
U    n TS:w  a  [        U [        [        45      (       a4  U R                  5       u  pEUS/:X  a  UnOk[        [        U5      5      U-   nOS[        U [        [        45      (       a  [        [        U R                  5      5      nOU R                  nOU R                  n[        [        T	U5      5      n[        U [        5      (       d  X&:w  a  U R
                  " U6 nOU nUT;   ae   [        T5      n[        U["        5      (       a+  [%        UR&                  UR(                  UR*                  5      nUTU'   TR-                  X45        U$ U$ s  snf ! [         a    [!        S5      ef = f)Nnoner!   z$Symbols iterator ran out of symbols.)r   r   r   r>   r    rx   r   r   r   rS   r   r   r   r   r   StopIteration
ValueErrorr   r   r
  rowscolsr&   )rc   r   r   	orig_exprr^   r  r>   new_exprsym_rebuildr   r   replacementssubsr   r  s            r2   r  tree_cse.<locals>._rebuild  s   $ 455KyyKD>>15;#H;99h''4<:	8D>D F?$f..8D
+b0DD3-00GDII./yy99DHd+,dK((H,<yy(+HH$I7m )Z00"388Y^^NN$ "DO0J O_ <F ! I !GHHIs   G!;G& &G<)rT   r   r   r&   )r   r   r   r   r  r?   reduced_exprs	reduced_er  r  r  r  r   r  r  s    ````   @@@@@@@r2   tree_cser#  G  s    &  5L%Ku"( "(H a1  E'DGLD7 7r Ma IIY'  &&r=   c           	         U(       d  [        U XX4US9$ [        U [        [        45      (       a  [	        U 5      n [        U [
        [        45      (       a  U /n U n/ nU  H  n	[        U	[        [        45      (       a'  UR                  [        U	R                  5       6 5        ME  [        U	[        [        45      (       a5  UR                  [        U	R                  5       R                  5       6 5        M  UR                  U	5        M     Un AUc  / nOUS:X  a  [         nU  V	s/ s H  n	[#        X5      PM     n
n	Uc  [%        [&        S9nO[)        U5      n[+        X5      n[-        XUXE5      u  pUn U VVs/ s H  u  pU[/        X5      4PM     nnnU
 V	s/ s H  n	[/        X5      PM     n
n	[1        U 5       H  u  p[        U	[        [        45      (       aR  [        U	R2                  U	R4                  X   5      X'   [        U	[        5      (       a  X   R7                  5       X'   Mp  Mr  [        U	[        [        45      (       d  M  [        U	R2                  U	R4                  0 5      nX    H  u  nnUUU'   M     [        U	[        5      (       a  UR7                  5       nUX'   M     Uc  X4$ U" X5      $ s  sn	f s  snnf s  sn	f )az  Perform common subexpression elimination on an expression.

Parameters
==========

exprs : list of SymPy expressions, or a single SymPy expression
    The expressions to reduce.
symbols : infinite iterator yielding unique Symbols
    The symbols used to label the common subexpressions which are pulled
    out. The ``numbered_symbols`` generator is useful. The default is a
    stream of symbols of the form "x0", "x1", etc. This must be an
    infinite iterator.
optimizations : list of (callable, callable) pairs
    The (preprocessor, postprocessor) pairs of external optimization
    functions. Optionally 'basic' can be passed for a set of predefined
    basic optimizations. Such 'basic' optimizations were used by default
    in old implementation, however they can be really slow on larger
    expressions. Now, no pre or post optimizations are made by default.
postprocess : a function which accepts the two return values of cse and
    returns the desired form of output from cse, e.g. if you want the
    replacements reversed the function might be the following lambda:
    lambda r, e: return reversed(r), e
order : string, 'none' or 'canonical'
    The order by which Mul and Add arguments are processed. If set to
    'canonical', arguments will be canonically ordered. If set to 'none',
    ordering will be faster but dependent on expressions hashes, thus
    machine dependent and variable. For large expressions where speed is a
    concern, use the setting order='none'.
ignore : iterable of Symbols
    Substitutions containing any Symbol from ``ignore`` will be ignored.
list : bool, (default True)
    Returns expression in list or else with same type as input (when False).

Returns
=======

replacements : list of (Symbol, expression) pairs
    All of the common subexpressions that were replaced. Subexpressions
    earlier in this list might show up in subexpressions later in this
    list.
reduced_exprs : list of SymPy expressions
    The reduced expressions with all of the replacements above.

Examples
========

>>> from sympy import cse, SparseMatrix
>>> from sympy.abc import x, y, z, w
>>> cse(((w + x + y + z)*(w + y + z))/(w + x)**3)
([(x0, y + z), (x1, w + x)], [(w + x0)*(x0 + x1)/x1**3])


List of expressions with recursive substitutions:

>>> m = SparseMatrix([x + y, x + y + z])
>>> cse([(x+y)**2, x + y + z, y + z, x + z + y, m])
([(x0, x + y), (x1, x0 + z)], [x0**2, x1, y + z, x1, Matrix([
[x0],
[x1]])])

Note: the type and mutability of input matrices is retained.

>>> isinstance(_[1][-1], SparseMatrix)
True

The user may disallow substitutions containing certain symbols:

>>> cse([y**2*(x + 1), 3*y**2*(x + 1)], ignore=(y,))
([(x0, x + 1)], [x0*y**2, 3*x0*y**2])

The default return value for the reduced expression(s) is a list, even if there is only
one expression. The `list` flag preserves the type of the input in the output:

>>> cse(x)
([], [x])
>>> cse(x, list=False)
([], x)
)r   rd   postprocessr   r  basic)cls)_cse_homogeneousr   intfloatr   r   r   r   r   r&   r	   flatr   r   todokr   basic_optimizationsrg   r   r   r   r  r#  rj   r$   r  r  as_immutable)r   r   rd   r%  r   r  rS   copytempr?   r!  r   r  r  subtreer1   r  r   r   s                      r2   cser2    s   ` #A 	A %#u&& %%,--DDa&/233KKqvvx()L*?@AAKKqwwy012KKN  E	'	!+ DII5a'95MI"v. w- },H #+=8+0#:L E(46(4 -gEF(4  6 ,-+ ):+  - % a&/233%affaffm6FGM!_--#0#3#@#@#B  .L*?@AAQVVQVVR0A%(1! )!233NN$ M ! **|33Q J$6-s   !J55J:K c                    [        U [        5      (       a$  [        [        U 5      40 UD6u  p#U[	        U5      4$ [        U [
        [        [        45      (       a!  [        U 40 UD6u  p#U[        U 5      " U5      4$ [        U [        5      (       aQ  [        U R                  5       5      n[        U Vs/ s H  oPU   PM	     sn40 UD6u  p&[        [        XF5      5      nX#4$  [        U 40 UD6u  nu  nX#4$ s  snf ! [         a    / U 4s $ f = f)a  
Same as ``cse`` but the ``reduced_exprs`` are returned
with the same type as ``exprs`` or a sympified version of the same.

Parameters
==========

exprs : an Expr, iterable of Expr or dictionary with Expr values
    the expressions in which repeated subexpressions will be identified
kwargs : additional arguments for the ``cse`` function

Returns
=======

replacements : list of (Symbol, expression) pairs
    All of the common subexpressions that were replaced. Subexpressions
    earlier in this list might show up in subexpressions later in this
    list.
reduced_exprs : list of SymPy expressions
    The reduced expressions with all of the replacements above.

Examples
========

>>> from sympy.simplify.cse_main import cse
>>> from sympy import cos, Tuple, Matrix
>>> from sympy.abc import x
>>> output = lambda x: type(cse(x, list=False)[1])
>>> output(1)
<class 'sympy.core.numbers.One'>
>>> output('cos(x)')
<class 'str'>
>>> output(cos(x))
cos
>>> output(Tuple(1, x))
<class 'sympy.core.containers.Tuple'>
>>> output(Matrix([[1,0], [0,1]]))
<class 'sympy.matrices.dense.MutableDenseMatrix'>
>>> output([1, x])
<class 'list'>
>>> output((1, x))
<class 'tuple'>
>>> output({1, x})
<class 'set'>
)r   rX   r(  r   reprrS   tuplerT   r2  typedictr   rR   	TypeError)r   kwargsr  r!  r   r   valuess          r2   r(  r(  q  s   \ %&6EN'&$'&#T-000%$s+,,&)%&:6&:#T%[777%EJJL!"d#;d!Hd#;FvFS./**+),U)=f)=&&} ** $<  5ys   2C6"C; ;DD)	canonical)Nr;  ra   )NNNr;  ra   T)<r   collectionsr   
sympy.corer   r   r   r   r   sympy.core.containersr	   r
   sympy.core.exprtoolsr   sympy.core.singletonr   sympy.core.sortingr   sympy.core.symbolr   r   sympy.matricesr   r   r   r   r   sympy.matrices.expressionsr   r   r   r   r   r   "sympy.matrices.expressions.matexprr   sympy.polys.rootoftoolsr   sympy.utilities.iterablesr   r   r   r     r"   sub_presub_postr-  r3   rA   r_   rg   rj   rl   r   r   r  r#  r2  r(  ra   r=   r2   <module>rK     s    # 4 4 3 - " & -A AA A < *# #  !(((*;*;<$d+- @:!4@L04|5 |5~ ([)|yxN'b >B+/V4r@+r=   