
    \hf                      S r SSK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  SSKrSSKrSS	KJrJr  SS
KJr  SSK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$J%r%  SSK&J'r'  SSK(J)r)  SSK*J+r+J,r,J-r-  SSK.J/r/J0r0  SSK1J2r2  SSK3J4r4  SSK5J6r6  SSK7J8r8J9r9J:r:  SSK;J<r<J=r=  SSK>J?r?  S r@S rAS rB " S S\/5      rCS rD " S S \/5      rE\E" 5       rF " S! S"5      rG\G" 5       rH " S# S$\5      rI " S% S&\5      rJS' rK " S( S)\5      rL\=" S*S+S,S-9S. 5       rM\=" S/S+S0S-9 " S1 S2\5      5       rN\=" S3S+S4S-9S[S5 j5       rO " S6 S7\5      rPS[S8 jrQ " S9 S:\\5      rR " S; S<\R\25      rS " S= S>\R5      rT " S? S@\R\25      rU " SA SB\R5      rV " SC SD\P5      rW " SE SF\T5      rX " SG SH\J5      rY " SI SJ\5      rZSK r[SL r\SM r]SN r^SO r_SP r`SQ raSR rbSS rcST rdSU reS\SV jrfSW rgSX rhSY riSZ\i" \5      /0\R                  \R'   g)]a  
This module defines tensors with abstract index notation.

The abstract index notation has been first formalized by Penrose.

Tensor indices are formal objects, with a tensor type; there is no
notion of index range, it is only possible to assign the dimension,
used to trace the Kronecker delta; the dimension can be a Symbol.

The Einstein summation convention is used.
The covariant indices are indicated with a minus sign in front of the index.

For instance the tensor ``t = p(a)*A(b,c)*q(-c)`` has the index ``c``
contracted.

A tensor expression ``t`` can be called; called with its
indices in sorted order it is equal to itself:
in the above example ``t(a, b) == t``;
one can call ``t`` with different indices; ``t(c, d) == p(c)*A(d,a)*q(-a)``.

The contracted indices are dummy indices, internally they have no name,
the indices being represented by a graph-like structure.

Tensors are put in canonical form using ``canon_bp``, which uses
the Butler-Portugal algorithm for canonicalization using the monoterm
symmetries of the tensors.

If there is a (anti)symmetric metric, the indices can be raised and
lowered when the tensor is put in canonical form.
    )annotations)Any)reduce)prod)abstractmethodABC)defaultdictN)IntegerRationalPermutation)get_symmetric_group_sgsbsgs_direct_productcanonicalizeriemann_bsgs)BasicExprsympifyAddMulS)clear_cache)TupleDict)WildFunction)default_sort_key)SymbolsymbolsWild)CantSympify_sympify)AssocOp)
SYMPY_INTS)eye)sympy_deprecation_warningSymPyDeprecationWarningignore_warnings)memoize_property
deprecated)siftc                     [        SSSSS9  g )Nz|
        The data attribute of TensorIndexType is deprecated. Use The
        replace_with_arrays() method instead.
        z1.4z deprecated-tensorindextype-attrs   deprecated_since_versionactive_deprecations_target
stacklevelr%        K/var/www/auris/envauris/lib/python3.13/site-packages/sympy/tensor/tensor.pydeprecate_datar5   ?   s    	 "'#Er3   c                     [        SSSSS9  g )Nzn
        The Tensor.fun_eval() method is deprecated. Use
        Tensor.substitute_indices() instead.
        1.5deprecated-tensor-fun-evalr,   r-   r1   r2   r3   r4   deprecate_fun_evalr9   J       	 "'#?r3   c                     [        SSSSS9  g )Nzx
        Calling a tensor like Tensor(*indices) is deprecated. Use
        Tensor.substitute_indices() instead.
        r7   r8   r,   r-   r1   r2   r3   r4   deprecate_callr<   V   r:   r3   c                      \ rS rSrSrSS jr\S 5       r\S 5       r\S 5       r	S r
\S 5       r\S	 5       r\S
 5       rSS jrS rS rS rS rS rS rSS jrS rSrg)_IndexStructureb   a  
This class handles the indices (free and dummy ones). It contains the
algorithms to manage the dummy indices replacements and contractions of
free indices under multiplications of tensor expressions, as well as stuff
related to canonicalization sorting, getting the permutation of the
expression and so on. It also includes tools to get the ``TensorIndex``
objects corresponding to the given index structure.
c                    Xl         X l        X0l        X@l        [	        U R                   5      S[	        U R                  5      -  -   U l        U R                  R                  S S9  g )N   c                    U S   $ Nr   r2   xs    r4   <lambda>*_IndexStructure.__init__.<locals>.<lambda>r   s    AaDr3   key)freedumindex_typesindiceslen	_ext_ranksort)selfrJ   rK   rL   rM   canon_bps         r4   __init___IndexStructure.__init__l   sI    	&TYY!CM/9.)r3   c                     [         R                  " U 6 u  pU  Vs/ s H  o3R                  PM     nn[         R                  XU5      n [        XX@5      $ s  snf )a6  
Create a new ``_IndexStructure`` object from a list of ``indices``.

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

``indices``     ``TensorIndex`` objects, the indices. Contractions are
                detected upon construction.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, _IndexStructure
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> _IndexStructure.from_indices(m0, m1, -m1, m3)
_IndexStructure([(m0, 0), (m3, 3)], [(1, 2)], [Lorentz, Lorentz, Lorentz, Lorentz])
)r>   _free_dum_from_indicestensor_index_type_replace_dummy_names)rM   rJ   rK   irL   s        r4   from_indices_IndexStructure.from_indicest   sR    * $::GD	4;<Gq**G<!66wcJt+?? =s   Ac                    / nU  H  nUR                  UR                  5        M      [        R                  XU5      n[        XX55      $ N)extendrL   r>   *generate_indices_from_free_dum_index_types)
componentsrJ   rK   rL   	componentrM   s         r4   from_components_free_dum(_IndexStructure.from_components_free_dum   sE    #Iy445 $!LLTXcdt+??r3   c                    [        U 5      nUS:X  a
  U S   S4// 4$ S/[        U 5      -  n0 n/ n[        U 5       H  u  pVUR                  nUR                  nUR                  n	Xx4U;   a|  X7U4   u  pU
(       a  U	(       a  [        SX4-  5      eSX+'   SX%'   OU	(       a	  SX+'   SX%'   O[        SX4-  5      eU	(       a  UR                  X[45        M  UR                  X45        M  UR                  U4X7U4'   M     [        U 5       VVs/ s H  u  pVX%   (       d  M  Xe4PM     nnnUR                  5         X$4$ s  snnf )a  
Convert ``indices`` into ``free``, ``dum`` for single component tensor.

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

``free``     list of tuples ``(index, pos, 0)``,
             where ``pos`` is the position of index in
             the list of indices formed by the component tensors

``dum``      list of tuples ``(pos_contr, pos_cov, 0, 0)``

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices,             _IndexStructure
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> _IndexStructure._free_dum_from_indices(m0, m1, -m1, m3)
([(m0, 0), (m3, 3)], [(1, 2)])
   r   Tz2two equal contravariant indices in slots %d and %dFz.two equal covariant indices in slots %d and %d)rN   	enumeratenamerW   is_up
ValueErrorappendrP   )rM   nrJ   
index_dictrK   rY   indexrg   typcontris_contrposs               r4   rV   &_IndexStructure._free_dum_from_indices   sL   0 L6QZO$b(( vc'l"
!'*HA::D))CKKE{j( *#; 7()]`c_g)ghh$)	"'$)	"'()Y\_[c)cddJJx(JJx(*/++q.
#;'3 +6 ,5W+=I+=xq

+=I		y Js   
D:D:c                     U R                   SS $ )zO
Get a list of indices, creating new tensor indices to complete dummy indices.
N)rM   rQ   s    r4   get_indices_IndexStructure.get_indices   s     ||Ar3   c                   S /[        U 5      S[        U5      -  -   -  nU  H	  u  pEXCU'   M     [        R                  U 5      nU H-  u  pxX'   n	U" U	5      n
[        XS5      X7'   [        XS5      X8'   M/     [        R	                  X0U5      $ )NrA   TF)rN   r>    _get_generator_for_dummy_indicesTensorIndexrX   )rJ   rK   rL   rM   idxrq   generate_dummy_namepos1pos2typ1indnames              r4   r_   :_IndexStructure.generate_indices_from_free_dum_index_types   s    &#d)Ac#hJ./HCCL  .NNtTJD$D)$/G't<GM'u=GM	  33G3GGr3   c           	     T  ^ [        [        5      mU  H  u  pUR                  R                  S5      S   UR                  R
                  :X  d  M=  [        TUR                     [        UR                  R                  S5      S   5      S-   5      TUR                  '   M     U4S jnU$ )N_r   re   c                ^   > [        TU    5      nTU ==   S-  ss'   U R                  S-   U-   $ Nre   r   str
dummy_namerW   ndcdts     r4   dummy_name_genH_IndexStructure._get_generator_for_dummy_indices.<locals>.dummy_name_gen   :    S*+,B!"a'"$//#5::r3   )r	   intrg   splitrW   r   max)rJ   indxiposr   r   s       @r4   rx   0_IndexStructure._get_generator_for_dummy_indices   s    # JDyys#A&$*@*@*K*KK.1#d6L6L2MsSWS\S\SbSbcfSghiSjOknoOo.pD**+ 	;
 r3   c                2   UR                  S S9  [        U 5      n[        U 5      [        U5      S[        U5      -  -   :X  d   e[        R	                  U5      nU H7  u  pVX5   R
                  nU" U5      n[        XS5      X5'   [        XS5      X6'   M9     U$ )Nc                    U S   $ rC   r2   rD   s    r4   rF   6_IndexStructure._replace_dummy_names.<locals>.<lambda>   s    qtr3   rH   rA   TF)rP   listrN   r>   rx   rW   ry   )	rM   rJ   rK   new_indicesr{   ipos1ipos2r~   r   s	            r4   rX   $_IndexStructure._replace_dummy_names   s    ^$7m7|s4y1SX:5555-NNtTLE%77D)$/G!,WD!AK!,WE!BK	  
 r3   c                `    [        U R                  S S9nU Vs/ s H  o"S   PM	     sn$ s  snf )z
Get a list of free indices.
c                    U S   $ Nre   r2   rD   s    r4   rF   2_IndexStructure.get_free_indices.<locals>.<lambda>  s    qtr3   rH   r   sortedrJ   )rQ   rJ   rY   s      r4   get_free_indices _IndexStructure.get_free_indices  s.    
 dii^4"#d!d###s   +c                d    SR                  U R                  U R                  U R                  5      $ )Nz_IndexStructure({}, {}, {}))formatrJ   rK   rL   rt   s    r4   __str___IndexStructure.__str__  s%    ,33DIItxxIYIYZZr3   c                "    U R                  5       $ r]   )r   rt   s    r4   __repr___IndexStructure.__repr__  s    ||~r3   c                D    U R                   S S  nUR                  S S9  U$ )Nc                    U S   $ rC   r2   rD   s    r4   rF   D_IndexStructure._get_sorted_free_indices_for_canon.<locals>.<lambda>  s    qtr3   rH   )rJ   rP   )rQ   sorted_frees     r4   "_get_sorted_free_indices_for_canon2_IndexStructure._get_sorted_free_indices_for_canon  s&    iil^,r3   c                ,    [        U R                  S S9$ )Nc                    U S   $ rC   r2   rD   s    r4   rF   C_IndexStructure._get_sorted_dum_indices_for_canon.<locals>.<lambda>  s    adr3   rH   )r   rK   rt   s    r4   !_get_sorted_dum_indices_for_canon1_IndexStructure._get_sorted_dum_indices_for_canon  s    dhhN33r3   c                    U R                  5       S   nS /U R                  -  n[        U R                  5       H  u  p4XBU" U5      '   M     U$ rC   )indices_canon_argsrO   rf   rL   )rQ   permutationrL   rY   its        r4   )_get_lexicographically_sorted_index_types9_IndexStructure._get_lexicographically_sorted_index_types  sN    --/2fT^^+t//0EA*,A' 1r3   c                    U R                  5       S   nS /U R                  -  n[        U R                  5       H  u  p4XBU" U5      '   M     U$ rC   )r   rO   rf   rM   )rQ   r   rM   rY   r   s        r4   %_get_lexicographically_sorted_indices5_IndexStructure._get_lexicographically_sorted_indices%  sK    --/2&'t||,EA&(KN# -r3   c                   U R                  5        Vs/ s H  o3S   PM	     nnU R                  5       nU R                  5       n[        U5      nU R                  n[        X-
  S-  5       Vs/ s H	  nS/S-  PM     n	n/ n
S/U-  nS/U-  n[        U5       Hp  nX   nX]   X'   Xm   X'   X:  a.  XM   nX   XM   R                  :X  d   eU
R                  X45        MF  X-
  n[        US5      u  nnU(       a	  X9U   S'   Mi  X9U   S'   Mr     U	 Vs/ s H  n[        U5      PM     n	n[        XX5      $ s  snf s  snf s  snf )a4  
Returns a ``_IndexStructure`` instance corresponding to the permutation ``g``.

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

``g``  permutation corresponding to the tensor in the representation
used in canonicalization

``is_canon_bp``   if True, then ``g`` is the permutation
corresponding to the canonical form of the tensor
r   rA   Nre   )r   r   r   rN   rO   rangerW   rj   divmodtupler>   )rQ   gis_canon_bprY   r   lex_index_typeslex_indicesnfreerankrK   rJ   rL   rM   giindjidumcovrE   s                      r4   perm2tensor_IndexStructure.perm2tensor,  sW    &*%L%L%NO%Nt%NOHHJ@@BK ~~!&q'8!9:!9Avax!9:fTk&+tAB,0KN$GJz!o"~)J)JJJJSH%J"1aL	c#$IaL#$IaL  "%%AuQx%t+??7 P
 ;( &s   D2,D7D<c                t   SSK Jn  U R                  nS/U-  X"S-   /-   nS n[        U R	                  5       5       H  u  nu  pgXSU'   M     [        U R                  5      n[        U R                  5      n	/ n
Sn/ n/ nU R                  5        H  u  pXU'   U	S-   X?'   U	S-  n	U R                  U   nUU:w  aB  U(       a  U
R                  U5        XS-   /nUnUR                  U" UR                  5      5        OUR                  XS-   /5        US-  nM     U(       a  U
R                  U5        U" U5      X4$ )z
Returns ``(g, dummies, msym, v)``, the entries of ``canonicalize``

See ``canonicalize`` in ``tensor_can.py`` in combinatorics module.
r   )_af_newNre   c                    U c  g U R                   nU[        R                  S5      :X  a  gU[        R                  S5      :X  a  gg )NrA   r   re   )symmetryTensorSymmetryfully_symmetric)metricsyms     r4   metric_symmetry_to_msymC_IndexStructure.indices_canon_args.<locals>.metric_symmetry_to_msymc  sB    ~//Cn44Q77n44R88r3   rA   ) sympy.combinatorics.permutationsr   rO   rf   r   rN   rJ   r   rL   rj   r   r^   )rQ   r   rk   r   r   rY   r   r   rq   r   dummiesprevamsymr   r   rn   s                    r4   r   "_IndexStructure.indices_canon_argsV  s9    	=NNF1HQ3x	  ))P)P)RSOA|dG  T$))n		N BBDLEeH1uAHFA""5)Cd{NN1%'N3CJJ?@#Qw(1HC E NN1qz7((r3   )rO   rK   rJ   rL   rM   NFreturnzlist[TensorIndex])__name__
__module____qualname____firstlineno____doc__rS   staticmethodrZ   rb   rV   ru   r_   rx   rX   r   r   r   r   r   r   r   r   r   __static_attributes__r2   r3   r4   r>   r>   b   s    * @ @2 @ @ < <| H H    
 
$[
4(@T4)r3   r>   c                   / nS nU  H/  nX2:X  a  US   S==   S-  ss'   M  UnUR                  US/5        M1     / nU H  u  pVUR                  S;   a  UR                  nO*[        R                  UR                  UR                  5      nUR                  UR                  R
                  UR                  R                  Xg45        M     U$ )Nre   r   re   )rj   commTensorManagerget_commr   base
generators)r`   numtypr   tvhrk   r   s           r4   components_canon_argsr     s    FD92JqMQMDMM4)$  	A66V66D ))!&&!&&9D	!**//1::#8#8!BC  Hr3   c                      \ rS rSr% Sr0 rS\S'   0 rS\S'   S rS r	\
S 5       rS	 rS
 rS rS rS rS rS rS r\
S 5       r\
S 5       r\
S 5       r\
SS j5       r\
S 5       r\
S 5       r\
S 5       rSrg)_TensorDataLazyEvaluatori  a  
EXPERIMENTAL: do not rely on this class, it may change without deprecation
warnings in future versions of SymPy.

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

This object contains the logic to associate components data to a tensor
expression. Components data are set via the ``.data`` property of tensor
expressions, is stored inside this class as a mapping between the tensor
expression and the ``ndarray``.

Computations are executed lazily: whereas the tensor expressions can have
contractions, tensor products, and additions, components data are not
computed until they are accessed by reading the ``.data`` property
associated to the tensor expression.
zdict[Any, Any]_substitutions_dict_substitutions_dict_tensmulc                    U R                  U5      nUc  g SSKJn  [        X#5      (       d  U$ UR	                  5       S:X  a  US   $ UR	                  5       S:X  a  [        U5      S:X  a  US   $ U$ )Nre   )	NDimArrayr   r2   )_getarrayr   
isinstancer   rN   )rQ   rI   datr   s       r4   __getitem__$_TensorDataLazyEvaluator.__getitem__  se    iin;$#))J88:?r7NXXZ1_SQq6M
r3   c           	     x   XR                   ;   a  U R                   U   $ [        U[        5      (       a  g[        U[        5      (       a  [	        UR                  5        Vs/ s H  o"R                  PM     sn5      nUR                  4U-   nX@R                  ;   a  U R                  U   $ U R                  U5      /nU R                  XQR                  UR                  5      $ [        U[        5      (       Ga  UR                  n[        U5      S:X  a  [        US   R                   5      S:X  aj  [	        US   R                  5        Vs/ s H  o"R                  PM     sn5      nUS   R                   S   4U-   nX@R                  ;   a  U R                  U   $ U Vs/ s HL  n[        U["        5      (       d  M  [        U[        5      (       a  U R                  U5      OUR$                  PMN     nn['        U Vs/ s H  n[        U["        5      (       a  M  UPM     sn5      n[)        S U 5       5      (       a  g[+        S U 5       5      (       a  [-        S5      eU R                  XqR                  UR                  5      n	X-  $ [        U[.        5      (       Gaw  / n/ n
UR                   H  n[        U["        5      (       aK  UR1                  UR$                  5        U
R1                  UR2                   Vs/ s H  oS   PM	     sn5        Mc  UR1                  U5        U
R1                  / 5        M     [)        S U 5       5      (       a  g[+        S U 5       5      (       a  [-        S5      e/ nSS	KJn  [9        Xz5       H  u  nn[        U5      S
:  a  UR1                  U5        M(  [;        U5       VVs0 s H	  u  nnUU_M     nnnUR<                   Vs/ s H  nUU   PM
     nnUR1                  U" UU5      5        M     [?        S U5      $ gs  snf s  snf s  snf s  snf s  snf s  snnf s  snf )a  
Retrieve ``data`` associated with ``key``.

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

This algorithm looks into ``self._substitutions_dict`` for all
``TensorHead`` in the ``TensExpr`` (or just ``TensorHead`` if key is a
TensorHead instance). It reconstructs the components data that the
tensor expression should have by performing on components data the
operations that correspond to the abstract tensor operations applied.

Metric tensor is handled in a different manner: it is pre-computed in
``self._substitutions_dict_tensmul``.
Nre   r   c              3  (   #    U  H  oS L v   M
     g 7fr]   r2   .0rY   s     r4   	<genexpr>0_TensorDataLazyEvaluator._get.<locals>.<genexpr>       0i9i   c              3  (   #    U  H  oS L v   M
     g 7fr]   r2   r  s     r4   r  r	    r
  r  zSMixing tensors with associated components data with tensors without components datac              3  (   #    U  H  oS L v   M
     g 7fr]   r2   r  s     r4   r  r	    r
  r  c              3  (   #    U  H  oS L v   M
     g 7fr]   r2   r  s     r4   r  r	    r
  r  permutedimsrA   c                
    X-   $ r]   r2   )rE   ys     r4   rF   /_TensorDataLazyEvaluator._get.<locals>.<lambda>  s    qsr3   ) r   r   
TensorHeadTensorr   ru   rh   ra   r   data_from_tensordata_contract_dumrK   ext_rankTensMulargsrN   r`   TensExprdatar   allanyri   TensAddrj   rJ   r   r  ziprf   	free_argsr   )rQ   rI   rY   	signaturesrch
array_listtensmul_args	data_listcoeffdata_resultfree_args_listargrE   sum_listr  r  r!  r  free_args_posaxess                       r4   r   _TensorDataLazyEvaluator._get  s     ***++C00c:&&c6"" 0AB0A1ww0ABCIMM#i/D77777==//45J))*ggs||LLc7##88L< A%#l1o.H.H*IQ*N "LO4O4O4Q"R4Qq774Q"RS	$Q22157)C;;;;;DAA`l  I`l[\pz{|  G  qHVZ65J5J..q1PQPVPVV`lI  I\Q\Ax9P!\QRE0i0000i000  "M N N00GGS\\RK$$c7##INxxc8,,$$SXX."))*BAQ4*BC$$S)"))"-   0i0000i000  "M N N H*#&y#Aiy>A%OOD)6?	6J$K6JdaQT6JM$K:=--H-3M#.-DHOOKd$;< $B *H55o C #S
 IQ +C  %LHs6   !P
PP";6P"<P'P'<P,
<P1P7c                Z    SSK JnJnJn  [	        [        XP5      5      nU" U6 nU" U/UQ76 $ )Nre   )tensorproducttensorcontractionMutableDenseNDimArray)r   r0  r1  r2  r   map)ndarray_listrK   r  r0  r1  r2  arraysprodarrs           r4   r  *_TensorDataLazyEvaluator.data_contract_dum  s2    RRc/>?( /3//r3   c                x    Uc  gU R                  UUR                  5       UR                  UR                  S5      $ )z
This method is used when assigning components data to a ``TensMul``
object, it converts components data to a fully contravariant ndarray,
which is then stored according to the ``TensorHead`` key.
NT)_correct_signature_from_indicesru   rJ   rK   )rQ   r  tensmul
tensorheads       r4   data_tensorhead_from_tensmul5_TensorDataLazyEvaluator.data_tensorhead_from_tensmul  s?     <33!LLKK 	r3   c                    UR                   nUR                  c  gU R                  UR                  UR                  5       UR                  UR
                  5      $ )z
This method corrects the components data to the right signature
(covariant/contravariant) using the metric associated with each
``TensorIndexType``.
N)ra   r  r9  ru   rJ   rK   )rQ   tensorr;  s      r4   r  )_TensorDataLazyEvaluator.data_from_tensor.  sP     %%
??"33OO KKJJ	 	r3   c                    [        U[        5      (       a  [        S5      e[        UR                  5      S:w  a  [        S5      eUR                  S   nU R                  X!U5      nX44$ )Nzcannot assign data to TensAddre   z6cannot assign data to TensMul with multiple componentsr   )r   r  ri   rN   r`   r<  )rQ   rI   r  r;  newdatas        r4   _assign_data_to_tensor_expr4_TensorDataLazyEvaluator._assign_data_to_tensor_expr?  sa    c7##<==s~~!#UVV^^A&
33DzJ""r3   c           	        SSK Jn  SSKJn  [	        U[
        5      (       a#  UR                  nUR                  R                  nO[	        U[        5      (       a0  UR                  nUR                  S   R                  R                  nOK[	        U[        5      (       a6  UR                  R                  nUR                  R                  R                  nW H  nU" W5      U:X  a  SOSnUn	Un
[        [        U[        U5      5      5      n[        UR!                  5       S-
  5       H3  nU" X5      n	[#        U" XU	-  -
  5      5      (       a  [%        S5      eU	n
M5     M     g )Nre   r  )Flattenr   r   z'Component data symmetry structure error)r   r  array.arrayoprF  r   r  r   r   r   r  r`   TensorIndexTyper   r   r3  r   orderr  ri   )rQ   tensr  r  rF  r   r   genersign_changedata_swapped	last_datapermute_axesrY   s                r4   _check_permutations_on_data4_TensorDataLazyEvaluator._check_permutations_on_dataI  s   &*dJ''99D11Jf%%99D+44??Jo..;;##D--88J
  E!&t!4"2KLIE5; 78L 5;;=?+*<Fwy|+CCDEE$%NOO(	 ,  r3   c                    [         R                  U5      nU R                  X5        [        U[        [
        45      (       d  U R                  X5      u  p[        U[        5      (       a  [        UR                  UR                  5       Hc  u  pEUR                  c  [        SR                  U5      5      eUR                  R                  (       d  MI  XER                  :w  d  MZ  [        S5      e   X0R                  U'   g)a  
Set the components data of a tensor object/expression.

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

Components data are transformed to the all-contravariant form and stored
with the corresponding ``TensorHead`` object. If a ``TensorHead`` object
cannot be uniquely identified, it will raise an error.
NzMindex type {} has no components data associated (needed to raise/lower index)zwrong dimension of ndarray)r   
parse_datarP  r   r  rH  rC  r   shaperL   r  ri   r   dim	is_numberr   )rQ   rI   valuer  rU  	indextypes         r4   __setitem__$_TensorDataLazyEvaluator.__setitem__h  s     (2259((3
 #
O<==88CICc:&&"%djj#//"B>>)$ &@@Fy@QS S }}..--'$%ABB #C )-  %r3   c                    U R                   U	 g r]   r   rQ   rI   s     r4   __delitem__$_TensorDataLazyEvaluator.__delitem__  s    $$S)r3   c                    XR                   ;   $ r]   r\  r]  s     r4   __contains__%_TensorDataLazyEvaluator.__contains__  s    ....r3   c                    X R                   USS4'   U R                  U5      nX0R                   USS4'   UR                  5       nUR                  5       nXE-  U R                   USS4'   XT-  U R                   USS4'   g)a  
Assign data to the ``metric`` tensor. The metric tensor behaves in an
anomalous way when raising and lowering indices.

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

A fully covariant metric is the inverse transpose of the fully
contravariant metric (it is meant matrix inverse). If the metric is
symmetric, the transpose is not necessary and mixed
covariant/contravariant metrics are Kronecker deltas.
TFN)r   inverse_transpose_matrixtomatrix)rQ   r   r  inverse_transposeminvts         r4   add_metric_data(_TensorDataLazyEvaluator.add_metric_data  s    " @D((t);< 99$? BS(()=> MMO ))+@A((u)<=@D(()<=r3   c                    SSK JnJn  UR                  5       nU R                  5       nUS:X  a  U" U" UU 5      SXR-   45      n U $ U" U" U U5      X&45      n U $ )Nre   r0  r1  r   )r   r0  r1  r   )r  r   rq   r0  r1  mdimddims          r4   _flip_index_by_metric._TensorDataLazyEvaluator._flip_index_by_metric  st    ;{{}yy{!8$ DHD  % D r3   c                h    U R                  5       R                  5       n[        R                  U5      $ r]   )re  invr   rS  ndarrayrg  s     r4   inverse_matrix'_TensorDataLazyEvaluator.inverse_matrix  s*    ""$'22155r3   c                |    U R                  5       R                  5       R                  n[        R	                  U5      $ r]   )re  rr  Tr   rS  rs  s     r4   rd  1_TensorDataLazyEvaluator.inverse_transpose_matrix  s0    ""$&&'22155r3   c                j   [        U5       H  u  pVUR                  (       d3  U(       d,  [        R                  XR                  R
                  U5      n MI  UR                  (       a  M\  U(       d  Me  [        R                  U [        R                  UR                  R
                  5      U5      n M     U $ )z
Utility function to correct the values inside the components data
ndarray according to whether indices are covariant or contravariant.

It uses the metric matrix to lower values of covariant indices.
)rf   rh   r   ro  rW   r  ru  )r  rM   rJ   rK   inverserY   r   s          r4   r9  8_TensorDataLazyEvaluator._correct_signature_from_indices  s     !)GA::g/EEdLbLbLgLgijkZZZGG/EE,;;D<R<R<W<WX	 * r3   c                   SSK Jn  U R                  R                  5       nU R                   Vs/ s H  oDS   PM	     nnUR                   Vs/ s H  oDS   PM	     nn[        [        U5      5       HC  n[        U[        U5      5       H'  nXW   Xd   :X  d  M  XW   XT   sXT'   XW'   U" X4U45      n  MA     ME     U$ s  snf s  snf )Nre   r  r   )r   r  r  copyrJ   r   rN   )oldnewr  new_datarY   old_freenew_freer   s           r4   _sort_data_axes(_TensorDataLazyEvaluator._sort_data_axes  s    &88==?"%((+(QaD(+"%((+(QaD(+s8}%A1c(m,;(+-/7{HK,HK*8V<H	 - &  ,+s   B:B?c                F   ^ ^ U U4S jnU" 5       [         R                  T '   g )Nc                 0   > [         R                  TT 5      $ r]   )r   r  )new_tensmulold_tensmuls   r4   sorted_compoJ_TensorDataLazyEvaluator.add_rearrange_tensmul_parts.<locals>.sorted_compo  s    +;;KUUr3   )r   r   )r  r  r  s   `` r4   add_rearrange_tensmul_parts4_TensorDataLazyEvaluator.add_rearrange_tensmul_parts  s     	V EQN 44[Ar3   c                    SSK Jn  [        X5      (       d<  [        U 5      S:X  a%  [	        U S   S5      (       a  U" U S   U S   5      n U $ U" U 5      n U $ )an  
Transform ``data`` to array. The parameter ``data`` may
contain data in various formats, e.g. nested lists, SymPy ``Matrix``,
and so on.

Examples
========

>>> from sympy.tensor.tensor import _TensorDataLazyEvaluator
>>> _TensorDataLazyEvaluator.parse_data([1, 3, -6, 12])
[1, 3, -6, 12]

>>> _TensorDataLazyEvaluator.parse_data([[1, 2], [4, 7]])
[[1, 2], [4, 7]]
re   r2  rA   r   __call__)r   r2  r   rN   hasattr)r  r2  s     r4   rS  #_TensorDataLazyEvaluator.parse_data  sY    " 	1$664yA~'$q':">">,T!Wd1g>  -T2r3   r2   Nr   )r   r   r   r   r   r   __annotations__r   r  r   r   r  r<  r  rC  rP  rY  r^  ra  ri  ro  ru  rd  r9  r  r  rS  r   r2   r3   r4   r   r     s    " +-,244Qf 0 0 "#)>->*/I<  0 6 6 6 6  (    S S  r3   r   c                  X    \ rS rSrSrS rS r\S 5       rS r	S r
S rS	 rS
 rS rSrg)_TensorManageri  a  
Class to manage tensor properties.

Notes
=====

Tensors belong to tensor commutation groups; each group has a label
``comm``; there are predefined labels:

``0``   tensors commuting with any other tensor

``1``   tensors anticommuting among themselves

``2``   tensors not commuting, apart with those with ``comm=0``

Other groups can be defined using ``set_comm``; tensors in those
groups commute with those with ``comm=0``; by default they
do not commute with any other group.
c                $    U R                  5         g r]   
_comm_initrt   s    r4   rS   _TensorManager.__init__,  s    r3   c                T   [        S5       Vs/ s H  n0 PM     snU l        [        S5       H'  nSU R                  S   U'   SU R                  U   S'   M)     SU R                  S   S'   S U R                  S   S'   S U R                  S   S'   SSSS.U l        SSSS.U l        g s  snf )N   r   re   rA   )r   re   rA   )r   _comm_comm_symbols2i_comm_i2symbolrQ   rY   s     r4   r  _TensorManager._comm_init/  s    "'(+(Qb(+
qA DJJqM! DJJqM!  

1a

1a

1a"#qA!"a1o ,s   B%c                    U R                   $ r]   )r  rt   s    r4   r   _TensorManager.comm:      zzr3   c                "   XR                   ;  ar  [        U R                  5      nU R                  R                  0 5        SU R                  U   S'   SU R                  S   U'   X R                   U'   XR                  U'   U$ U R                   U   $ )z
Get the commutation group number corresponding to ``i``.

``i`` can be a symbol or a number or a string.

If ``i`` is not already defined its commutation group number
is set.
r   )r  rN   r  rj   r  )rQ   rY   rk   s      r4   comm_symbols2i_TensorManager.comm_symbols2i>  s     (((DJJAJJb! DJJqM! DJJqM!&'  #%&"H##A&&r3   c                     U R                   U   $ )zC
Returns the symbol corresponding to the commutation group number.
)r  r  s     r4   comm_i2symbol_TensorManager.comm_i2symbolQ  s     ""1%%r3   c                   US;  a  [        S5      e[        U5      n[        U5      nXR                  ;  ap  [        U R                  5      nU R                  R                  0 5        SU R                  U   S'   SU R                  S   U'   X@R                  U'   XR                  U'   X R                  ;  ap  [        U R                  5      nU R                  R                  0 5        SU R                  S   U'   SU R                  U   S'   X@R                  U'   X R                  U'   U R                  U   nU R                  U   nX0R                  U   U'   X0R                  U   U'    [        5         g)a_  
Set the commutation parameter ``c`` for commutation groups ``i, j``.

Parameters
==========

i, j : symbols representing commutation groups

c  :  group commutation number

Notes
=====

``i, j`` can be symbols, strings or numbers,
apart from ``0, 1`` and ``2`` which are reserved respectively
for commuting, anticommuting tensors and tensors not commuting
with any other group apart with the commuting tensors.
For the remaining cases, use this method to set the commutation rules;
by default ``c=None``.

The group commutation number ``c`` is assigned in correspondence
to the group commutation symbols; it can be

0        commuting

1        anticommuting

None     no commutation property

Examples
========

``G`` and ``GH`` do not commute with themselves and commute with
each other; A is commuting.

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorHead, TensorManager, TensorSymmetry
>>> Lorentz = TensorIndexType('Lorentz')
>>> i0,i1,i2,i3,i4 = tensor_indices('i0:5', Lorentz)
>>> A = TensorHead('A', [Lorentz])
>>> G = TensorHead('G', [Lorentz], TensorSymmetry.no_symmetry(1), 'Gcomm')
>>> GH = TensorHead('GH', [Lorentz], TensorSymmetry.no_symmetry(1), 'GHcomm')
>>> TensorManager.set_comm('Gcomm', 'GHcomm', 0)
>>> (GH(i1)*G(i0)).canon_bp()
G(i0)*GH(i1)
>>> (G(i1)*G(i0)).canon_bp()
G(i1)*G(i0)
>>> (G(i1)*A(i0)).canon_bp()
A(i0)*G(i1)
)r   re   Nz+`c` can assume only the values 0, 1 or Noner   N)ri   r   r  rN   r  rj   r  r   )rQ   rY   r   crk   ninjs          r4   set_comm_TensorManager.set_commW  sM   d L JKKAJAJ(((DJJAJJb! DJJqM! DJJqM!&'  #%&"(((DJJAJJb! DJJqM! DJJqM!&'  #%&"!!!$!!!$

2r

2r	 	r3   c                @    U H  u  p#nU R                  X#U5        M     g)zx
Set the commutation group numbers ``c`` for symbols ``i, j``.

Parameters
==========

args : sequence of ``(i, j, c)``
N)r  )rQ   r  rY   r   r  s        r4   	set_comms_TensorManager.set_comms  s      GA!MM!" r3   c                b    U R                   U   R                  X!S:X  d  US:X  a  S5      $ S5      $ )zj
Return the commutation parameter for commutation group numbers ``i, j``

see ``_TensorManager.set_comm``
r   N)r  get)rQ   rY   r   s      r4   r   _TensorManager.get_comm  s1     zz!}  a16ADDtDDr3   c                $    U R                  5         g)z
Clear the TensorManager.
Nr  rt   s    r4   clear_TensorManager.clear  s     	r3   )r  r  r  N)r   r   r   r   r   rS   r  propertyr   r  r  r  r  r   r  r   r2   r3   r4   r  r    sF    &	.  '&&Qf
#Er3   r  c                  B   \ rS rSrSr  SS jr\S 5       r\S 5       r\S 5       r	\S 5       r
\S	 5       r\S
 5       r\S 5       rS rS rS r\r\S 5       r\R(                  S 5       r\R*                  S 5       r\" SSSS9S 5       r\" SSSS9S 5       rS rSrg)rH  i  a  
A TensorIndexType is characterized by its name and its metric.

Parameters
==========

name : name of the tensor type
dummy_name : name of the head of dummy indices
dim : dimension, it can be a symbol or an integer or ``None``
eps_dim : dimension of the epsilon tensor
metric_symmetry : integer that denotes metric symmetry or ``None`` for no metric
metric_name : string with the name of the metric tensor

Attributes
==========

``metric`` : the metric tensor
``delta`` : ``Kronecker delta``
``epsilon`` : the ``Levi-Civita epsilon`` tensor
``data`` : (deprecated) a property to add ``ndarray`` values, to work in a specified basis.

Notes
=====

The possible values of the ``metric_symmetry`` parameter are:

    ``1``   :   metric tensor is fully symmetric
    ``0``   :   metric tensor possesses no index symmetry
    ``-1``  :   metric tensor is fully antisymmetric
    ``None``:   there is no metric tensor (metric equals to ``None``)

The metric is assumed to be symmetric by default. It can also be set
to a custom tensor by the ``.set_metric()`` method.

If there is a metric the metric is used to raise and lower indices.

In the case of non-symmetric metric, the following raising and
lowering conventions will be adopted:

``psi(a) = g(a, b)*psi(-b); chi(-a) = chi(b)*g(-b, -a)``

From these it is easy to find:

``g(-a, b) = delta(-a, b)``

where ``delta(-a, b) = delta(b, -a)`` is the ``Kronecker delta``
(see ``TensorIndex`` for the conventions on indices).
For antisymmetric metrics there is also the following equality:

``g(a, -b) = -delta(a, -b)``

If there is no metric it is not possible to raise or lower indices;
e.g. the index of the defining representation of ``SU(N)``
is 'covariant' and the conjugate representation is
'contravariant'; for ``N > 2`` they are linearly independent.

``eps_dim`` is by default equal to ``dim``, if the latter is an integer;
else it can be assigned (for use in naive dimensional regularization);
if ``eps_dim`` is not an integer ``epsilon`` is ``None``.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> Lorentz.metric
metric(Lorentz,Lorentz)
Nc           	     r   SU;   a  US   n[        SU S3SSS9  Un[        U[        5      (       a  [        U5      nUc  [        U5      S   n[        U[        5      (       a  [        U5      nUc  [        SUR                  -   5      nO[        U5      nUc  UnO[        U5      n[        U5      n[        U[        5      (       a  [        U5      nS	U;   a@  [        S
SSS9  UR                  S	5      n	U	b!  U	S;   a  S	nOU	R                  nU	(       a  SnOSn[        R                  " XX#UXV5      n
/ U
l
        U
$ )N	dummy_fmtzh
                The dummy_fmt keyword to TensorIndexType is deprecated. Use
                dummy_name=z instead.
                r7   z$deprecated-tensorindextype-dummy-fmtr.   r/   r   dim_r   z
                The 'metric' keyword argument to TensorIndexType is
                deprecated. Use the 'metric_symmetry' keyword argument or the
                TensorIndexType.set_metric() method instead.
                z!deprecated-tensorindextype-metric)TFr   re   r   re   )r%   r   r   r   rg   r   r&   r  r   __new___autogenerated)clsrg   r   rU  eps_dimmetric_symmetrymetric_namekwargsr  r   objs              r4   r  TensorIndexType.__new__  sV   & {+I%%; ' */+Q #JdC  $<DT1Jj#&&
+J;*//12C#,C?Gg&G!/2k3'' -Kv#
 */+N ZZ)F!00"*K #)++K &(O&'OmmCz+:  
r3   c                4    U R                   S   R                  $ rC   r  rg   rt   s    r4   rg   TensorIndexType.nameQ      yy|   r3   c                4    U R                   S   R                  $ r   r  rt   s    r4   r   TensorIndexType.dummy_nameU  r  r3   c                     U R                   S   $ NrA   r  rt   s    r4   rU  TensorIndexType.dimY      yy|r3   c                     U R                   S   $ Nr  r  rt   s    r4   r  TensorIndexType.eps_dim]  r  r3   c                   U R                   S   nU R                   S   nUc  g US:X  a  [        R                  S5      nO7US:X  a  [        R                  S5      nOUS:X  a  [        R                  S5      n[	        X /S-  W5      $ )Nr,      r   rA   re   r   r   )r  r   no_symmetryr   r  )rQ   r  r  r   s       r4   r   TensorIndexType.metrica  s    ))A,iil"a%11!4H!%55a8H"%55b9H+vax::r3   c                J    [        SU /S-  [        R                  S5      5      $ )NKDrA   )r  r   r   rt   s    r4   deltaTensorIndexType.deltaq  s"    $q.*H*H*KLLr3   c                    [        U R                  [        [        45      (       d  g [        R                  U R                  * 5      n[        SU /U R                  -  U5      $ )NEps)r   r  r#   r
   r   r   r  )rQ   r   s     r4   epsilonTensorIndexType.epsilonu  sK    $,,W(=>>!114<<-@%$!4h??r3   c                    Xl         g r]   _metric)rQ   r?  s     r4   
set_metricTensorIndexType.set_metric|  s    r3   c                4    U R                   UR                   :  $ r]   rg   rQ   others     r4   __lt__TensorIndexType.__lt__  s    yy5::%%r3   c                    U R                   $ r]   r  rt   s    r4   r   TensorIndexType.__str__  s    yyr3   c                |    [        5         [        [        5         [        U    sS S S 5        $ ! , (       d  f       g = fr]   r5   r'   r&   _tensor_data_substitution_dictrt   s    r4   r  TensorIndexType.data  %    451$7 655   	-
;c                   [        5         SSKJn  [        R	                  U5      nUR                  5       S:  a  [        S5      eUR                  5       S:X  a  U R                  R                  (       a)  UR                  S   nX0R                  :w  a  [        S5      eUR                  S   nUR                  XD5      n[        U5       H
  u  pgXuXf4'   M     UnUR                  u  pX:w  a  [        S5      eU R                  R                  (       a  U R                  U:w  a  [        S5      eU[        U '   [        R                  U R                  U5        [        [         5         U R#                  5       n
S S S 5        [%        SU 5      n[%        S	U 5      n[        [         5         [        R	                  ['        U5      5      W
" X* 5      l        S S S 5        g ! , (       d  f       Ni= f! , (       d  f       g = f)
Nre   r  rA   z1data have to be of rank 1 (diagonal metric) or 2.r   zDimension mismatchzNon-square matrix tensor.i1i2)r5   r   r2  r   rS  r   ri   rU  rV  rT  zerosrf   r  ri  r   r'   r&   get_kronecker_deltary   r$   r  )rQ   r  r2  nda_dimrU  
newndarrayrY   valdim1dim2r  r  r  s                r4   r  r    s    	1'224899;?PQQ99;!xx!!**Q-hh&$%9::**Q-C.44S>J#D/#&14  *DZZ
<89988xx4 !566/3&t,&66t{{DI45,,.E 6t$t$45":"E"Ec$i"PE"cN 65	 65 65s   $G$+G)
G&)
G7c                    [        5         [        [        5         U [        ;   a  [        U 	 U R                  [        ;   a  [        U R                  	 S S S 5        g ! , (       d  f       g = fr]   r5   r'   r&   r  r   rt   s    r4   r  r    G    4555248{{<<24;;?	 655   7A
A(z
        The TensorIndexType.get_kronecker_delta() method is deprecated. Use
        the TensorIndexType.delta attribute instead.
        r7   z"deprecated-tensorindextype-methodsr  c                P    [        [        S5      5      n[        SU /S-  U5      nU$ )NrA   r  )r   r   r  )rQ   sym2r  s      r4   r  #TensorIndexType.get_kronecker_delta  s-     5a894$40r3   z
        The TensorIndexType.get_epsilon() method is deprecated. Use
        the TensorIndexType.epsilon attribute instead.
        c                    [        U R                  [        [        45      (       d  g [	        [        U R                  S5      5      n[        SU /U R                  -  U5      nU$ )Nre   r  )r   _eps_dimr#   r
   r   r   r  )rQ   r   r  s      r4   get_epsilonTensorIndexType.get_epsilon  sQ     $--*g)>??4T]]AFGUTF4==$8#>r3   c                   U [         ;   a  [         U 	 S nU" U R                  SS45        U" U R                  SS45        U" U R                  SS45        U" U R                  SS45        U R                  5       nU[         ;   a  [         U	 gg)z
EXPERIMENTAL: do not rely on this API method.

This destroys components data associated to the ``TensorIndexType``, if
any, specifically:

* metric tensor data
* Kronecker tensor data
c                P    U [         R                  ;   a  [         R                  U 	 g g r]   )r  r   rH   s    r4   delete_tensmul_dataJTensorIndexType._components_data_full_destroy.<locals>.delete_tensmul_data  s%    4PPP2NNsS Qr3   TFN)r  r   r  )rQ   r  r  s      r4   _components_data_full_destroy-TensorIndexType._components_data_full_destroy  s     11.t4	T
 	T[[$56T[[$67T[[%67T[[%78 ((*22.u5 3r3   r  )NNNre   r   )r   r   r   r   r   r  r  rg   r   rU  r  r(   r   r  r  r  r  r   r   r  setterdeleterr)   r  r  r  r   r2   r3   r4   rH  rH    sY   CJ ?C/7AF ! ! ! !     ; ; M M @ @& H 8 8
 
[["Q "QH 
\\@ @ 	 "'#G
 	 "'#G6r3   rH  c                  d    \ rS rSrSrSS jr\S 5       r\S 5       r\S 5       r	S r
S rS	 rS
rg)ry   i  a  
Represents a tensor index

Parameters
==========

name : name of the index, or ``True`` if you want it to be automatically assigned
tensor_index_type : ``TensorIndexType`` of the index
is_up :  flag for contravariant index (is_up=True by default)

Attributes
==========

``name``
``tensor_index_type``
``is_up``

Notes
=====

Tensor indices are contracted with the Einstein summation convention.

An index can be in contravariant or in covariant form; in the latter
case it is represented prepending a ``-`` to the index name. Adding
``-`` to a covariant (is_up=False) index makes it contravariant.

Dummy indices have a name with head given by
``tensor_inde_type.dummy_name`` with underscore and a number.

Similar to ``symbols`` multiple contravariant indices can be created
at once using ``tensor_indices(s, typ)``, where ``s`` is a string
of names.


Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, TensorIndex, TensorHead, tensor_indices
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> mu = TensorIndex('mu', Lorentz, is_up=False)
>>> nu, rho = tensor_indices('nu, rho', Lorentz)
>>> A = TensorHead('A', [Lorentz, Lorentz])
>>> A(mu, nu)
A(-mu, nu)
>>> A(-mu, -rho)
A(mu, -rho)
>>> A(mu, -mu)
A(-L_0, L_0)
c                n   [        U[        5      (       a  [        U5      nOs[        U[        5      (       a  UnO[USL aK  SR                  [	        UR
                  5      5      n[        U5      nUR
                  R                  U5        O[        S5      e[        U5      n[        R                  " XX#5      $ NTz_i{}invalid namer   r   r   r   rN   r  rj   ri   r   r   r  )r  rg   rW   rh   name_symbols        r4   r  TensorIndex.__new__(  s    dC   ,Kf%%KT\==%6%E%E!FGD ,K,,33K@^,,}}S/@HHr3   c                4    U R                   S   R                  $ rC   r  rt   s    r4   rg   TensorIndex.name7  r  r3   c                     U R                   S   $ r   r  rt   s    r4   rW   TensorIndex.tensor_index_type;  r  r3   c                     U R                   S   $ r  r  rt   s    r4   rh   TensorIndex.is_up?  r  r3   c                J    U R                   nU R                  (       d  SU-  nU$ )Nz-%s)rg   rh   )rQ   ss     r4   _printTensorIndex._printC  s     IIzz	Ar3   c                d    U R                   U R                  4UR                   UR                  4:  $ r]   )rW   rg   r  s     r4   r  TensorIndex.__lt__I  s0    ''3((%**56 	7r3   c                f    [        U R                  U R                  U R                  (       + 5      nU$ r]   )ry   rg   rW   rh   rQ   t1s     r4   __neg__TensorIndex.__neg__M  s(    D$:$:ZZ"	r3   r2   NT)r   r   r   r   r   r  r  rg   rW   rh   r!  r  r(  r   r2   r3   r4   ry   ry     sY    0bI ! !    7r3   ry   c                    [        U [        5      (       a$  [        U SS9 Vs/ s H  o"R                  PM     nnO[	        S5      eU Vs/ s H  n[        XA5      PM     nn[        U5      S:X  a  US   $ U$ s  snf s  snf )ay  
Returns list of tensor indices given their names and their types.

Parameters
==========

s : string of comma separated names of indices

typ : ``TensorIndexType`` of the indices

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> a, b, c, d = tensor_indices('a,b,c,d', Lorentz)
Tseqexpecting a stringre   r   )r   r   r   rg   ri   ry   rN   )r   rn   rE   r   rY   tilists         r4   tensor_indicesr0  S  s|    $ !S$QD121VV12-..+,-1ak!!1F-
6{aayM 3 .s   A6	A;c                      \ rS rSrSrS r\S 5       r\S 5       r\S 5       r	\
S 5       r\
S 5       r\
S	 5       r\
S
 5       rSrg)r   ip  a  
Monoterm symmetry of a tensor (i.e. any symmetric or anti-symmetric
index permutation). For the relevant terminology see ``tensor_can.py``
section of the combinatorics module.

Parameters
==========

bsgs : tuple ``(base, sgs)`` BSGS of the symmetry of the tensor

Attributes
==========

``base`` : base of the BSGS
``generators`` : generators of the BSGS
``rank`` : rank of the tensor

Notes
=====

A tensor can have an arbitrary monoterm symmetry provided by its BSGS.
Multiterm symmetries, like the cyclic symmetry of the Riemann tensor
(i.e., Bianchi identity), are not covered. See combinatorics module for
information on how to generate BSGS for a general index permutation group.
Simple symmetries can be generated using built-in methods.

See Also
========

sympy.combinatorics.tensor_can.get_symmetric_group_sgs

Examples
========

Define a symmetric tensor of rank 2

>>> from sympy.tensor.tensor import TensorIndexType, TensorSymmetry, get_symmetric_group_sgs, TensorHead
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> sym = TensorSymmetry(get_symmetric_group_sgs(2))
>>> T = TensorHead('T', [Lorentz]*2, sym)

Note, that the same can also be done using built-in TensorSymmetry methods

>>> sym2 = TensorSymmetry.fully_symmetric(2)
>>> sym == sym2
True
c                   [        U5      S:X  a  US   u  p4O[        U5      S:X  a  Uu  p4O[        S5      e[        U[        5      (       d  [        U6 n[        U[        5      (       d  [        U6 n[        R
                  " XU40 UD6$ )Nre   r   rA   z:bsgs required, either two separate parameters or one tuple)rN   	TypeErrorr   r   r   r  )r  r  kw_argsr   r   s        r4   r  TensorSymmetry.__new__  s    t9>#AwD*Y!^#D*XYY$&&$<D*e,,
+J}}S
>g>>r3   c                     U R                   S   $ rC   r  rt   s    r4   r   TensorSymmetry.base  r  r3   c                     U R                   S   $ r   r  rt   s    r4   r   TensorSymmetry.generators  r  r3   c                :    U R                   S   R                  S-
  $ )Nr   rA   )r   sizert   s    r4   r   TensorSymmetry.rank  s    q!&&**r3   c                    US:  a  [        US5      nO(US:  a  [        U* S5      nOUS:X  a  / [        S5      /4n[        W5      $ )zj
Returns a fully symmetric (antisymmetric if ``rank``<0)
TensorSymmetry object for ``abs(rank)`` indices.
r   FTre   )r   r   r   )r  r   bsgss      r4   r   TensorSymmetry.fully_symmetric  sO     !8*47DAX*D5$7DQYQ()Dd##r3   c                    / [        S5      /p2U H:  nUS:  a  [        US5      nOUS:  a  [        U* S5      nOM,  [        X#/UQ76 u  p#M<     [        X#5      $ )aF  
Returns a TensorSymmetry object that is being a direct product of
fully (anti-)symmetric index permutation groups.

Notes
=====

Some examples for different values of ``(*args)``:
``(1)``         vector, equivalent to ``TensorSymmetry.fully_symmetric(1)``
``(2)``         tensor with 2 symmetric indices, equivalent to ``.fully_symmetric(2)``
``(-2)``        tensor with 2 antisymmetric indices, equivalent to ``.fully_symmetric(-2)``
``(2, -2)``     tensor with the first 2 indices commuting and the last 2 anticommuting
``(1, 1, 1)``   tensor with 3 indices without any symmetry
re   r   FT)r   r   r   r   )r  r  r   sgsr*  bsgs2s         r4   direct_productTensorSymmetry.direct_product  sg      Q(cCQw/U;q/d;+D>>ID#  d((r3   c                     [        [        5      $ )z4
Returns a monotorem symmetry of the Riemann tensor
)r   r   )r  s    r4   riemannTensorSymmetry.riemann  s    
 l++r3   c                4    [        / [        US-   5      /5      $ )z=
TensorSymmetry object for ``rank`` indices with no symmetry
re   )r   r   )r  r   s     r4   r  TensorSymmetry.no_symmetry  s    
 b;tAv#6"788r3   r2   N)r   r   r   r   r   r  r  r   r   r   classmethodr   rC  rF  r  r   r2   r3   r4   r   r   p  s    .^?     + + $ $ ) )6 , , 9 9r3   r   zf
    The tensorsymmetry() function is deprecated. Use the TensorSymmetry
    constructor instead.
    r7   zdeprecated-tensorsymmetryr  c                 T   SSK Jn  S nU (       d#  [        [        5       [        U" S5      5      5      $ [	        U 5      S:X  a"  [        U S   S   U5      (       a  [        U 5      $ U" U S   5      u  p4U SS  H  nU" U5      u  pg[        X4Xg5      u  p4M     [        [        X45      5      $ )a  
Returns a ``TensorSymmetry`` object. This method is deprecated, use
``TensorSymmetry.direct_product()`` or ``.riemann()`` instead.

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

One can represent a tensor with any monoterm slot symmetry group
using a BSGS.

``args`` can be a BSGS
``args[0]``    base
``args[1]``    sgs

Usually tensors are in (direct products of) representations
of the symmetric group;
``args`` can be a list of lists representing the shapes of Young tableaux

Notes
=====

For instance:
``[[1]]``       vector
``[[1]*n]``     symmetric tensor of rank ``n``
``[[n]]``       antisymmetric tensor of rank ``n``
``[[2, 2]]``    monoterm slot symmetry of the Riemann tensor
``[[1],[1]]``   vector*vector
``[[2],[1],[1]`` (antisymmetric tensor)*vector*vector

Notice that with the shape ``[2, 2]`` we associate only the monoterm
symmetries of the Riemann tensor; this is an abuse of notation,
since the shape ``[2, 2]`` corresponds usually to the irreducible
representation characterized by the monoterm symmetries and by the
cyclic symmetry.
r   r   c                    [        U 5      S:X  a  U S   n[        US5      nU$ [        S U  5       5      (       a  [        U 5      n[        U5      nU$ U SS/:X  a  [        nU$ [        e)Nre   r   c              3  *   #    U  H	  oS :H  v   M     g7f)re   Nr2   r  rE   s     r4   r  7tensorsymmetry.<locals>.tableau2bsgs.<locals>.<genexpr>(  s     %1a61s   rA   )rN   r   r  r   NotImplementedError)r   rk   r>  s      r4   tableau2bsgs$tensorsymmetry.<locals>.tableau2bsgs"  sw    q6Q;!A*1a0D  %1%%%F.q1
 	 q!f#  *)r3   re   rA   N)sympy.combinatoricsr   r   r   rN   r   r   )r  r   rQ  r   rA  r   basexsgsxs           r4   tensorsymmetryrV    s    X 0  egu[^'<==
4yA~*T!WQZ==d##T!W%ID!"X"1o'5?	c  %*++r3   z5TensorType is deprecated. Use tensor_heads() instead.zdeprecated-tensortypec                  b    \ rS rSrSrSrS r\S 5       r\S 5       r	\S 5       r
S rSS	 jrS
rg)
TensorTypei=  a5  
Class of tensor types. Deprecated, use tensor_heads() instead.

Parameters
==========

index_types : list of ``TensorIndexType`` of the tensor indices
symmetry : ``TensorSymmetry`` of the tensor

Attributes
==========

``index_types``
``symmetry``
``types`` : list of ``TensorIndexType`` without repetitions
Fc                z    UR                   [        U5      :X  d   e[        R                  " U [	        U6 U40 UD6nU$ r]   )r   rN   r   r  r   )r  rL   r   r4  r  s        r4   r  TensorType.__new__U  s:    }}K 0000mmC!4hJ'J
r3   c                     U R                   S   $ rC   r  rt   s    r4   rL   TensorType.index_typesZ  r  r3   c                     U R                   S   $ r   r  rt   s    r4   r   TensorType.symmetry^  r  r3   c                >    [        [        U R                  5      S S9$ )Nc                    U R                   $ r]   r  rD   s    r4   rF   "TensorType.types.<locals>.<lambda>d  s    166r3   rH   )r   setrL   rt   s    r4   typesTensorType.typesb  s    c$**+1ABBr3   c                ^    SU R                    Vs/ s H  n[        U5      PM     sn-  $ s  snf )NzTensorType(%s))rL   r   rQ   rE   s     r4   r   TensorType.__str__f  s+    D4D4D#E4DqCF4D#EFF#Es   *c           	     j   [        U[        5      (       a$  [        USS9 Vs/ s H  o3R                  PM     nnO[	        S5      e[        U5      S:X  a%  [        US   U R                  U R                  U5      $ U Vs/ s H$  n[        XPR                  U R                  U5      PM&     sn$ s  snf s  snf )z
Return a TensorHead object or a list of TensorHead objects.

Parameters
==========

s : name or string of names.

comm : Commutation group.

see ``_TensorManager.set_comm``
Tr,  r.  re   r   )	r   r   r   rg   ri   rN   r  rL   r   )rQ   r   r   rE   namesrg   s         r4   r  TensorType.__call__i  s     a%,QD%9:%9VV%9E:E122u:?eAh(8(8$--NNX]^X]PTJt%5%5t}}dKX]^^ ; _s   B+=+B0r2   N)r   )r   r   r   r   r   is_commutativer  r  rL   r   rc  r   r  r   r2   r3   r4   rX  rX  =  s]      N
     C CG_r3   rX  zN
    The tensorhead() function is deprecated. Use tensor_heads() instead.
    zdeprecated-tensorheadc                    Uc%  [        [        U5      5       Vs/ s H  nS/PM     nn[        [        5         [	        U6 nSSS5        [        XX#5      $ s  snf ! , (       d  f       N= f)aG  
Function generating tensorhead(s). This method is deprecated,
use TensorHead constructor or tensor_heads() instead.

Parameters
==========

name : name or sequence of names (as in ``symbols``)

typ :  index types

sym :  same as ``*args`` in ``tensorsymmetry``

comm : commutation group number
see ``_TensorManager.set_comm``
Nre   )r   rN   r'   r&   rV  r  )rg   rn   r   r   rY   s        r4   r;  r;    sX    0 {!#c(O,OqsO,	0	1c" 
2d++ -	1	1s   A	A
A(c                      \ rS rSrSrSrSS jr\S 5       r\S 5       r	\S 5       r
\S	 5       r\S
 5       rS rS rS rS rS r\S 5       r\R&                  S 5       r\R(                  S 5       rS rS rSrg)r  i  a4  
Tensor head of the tensor.

Parameters
==========

name : name of the tensor
index_types : list of TensorIndexType
symmetry : TensorSymmetry of the tensor
comm : commutation group number

Attributes
==========

``name``
``index_types``
``rank`` : total number of indices
``symmetry``
``comm`` : commutation group

Notes
=====

Similar to ``symbols`` multiple TensorHeads can be created using
``tensorhead(s, typ, sym=None, comm=0)`` function, where ``s``
is the string of names and ``sym`` is the monoterm tensor symmetry
(see ``tensorsymmetry``).

A ``TensorHead`` belongs to a commutation group, defined by a
symbol on number ``comm`` (see ``_TensorManager.set_comm``);
tensors in a commutation group have the same commutation properties;
by default ``comm`` is ``0``, the group of the commuting tensors.

Examples
========

Define a fully antisymmetric tensor of rank 2:

>>> from sympy.tensor.tensor import TensorIndexType, TensorHead, TensorSymmetry
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> asym2 = TensorSymmetry.fully_symmetric(-2)
>>> A = TensorHead('A', [Lorentz, Lorentz], asym2)

Examples with ndarray values, the components data assigned to the
``TensorHead`` object are assumed to be in a fully-contravariant
representation. In case it is necessary to assign components data which
represents the values of a non-fully covariant tensor, see the other
examples.

>>> from sympy.tensor.tensor import tensor_indices
>>> from sympy import diag
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> i0, i1 = tensor_indices('i0:2', Lorentz)

Specify a replacement dictionary to keep track of the arrays to use for
replacements in the tensorial expression. The ``TensorIndexType`` is
associated to the metric used for contractions (in fully covariant form):

>>> repl = {Lorentz: diag(1, -1, -1, -1)}

Let's see some examples of working with components with the electromagnetic
tensor:

>>> from sympy import symbols
>>> Ex, Ey, Ez, Bx, By, Bz = symbols('E_x E_y E_z B_x B_y B_z')
>>> c = symbols('c', positive=True)

Let's define `F`, an antisymmetric tensor:

>>> F = TensorHead('F', [Lorentz, Lorentz], asym2)

Let's update the dictionary to contain the matrix to use in the
replacements:

>>> repl.update({F(-i0, -i1): [
... [0, Ex/c, Ey/c, Ez/c],
... [-Ex/c, 0, -Bz, By],
... [-Ey/c, Bz, 0, -Bx],
... [-Ez/c, -By, Bx, 0]]})

Now it is possible to retrieve the contravariant form of the Electromagnetic
tensor:

>>> F(i0, i1).replace_with_arrays(repl, [i0, i1])
[[0, -E_x/c, -E_y/c, -E_z/c], [E_x/c, 0, -B_z, B_y], [E_y/c, B_z, 0, -B_x], [E_z/c, -B_y, B_x, 0]]

and the mixed contravariant-covariant form:

>>> F(i0, -i1).replace_with_arrays(repl, [i0, -i1])
[[0, E_x/c, E_y/c, E_z/c], [E_x/c, 0, B_z, -B_y], [E_y/c, -B_z, 0, B_x], [E_z/c, B_y, -B_x, 0]]

Energy-momentum of a particle may be represented as:

>>> from sympy import symbols
>>> P = TensorHead('P', [Lorentz], TensorSymmetry.no_symmetry(1))
>>> E, px, py, pz = symbols('E p_x p_y p_z', positive=True)
>>> repl.update({P(i0): [E, px, py, pz]})

The contravariant and covariant components are, respectively:

>>> P(i0).replace_with_arrays(repl, [i0])
[E, p_x, p_y, p_z]
>>> P(-i0).replace_with_arrays(repl, [-i0])
[E, -p_x, -p_y, -p_z]

The contraction of a 1-index tensor by itself:

>>> expr = P(i0)*P(-i0)
>>> expr.replace_with_arrays(repl, [])
E**2 - p_x**2 - p_y**2 - p_z**2
FNc           	     X   [        U[        5      (       a  [        U5      nO#[        U[        5      (       a  UnO[        S5      eUc  [        R                  [        U5      5      nOUR                  [        U5      :X  d   e[        R                  " X[        U6 U[        U5      5      nU$ )Nr  )r   r   r   ri   r   r  rN   r   r   r  r   r   )r  rg   rL   r   r   r  r  s          r4   r  TensorHead.__new__  s    dC   ,Kf%%K^,,%11#k2BCH==C$4444mmCe[.A8WUY][
r3   c                4    U R                   S   R                  $ rC   r  rt   s    r4   rg   TensorHead.name!  r  r3   c                2    [        U R                  S   5      $ r   r   r  rt   s    r4   rL   TensorHead.index_types%  s    DIIaL!!r3   c                     U R                   S   $ r  r  rt   s    r4   r   TensorHead.symmetry)  r  r3   c                F    [         R                  U R                  S   5      $ r  )r   r  r  rt   s    r4   r   TensorHead.comm-  s    ++DIIaL99r3   c                ,    [        U R                  5      $ r]   )rN   rL   rt   s    r4   r   TensorHead.rank1  s    4##$$r3   c                d    U R                   U R                  4UR                   UR                  4:  $ r]   )rg   rL   r  s     r4   r  TensorHead.__lt__5  s+    		4++,

E<M<M/NNNr3   c                Z    [         R                  U R                  UR                  5      nU$ )z
Returns ``0`` if ``self`` and ``other`` commute, ``1`` if they anticommute.

Returns ``None`` if ``self`` and ``other`` neither commute nor anticommute.
)r   r   r   )rQ   r  rs      r4   commutes_withTensorHead.commutes_with8  s#     ""499ejj9r3   c           
         U R                   < SSR                  U R                   Vs/ s H  n[        U5      PM     sn5      < S3$ s  snf )N(,))rg   joinrL   r   rf  s     r4   r!  TensorHead._printA  s8    ))SXXt?O?O.P?O!s1v?O.P%QRR.Ps   Ac           	        / n[        XR                  5       H  u  pE[        U[        5      (       aq  UR	                  5       R                  SS5      nUR                  S5      (       a  UR                  [        USS USS95        Mo  UR                  [        XE5      5        M  UR                  U5        M     X1[        U5      S -  n[        X40 UD6nUR                  5       $ )a  
Returns a tensor with indices.

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

There is a special behavior in case of indices denoted by ``True``,
they are considered auto-matrix indices, their slots are automatically
filled, and confer to the tensor the behavior of a matrix or vector
upon multiplication with another tensor containing auto-matrix indices
of the same ``TensorIndexType``. This means indices get summed over the
same way as in matrix multiplication. For matrix behavior, define two
auto-matrix indices, for vector behavior define just one.

Indices can also be strings, in which case the attribute
``index_types`` is used to convert them to proper ``TensorIndex``.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorSymmetry, TensorHead
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> a, b = tensor_indices('a,b', Lorentz)
>>> A = TensorHead('A', [Lorentz]*2, TensorSymmetry.no_symmetry(2))
>>> t = A(a, -b)
>>> t
A(a, -b)

  -re   NFrh   )r   rL   r   r   stripreplace
startswithrj   ry   rN   r  doit)rQ   rM   r4  updated_indicesrz   rn   r?  s          r4   r  TensorHead.__call__D  s    > G%5%56HC#s##iik))#r2>>#&&#**;s12w16,8 9 $**;s+@A&&s+ 7 	3#7#89999{{}r3   c           	        [        5         [        [        5         U R                  c  [	        S5      eSSKJnJn  U R                   Vs/ s H  oDR                  PM     nnU R                  nUR                  5       nU H   nU" XhU5      nU" USU4US-   US-   45      nM"     Xa[        R                  -  -  sS S S 5        $ s  snf ! , (       d  f       g = f)NzNo power on abstract tensors.re   rl  r   rA   )r5   r'   r&   r  ri   r   r0  r1  rL   r   r   Half)	rQ   r  r0  r1  r   metricsmarray	marraydimr   s	            r4   __pow__TensorHead.__pow__v  s    45yy  !@AA?'+'7'78'7!vv'7G8YYFI!&vv>*6Ay>IaKQZ[\Q\C]^ " affn- 65 9	 65s   /C	C AC C
Cc                |    [        5         [        [        5         [        U    sS S S 5        $ ! , (       d  f       g = fr]   r  rt   s    r4   r  TensorHead.data  r  r  c                |    [        5         [        [        5         U[        U '   S S S 5        g ! , (       d  f       g = fr]   r  rQ   r  s     r4   r  r    (    4537*40 655   
-
;c                <    [        5         U [        ;   a  [        U 	 g g r]   )r5   r  rt   s    r4   r  r    s    11.t4 2r3   c                    [        5         [        [        5         U R                  R	                  5       sS S S 5        $ ! , (       d  f       g = fr]   r5   r'   r&   r  __iter__rt   s    r4   r  TensorHead.__iter__  -    4599%%' 655	   >
Ac                ^    [        5         U R                  S:X  a  gU [        ;   a  [        U 	 gg)z
EXPERIMENTAL: do not rely on this API method.

Destroy components data associated to the ``TensorHead`` object, this
checks for attached components data, and destroys components data too.
r  N)r5   rg   r  rt   s    r4   r  (TensorHead._components_data_full_destroy  s1     	99
 11.t4 2r3   r2   rC   )r   r   r   r   r   rk  r  r  rg   rL   r   r   r   r  r  r!  r  r  r  r  r  r  r  r   r2   r3   r4   r  r    s    n^ N  ! ! " "   : : % %OS.d.  8 8
 
[[8 8
 
\\5 5
(
5r3   r  c           	        [        U [        5      (       a$  [        U SS9 Vs/ s H  oDR                  PM     nnO[	        S5      eU Vs/ s H  n[        XaX#5      PM     nn[        U5      S:X  a  US   $ U$ s  snf s  snf )z5
Returns a sequence of TensorHeads from a string `s`
Tr,  r.  re   r   )r   r   r   rg   ri   r  rN   )r   rL   r   r   rE   ri  rg   thlists           r4   tensor_headsr    s     !S!(!56!5A!56-..HMNjH;FN
6{aayM 7 Os   A7	A<c                  r   \ rS rSrSrSrSrS rS rS r	S r
S	 rS
 rS rS rS rS rS rS r\\S 5       5       r\\S 5       5       r\S 5       r\S'S j5       r\S(S j5       rS rS r\S 5       rS rS rS r \S 5       r!\S 5       r"\S 5       r#\S 5       r$\S  5       r%S)S" jr&S# r'S$ r(S*S% jr)S&r*g!)+r  i  a  
Abstract base class for tensor expressions

Notes
=====

A tensor expression is an expression formed by tensors;
currently the sums of tensors are distributed.

A ``TensExpr`` can be a ``TensAdd`` or a ``TensMul``.

``TensMul`` objects are formed by products of component tensors,
and include a coefficient, which is a SymPy expression.


In the internal representation contracted indices are represented
by ``(ipos1, ipos2, icomp1, icomp2)``, where ``icomp1`` is the position
of the component tensor with contravariant index, ``ipos1`` is the
slot which the index occupies in that component tensor.

Contracted indices are therefore nameless in the internal representation.
g      (@Fc                (    U [         R                  -  $ r]   )r   NegativeOnert   s    r4   r(  TensExpr.__neg__  s    AMM!!r3   c                    [         er]   rP  rt   s    r4   __abs__TensExpr.__abs__      !!r3   c                2    [        X5      R                  SS9$ NFdeepr  r  r  s     r4   __add__TensExpr.__add__  s    t#((e(44r3   c                2    [        X5      R                  SS9$ r  r  r  s     r4   __radd__TensExpr.__radd__      u#((e(44r3   c                4    [        X* 5      R                  SS9$ r  r  r  s     r4   __sub__TensExpr.__sub__  s    tV$))u)55r3   c                4    [        X* 5      R                  SS9$ r  r  r  s     r4   __rsub__TensExpr.__rsub__  s    ue$))u)55r3   c                2    [        X5      R                  SS9$ )a!  
Multiply two tensors using Einstein summation convention.

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

If the two tensors have an index in common, one contravariant
and the other covariant, in their product the indices are summed

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz)
>>> g = Lorentz.metric
>>> p, q = tensor_heads('p,q', [Lorentz])
>>> t1 = p(m0)
>>> t2 = q(-m0)
>>> t1*t2
p(L_0)*q(-L_0)
Fr  r  r  r  s     r4   __mul__TensExpr.__mul__  s    . t#((e(44r3   c                2    [        X5      R                  SS9$ r  r  r  s     r4   __rmul__TensExpr.__rmul__  r  r3   c                    [        U5      n[        U[        5      (       a  [        S5      e[	        U [
        R                  U-  5      R                  SS9$ )Ncannot divide by a tensorFr  )r!   r   r  ri   r  r   Oner  r  s     r4   __truediv__TensExpr.__truediv__	  sG    eX&&899tQUU5[)..E.::r3   c                    [        S5      e)Nr  )ri   r  s     r4   __rtruediv__TensExpr.__rtruediv__  s    455r3   c           	        [        5         [        [        5         U R                  c  [	        S5      eSSKJnJn  U R                  nU R                  nUR                  5       nU H6  nU" U" UUS   R                  R                  U5      SU4US-   US-   45      nM8     XQ[        R                  -  -  sS S S 5        $ ! , (       d  f       g = f)NzNo power without ndarray data.re   rl  r   rA   )r5   r'   r&   r  ri   r   r0  r1  rJ   r   rW   r   r  )rQ   r  r0  r1  rJ   r  rm  r   s           r4   r  TensExpr.__pow__  s    45yy  !ABB?99DYYF;;=D*!1I//44 IQQ/  affn- 655s   BB==
Cc                    [         er]   r  r  s     r4   __rpow__TensExpr.__rpow__%  r  r3   c                    [        S5      eNzabstract methodr  rt   s    r4   nocoeffTensExpr.nocoeff(       ""344r3   c                    [        S5      er  r  rt   s    r4   r'  TensExpr.coeff-  r  r3   c                    [        S5      er  r  rt   s    r4   ru   TensExpr.get_indices2      !"344r3   c                    [        S5      er  r  rt   s    r4   r   TensExpr.get_free_indices6  r  r3   c                    [        S5      er  r  rQ   repls     r4   _replace_indicesTensExpr._replace_indices:  r  r3   c                4    [        5         U R                  " U6 $ r]   )r9   substitute_indices)rQ   index_tupless     r4   fun_evalTensExpr.fun_eval>  s    &&55r3   c                X   SSK Jn  [        5         [        [        5         SU R
                  s=:  a  S::  a  O  OU R                  R                  S   nU R
                  S:X  a  U R                  R                  S   OSnU R
                  S:X  aR  / U-  n[        U5       H=  nUR                  / 5        [        U5       H  nXE   R                  XU4   5        M     M?     OS/U-  n[        U5       H	  nX   XE'   M     U" U5      sSSS5        $ [        S5      e! , (       d  f       g= f)z
DEPRECATED: do not use.

Returns ndarray components data as a matrix, if components data are
available and ndarray dimension does not exceed 2.
r   )MatrixrA   re   Nz-missing multidimensional reduction to matrix.)sympy.matrices.denser  r5   r'   r&   r   r  rT  r   rj   rP  )rQ   r  rowscolumnsmat_listrY   r   s          r4   
get_matrixTensExpr.get_matrixB  s     	045499!!yyq)04		Q$))//!,A99>!DyH"4[ +!&wA$K..tqDz: "0 )
 !%v}H"4[&*g )h' 65  *CE E! 65s   C&DD
D)c                N    U Vs/ s H  o R                  U5      PM     sn$ s  snf r]   rm   )indices1indices2rY   s      r4   _get_indices_permutation!TensExpr._get_indices_permutation^  s!    +348aq!8444s   "c                    [        5       nU R                   H9  n[        U[        5      (       d  M  UR	                  UR                  5       5        M;     U$ r]   )rb  r  r   r  update_get_free_indices_setrQ   indsetr*  s      r4   r  TensExpr._get_free_indices_setb  s@    99C#x((c779:  r3   c                    [        5       nU R                   H9  n[        U[        5      (       d  M  UR	                  UR                  5       5        M;     U$ r]   )rb  r  r   r  r  _get_dummy_indices_setr   s      r4   r  TensExpr._get_dummy_indices_seti  s@    99C#x((c88:;  r3   c                    [        5       nU R                   H9  n[        U[        5      (       d  M  UR	                  UR                  5       5        M;     U$ r]   )rb  r  r   r  r  _get_indices_setr   s      r4   r  TensExpr._get_indices_setp  s@    99C#x((c2245  r3   c                F   ^^ U R                  5       mUU4S jmT" U S5      $ )Nc              3     >#    [        U [        5      (       a  U T;   a  X4v   g g [        U [        [        45      (       a3  [	        U R
                  5       H  u  p#T" X1U4-   5       S h  vN   M     g g  N
7fr]   r   ry   r   r  rf   r  )exprrq   pr*  	dummy_setrecursors       r4   r  1TensExpr._iterate_dummy_indices.<locals>.recursor{  sk     $,,9$+% %D5("344'		2FA'!X666 3 56   A'A7*A5+A7r2   )r  )rQ   r  r  s    @@r4   _iterate_dummy_indicesTensExpr._iterate_dummy_indicesw  s%    //1		7 b!!r3   c                F   ^^ U R                  5       mUU4S jmT" U S5      $ )Nc              3     >#    [        U [        5      (       a  U T;   a  X4v   g g [        U [        [        45      (       a3  [	        U R
                  5       H  u  p#T" X1U4-   5       S h  vN   M     g g  N
7fr]   r  )r  rq   r  r*  free_setr  s       r4   r  0TensExpr._iterate_free_indices.<locals>.recursor  sk     $,,8#+% $D5("344'		2FA'!X666 3 56r  r2   )r  )rQ   r  r  s    @@r4   _iterate_free_indicesTensExpr._iterate_free_indices  s%    --/	7 b!!r3   c                "   ^ U4S jmT" U S5      $ )Nc              3     >#    [        U [        5      (       a  X4v   g [        U [        [        45      (       a3  [	        U R
                  5       H  u  p#T" X1U4-   5       S h  vN   M     g g  N
7fr]   r  )r  rq   r  r*  r  s       r4   r  +TensExpr._iterate_indices.<locals>.recursor  s^     $,,k!D5("344'		2FA'!X666 3 56s   A A0#A.$A0r2   r2   )rQ   r  s    @r4   _iterate_indicesTensExpr._iterate_indices  s    	7 b!!r3   c                    SSK JnJnJn  U" U" X5      SSU-   45      n[	        [        U5      5      nXr   US   sUS'   Xr'   U" X5      $ )Nre   )r1  r0  r  rA   r   )r   r1  r0  r  r   r   )r   r   rq   rU  r1  r0  r  permus           r4   !_contract_and_permute_with_metric*TensExpr._contract_and_permute_with_metric  sU     	IH!-">AcE
KU3Z $z58a%*5((r3   c           	        SSK Jn  U Vs/ s H  oUR                  PM     nn/ n/ nUS S  n	[        U5       H  u  pX;   a  U	R	                  U5      nS X'   M!  U* U	;   aQ  U	R	                  U* 5      nS X'   XU'   UR
                  (       a  UR                  U5        Mf  UR                  U5        My  X   nUc  [        SU< SU< 35      eS X'   XU
'   UR
                  UR
                  -  (       d  M  UR
                  (       a  UR                  U
5        M  UR                  U
5        M     [        [        U5      [        U5      -  5      [        U5      :  a  [        SU< SU< 35      eU HP  nXn   nX;  a  [        S5      eX?   n[        R                  U5      n[        R                  UX[        U5      5      n MR     U H;  nXn   nX;  a  [        S5      eX?   n[        R                  UX[        U5      5      n M=     U(       a  [        R                  X!5      nU" U U5      n [        U S5      (       a  U R!                  5       S:X  a  U S   n X 4$ s  snf )	Nre   r  zincompatible indices: z and z!No metric provided to lower indexr   r   r2   )r   r  rW   rf   rm   rh   rj   ri   rN   rb  r   ru  r  r!  r  r  r   )r   	free_ind1	free_ind2replacement_dictr  rY   index_types1pos2uppos2downfree2remainingr|   index1r}   index2rq   index_type_posr   metric_inverser   s                      r4    _match_indices_with_other_tensor)TensExpr._match_indices_with_other_tensor  s3   &5>?Y++Y? "1%i0LD'%++F3'+$w.(%++VG4'+$"($<<MM$'OOD)'->$)U^%_``'+$"($<<&,,..||d+ -/ 12 s9~I./#i.@)YWXX C).N5 !DEE%5F5DDVLN>>~u[^_h[ijE  C).N5 !DEE%5F>>vuSVW`SabE  ";;IQK{3E5&!!ejjla&7"IEs @s   INc           	        SSK Jn  U=(       d    / nU R                  5        Vs0 s H3  oDR                  (       a  UR                  S   OUR                  S   * U_M5     nn[        U5       H7  u  pg[        U[        [        45      (       d  M"  Xu;   a  XW   X&'   M/  XW*    * X&'   M9     UR                  5        VV	s0 s H  u  pX" U	5      _M     nnn	UR                  5        H  u  p[        U[        5      (       a%  [        S5       Vs/ s H  ohR                  PM     n
nO%UR                   Vs/ s H  oR                  PM     n
n[        U
5      U	R                  5       :w  d-  [!        S [#        U
U	R$                  5       5       5      (       a  M  ['        SU< SU
< SU	R$                  < 35      e   U R)                  U5      u  pU R+                  XX5      u  pU	$ s  snf s  sn	nf s  snf s  snf )	a  
Replace the tensorial expressions with arrays. The final array will
correspond to the N-dimensional array with indices arranged according
to ``indices``.

Parameters
==========

replacement_dict
    dictionary containing the replacement rules for tensors.
indices
    the index order with respect to which the array is read. The
    original index order will be used if no value is passed.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices
>>> from sympy.tensor.tensor import TensorHead
>>> from sympy import symbols, diag

>>> L = TensorIndexType("L")
>>> i, j = tensor_indices("i j", L)
>>> A = TensorHead("A", [L])
>>> A(i).replace_with_arrays({A(i): [1, 2]}, [i])
[1, 2]

Since 'indices' is optional, we can also call replace_with_arrays by
this way if no specific index order is needed:

>>> A(i).replace_with_arrays({A(i): [1, 2]})
[1, 2]

>>> expr = A(i)*A(j)
>>> expr.replace_with_arrays({A(i): [1, 2]})
[[1, 2], [2, 4]]

For contractions, specify the metric of the ``TensorIndexType``, which
in this case is ``L``, in its covariant form:

>>> expr = A(i)*A(-i)
>>> expr.replace_with_arrays({A(i): [1, 2], L: diag(1, -1)})
-3

Symmetrization of an array:

>>> H = TensorHead("H", [L, L])
>>> a, b, c, d = symbols("a b c d")
>>> expr = H(i, j)/2 + H(j, i)/2
>>> expr.replace_with_arrays({H(i, j): [[a, b], [c, d]]})
[[a, b/2 + c/2], [b/2 + c/2, d]]

Anti-symmetrization of an array:

>>> expr = H(i, j)/2 - H(j, i)/2
>>> repl = {H(i, j): [[a, b], [c, d]]}
>>> expr.replace_with_arrays(repl)
[[0, b/2 - c/2], [-b/2 + c/2, 0]]

The same expression can be read as the transpose by inverting ``i`` and
``j``:

>>> expr.replace_with_arrays(repl, [j, i])
[[0, -b/2 + c/2], [b/2 - c/2, 0]]
re   Arrayr   rA   c              3  T   #    U  H  u  pUR                   (       a  X:H  OS v   M      g7f)TN)rV  )r  r  r  s      r4   r  /TensExpr.replace_with_arrays.<locals>.<genexpr><	  s0      ?<ZT @D|$(@)<s   &(zshapes for tensor z expected to be z, replacement array shape is )r   r3  r   rh   r  rf   r   r   r   itemsrH  r   rU  rL   rN   r   r  r   rT  ri   _extract_datar/  )rQ   r&  rM   r3  kremaprY   rm   r?  r   expected_shape
index_typeret_indiceslast_indicess                 r4   replace_with_arraysTensExpr.replace_with_arrays  s   D 	!-RBFBWBWBYZBYQggAFF1I:q8BYZ!'*HA%&#//>!&GJ"'-GJ + GWF\F\F^_F^]VFE%L0F^_ .335MF&/226;Ah!?h**h!?CICUCU!VCUZ..CU!V>"ejjl23 ?;>~<? < < !7=~KK"! " " 6 "//0@A"CCET_r5 [ `
 "@!Vs   :G9GG%-G*c                    SSK Jn  U R                  5       nU R                  nU VVs/ s H%  u  pgX&   SXF   R                  R
                  S-
  4PM'     nnnU(       a	  U" U/UQ76 nU$ s  snnf )Nr   Sumre   )sympy.concrete.summationsrB  ru   rK   rW   rU  )	rQ   r  index_symbolsrB  rM   rK   rY   r   sum_indicess	            r4   _check_add_SumTensExpr._check_add_SumH	  s}    1""$hh<?A<?DA ')1J((,,Q.0<? 	 At*k*D	As   ,A)c           	         U R                   " U R                   Vs/ s H*  n[        U[        5      (       a  UR	                  5       OUPM,     sn6 $ s  snf r]   )funcr  r   r  _expand_partial_derivative)rQ   r   s     r4   rJ  #TensExpr._expand_partial_derivativeR	  s]     yy "YY( ' "!X.. 002456&( ) 	) (s   1Ac                D   Uc  0 nOUR                  5       n[        U[        5      (       d  [        U R	                  5       5      S:  a  gO5[        U R	                  5       5      [        UR	                  5       5      :w  a  g[        X-
  5      [        R                  :X  a  U$ g)z5
Matches assuming there are no wild objects in self.
Nr   )	r~  r   r  rN   r   rb  rR   r   ZerorQ   r  	repl_dictr  s       r4   _matches_simpleTensExpr._matches_simpleZ	  s     I!(I$))4((*+a/ 0 &&()S1F1F1H-IIDK AFF*r3   r2   r   r  zdict[TensorIndex, TensorIndex]r   r  r]   NF)+r   r   r   r   r   _op_priorityrk  r(  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r'  ru   r   r  r  r  r   r  r  r  r  r  r  r  r!  r/  r>  rF  rJ  rP  r   r2   r3   r4   r  r    sl   . LN""5566525;6.&" 5  5 5  5 5 5 5 5 5 56E8 5 5 " " " " " " ) ) <  < |_B)r3   r  c                  l   \ rS rSrSrS r\S 5       r\S 5       rS"S jr	S#S jr
\S 5       r\S	 5       r\S
 5       rS$S jr\S 5       r\S 5       r\S 5       rS rS rS rS rS rS rS rS rS rS r\S 5       r\R>                  S 5       r\R@                  S 5       rS r!S r"S r#S%S  jr$S!r%g)&r  iq	  a|  
Sum of tensors.

Parameters
==========

free_args : list of the free indices

Attributes
==========

``args`` : tuple of addends
``rank`` : rank of the tensor
``free_args`` : list of the free indices in sorted order

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_heads, tensor_indices
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> a, b = tensor_indices('a,b', Lorentz)
>>> p, q = tensor_heads('p,q', [Lorentz])
>>> t = p(a) + q(a); t
p(a) + q(a)

Examples with components data added to the tensor expression:

>>> from sympy import symbols, diag
>>> x, y, z, t = symbols("x y z t")
>>> repl = {}
>>> repl[Lorentz] = diag(1, -1, -1, -1)
>>> repl[p(a)] = [1, 2, 3, 4]
>>> repl[q(a)] = [x, y, z, t]

The following are: 2**2 - 3**2 - 2**2 - 7**2 ==> -58

>>> expr = p(a) + q(a)
>>> expr.replace_with_arrays(repl, [a])
[x + 1, y + 2, z + 3, t + 4]
c                ,   U Vs/ s H  o3(       d  M  [        U5      PM     nn[        R                  U5      nUR                  [        S9  U(       d  [
        R                  $ [        U5      S:X  a  US   $ [        R                  " U /UQ70 UD6$ s  snf )NrH   re   r   )
r!   r  _tensAdd_flattenrP   r   r   rM  rN   r   r  )r  r  r4  rE   s       r4   r  TensAdd.__new__	  s{    %)/TQT/''-		&	'66Mt9>7N}}S343733 0s
   
BBc                "    [         R                  $ r]   r   r  rt   s    r4   r'  TensAdd.coeff	      uur3   c                    U $ r]   r2   rt   s    r4   r  TensAdd.nocoeff	      r3   c                    U R                   $ r]   )free_indicesrt   s    r4   r   TensAdd.get_free_indices	  s       r3   c                    U R                    Vs/ s H+  n[        U[        5      (       a  UR                  U5      OUPM-     nnU R                  " U6 $ s  snf r]   )r  r   r  r  rI  )rQ   r  r*  newargss       r4   r  TensAdd._replace_indices	  sQ    _c_h_hi_hX[C1J1J3''-PSS_hiyy'"" js   2Ac                z    [        U R                  S   [        5      (       a  U R                  S   R                  $ grC   )r   r  r  r   rt   s    r4   r   TensAdd.rank	  s.    diilH--99Q<$$$r3   c                |    [        U R                  S   [        5      (       a  U R                  S   R                  $ / $ rC   )r   r  r  r!  rt   s    r4   r!  TensAdd.free_args	  s0    diilH--99Q<)))Ir3   c                    [        U R                  S   [        5      (       a  U R                  S   R                  5       $ [	        5       $ rC   )r   r  r  r   rb  rt   s    r4   ra  TensAdd.free_indices	  s5    diilH--99Q<00225Lr3   c                \   UR                  SS5      nU(       a,  U R                   Vs/ s H  o3R                  " S0 UD6PM     nnOU R                  nU Vs/ s H  o3[        R                  :w  d  M  UPM     nn[        U5      S:X  a  [        R                  $ [        U5      S:X  a  US   $ [        R                  U5        [        R                  U5      nS nUR                  US9  U(       d  [        R                  $ [        U5      S:X  a  US   $ U R                  " U6 nU$ s  snf s  snf )Nr  Tr   re   c                    [        U [        5      (       d  / / / 4$ [        U S5      (       a?  [        U S5      (       a.  [        U 5      nU R                  UR
                  UR                  4$ / / / 4$ )N_index_structurer`   )r   r  r  get_index_structurer`   rJ   rK   )r   rE   s     r4   sort_keyTensAdd.doit.<locals>.sort_key	  sd    a**2rz!q,--'!\2J2J'*||QVVQUU22r2:r3   rH   r2   )r  r  r  r   rM  rN   r  _tensAdd_check_tensAdd_collect_termsrP   rI  )rQ   hintsr  r*  r  rp  r  s          r4   r  TensAdd.doit	  s    yy&15;#HH%u%D;D99D  $5taff}t5t9>66MY!^7N 	t$ --d3	 			h	66Mt9>7Nii
G <
 6s   D$D)1D)c                   / nU  HU  n[        U[        [        45      (       a&  UR                  [	        UR
                  5      5        MD  UR                  U5        MW     U Vs/ s H  o"R                  (       d  M  UPM     n nU $ s  snf r]   )r   r   r  r^   r   r  rj   r'  )r  r   rE   s      r4   rW  TensAdd._tensAdd_flatten	  sg     A!c7^,,aff&	 
 (1a1( )s   "B:Bc                   ^ SS jnU" U S   5      mU SS   Vs/ s H
  o!" U5      PM     nn[        U4S jU 5       5      (       d  [        S5      eg s  snf )Nc                r    [        U [        5      (       a  [        U R                  5       5      $ [        5       $ r]   )r   r  rb  r   rD   s    r4   get_indices_set/TensAdd._tensAdd_check.<locals>.get_indices_set
  s*    !X&&1--/005Lr3   r   re   c              3  ,   >#    U  H	  oT:H  v   M     g 7fr]   r2   )r  rE   indices0s     r4   r  )TensAdd._tensAdd_check.<locals>.<genexpr>	
  s     7,Q=,s   z&all tensors must have the same indices)rE   r   r   zset[TensorIndex])r  ri   )r  rz  r*  list_indicesr}  s       @r4   rr  TensAdd._tensAdd_check	  s_    	
 #47+8<QRA,A7,777EFF 8 Bs   Ac           	        [        [        5      n[        R                  n[	        U S   [
        5      (       a  [        U S   R                  5       5      nO
[        5       nU  H  n[	        U[
        5      (       d  U[        5       :w  a  [        S5      eX$-  nM7  U[        UR                  5       5      :w  a  [        S5      eXR                     R                  UR                  5        M     UR                  5        VVs/ s H2  u  pV[        U6 S:w  d  M  [        [        U6 U5      R                  SS9PM4     nnn[	        U[        5      (       a  [        UR                   5      U-   nU$ US:w  a  U/U-   nU$ s  snnf )Nr   zwrong valenceFr  )r	   r   r   rM  r   r  rb  r   ri   r  rj   r'  r6  r   r  r  r  )r  
terms_dictscalarsra  r*  r   r'  new_argss           r4   rs  TensAdd._tensAdd_collect_terms
  sO    !&
&&d1gx((tAw779:L5LCc8,,35($_55s3#7#7#9:: 11 {{#**3995  NXM]M]M_tM_cfhmcnrscs<GCK+00e0<M_tgs##GLL)H4H  \y8+H us   >E7#E7c                    / nU R                    H5  nUR                  [        U5       Vs/ s H  o3U;  d  M
  UPM     sn5        M7     U$ s  snf r]   )r  r^   ru   )rQ   rM   r*  rY   s       r4   ru   TensAdd.get_indices)
  sG    99CNN{3'7L'7!G;KA'7LM  Ms
   	A

A

c                   [        5         U R                  n[        U5      nU Vs/ s H  o3R                  PM     snU Vs/ s H  o3R                  PM     sn:w  a  [	        S5      eX:X  a  U $ [        [        X!5      5      nU R                   Vs/ s H(  o3R                  " UR                  " U6 R                  6 PM*     nn[        U6 R                  SS9nU$ s  snf s  snf s  snf )Nincompatible typesFr  )r<   r!  r   rW   ri   r   r  rI  r  r  r  )rQ   rM   r!  rE   r  r   ress          r4   r  TensAdd.__call__0
  s    NN	w-)01A1S\5]S\a6I6IS\5]]122KC	34HL		R	1VVQ))<8==>	RqkE*
 25]
 Ss   CC/C"c                    U R                  5       n[        XR                  5      (       a<  UR                   Vs/ s H  n[	        U5      PM     nn[        U6 R                  SS9nU$ [	        U5      $ s  snf )zb
Canonicalize using the Butler-Portugal algorithm for canonicalization
under monoterm symmetries.
Fr  )expandr   rI  r  rR   r  r  )rQ   r  rE   r  r  s        r4   rR   TensAdd.canon_bp=
  se    
 {{}dII&&)-3AHQKD34.%%5%1CJD>!	 4s   A2c                <   [        U5      n[        U[        5      (       a,  UR                  S:X  a  [	        S U R
                   5       5      $ [        U[        5      (       a  U R                  UR                  :w  a  g[        U[        5      (       a.  [        U R
                  5      [        UR
                  5      :w  a  ggX-
  n[        U[        5      (       d  US:H  $ [        U[        5      (       a  UR                  S:H  $ [	        S UR
                   5       5      $ )Nr   c              3  >   #    U  H  oR                   S :H  v   M     g7fr   Nr'  rN  s     r4   r  !TensAdd.equals.<locals>.<genexpr>M
  s     7Yww!|Y   FTc              3  >   #    U  H  oR                   S :H  v   M     g7fr  r  rN  s     r4   r  r  ]
  s     8A77a<r  )
r!   r   r  r'  r  r  r  r   r  rb  )rQ   r  r   s      r4   equalsTensAdd.equalsJ
  s    eW%%%++*:7TYY777eX&&yyEJJ&eW%%499~UZZ0L!X&&6M!W%%ww!|#8888r3   c                    [        5         [        [        5         U R                  U   sS S S 5        $ ! , (       d  f       g = fr]   r5   r'   r&   r  rQ   items     r4   r  TensAdd.__getitem___
  (    4599T? 655	   3
Ac                    U R                    Vs/ s H+  n[        U[        5      (       a  UR                  U5      OUPM-     nn[	        U6 R                  SS9n[        U5      $ s  snf r  )r  r   r  contract_deltar  r  rR   )rQ   r  rE   r  r   s        r4   r  TensAdd.contract_deltad
  sa    SWS\S\]S\a:a+B+B  'IS\]TNU+{ ^s   2A#c                    U R                    Vs/ s H  n[        X!5      PM     nn[        U6 R                  SS9n[	        U5      $ s  snf )z
Raise or lower indices with the metric ``g``.

Parameters
==========

g :  metric

contract_all : if True, eliminate all ``g`` which are contracted

Notes
=====

see the ``TensorIndexType`` docstring for the contraction conventions
Fr  )r  contract_metricr  r  rR   )rQ   r   rE   r  r   s        r4   r  TensAdd.contract_metrici
  sG    " 04yy9y!%y9TNU+{ :s   Ac                    / nU R                    H8  n[        U[        5      (       a  UR                  " U6 nUR	                  U5        M:     [        U6 R                  SS9$ r  )r  r   r  r  rj   r  r  rQ   r  r  r*  s       r4   r  TensAdd.substitute_indices~
  Y    99C#x((,,l;OOC   !&&E&22r3   c                    / nU R                   nU H  nUR                  [        U5      5        M     SR                  U5      nUR	                  SS5      nU$ )Nz + z+ -z- )r  rj   r   r  r  )rQ   r   r  rE   r   s        r4   r!  TensAdd._print
  sL    yyAHHSV JJqMIIeT"r3   c           	        SSK JnJn  [        U R                   Vs/ s H-  n[        U[        5      (       a  UR                  U5      O/ U4PM/     sn6 u  pVU Vs/ s H
  or" U5      PM     nnUS   n[        S[        U5      5       H*  nXW   n	Xg   n
[        R                  X5      nU" X5      Xg'   M,     U[        XbR                  " W
R                  6 5      4$ s  snf s  snf )Nr   )r3  r  re   )sympy.tensor.arrayr3  r  r   r  r   r  r7  r   rN   r  r  sumr  rT  )rQ   r&  r3  r  r*  args_indicesr5  rY   ref_indicesrM   r   r   s               r4   r7  TensAdd._extract_data
  s    9"@D		%
@IJsH%% ./,.95@I%
   %++Fq%(F+"1oq#l+,A"oGIE!::7PK#E7FI	 -
 CU[[(ABBB%
 ,s   4CCc                    [        5         [        [        5         [        U R	                  5          sS S S 5        $ ! , (       d  f       g = fr]   r5   r'   r&   r  r  rt   s    r4   r  TensAdd.data
  s+    451$++-@ 655s	   ;
A	c                |    [        5         [        [        5         U[        U '   S S S 5        g ! , (       d  f       g = fr]   r  r  s     r4   r  r  
  r  r  c                    [        5         [        [        5         U [        ;   a  [        U 	 S S S 5        g ! , (       d  f       g = fr]   r  rt   s    r4   r  r  
  s.    4555248 655s	   5
Ac                    [        5         U R                  (       d  [        S5      eU R                  R                  5       R	                  5       $ Nz No iteration on abstract tensors)r5   r  ri   flattenr  rt   s    r4   r  TensAdd.__iter__
  s7    yy?@@yy  "++--r3   c                .    [         R                  " U5      $ r]   )r   fromiter)rQ   r  r  s      r4   _eval_rewrite_as_Indexed TensAdd._eval_rewrite_as_Indexed
  s    ||D!!r3   c                8   / nU R                    Hm  n[        U[        5      (       a"  UR                  UR	                  U5      5        M:  UR
                  (       d  MM  UR                  UR                  U5      5        Mo     U R                  " U6 R                  SS9$ r  )	r  r   r  rj   _eval_partial_derivative	_diff_wrt_eval_derivativerI  r  )rQ   r   list_addendsr   s       r4   r   TensAdd._eval_partial_derivative
  s|    A!X&&##A$>$>q$AB##A$6$6q$9:  yy,',,%,88r3   Nc                v   [        U5      nUc  0 nOUR                  5       n[        U[        5      (       d  g [	        [        U 5      5      S:X  a  U R                  XU5      $ S n[        U R                  U5      n[        UR                  U5      n/ nUS    HZ  nSn	US    HC  n
X;   a  M
  UR                  XUS9nUc  M  Sn	UR                  U5        UR                  U
5          O   U	(       a  MZ    g    US    Vs/ s H  oU;  d  M
  UPM     nnUS    Hr  nU Hi  nUR                  U5      nUc  M  UR                  U5        XR                  5       ;   a  X.==   UR                  U5      -  ss'   UR                  U5        Mk     Mt     US    Vs/ s H  oU;  d  M
  UPM     nnUS    H  nU H  nUR                  U5      nUc  M  UR                  U5        UR                  UR                  5       ;   a/  X.R                  ==   UR                  UR                  5      -  ss'   UR                  U5        M     M     US    Vs/ s H  oU;  d  M
  UPM     nnUS	    H  nU H  nUR                  U5      nUc  M  UR                  U5        UR                  UR                  5       ;   a/  X.R                  ==   UR                  UR                  5      -  ss'   UR                  U5        M     M     US    Vs/ s H  oU;  d  M
  UPM     nn[	        U5      S:  a  g U$ s  snf s  snf s  snf s  snf )
Nr   c                    [        U 5      n[        U[        5      n[        U5      S:X  a  g[        UR                  5       ;   a,  US    H"  n[        UR                  5       5      S:X  d  M"    g   gg)Nr   nonwild
WildTensorindexless_wildtensor
wildtensor	otherwild)
_get_wildsr*   typerN   r  keysru   )r*  	wildatomswildatom_typesws       r4   siftkey TensAdd.matches.<locals>.siftkey
  sd    "3I!)T2N9~" ~2244'5A1==?+q05 6 $"r3   r  F)rO  r  Tr  r  r  )r   r~  r   r  rN   r  rP  r*   r  matchesr  rj   r  popra   )rQ   r  rO  r  r  query_siftedexpr_siftedmatched_e_tensorsq_tensormatched_this_qe_tensorrg  r   remaining_e_tensorsr  es                   r4   r  TensAdd.matches
  s   t}I!(I$((z$ A%''==	# DIIw/499g. $Y/H"N'	20$$X$L9%)N$$Q'%,,X6 3 ">! 0$ +6i*@_*@QM^D^q*@_k*A(IIaL=%,,Q/NN,,!a0$$Q' ) + +6i*@_*@QM^D^q*@_l+A(IIaL=%,,Q/{{inn&66!++.!%%2DD.$$Q' ) , +6i*@_*@QM^D^q*@_45A(IIaL=%,,Q/{{inn&66!++.!%%2DD.$$Q' ) 6 +6i*@_*@QM^D^q*@_"#a'E ` ` ` `s0   =	L'
L'	L,!L,
	L1L1 	L6L6r2   r   rR  )r   r   rS  )&r   r   r   r   r   r  r  r'  r  r   r  r(   r   r!  ra  r  r   rW  rr  rs  ru   r  rR   r  r  r  r  r  r!  r7  r  r  r  r  r  r  r  r   r2   r3   r4   r  r  q	  sM   'R	4    !#      &P 	 	 G G  8"9*#

*3C A A
 
[[8 8
 
\\9 9."
9Tr3   r  c                  ~   \ rS rSr% SrSrS\S'   S\S'   SS.S	 jr\S
 5       r	\S 5       r
\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       rS r\S 5       rS=S jrSS.S jrS rS rS r\S 5       r\S 5       r\S  5       r S! r!S=S" jr"S# r#S$ r$S% r%S>S& jr&S>S' jr'S?S( jr(S) r)S* r*S+ r+S@S- jr,S@S. jr-S/ r.S0 r/S1 r0S2 r1\S3 5       r2\2Rf                  S4 5       r2\2Rh                  S5 5       r2S6 r5S7 r6S8 r7S9 r8S: r9SAS; jr:S<r;g,)Br  i  a!  
Base tensor class, i.e. this represents a tensor, the single unit to be
put into an expression.

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

This object is usually created from a ``TensorHead``, by attaching indices
to it. Indices preceded by a minus sign are considered contravariant,
otherwise covariant.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorHead
>>> Lorentz = TensorIndexType("Lorentz", dummy_name="L")
>>> mu, nu = tensor_indices('mu nu', Lorentz)
>>> A = TensorHead("A", [Lorentz, Lorentz])
>>> A(mu, -nu)
A(mu, -nu)
>>> A(mu, -mu)
A(L_0, -L_0)

It is also possible to use symbols instead of inidices (appropriate indices
are then generated automatically).

>>> from sympy import Symbol
>>> x = Symbol('x')
>>> A(x, mu)
A(x, mu)
>>> A(x, -x)
A(L_0, -L_0)

Fr>   rn  ztuple[TensorHead, Tuple]r  r   c               0   U R                  X5      n[        R                  " X[        U6 40 UD6n[        R
                  " U6 Ul        UR                  R                  S S  Ul        UR                  R                  S S  Ul
        UR                  R                  Ul        [        R                  Ul        XUl        Xl        U/Ul        UR$                  ['        U5      :w  a  [)        S5      eX5l        [,        R/                  X%R                  5      Ul        U$ )Nwrong number of indices)_parse_indicesr   r  r   r>   rZ   rn  rJ   _freerK   _dumrO   r   r  _coeff_nocoeff
_component_componentsr   rN   ri   r   r  _build_index_map
_index_map)r  tensor_headrM   r   r4  r  s         r4   r  Tensor.__new__F  s    $$[:mmCeWoII.;;WE((--a0	''++A.,,66UU
$&-s7|+677%00:N:NO
r3   c                    U R                   $ r]   r  rt   s    r4   rJ   Tensor.freeW  r  r3   c                    U R                   $ r]   r  rt   s    r4   rK   
Tensor.dum[  s    yyr3   c                    U R                   $ r]   rO   rt   s    r4   r  Tensor.ext_rank_  s    ~~r3   c                    U R                   $ r]   r  rt   s    r4   r'  Tensor.coeffc  s    {{r3   c                    U R                   $ r]   )r  rt   s    r4   r  Tensor.nocoeffg  s    }}r3   c                    U R                   $ r]   )r  rt   s    r4   ra   Tensor.componentk  s    r3   c                    U R                   $ r]   )r  rt   s    r4   r`   Tensor.componentso  s    r3   c                     U R                   S   $ rC   r  rt   s    r4   headTensor.heads  r  r3   c                     U R                   S   $ r   r  rt   s    r4   rM   Tensor.indicesw  r  r3   c                H    [        U R                  R                  5       5      $ r]   )rb  rn  r   rt   s    r4   ra  Tensor.free_indices{  s    4((99;<<r3   c                .    U R                   R                  $ r]   )r   rL   rt   s    r4   rL   Tensor.index_types  s    yy$$$r3   c                ,    [        U R                  5      $ r]   )rN   ra  rt   s    r4   r   Tensor.rank  s    4$$%%r3   c                D    0 nU  H  nU R                  U5      4X#'   M     U$ r]   r  )rM   index_structure	index_maprz   s       r4   r  Tensor._build_index_map  s*    	C%mmC02IN r3   c                >    [         R                  U /5      u  p#pEUS   $ rC   )r  _tensMul_contract_indices)rQ   rt  r  rM   rJ   rK   s         r4   r  Tensor.doit  s"    #*#D#DdV#L tAwr3   c           	     R   [        U[        [        [        45      (       d  [	        S[        U5      -  5      e[        U5      n[        U5       H  u  p#[        U[        5      (       a  [        X0R                  U   S5      X'   M7  [        U[        5      (       aX  UR                  5       u  pEUS:X  a2  [        U[        5      (       a  [        XPR                  U   S5      X'   M  [        SU-  5      e[        U[        5      (       a  M  [	        SU< S[        U5      < 35      e   U$ )Nz"indices should be an array, got %sTr   Fzindex not understood: %szwrong type for index: z is )r   r   r   r   r3  r  rf   r   ry   rL   r   as_coeff_Mulri   )r  rM   rY   rm   r  r  s         r4   r  Tensor._parse_indices  s    'E4#788@4=PQQw-!'*HA%(((0G0G0JDQ
E3''))+7z!V44!,Q0G0G0JE!RGJ$%?%%GHH{33E4PU; WXX + r3   c                F    UR                  5       nU R                  " USU06$ Nr   ru   _set_indicesrQ   imr   rM   s       r4   _set_new_index_structureTensor._set_new_index_structure  $    .."  'C{CCr3   c                   [        U5      U R                  :w  a  [        S5      eU R                  U R                  S   X!S9R                  5       $ )Nindices length mismatchr   r  )rN   r  ri   rI  r  r  )rQ   r   rM   r4  s       r4   r  Tensor._set_indices  sB    w<4==(677yy1wyHMMOOr3   c                ^    U R                   R                   Vs1 s H  oS   iM	     sn$ s  snf rC   )rn  rJ   r  s     r4   r  Tensor._get_free_indices_set  s*    "338898!8999s   *c                    [        [        R                  " U R                  R                  6 5      n[        U R                  S   5       VVs1 s H  u  p#X!;   d  M  UiM     snn$ s  snnf r   )rb  	itertoolschainrn  rK   rf   r  rQ   	dummy_posrY   rz   s       r4   r  Tensor._get_dummy_indices_set  sN    	)>)>)B)BCD	"+DIIaL"9L"9Q^"9LLLs   A%A%c                F    [        U R                  S   R                  5      $ r   )rb  r  rt   s    r4   r  Tensor._get_indices_set  s    499Q<$$%%r3   c                T    U R                    VVs/ s H	  u  pXS4PM     snn$ s  snnf rC   rJ   )rQ   r   rq   s      r4   free_in_argsTensor.free_in_args  s$    .2ii8i(#1i888s   $c                V    U R                    VVs/ s H
  u  pXSS4PM     snn$ s  snnf rC   )rK   )rQ   p1p2s      r4   dum_in_argsTensor.dum_in_args  s&    -1XX6X62AX666s   %c                \    [        U R                   Vs/ s H  oS   PM	     sn5      $ s  snf rC   r   rf  s     r4   r!  Tensor.free_args  %    TYY/YtY/00/   )c                    [        U[        5      (       d  g[        U[        5      (       a%  U R                  R	                  UR                  5      $ [
        $ )zd
:param other:
:return:
    0  commute
    1  anticommute
    None  neither commute nor anticommute
r   )r   r  r  ra   r  rP  r  s     r4   r  Tensor.commutes_with  s@     %**v&&>>//@@""r3   c                    [        XU5      $ )z
Returns the tensor corresponding to the permutation ``g``.

For further details, see the method in ``TIDS`` with the same name.
r   rQ   r   r   s      r4   r   Tensor.perm2tensor  s     4K00r3   c                   U R                   (       a  U $ U R                  5       nUR                  R                  5       u  p#n[	        UR
                  /5      n[        X#U/UQ76 nUS:X  a  [        R                  $ U R                  US5      nU$ )Nr   T)
r   r  rn  r   r   ra   r   r   rM  r   )rQ   r  r   r   r   r   canr?  s           r4   rR   Tensor.canon_bp  s}    K{{}00CCED!4>>"231t0a0!866M!!#t,r3   c                    U /$ r]   r2   rt   s    r4   r   Tensor.split  s	    vr3   c                    U $ r]   r2   rt   s    r4   sorted_componentsTensor.sorted_components  s    r3   c                2    [        U R                  S   5      $ )z>
Get a list of indices, corresponding to those of the tensor.
re   rs  rt   s    r4   ru   Tensor.get_indices  s     DIIaL!!r3   c                6    U R                   R                  5       $ )zC
Get a list of free indices, corresponding to those of the tensor.
rn  r   rt   s    r4   r   Tensor.get_free_indices  s     $$5577r3   c                $    U R                  U5      $ r]   xreplacer  s     r4   r  Tensor._replace_indices  s     }}T""r3   c                &    U [         R                  4$ r]   rZ  rt   s    r4   as_base_expTensor.as_base_exp  s    QUU{r3   c                p   / nU R                    H  nU H|  u  pEUR                  UR                  :X  d  M!  UR                  UR                  :X  d  M=  UR                  UR                  :X  a  UR	                  U5        OUR	                  U* 5          M     UR	                  U5        M     U R
                  " U6 $ )a-  
Return a tensor with free indices substituted according to ``index_tuples``.

``index_types`` list of tuples ``(old_index, new_index)``.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads, TensorSymmetry
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> i, j, k, l = tensor_indices('i,j,k,l', Lorentz)
>>> A, B = tensor_heads('A,B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
>>> t = A(i, k)*B(-k, -j); t
A(i, L_0)*B(-L_0, -j)
>>> t.substitute_indices((i, k),(-j, l))
A(k, L_0)*B(-L_0, l)
)rM   rg   rW   rh   rj   r   )rQ   r  rM   rm   ind_oldind_news         r4   r  Tensor.substitute_indices  s    $ \\E$0 JJ',,.53J3J3:3L3L4M{{gmm3w/x0 %1 u% " yy'""r3   c                   U R                   nUR                  R                  nUR                  nSnU 1nXT:w  a  UR	                  5       nU H  nU H  nUR                  5       n[        SU5       V	s/ s H  oR                  U	5      PM     n
n	SUR                  U5      U-
  -  n[        [        X V	s/ s H  oU	   PM	     sn	5      5      nUR                  XR                  U5      -  5        M     M     XT:w  a  M  U$ s  sn	f s  sn	f )z\
Return a list giving all possible permutations of self that are allowed by its symmetries.
Nr   r   )ra   r   r   r   r~  ru   r   applydictr   addr  )rQ   compgensr   	old_perms	new_permsrJ  genindsrY   persignind_maps                r4   _get_symmetrized_formsTensor._get_symmetrized_forms  s     ~~}}''yy	F	$!(I!C++-D16q?A99Q<C?#))D/D"89D"3ts-Cs!1gs-C#DEGMM4*?*?*H#HJ   " $  @-Cs   1C>2DNc                4   [        U5      nUc  0 nOUR                  5       nX:X  a  U$ [        U[        5      (       d  g U R                  UR                  :w  a  g UR                  5        H+  nU R                  XBUS9nUc  M  UR                  U5        Us  $    g )Nr  )r   r~  r   r  r   rb  _matchesr  )rQ   r  rO  r  new_exprrg  s         r4   r  Tensor.matches5  s    t}I!(I <$''99		! 335Hhs;A}  #  	 6 r3   c                    [        U5      nUc  0 nOUR                  5       nX:X  a  U$ [        U[        5      (       d  gU R                  UR                  :w  a  gU R                  5       nUR                  5       n[        U5      [        U5      :w  a  g[        [        U5      5       HS  nXF   nUR                  XV   5      nUc    gU* UR                  5       ;   a  X'*    * X   :w  a    gUR                  U5        MU     U$ )z4
This does not account for index symmetries of expr
N)r   r~  r   r  r   ru   rN   r   r  r  r  )	rQ   r  rO  r  	s_indices	e_indicesrY   s_indrg  s	            r4   rf  Tensor._matchesN  s     t}I!(I <$''99		!$$&	$$&	y>S^+s9~&ALEil+Ay9>>++61B0Bah0N  # ' r3   c                   [        5         U R                  n[        U5      nU Vs/ s H  o3R                  PM     snU Vs/ s H  o3R                  PM     sn:w  a  [	        S5      eX:X  a  U $ U R
                  " [        [        X!5      5      6 n[        U Vs1 s H  oUR                  (       a  UOU* iM     sn5      [        U5      :w  a  UR                  " UR                  6 $ U$ s  snf s  snf s  snf Nr  r<   r!  r   rW   ri   r  r   rN   rh   rI  r  rQ   rM   r!  rE   r   rY   s         r4   r  Tensor.__call__s      NN	w-)01A1S\5]S\a6I6IS\5]]122K##T#i*A%BC g6gWW1"$g673w<G66166?" 25] 7   C&C+C0c                    [        5         [        [        5         U R                  R	                  5       sS S S 5        $ ! , (       d  f       g = fr]   r  rt   s    r4   r  Tensor.__iter__  r  r  c                    [        5         [        [        5         U R                  U   sS S S 5        $ ! , (       d  f       g = fr]   r  r  s     r4   r  Tensor.__getitem__  r  r  c           
        SSK Jn  UR                  5        HB  u  p4[        U[        5      (       d  M  UR
                  S   U R
                  S   :X  d  M>  UnUn  O   [        U < SU< 35      eUR                  5        VVs0 s H  u  p4X2" U5      _M     nnnU" U5      nU R                  nUR                  n[        U5      S:  a5  U H  n	X;  d  M
  [        SU-  5      e   U V	s/ s H  oU;  d  M
  U	PM     nn	[        U5      S:  a  U R                  5       n
UR                  5       n0 nU H  u  pX   * XU   '   X4 H|  nX   R                  X   R                  -  (       d  M'  XU   R                     nX   R                  (       a  [        R                  U5      nU R                  UXo[        U5      5      nM~     M     UR!                  U5      R#                  5       n[        R%                  U/U[        U5      5      nU R'                  5       nUR'                  5       nU R)                  UUUU5      $ s  snnf s  sn	f )Nre   r2  r   z not found in z'%s with contractions is not implemented)r   r3  r6  r   r  r  ri   rK   rN   rP  ru   rh   rW   r   ru  r!  rL  r  r  r   r/  )rQ   r&  r3  r8  r   r  r   dum1dum2pairr  r  r  r/  r0  rq   r   r$  r%  s                      r4   r7  Tensor._extract_data  s    $**,DA!V$$diil)B	 - T;KLMM 5E4J4J4LM4LDAAuQxK4LMexxyyt9q=#-.WZ_._`` 
 &*>TT-=DTD>t9q='')H((*HD&.l]b\"8C}**X]-@-@@@!13-2Q2Q!R#=..%=%L%LV%TF $ F Fvu[^_g[h i $  NN4(--/E,>>wcRZm\E))+	**,	44UIyRbcc? N ?s   H:(	I 5I c                |    [        5         [        [        5         [        U    sS S S 5        $ ! , (       d  f       g = fr]   r  rt   s    r4   r  Tensor.data  r  r  c                |    [        5         [        [        5         U[        U '   S S S 5        g ! , (       d  f       g = fr]   r  r  s     r4   r  r    s(    4537*40 655r  c                    [        5         [        [        5         U [        ;   a  [        U 	 U R                  [        ;   a  [        U R                  	 S S S 5        g ! , (       d  f       g = fr]   r   rt   s    r4   r  r    r  r  c                    U R                    Vs/ s H  n[        U5      PM     nnU R                  nUR                  S:  a#  UR                  < SSR                  U5      < S3$ SUR                  -  $ s  snf )Nr   r  z, r  z%s)rM   r   ra   r   rg   r  )rQ   r   rM   ra   s       r4   r!  Tensor._print  s_    '+||4|3s8|4NN	>>A )		'0BCD9>>)* 5s   A4c                    US:X  a  U R                   S:H  $ [        U5      n[        U[        5      (       d&  U R                  (       a   e[
        R                  U:H  $ S nU" U 5      U" U5      :H  $ )Nr   c                    U R                  5       nUR                  [        UR                  5      [        [	        UR
                  5      5      [        [	        UR                  5      5      4nU$ r]   )rR   r'  r   r`   r   rJ   rK   )rQ   r   r~  s      r4   _get_compar_comp'Tensor.equals.<locals>._get_compar_comp  sK    A%-&.)5+?AAHr3   )r'  r!   r   r  r`   r   r  )rQ   r  r  s      r4   r  Tensor.equals  se    A:::?"%**&&55E>!	  %)9%)@@@r3   c                
   U R                   U:w  a  U $ [        U R                  5      S:w  a  U $ UR                  [        R                  S5      :X  a  SnORUR                  [        R                  S5      :X  a  SnO,UR                  [        R                  S5      :X  a  S nO[        e[        R                  nUR                  S   nU(       d  X4R                  -  nU$ X4R                  -  nU R                  S   u  pVXV:  a  U* nU$ )Nr   r   re   rA   )ra   rN   rJ   r   r   r   r  rP  r   r  rL   rU  rK   )rQ   r   antisymr`  rn   dp0dp1s          r4   r  Tensor.contract_metric  s    >>QKtyy>QK ::77;;GZZ>99!<<GZZ>55a88G%%uummA<D  <Dxx{HCyur3   c                $    U R                  U5      $ r]   r  )rQ   r   s     r4   r  Tensor.contract_delta  s    ##F++r3   c                    SSK Jn  U R                  5        Vs/ s H  oUR                  S   PM     nnU" UR                  S   /UQ76 nU R	                  Xv5      $ s  snf )Nr   )Indexed)sympy.tensor.indexedr  ru   r  rF  )rQ   rJ  rM   r  r  rY   rD  r  s           r4   r  Tensor._eval_rewrite_as_Indexed  sX    0,0,<,<,>?,>q,>?tyy|4m4""477 @s   Ac                   [        U[        5      (       d  [        R                  $ U R                  UR                  :w  a  [        R                  $ S/n[        [        U R                  5       UR                  5       5      5       H  u  nu  pEUR                  UR                  :w  a  [        S5      eUR                  nUR                  n[        S[        U5      -   UUR                  S9nUR                  UR                  :X  a  UR                  XE* 5      n	O$[        U" XH5      UR                  U* U* 5      5      n	UR!                  U	5        M     [        R#                  U5      R%                  SS9$ )Nre   zindex types not compatibled_r  Fr  )r   r  r   rM  r   rf   r   r   rW   ri   r   ry   r   rh   r  r  rj   r  r  )
rQ   r   kronecker_delta_listcountiselfiotherrW   tensor_metricdummykroneckerdeltas
             r4   r  Tensor._eval_partial_derivative  sE   !V$$66M yyAFF"vv %&3  -6c$:O:O:QSTSeSeSg6h,i(**f.F.FF$%ABB(-(?(?%$5$<$<M's5z(9;L.3kk;E{{fll2):)@)@)P $M%$?$5$;$;UFVG$LN ' )//? -j  ##$89>>E>JJr3   r2   r   r   rR  rS  )r   r  r   r   )<r   r   r   r   r   rk  r  r  r  rJ   rK   r  r'  r  ra   r`   r   rM   ra  rL   r   r   r  r  r  r  r  r  r  r  r,  r1  r!  r  r   rR   r   rC  ru   r   r  rO  r  rb  r  rf  r  r  r  r7  r  r  r  r!  r  r  r  r  r  r   r2   r3   r4   r  r    s]   !F N%%
"":? "                     = = % % & &    "D 27 P
:M& 9 9 7 7 1 1#1
"8#
#@,2#J"(#
*dX 8 8
 
[[8 8 
\\@ @+A  D,8)Kr3   r  c                     \ rS rSr% Sr\R                  rS\S'   S r	\
" S 5      r\
" S 5      r\
" S 5      r\
" S	 5      r\
" S
 5      r\
" S 5      r\S 5       r\S 5       r\SBS j5       r\S 5       r\S 5       rS r\S 5       r\S 5       rS rS rS r\
S 5       r\
S 5       r\
S 5       r\
S 5       r \
S 5       r!\
S 5       r"S r#S r$SCS jr%SDS  jr&S! r'S" r(S# r)S$ r*S% r+S& r,S' r-SES) jr.S* r/S+ r0S, r1S- r2SES. jr3S(S/.S0 jr4\S1 5       r5S2 r6S3 r7S4 r8\
S5 5       r9\9Rt                  S6 5       r9\9Rv                  S7 5       r9S8 r<\S9 5       r=S: r>S; r?S< r@S= rASFS? jrBSFS@ jrCSArDg>)Gr  iB  a  
Product of tensors.

Parameters
==========

coeff : SymPy coefficient of the tensor
args

Attributes
==========

``components`` : list of ``TensorHead`` of the component tensors
``types`` : list of nonrepeated ``TensorIndexType``
``free`` : list of ``(ind, ipos, icomp)``, see Notes
``dum`` : list of ``(ipos1, ipos2, icomp1, icomp2)``, see Notes
``ext_rank`` : rank of the tensor counting the dummy indices
``rank`` : rank of the tensor
``coeff`` : SymPy coefficient of the tensor
``free_args`` : list of the free indices in sorted order
``is_canon_bp`` : ``True`` if the tensor in in canonical form

Notes
=====

``args[0]``   list of ``TensorHead`` of the component tensors.

``args[1]``   list of ``(ind, ipos, icomp)``
where ``ind`` is a free index, ``ipos`` is the slot position
of ``ind`` in the ``icomp``-th component tensor.

``args[2]`` list of tuples representing dummy indices.
``(ipos1, ipos2, icomp1, icomp2)`` indicates that the contravariant
dummy index is the ``ipos1``-th slot position in the ``icomp1``-th
component tensor; the corresponding covariant index is
in the ``ipos2`` slot position in the ``icomp2``-th component tensor.

r>   rn  c           	        UR                  SS5      n[        [        [        U5      5      n U Vs/ s H  n[	        U5      PM     nn[        [        R                  " U6 5      n/ nU H  n[        [        U5      5      nU Vs/ s H  n[        U5      PM     n	n[        [        R                  " U	6 5      n	[        [	        U5      5      n
[        UR                  U5      5      S:  a'  U
R                  XY5      n[        R                  XK5      nOUnUR                  U5        M     UnU VVs/ s H6  n[        U[        [         45      (       a  UR"                  OU/  H  oPM     M8     nnn[        R%                  USS9u  pp_U Vs/ s H  oR&                  PM     nn[)        X_UXS9n[*        R,                  " U /UQ76 nUUl        UR1                  5       Ul        UUl        UR6                  S S  Ul        UR:                  S S  Ul        UR6                   Vs1 s H  nUS   iM
     snUl        [        UR6                  5      Ul         [        UR4                  R6                  5      S[        UR4                  R:                  5      -  -   Ul!        [D        RF                  Ul$        UUl%        U$ s  snf s  snf s  snnf s  snf s  snf )Nr   Fr   )replace_indicesrR   rA   )&r  r   r3  r!   r   rb  r#  r$  get_dummy_indicesrN   intersectionunionr  _dedupe_indicesrj   r   r   r  r  rW   r>   r  r  _indicesr~  _index_typesrn  rJ   r  rK   r  _free_indices_rankrO   r   r  r  _is_canon_bp)r  r  r4  r   r*  rJ   rd  dum_thisr   	dum_other	free_thisexcludenewargrY   rM   rK   rL   r  r  rE   s                       r4   r  TensMul.__new__m  so   kk-7C$'(	 266# %69??D)*C,S12H7>?w!*1-wI?IOOY78I,S12I8((./!3#//$: 00>NN6"   "dTc
3RU8W8WCHH^a]b,ba,bTd#*#D#DT[`#D#a t 5<<Gq**G<)$['`s*T*&++-.#((+	"&&q)+.8848aQqT84M	C005563s?S?S?W?W;X9XXUU
&
K 7
 @ e
 = 5s   J0J5-=J:K Kc                    U R                   $ r]   )r  rt   s    r4   rF   TensMul.<lambda>  s
    (9(9r3   c                    U R                   $ r]   r  rt   s    r4   rF   r        r3   c                    U R                   $ r]   r  rt   s    r4   rF   r    s    		r3   c                    U R                   $ r]   r  rt   s    r4   rF   r    s
    ););r3   c                    U R                   $ r]   )r  rt   s    r4   rF   r    r  r3   c                    U R                   $ r]   r  rt   s    r4   rF   r    s    T^^r3   c           	        0 n0 n/ n/ nSn[        U 5       H  u  pgU H  n[        U[        5      (       d  [        S5      eU* U;   aq  UR	                  U* 5      n	UR	                  U* 5      n
UR
                  (       a  UR                  XXU
45        OUR                  U* XX45        UR                  U5        O,X;   a  [        SU-  5      eXaU'   XRU'   UR                  U5        US-  nM     M     [        UR                  5       5      nUR                  5        Vs/ s H  oR                  PM     nnUR                  S S9  XKX4$ s  snf )Nr   zexpected TensorIndexzRepeated index: %sre   c                    U S   $ r  r2   rD   s    r4   rF   .TensMul._indices_to_free_dum.<locals>.<lambda>  s    adr3   rH   )rf   r   ry   r3  r  rh   rj   ri   r   r6  r  rg   rP   )r  	free2pos1	free2pos2
dummy_datarM   r}   r|   arg_indicesrm   
other_pos1
other_pos2rJ   rY   
free_namess                 r4   _indices_to_free_dumTensMul._indices_to_free_dum  sG   		
 !*<!8D$!%55#$:;;6Y&!*v!6J!*v!6J{{"))5
**UV"))E6:Z*VWNN5)'$%9E%ABB'+e$'+e$NN5)	% % "9, IOO%&&/nn&67&6ff&6
7N+j44 8s   Ec                T    U  VVVVVs/ s H
  u  pp4oTU4PM     snnnnn$ s  snnnnnf r]   r2   )r  rY   p1ap1bp2ap2bs         r4   _dummy_data_to_dumTensMul._dummy_data_to_dum  s#    :DE*6#c
*EEEs   !c                  ^ U  Vs/ s H  n0 PM     nnU  Vs/ s H  n[        U5      PM     nn[        R                  U5      u  pgp[        [        5      mU4S jn
U(       a  U	 H_  u  ppnUR
                  n U
" U5      nUU;  a  OM  UR                  " UU/UR                  SS  Q76 nUX<   U'   U* X=   U* '   UXn'   U* Xo'   Ma     [        X5       VVs/ s H.  u  nn[        U[        5      (       a  UR                  U5      OUPM0     n nn U  Vs/ s H  n[        U5      PM     nn[        R                  U5      u  pgp[        R                  U	5      nXUU4$ s  snf s  snf s  snnf s  snf )Nc                ^   > [        TU    5      nTU ==   S-  ss'   U R                  S-   U-   $ r   r   r   s     r4   r   9TensMul._tensMul_contract_indices.<locals>.dummy_name_gen  r   r3   rA   )ru   r  r  r	   r   rW   rI  r  r   r   r  r  r  )r  r  r   replacementsr*  r  rM   rJ   r  r  r   	old_indexpos1cov
pos1contrapos2cov
pos2contrar;  r   r  r  rK   r   s                        @r4   r  !TensMul._tensMul_contract_indices  s   $()DqD) 599DSC(D9070L0L\0Z-z#	;
 GQC	J&88
!/
!;J!3  "z:S	qr@RS38%i08=v()4#( ',f# HR "%T!8:!8IC /9h.G.G$$T*SP!8  : 9==K,L=4;4P4PQ]4^1G:((4dC''M * :,: >s   EE!5E&E,c                    / nU  HL  n[        U[        5      (       d  M  [        U[        5      (       a  M1  UR                  UR                  5        MN     U$ )zY
Get a list of ``Tensor`` objects having the same ``TIDS`` if multiplied
by one another.
)r   r  r  r^   r`   )r  r`   r*  s      r4   _get_components_from_args!TensMul._get_components_from_args   sM     
Cc8,,#w''cnn-  r3   c                    UR                  5       nSn[        U 5       HF  u  pE[        U[        5      (       d  M  UnX5R                  -  n[        UR                  X&U 5      X'   MH     g rC   )ru   rf   r   r  r  r  ra   )r  r  rM   ind_posrY   r*  prev_poss          r4   _rebuild_tensors_listTensMul._rebuild_tensors_list  s]    !--/oFAc8,,H||#GS]]GW,EFDG &r3   c           
        U R                   nUR                  SS5      nU(       a{  U R                   Vs/ s H  oDR                  " S0 UD6PM     nn [	        [        U R                  U5      5      nU R                  U5      nU R                   Vs/ s H  ovU   PM	     nnOU R                  nU Vs/ s H  oDU R                  :w  d  M  UPM     nn[        S U Vs/ s H  n[        U[        5      (       a  M  UPM     sn[        R                  5      nU Vs/ s H  n[        U[        5      (       d  M  UPM     nn[        U5      S:X  a  U$ XR                  :w  a  U/U-   nUS:X  a  [        R                  $ [        U5      S:X  a  US   $ [        R!                  U5      u  pYpU	 Vs/ s H  oR"                  PM     nn[%        XXUS9nU R&                  " U6 nXl        Xl        [        UR*                  R,                  5      S[        UR*                  R.                  5      -  -   Ul        Xl        X/l         U$ s  snf s  snf s  snf s  snf s  snf s  snf )	Nr  Tc                
    X-  $ r]   r2   r   bs     r4   rF   TensMul.doit.<locals>.<lambda>1  s    ACr3   r   re   r  rA   r2   )r  r  r  r  rW  r   _dedupe_indices_in_ruleidentityr   r   r  r   r  rN   rM  r  r  rW   r>   rI  r  rn  rJ   rK   rO   r  )rQ   rt  r   r  r*  r  ruler   r'  rM   rJ   rK   rY   rL   r  r  s                   r4   r  TensMul.doit  s   ''yy&15;#HH%u%D; DIIt,-D//5D%)YY/YGYD/D 99D#<tdmm';t< ')_#ZPSU]E^#)_abafafg#Atz#x'@tAt9>LMM!7T>DA:66Mt9>7N#*#D#DT#J t 5<<Gq**G<)$[T_`ii&.C005563s?S?S?W?W;X9XX
&
Y < 0
 = *`A  =s5   H;I 1III

8I

I5I)Ic                b    [        U /[         R                  XU5      Q70 UD6R                  SS9$ r  )r  %_get_tensors_from_components_free_dumr  )r'  r`   rJ   rK   r4  s        r4   	from_dataTensMul.from_dataO  s;    uowLLZ_bcognottzt  A  	Ar3   c                    [         R                  XU5      nUR                  5       nU  Vs/ s H  nSPM     nnSn[        U 5       H$  u  pXUn	XxR                  -  n[        XX 5      Xe'   M&     U$ s  snf )zf
Get a list of ``Tensor`` objects by distributing ``free`` and ``dum`` indices on the ``components``.
Nr   )r>   rb   ru   rf   r   r  )
r`   rJ   rK   r  rM   rY   tensorsr  ra   r  s
             r4   r  -TensMul._get_tensors_from_components_free_dumS  s    
 *BB:UXY!--/!+,A4, %j1LAH~~%G	8+DEGJ 2  -s   A0c                J    U R                    Vs1 s H  oS   iM	     sn$ s  snf rC   r+  r  s     r4   r  TensMul._get_free_indices_setd  s     "ii(i!i(((s    c                    [        [        R                  " U R                  6 5      n[	        U R
                  R                  5       5       VVs1 s H  u  p#X!;   d  M  UiM     snn$ s  snnf r]   )rb  r#  r$  rK   rf   rn  ru   r%  s       r4   r  TensMul._get_dummy_indices_setg  sO    	23	"+D,A,A,M,M,O"Pc"PTUTb"Pcccs   A&A&c                   [        U R                  5       Vs/ s H  nS PM     nnSnU R                   HJ  n[        U[        5      (       d  M  [        UR                  5       H	  nX2XS-   '   M     X4R                  -  nML     U$ s  snf rC   )r   r  r  r   r  )rQ   rY   
arg_offsetcounterr*  r   s         r4    _get_position_offset_for_indices(TensMul._get_position_offset_for_indicesk  sz    $)$--$89$8qd$8
999Cc8,,3<<(*11;' )||#G   :s   Bc                \    [        U R                   Vs/ s H  oS   PM	     sn5      $ s  snf rC   r   rf  s     r4   r!  TensMul.free_argsv  r5  r6  c                8    U R                  U R                  5      $ r]   )r  r  rt   s    r4   r`   TensMul.componentsz  s    --dii88r3   c                    U R                  5       nU R                  5       nU R                   VVs/ s H  u  p4X4X   -
  X$   4PM     snn$ s  snnf r]   )r  _get_indices_to_args_posrJ   )rQ   r  argposr   rq   s        r4   r,  TensMul.free_in_args~  sJ    ::<
..0JN))T)JS*/)6;7)TTTs   Ac                    U R                   $ r]   r  rt   s    r4   r'  TensMul.coeff  s     {{r3   c                r    U R                   " / U R                  QSU R                  -  P76 R                  SS9$ Nre   Fr  )rI  r  r'  r  rt   s    r4   r  TensMul.nocoeff  s3    yy2$))2Qtzz\277U7CCr3   c           	         U R                  5       nU R                  5       nU R                   VVs/ s H  u  p4X1U   -
  XAU   -
  X#   X$   4PM     snn$ s  snnf r]   )r  r  rK   )rQ   r  r  r/  r0  s        r4   r1  TensMul.dum_in_args  s]    ::<
..0]a]e]ef]eSYSUrN"B"~$5vz6:N]efffs    Ac                    US:X  a  U R                   S:H  $ [        U5      n[        U[        5      (       d"  U R                  (       a   eU R                   U:H  $ U R                  5       UR                  5       :H  $ rC   )r'  r!   r   r  r`   rR   r  s     r4   r  TensMul.equals  sa    A:::?"%**&&::&&}}%.."222r3   c                    U R                   $ )a  
Returns the list of indices of the tensor.

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

The indices are listed in the order in which they appear in the
component tensors.
The dummy indices are given a name which does not collide with
the names of the free indices.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz)
>>> g = Lorentz.metric
>>> p, q = tensor_heads('p,q', [Lorentz])
>>> t = p(m1)*g(m0,m2)
>>> t.get_indices()
[m1, m0, m2]
>>> t2 = p(m1)*g(-m1, m2)
>>> t2.get_indices()
[L_0, -L_0, m2]
)r  rt   s    r4   ru   TensMul.get_indices  s    6 }}r3   c                6    U R                   R                  5       $ )a)  
Returns the list of free indices of the tensor.

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

The indices are listed in the order in which they appear in the
component tensors.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz)
>>> g = Lorentz.metric
>>> p, q = tensor_heads('p,q', [Lorentz])
>>> t = p(m1)*g(m0,m2)
>>> t.get_free_indices()
[m1, m0, m2]
>>> t2 = p(m1)*g(-m1, m2)
>>> t2.get_free_indices()
[m2]
rH  rt   s    r4   r   TensMul.get_free_indices  s    2 $$5577r3   c           	         U R                   " U R                   Vs/ s H+  n[        U[        5      (       a  UR	                  U5      OUPM-     sn6 $ s  snf r]   )rI  r  r   r  r  )rQ   r  r*  s      r4   r  TensMul._replace_indices  sJ    yygkgpgpqgp`cC9R9R3//5X[[gpqrrqs   2Ac                    U R                   S:X  a  U /$ / nSnU R                    H3  n[        U[        5      (       a  UR                  X#-  5        SnM/  X#-  nM5     U$ )am  
Returns a list of tensors, whose product is ``self``.

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

Dummy indices contracted among different tensor components
become free indices with the same name as the one used to
represent the dummy indices.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads, TensorSymmetry
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> a, b, c, d = tensor_indices('a,b,c,d', Lorentz)
>>> A, B = tensor_heads('A,B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
>>> t = A(a,b)*B(-b,c)
>>> t
A(a, L_0)*B(-L_0, c)
>>> t.split()
[A(a, L_0), B(-L_0, c)]
r2   re   )r  r   r  rj   )rQ   splitpr  r*  s       r4   r   TensMul.split  s\    0 99?6M99C#v&&cg&
  r3   c           	        U R                    Vs/ s H-  n[        U[        [        45      (       a  UR                   OU4PM/     nn[        [        R
                  " U6  Vs/ s H  n[        U6 R                  SS9PM     sn6 $ s  snf s  snf r  )r  r   r   r  r#  productr  r  )rQ   rt  r*  args1rY   s        r4   _eval_expand_mulTensMul._eval_expand_mul  s    TXT]T]^T]SZc7^<<3&HT]^2;2C2CU2KM2KQGQK%(2KM 
 	
 _Ms   4BBc                `    [        [        R                  X R                  S9R	                  SS9$ )Nr  Fr  )r  r   r  r  r  rt   s    r4   r(  TensMul.__neg__  s(    q}}d8I8IJOOUZO[[r3   c                    [        5         [        [        5         U R                  U   sS S S 5        $ ! , (       d  f       g = fr]   r  r  s     r4   r  TensMul.__getitem__  r  r  c                    [        U R                  5      nU R                  R                  5       (       a.  SnUS   [        R
                  :X  a  USS  nX!4$ US   * US'    X!4$ SnX!4$ )Nr  r   re   r  )r   r  r'  could_extract_minus_signr   r  )rQ   r  r`  s      r4   !_get_args_for_traditional_printer)TensMul._get_args_for_traditional_printer
  sv    DII::..00DAw!--'ABx
 z  7(Q z Dzr3   c           	        U R                    Vs/ s H  n[        U[        5      (       d  M  UPM     nnSn[        U5      S-
  n[	        U5       H  n[	        XES5       H  nX&S-
     R                  X&   5      nUS;  a  M#  [        [        X&S-
     R                  R                  5      S S9n[        [        X&   R                  R                  5      S S9n	XUS-
     R                  R                  4XU   R                  R                  4:  d  M  X&   X&S-
     sX&S-
  '   X&'   U(       d  M  U* nM     M     X0R                  -  n
U
S:w  a  U
/U-   $ U$ s  snf )z
Returns the ``args`` sorted according to the components commutation
properties.

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

The sorting is done taking into account the commutation group
of the component tensors.
re   r   r   c                    U R                   $ r]   r  rD   s    r4   rF   :TensMul._sort_args_for_sorted_components.<locals>.<lambda>+  s    PQPVPVr3   rH   c                    U R                   $ r]   r  rD   s    r4   rF   r"  ,  s    affr3   )r  r   r  rN   r   r  r   rb  ra   rL   rg   r'  )rQ   r*  cvr`  rk   rY   r   r  r~   typ2r'  s              r4    _sort_args_for_sorted_components(TensMul._sort_args_for_sorted_components  s<    "YYDYc*S(*CcYDGaKqA1_sG))"%0F?c"qS'"3"3"?"?@FVWc"%//"="=>DTUQqS'++001Ta5??;O;O4PP%'UBsGNBsGRUq $u %  zz!A:7R<	) Es
   EEc                H    [        U R                  5       6 R                  SS9$ )z2
Returns a tensor product with sorted components.
Fr  )r  r&  r  rt   s    r4   rC  TensMul.sorted_components8  s&     ==?@EE5EQQr3   Fc                    [        XUS9$ )
Returns the tensor corresponding to the permutation ``g``

For further details, see the method in ``TIDS`` with the same name.
r  r:  r;  s      r4   r   TensMul.perm2tensor>  s     4<<r3   c                   U R                   (       a  U $ U R                  5       n[        U[        5      (       a  UR	                  5       $ UR
                  (       d  U$ UR                  SS9nUR                  5       nUR                  R                  5       u  p4n[        UR
                  5      n[        X4U/UQ76 nUS:X  a  [        R                  $ UR                  US5      nU$ )a  
Canonicalize using the Butler-Portugal algorithm for canonicalization
under monoterm symmetries.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorHead, TensorSymmetry
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz)
>>> A = TensorHead('A', [Lorentz]*2, TensorSymmetry.fully_symmetric(-2))
>>> t = A(m0,-m1)*A(m1,-m0)
>>> t.canon_bp()
-A(L_0, L_1)*A(-L_0, -L_1)
>>> t = A(m0,-m1)*A(m1,-m2)*A(m2,-m0)
>>> t.canon_bp()
0
Fr  r   T)r  r  r   r  rR   r`   r  rC  rn  r   r   r   r   rM  r   )	rQ   r  r   r   r   r   r   r>  tmuls	            r4   rR   TensMul.canon_bpF  s    & K{{}dG$$==?"Kyyey$""$--@@BD!!,,/1t0a0!866M}}S$'r3   c                (    U R                  U5      nU$ r]   r  )rQ   r  r   s      r4   r  TensMul.contract_deltaj  s      'r3   c                    0 nSn[        U R                  5       HX  u  p4[        U[        5      (       d  M  [        U[        5      (       d   e[        UR                  5       H  nX1U'   US-  nM     MZ     U$ )zE
Get a dict mapping the index position to TensMul's argument number.
r   re   )rf   r  r   r  r  r   r  )rQ   pos_mappos_counterarg_ir*  rY   s         r4   r   TensMul._get_indices_to_args_posn  sr     #DII.JEc8,,c6****3<<(',$q  )	 / r3   c           	     	   U R                  5       R                  SS9nX:w  a  [        U5      n[        X!5      $ U R	                  5       n[        U R                  5      nUR                  [        R                  S5      :X  a  SnORUR                  [        R                  S5      :X  a  SnO,UR                  [        R                  S5      :X  a  SnO[        e[        U R                  5       VVs/ s H0  u  pg[        U[        5      (       d  M  UR                  U:X  d  M.  UPM2     nnnU(       d  U $ Sn	U R                   SS n
U R"                  SS n[%        5       nU GHE  nX;   a  M  U Vs/ s H  osUS      U:X  d  M  UPM     nnU
 Vs/ s H  osUS      U:X  d  X7S      U:X  d  M  UPM     nnU(       d  M]  UR'                  U5        SXM'   [)        U5      S:X  a  U(       dH  Uu  nnUUS      U:X  a  US   nOUS   nUUS      U:X  a  US   nOUS   nU
R+                  UU45        GOCUu  nnUUS      U:X  a  US   nUS   S:X  a  U	* n	OUS   nUS   S:X  a  U	* n	UUS      U:X  a	  US   nU	* n	OUS   nU
R+                  UU45        O[)        U5      S:X  a  U(       d]  US   u  nnUU   UU   :X  a  UR,                  S   nU	UR.                  -  n	OUU   U:X  a  UnOUnUS   u  nnUR+                  UU45        OnUS   u  nnUU   UU   :X  a(  UR,                  S   nU	UR.                  -  n	UU:  a  U	* n	O2UU   U:X  a  UnUS:X  a  U	* n	OUnUS   u  nnUR+                  UU45        U
 Vs/ s H  owU;  d  M
  UPM     n
nU Vs/ s H  owU;  d  M
  UPM     nnGMH     SnS/[)        U5      -  n[1        [)        U5      5       H  nXl;   a  US-  nM  UUU'   M     U VVs/ s H  u  nnUU   U;  d  M  UUUUU      -
  4PM      nnnU
 VVs/ s H2  u  nnUU   U;  d  M  UU   U;  d  M  UUUU      -
  UUUU      -
  4PM4     n
nnU	[3        U6 -  R                  SS9n[        U[4        5      (       d  U$ [6        R9                  UR:                  X5      nUR=                  U5      $ s  snnf s  snf s  snf s  snf s  snf s  snnf s  snnf )aA  
Raise or lower indices with the metric ``g``.

Parameters
==========

g : metric

Notes
=====

See the ``TensorIndexType`` docstring for the contraction conventions.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz)
>>> g = Lorentz.metric
>>> p, q = tensor_heads('p,q', [Lorentz])
>>> t = p(m0)*q(m1)*g(-m0, -m1)
>>> t.canon_bp()
metric(L_0, L_1)*p(-L_0)*q(-L_1)
>>> t.contract_metric(g).canon_bp()
p(L_0)*q(-L_0)
Fr  r   re   rA   r   N)r  r  rR   r  r  r   r  r   r   r   r  rP  rf   r   r  ra   rK   rJ   rb  rX  rN   rj   rL   rU  r   r  r  r>   rb   r`   r  )rQ   r   r  r3  r  r  rY   rE   gposr`  rK   rJ   elimgposxfree1rz  dum10dum11p0r/  r  r  rn   r   r  shiftshiftsr  r  s                                r4   r  TensMul.contract_metric}  s;   8 {{}!!u!-<D>D"4++//1DII ::77;;GZZ>99!<<GZZ>55a88G%% (		2a2dajF6KPQP[P[_`P`2aK hhqkyy|uE} $?1!(>QE?"Ws!admu&<!QV@VAsDWHHUODK4yA~#'LE5uQx(E1"1X #1XuQx(E1"1X #1XJJBx(#'LE5 uQx(E1"1X 8q=$(5D #1X 8q=$(5DuQx(E1"1X $u #1XJJBx(Ta#AwHCs|ws|3mmA.#CGG| #3<50!$B!$B!&qQS"I.#AwHCs|ws|3mmA.#CGG|9$(5D #3<50!$B"ax(,u!$B!&qQS"I.!3cd]1cC3#6t!~AtD6Ds x SYs4y!Ay
F1I	 "
 ?C]d(3gajX\F\-a&,,-d]RU  NRUBY`acYdlpYpCu|}  vA  IM  vMCVGBK(("vgbk/B*BCRU  NWd^#***6#x((J55cnndP++B//i b @Wh 46 ^ Ns`   .R2R2R2,R8?R8R=)R=4	SS	SS)S=SS*S5Sc                F    UR                  5       nU R                  " USU06$ r  r  r  s       r4   r   TensMul._set_new_index_structure!  r  r3   r  c               v   [        U5      U R                  :w  a  [        S5      e[        U R                  5      nSn[        U5       HX  u  pg[        U[        5      (       d  M  [        U[        5      (       d   eUR                  nUR                  " X%XX-    6 XF'   XX-  nMZ     [        USU06R                  SS9$ )Nr  r   r   Fr  )rN   r  ri   r   r  rf   r   r  r  r  r  r  )	rQ   r   rM   r4  r  rq   rY   r*  r  s	            r4   r  TensMul._set_indices%  s    w<4==(677DIIoFAc8,,c6****||H&&CL(ABDGOC & 6+6;;;GGr3   c                r    U  H1  n[        U[        5      (       d  M  [        U[        5      (       a  M1   e   g r]   )r   r  r  )r  rJ   rK   r*  s       r4   &_index_replacement_for_contract_metric.TensMul._index_replacement_for_contract_metric3  s/    Cc8,,c6**** r3   c                    / nU R                    H8  n[        U[        5      (       a  UR                  " U6 nUR	                  U5        M:     [        U6 R                  SS9$ r  )r  r   r  r  rj   r  r  r  s       r4   r  TensMul.substitute_indices:  r  r3   c                   [        5         U R                  n[        U5      nU Vs/ s H  o3R                  PM     snU Vs/ s H  o3R                  PM     sn:w  a  [	        S5      eX:X  a  U $ U R
                  " [        [        X!5      5      6 n[        U Vs1 s H  oUR                  (       a  UOU* iM     sn5      [        U5      :w  a  UR                  " UR                  6 $ U$ s  snf s  snf s  snf ro  rp  rq  s         r4   r  TensMul.__call__B  rs  rt  c           
     Z   [        U R                   Vs/ s H+  n[        U[        5      (       d  M  UR	                  U5      PM-     sn6 u  p4[        [        R                  U R                   Vs/ s H  n[        U[        5      (       a  M  UPM     sn[        R                  5      n[        R                  U5      u  pxp[        R                  U
5      nU R                  nUR                  S S9  U Vs/ s H  oS   PM	     nnX[        R!                  XKU5      -  4$ s  snf s  snf s  snf )Nc                    U S   $ r   r2   rD   s    r4   rF   'TensMul._extract_data.<locals>.<lambda>X  s    !r3   rH   r   )r   r  r   r  r7  r   operatormulr   r  r  r  r  r  rP   r   r  )rQ   r&  r*  r  r5  r   r'  rM   rJ   r  r  rK   r  rY   ra  s                  r4   r7  TensMul._extract_dataR  s    "TXT]T]${T]Sakloqyaz%HS%6%67G%HT]${|x||%ZA*QPXBYa%Z\]\a\ab070L0L\0Z-z((4==		n	%&*+d!d+#;#M#Mf[c#dddd %|%Z
 ,s   DD.D#
D#
4D(c                    [        5         [        [        5         [        U R	                  5          nS S S 5        U$ ! , (       d  f       W$ = fr]   r  )rQ   r  s     r4   r  TensMul.data\  s9    450?C 6
 65
s	   <
Ac                ,    [        5         [        S5      e)Nz9Not possible to set component data to a tensor expressionr5   ri   r  s     r4   r  rT  c  s    TUUr3   c                ,    [        5         [        S5      e)Nz<Not possible to delete component data to a tensor expressionrV  rt   s    r4   r  rT  h  s    WXXr3   c                    [        5         [        [        5         U R                  c  [	        S5      eU R                  R                  5       sS S S 5        $ ! , (       d  f       g = fr  )r5   r'   r&   r  ri   r  rt   s    r4   r  TensMul.__iter__m  sC    45yy  !CDD99%%' 655s   2A
A$c                L   [        U5      n[        [        U 5      5      n[        [        U 5      5      nUR                  U5      n[	        U5      S:X  a  g UR                  U5        UR                  U5        U Vs/ s H  oUS4PM     nn[        R                  U5      n0 nU HV  n	U	* UR                  5       ;   a  M  U" U	R                  5      n
U	R                  " U
/U	R                  SS Q76 nXU	'   U* X* '   MX     [	        U5      S:X  a  gU R                  U5      nU$ s  snf )z
exclude: set
new: TensExpr

If ``new`` has any dummy indices that are in ``exclude``, return a version
of new with those indices replaced. If no replacements are needed,
return None

r   Nre   )rb  r  r   r  rN   r  r>   rx   r  rW   rI  r  r  )r  r  dums_newfree_new	conflictsrY   exclude_for_genr]  r  dnewnamenew_dnew_renameds                r4   r  TensMul._dedupe_indicest  s    g,(-.',-))'2	y>Q	
 	x x .56gt9g6>>OArTYY[ !--.GFF70QVVABZ0EGvDH  t9>**40 7s   <D!c                   UR                  5        VVs0 s H  u  p#[        U[        5      (       d  M  X#_M      nnnUR                  5        VVs0 s H  u  p#X$R                  5       ;  d  M  X#_M     nnn[	        U R                  5       5      n0 nUR                  U5        UR                  UR                  5       5        UR                  UR                  5       5        UR                  5        HF  u  p[        R                  X5      n
X:X  d  U
c  XU'   M(  XU'   UR                  [        U
5      5        MH     U$ s  snnf s  snnf )zJ
rule: dict

This applies TensMul._dedupe_indices on all values of rule.

)
r6  r   ry   r  rb  ru   r  valuesr  r  )rQ   r  r8  r   index_rulesother_rulesr  newruler  r  rb  s              r4   r  TensMul._dedupe_indices_in_rule  s    '+jjlQlsqjK6PsqslQ&*jjlRlsqa?O?O?Q6QsqslRd&&(){#{'')*{))+,#))+HC!11#?Kz[0"*{;78 ,  RRs   D;D;E,Ec                    [        U[        5      (       d  gU1nU R                  X5      nUc  gUR                  X5      R	                  SS9$ )zh
If new is an index which is already present in self as a dummy, the dummies in self should be renamed.
NFr  )r   ry   r  _subsr  )rQ   r  r  r  self_renameds        r4   
_eval_subsTensMul._eval_subs  sS    
 #{++%++D:%%c/44%4@@r3   c                *   SSK Jn  U R                  5        Vs/ s H  oDR                  S   PM     nnU Vs/ s H$  n[	        Xc5      (       a  UR                  S   OUPM&     nn[
        R                  " U5      nU R                  Xu5      $ s  snf s  snf )Nr   rA  )rC  rB  ru   r  r   r   r  rF  )rQ   r  r  rB  rY   rD  r*  r  s           r4   r   TensMul._eval_rewrite_as_Indexed  s}    1,0,<,<,>?,>q,>?HLMz#33<M||D!""477 @Ms
   B+Bc           	        / n[        U R                  5       H  u  p4[        U[        5      (       a  UR	                  U5      nO3UR
                  (       a  UR                  U5      nO[        R                  nU(       d  Mh  UR                  [        R                  U R                  S U U4-   U R                  US-   S  -   5      R                  SS95        M     [        R                  U5      R                  SS9$ r  )rf   r  r   r  r  r  r  r   rM  rj   r  r  r  r  )rQ   r   termsrY   r*  r_  s         r4   r   TensMul._eval_partial_derivative  s    		*FA #x((003 ;;,,Q/AAqW--diimqd.BTYYqSTuvEV.VW\\bg\hi + &+++77r3   Nc           
     \  ^$^% [        U[        5      (       d(  [        U[        [        45      (       a  [        U5      nOgUc  0 nO^UR	                  5       nUR                  5        Vs/ s H  n[        U[        5      (       d  M  UPM     snm%U%4S jnU" U 5      n U" U5      n[        S UR                   Vs/ s H  n[        U[        5      (       a  M  UPM     sn[        R                  5      nX:X  a  U$ [        [        U 5      5      S:X  a  U R                  XU5      $ S n[        U R                  U5      n	[        UR                  U5      n
SU	R                  5       ;   a7  [        U	S   6 R!                  SS9U R"                  :w  a  [%        S	U	S    35      eSU
R                  5       ;   a-  [        U
S   6 R!                  SS9U:w  a  [%        S	U
S    35      eU	S
    Vs1 s H  n['        [)        US/ 5      5      iM     nnU
S
    Vs1 s H  n['        [)        US/ 5      5      iM     nnUR+                  U5      (       d  g[        U	S
   5      S:  Ga  U	S
   S   n UR-                  5        GHx  nU
S
    GHj  n[        U[        5      (       a  SnOSn UU-  R/                  U5      nUc  M8  U R0                  " U/U R                   Vs/ s H  nUU:w  d  M  UPM     snQ76 R!                  SS9nUR0                  " UR                   Vs/ s H  nUU:w  d  M  UPM     sn6 R!                  SS9n0 nUR3                  U5        UR3                  U5        UR5                  UUS9nUc  M  SnUR                  5        HC  n[        U[        5      (       d  M  U* UR                  5       ;   d  M1  UU*    UU   * :w  d  MA  Sn  O   U(       d  GMV  UR3                  U5        Us  s  $    GM{     g/ nU
S
   n[        U	S   S SS9u  nnU H  n[7        UR9                  5       5      n/ nU HV  n U R9                  5       n!Sn"U! H!  m$[;        U$4S jU 5       5      (       d  M  Sn"M#     U"(       d  ME  UR=                  U 5        MX     UR5                  [        U6 R!                  SS95      nUc    gU H  n#UR=                  U#5        M     UR3                  U5        M     U
S
    V s/ s H  n U U;  d  M  U PM     nn [        U5      S:  aA  US   R5                  [        S/UQ76 R!                  SS95      nUc  gUR3                  U5        O[        U5      S:  a  gU R"                  R5                  XsS9nUc  gUR3                  U5        U$ s  snf s  snf s  snf s  snf s  snf s  snf s  sn f )z
Match assuming all tensors commute. But note that we are not assuming anything about their symmetry under index permutations.
Nc                >   > [         R                  U T5      nUb  U$ U $ r]   )r  r  )r  renamedrM   s     r4   dedupe,TensMul._matches_commutative.<locals>.dedupe  s%    !11$@&"NKr3   c                
    X-  $ r]   r2   r  s     r4   rF   .TensMul._matches_commutative.<locals>.<lambda>   s    r3   r   c                h    [        U [        5      (       a  g[        U [        [        45      (       a  gg)Nr  r  r'  )r   r  r  r  )r*  s    r4   r  -TensMul._matches_commutative.<locals>.siftkey	  s*    #z**#C&(!344r3   r'  Fr  z/Found something that we do not know to handle: r  r`   r   re   )rO  Tr  c                :    [        U R                  5       5      S:H  $ rC   )rN   r   rD   s    r4   rF   rz  N  s    CPQPbPbPdLeijLjr3   )binaryc              3  H   >#    U  H  oR                  T5      S L v   M     g 7fr]   )r  )r  r   rY   s     r4   r  /TensMul._matches_commutative.<locals>.<genexpr>W  s     HA99Q<4/s   "re  )r   r  r  r   r~  re  ry   r   r  r   r  rN   r  rP  r*   r  r  r'  rP  r   getattrissubsetrb  rf  rI  r  r  rb  r   r  rj   )&rQ   r  rO  r  r8  rw  r*  
expr_coeffr  r  r  rE   query_tens_headsexpr_tens_headsr  q_tensr  r`  rg  r   	rem_queryrem_exprtmp_replrem_minternally_consistentr  r  indexless_wildswildsr  free_this_wildtensors_to_tryr   rJ   shares_indices_with_wildrJ  rY   rM   s&                                       @@r4   _matches_commutativeTensMul._matches_commutative  s   
 $(($4 011t} I!(I #,"2"2"4S"4Q
1k8Rq"4SG  $<D$<D ,dii.iiszZ]_gOhsi.iklkpkpq
 <z$ A%''==	 DIIw/499g. l''))W-.333?4::M),[\hip\q[r*sttk&&((G,-222>*L),[\gho\p[q*rssIUV^I_`I_AE'!\2">?I_`HST\H]^H]15L"!=>H]^((99 |H%&*#H-a0H #99;$X.A!&'22!  f..q1Ay  $		$ YTYY1XY!x-!Y1X Y ^ ^di ^ jI#yydii*Ji161i*JKPPV[P\H!HOOI.OOA&%--h(-KE(04-!&A)!K88$%2#5%)ay:P<A$9$)	 ".
 10%,,U3#,,= / <B  )(3!%l<&@Bjsw!xA !3!3!56NN())++/(AHHHH380  ,+"))!, ) 		'>277U7CEAy*D%,,T2 +  #' , +6h*?^*?Q1L]C]q*?^!# #++WQ-L8K-L-Q-QW\-Q-]_Ay  #$%) JJz39QK T /j8 a^4 2Y*J\ _sH   (VV9V
V
% V V
VV
V$V$%
V)3V)c                    [        U5      nUc  0 nOUR                  5       n[        S UR                   5       5      nU(       a  U R	                  XU5      $ [        S5      e)Nc              3     #    U  H5  n[        U[        5      (       d  M  UR                  R                  S :H  v   M7     g7fr  )r   r  ra   r   )r  r*  s     r4   r  "TensMul.matches.<locals>.<genexpr>  s-     ^#jQTV\F]-cmm((A-s   ? ?z9Tensor matching not implemented for non-commuting tensors)r   r~  r  r  r  rP  )rQ   r  rO  r  commutes        r4   r  TensMul.matchesz  sX    t}I!(I^^^,,TcBB%&abbr3   r2   r*  r   rR  r   rS  )Er   r   r   r   r   r   r  r  r  r  r  rL   rJ   rK   ra  r   r  r   r  r  r  r  r  r  r  r  r  r  r  r!  r`   r,  r'  r  r1  r  ru   r   r  r   r  r(  r  r  r&  rC  r   rR   r  r  r  r  r  rG  r  r  r7  r  r  r  r  r  r  rm  r  r  r  r  r   r2   r3   r4   r  r  B  s   %L uuH%%-^ 9:K+,D
)
*C;<L+,D34H,5 ,5\ F F '( '(R   	G 	G0h A A   )d	 1 1 9 9 U U
   D D g g
3:86s"H
\#
BR="Hb0HD 27 H + +3 e   
[[V V 
\\Y Y( ( (T0A88&Xtcr3   r  c                      \ rS rSrSrS r\S 5       r\S 5       r\S 5       r	\S 5       r
\S 5       r\S	 5       rS
 rSS jrS rS rSrg)TensorElementi  a  
Tensor with evaluated components.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, TensorHead, TensorSymmetry
>>> from sympy import symbols
>>> L = TensorIndexType("L")
>>> i, j, k = symbols("i j k")
>>> A = TensorHead("A", [L, L], TensorSymmetry.fully_symmetric(2))
>>> A(i, j).get_free_indices()
[i, j]

If we want to set component ``i`` to a specific value, use the
``TensorElement`` class:

>>> from sympy.tensor.tensor import TensorElement
>>> te = TensorElement(A(i, j), {i: 2})

As index ``i`` has been accessed (``{i: 2}`` is the evaluation of its 3rd
element), the free indices will only contain ``j``:

>>> te.get_free_indices()
[j]
c           	        [        U[        5      (       dV  [        U[        5      (       d  [        SU-  5      eUR                  " UR
                   Vs/ s H  n[        X25      PM     sn6 $ UR                  5       nU Vs0 s H  oUR
                  S   U_M     nnUR                  5        VVs0 s H  u  pxUR                  Xw5      U_M     nnnUR                  5        VVs0 s H  u  pxXt;   d  M  Xx_M     nnn[        U5      S:X  a  U$ U Vs/ s H  oUUR                  5       ;  d  M  UPM     n	n[        U5      n[        R                  XU5      n
Xl        U
$ s  snf s  snf s  snnf s  snnf s  snf )Nz%s is not a tensor expressionr   )r   r  r  r3  rI  r  r  r   r6  r  rN   r  r   r  r  )r  r  r  r*  expr_free_indicesrY   name_translationrm   rW  ra  r  s              r4   r  TensorElement.__new__  sL   $''dH-- ?$ FGG99		R	}S<	RSS 1132CD2CQFF1IqL2CDS\SbSbSdeSd<5%))%7>Sd	e6?oo6Gf6Gle5Ke\U\6G	fy>QK#4R#4aAQ8Q#4RO	s)4(
 SDef Ss*   E E .E%"E+1E+E1*E1c                l    [        U R                  5       5       VVs/ s H  u  pX!4PM
     snn$ s  snnf r]   )rf   r   )rQ   rY   rm   s      r4   rJ   TensorElement.free  s.    +4T5J5J5L+MN+Mxq
+MNNNs   0c                    / $ r]   r2   rt   s    r4   rK   TensorElement.dum  s	     	r3   c                     U R                   S   $ rC   _argsrt   s    r4   r  TensorElement.expr      zz!}r3   c                     U R                   S   $ r   r  rt   s    r4   r  TensorElement.index_map  r  r3   c                "    [         R                  $ r]   rZ  rt   s    r4   r'  TensorElement.coeff  r\  r3   c                    U $ r]   r2   rt   s    r4   r  TensorElement.nocoeff  r_  r3   c                    U R                   $ r]   r  rt   s    r4   r   TensorElement.get_free_indices  s    !!!r3   c                $    U R                  U5      $ r]   rK  r  s     r4   r  TensorElement._replace_indices  s    }}T""r3   c                "    U R                  5       $ r]   )r   rt   s    r4   ru   TensorElement.get_indices  s    $$&&r3   c                   ^ U R                   R                  U5      u  p#U R                  m[        U4S jU 5       5      nU Vs/ s H  oUT;  d  M
  UPM     nnUR	                  U5      nX#4$ s  snf )Nc              3  Z   >#    U  H   nTR                  U[        S 5      5      v   M"     g 7fr]   )r  slice)r  rY   r  s     r4   r  .TensorElement._extract_data.<locals>.<genexpr>  s#     O;aIMM!U4[99;s   (+)r  r7  r  r   r  )rQ   r&  r<  r   slice_tuplerY   r  s         @r4   r7  TensorElement._extract_data  sl    !YY445EFNN	O;OO"-D+Q)1Cq+D!!+.!! Es   	A-A-r2   NrR  )r   r   r   r   r   r  r  rJ   rK   r  r  r'  r  r   r  ru   r7  r   r2   r3   r4   r  r    s    6$ O O          "#'"r3   r  c                  8    \ rS rSrSrSS jr\S 5       rS rSr	g)	WildTensorHeadi  a  
A wild object that is used to create ``WildTensor`` instances

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

Examples
========
>>> from sympy.tensor.tensor import TensorHead, TensorIndex, WildTensorHead, TensorIndexType
>>> R3 = TensorIndexType('R3', dim=3)
>>> p = TensorIndex('p', R3)
>>> q = TensorIndex('q', R3)

A WildTensorHead can be created without specifying a ``TensorIndexType``

>>> W = WildTensorHead("W")

Calling it with a ``TensorIndex`` creates a ``WildTensor`` instance.

>>> type(W(p))
<class 'sympy.tensor.tensor.WildTensor'>

The ``TensorIndexType`` is automatically detected from the index that is passed

>>> W(p).component
W(R3)

Calling it with no indices returns an object that can match tensors with any number of indices.

>>> K = TensorHead('K', [R3])
>>> Q = TensorHead('Q', [R3, R3])
>>> W().matches(K(p))
{W: K(p)}
>>> W().matches(Q(p,q))
{W: Q(p, q)}

If you want to ignore the order of indices while matching, pass ``unordered_indices=True``.

>>> U = WildTensorHead("U", unordered_indices=True)
>>> W(p,q).matches(Q(q,p))
>>> U(p,q).matches(Q(q,p))
{U(R3,R3): _WildTensExpr(Q(q, p))}

Parameters
==========
name : name of the tensor
unordered_indices : whether the order of the indices matters for matching
    (default: False)

See also
========
``WildTensor``
``TensorHead``

Nc           
        [        U[        5      (       a  [        U5      nO#[        U[        5      (       a  UnO[        S5      eUc  / nUc  [        R                  [        U5      5      nOUR                  [        U5      :X  d   eU[        R                  [        U5      5      :w  a  [        S5      e[        R                  " X[        U6 [        U5      [        U5      [        U5      5      nU$ )Nr  z3Wild matching based on symmetry is not implemented.)r   r   r   ri   r   r  rN   r   rP  r   r  r   r   )r  rg   rL   r   r   unordered_indicesr  r  s           r4   r  WildTensorHead.__new__  s    dC   ,Kf%%K^,,K%11#k2BCH==C$4444~11#k2BCC%&[\\mmCe[.A78CTV]^bVcelm~e  A
r3   c                     U R                   S   $ )Nr,   r  rt   s    r4   r   WildTensorHead.unordered_indices1  r  r3   c                :    [        X40 UD6nUR                  5       $ r]   )r  r  )rQ   rM   r  r?  s       r4   r  WildTensorHead.__call__5  s    D4V4{{}r3   r2   )NNr   F)
r   r   r   r   r   r  r  r  r  r   r2   r3   r4   r  r    s&    6n.  r3   r  c                  2    \ rS rSrSrS rSS jrSS jrSrg)	r  i:  a0  
A wild object which matches ``Tensor`` instances

Explanation
===========
This is instantiated by attaching indices to a ``WildTensorHead`` instance.

Examples
========
>>> from sympy.tensor.tensor import TensorHead, TensorIndex, WildTensorHead, TensorIndexType
>>> W = WildTensorHead("W")
>>> R3 = TensorIndexType('R3', dim=3)
>>> p = TensorIndex('p', R3)
>>> q = TensorIndex('q', R3)
>>> K = TensorHead('K', [R3])
>>> Q = TensorHead('Q', [R3, R3])

Matching also takes the indices into account
>>> W(p).matches(K(p))
{W(R3): _WildTensExpr(K(p))}
>>> W(p).matches(K(q))
>>> W(p).matches(K(-p))

If you want to match objects with any number of indices, just use a ``WildTensor`` with no indices.
>>> W().matches(K(p))
{W: K(p)}
>>> W().matches(Q(p,q))
{W: Q(p, q)}

See Also
========
``WildTensorHead``
``Tensor``

c                   UR                  SS5      nUR                  [        :X  a   [        X4SU0UD6$ UR                  [        :X  a  U" U6 $ U R                  X5      nU Vs/ s H  oUR                  PM     nnUR                  UR                  US UR                  UR                  S9n[        R                  " X[        U6 5      nUR                  Ul        [        R                  " U6 Ul        UR                  R                   S S  Ul        UR                  R$                  S S  Ul        UR                  R(                  Ul        [*        R,                  Ul        Xwl        Xl        U/Ul        UR6                  [9        U5      :w  a  [;        S5      eXGl        UR?                  X'R                  5      Ul         U$ s  snf )Nr   F)r   r   r  r  )!r  rI  r  r  _WildTensExprr  rW   rg   r   r  r   r  r   r>   rZ   rn  rJ   r  rK   r  rO   r   r  r  r  r  r  r   rN   ri   r   r  r  )r  r  rM   r4  r   r   rL   r  s           r4   r  WildTensor.__new__^  s   kk-7z) +SKS7SS.(($$[:8?@,,@!&&!!);; '  mmCeWo>##.;;WE((--a0	''++A.,,66UU
$&-s7|+677%--g7K7KL
1 As   $F>Nc                   [        U[        5      (       d  U[        S5      :w  a  g Uc  0 nOUR                  5       n[	        U R
                  5      S:  a  [        US5      (       d  g UR                  5       n[	        U5      [	        U R
                  5      :w  a  g U R                  R                  (       a'  U R                  U5      nUc  g UR                  U5        OQ[        [	        U5      5       H9  nU R
                  U   R                  XF   5      nUc    g UR                  U5        M;     [        U5      X R                  '   U$ XU '   U$ )Nre   r   r   )r   r  r   r~  rN   rM   r  r   r  r  _match_indices_ignoring_orderr  r   r  r  ra   )rQ   r  rO  r  expr_indicesrg  rY   s          r4   r  WildTensor.matches  s   $))dadlI!(It||q 4!344002L< C$550066t<9$$Q's<01AQ//@Ay#!((+ 2 )6d(;Inn%
  #dOr3   c                    Uc  0 nOUR                  5       nS n[        U R                  U5      n/ nUR                  5       nUS    HX  nSn	U HD  n
X;   a  M
  UR	                  U
5      nUc  M   Sn	UR                  U5        UR                  U
5          O   U	(       a  MX    g   U Vs/ s H  oU;  d  M
  UPM     nnUS    Hu  nSn	U Ha  n
UR	                  U
5      nUc  M  U* UR                  5       ;   a  X(*    * X   :w  a      gSn	UR                  U5        UR                  U
5          O   U	(       a  Mu    g   U Vs/ s H  oU;  d  M
  UPM     nnUS    Hu  nSn	U Ha  n
UR	                  U
5      nUc  M  U* UR                  5       ;   a  X(*    * X   :w  a      gSn	UR                  U5        UR                  U
5          O   U	(       a  Mu    g   [        U5      [        U R                  5      :  a  gU$ s  snf s  snf )zf
Helper method for matches. Checks if the indices of self and expr
match disregarding index ordering.
Nc                T    [        U [        5      (       a  U R                  (       a  ggg)Nwild, updownwildr  )r   WildTensorIndexignore_updown)r   s    r4   r  9WildTensor._match_indices_ignoring_order.<locals>.siftkey  s!    #//$$)! r3   r  FTr  r  )	r~  r*   rM   ru   r  r  rj   r  rN   )rQ   r  rO  r  r  indices_siftedmatched_indicesexpr_indices_remainingr   matched_this_inde_indrg  rY   s                r4   r  (WildTensor._match_indices_ignoring_order  s+   
 I!(I	! dllG4!%!1!1!3!),C$/+KK&='+$$$Q'#**51 0 $# - .D!`-CP_G_!-C!`!&)C$/KK&=ty~~//Yt_4D4N#'+$$$Q'#**51 0 $# * .D!`-CP_G_!-C!`!.1C$/KK&=ty~~//Yt_4D4N#'+$$$Q'#**51 0 $# 2 #dll"33C "a "as   '	G64G6>	G;G;r2   rS  )	r   r   r   r   r   r  r  r  r   r2   r3   r4   r  r  :  s    "F$N"HFr3   r  c                  B    \ rS rSrSrS	S jr\S 5       rS rS
S jr	Sr
g)r  i  a  
A wild object that matches TensorIndex instances.

Examples
========
>>> from sympy.tensor.tensor import TensorIndex, TensorIndexType, WildTensorIndex
>>> R3 = TensorIndexType('R3', dim=3)
>>> p = TensorIndex("p", R3)

By default, covariant indices only match with covariant indices (and
similarly for contravariant)

>>> q = WildTensorIndex("q", R3)
>>> (q).matches(p)
{q: p}
>>> (q).matches(-p)

If you want matching to ignore whether the index is co/contra-variant, set
ignore_updown=True

>>> r = WildTensorIndex("r", R3, ignore_updown=True)
>>> (r).matches(-p)
{r: -p}
>>> (r).matches(p)
{r: p}

Parameters
==========
name : name of the index (string), or ``True`` if you want it to be
    automatically assigned
tensor_index_type : ``TensorIndexType`` of the index
is_up :  flag for contravariant index (is_up=True by default)
ignore_updown : bool, Whether this should match both co- and contra-variant
    indices (default:False)
c                   [        U[        5      (       a  [        U5      nOs[        U[        5      (       a  UnO[USL aK  SR                  [	        UR
                  5      5      n[        U5      nUR
                  R                  U5        O[        S5      e[        U5      n[        U5      n[        R                  " XX#U5      $ r  r  )r  rg   rW   rh   r  r  s         r4   r  WildTensorIndex.__new__  s    dC   ,Kf%%KT\==%6%E%E!FGD ,K,,33K@^,,.}}S/@WWr3   c                     U R                   S   $ r  r  rt   s    r4   r  WildTensorIndex.ignore_updown%  r  r3   c                |    [        U R                  U R                  U R                  (       + U R                  5      nU$ r]   )r  rg   rW   rh   r  r&  s     r4   r(  WildTensorIndex.__neg__)  s0    TYY(>(>ZZ$"4"46	r3   Nc                    [        U[        5      (       d  g U R                  UR                  :w  a  g U R                  (       d  U R                  UR                  :w  a  g Uc  0 nOUR                  5       nXU '   U$ r]   )r   ry   rW   r  rh   r~  rN  s       r4   r  WildTensorIndex.matches.  si    $,,!!T%;%;;!!zzTZZ'I!(I$r3   r2   )TFrS  )r   r   r   r   r   r  r  r  r(  r  r   r2   r3   r4   r  r    s,    "FX   
r3   r  c                  l    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rSrg)r  i@  aD  
INTERNAL USE ONLY

This is an object that helps with replacement of WildTensors in expressions.
When this object is set as the tensor_head of a WildTensor, it replaces the
WildTensor by a TensExpr (passed when initializing this object).

Examples
========
>>> from sympy.tensor.tensor import WildTensorHead, TensorIndex, TensorHead, TensorIndexType
>>> W = WildTensorHead("W")
>>> R3 = TensorIndexType('R3', dim=3)
>>> p = TensorIndex('p', R3)
>>> q = TensorIndex('q', R3)
>>> K = TensorHead('K', [R3])
>>> print( ( K(p) ).replace( W(p), W(q)*W(-q)*W(p) ) )
K(R_0)*K(-R_0)*K(p)

c                P    [        U[        5      (       d  [        S5      eXl        g )Nz,_WildTensExpr expects a TensExpr as argument)r   r  r3  r  )rQ   r  s     r4   rS   _WildTensExpr.__init__T  s     $))JKK	r3   c                    U R                   R                  [        [        U R                   R	                  5       U5      5      5      $ r]   )r  r  rW  r   r   )rQ   rM   s     r4   r  _WildTensExpr.__call__Y  s1    yy))$s4993M3M3OQX/Y*Z[[r3   c                Z    U R                  U R                  [        R                  -  5      $ r]   )rI  r  r   r  rt   s    r4   r(  _WildTensExpr.__neg__\  s    yy1==011r3   c                    [         er]   r  rt   s    r4   r  _WildTensExpr.__abs___  r  r3   c                    UR                   U R                   :w  a%  [        SU R                    SUR                    35      eU R                  U R                  UR                  -   5      $ NzCannot add z to rI  r3  r  r  s     r4   r  _WildTensExpr.__add__b  sN    ::"k$))DEFFyy5::-..r3   c                    UR                   U R                   :w  a%  [        SU R                    SUR                    35      eU R                  UR                  U R                  -   5      $ r  r  r  s     r4   r  _WildTensExpr.__radd__g  sN    ::"k$))DEFFyyDII-..r3   c                    X* -   $ r]   r2   r  s     r4   r  _WildTensExpr.__sub__l  s    vr3   c                    X* -   $ r]   r2   r  s     r4   r  _WildTensExpr.__rsub__o  s    r3   c                    [         er]   r  r  s     r4   r  _WildTensExpr.__mul__r  r  r3   c                    [         er]   r  r  s     r4   r  _WildTensExpr.__rmul__u  r  r3   c                    [         er]   r  r  s     r4   r  _WildTensExpr.__truediv__x  r  r3   c                    [         er]   r  r  s     r4   r  _WildTensExpr.__rtruediv__{  r  r3   c                    [         er]   r  r  s     r4   r  _WildTensExpr.__pow__~  r  r3   c                    [         er]   r  r  s     r4   r  _WildTensExpr.__rpow__  r  r3   r  N)r   r   r   r   r   rS   r  r(  r  r  r  r  r  r  r  r  r  r  r  r   r2   r3   r4   r  r  @  sN    &
\2"/
/
""""""r3   r  c                P    [        U [        5      (       a  U R                  5       $ U $ )zh
Butler-Portugal canonicalization. See ``tensor_can.py`` from the
combinatorics module for the details.
)r   r  rR   )r  s    r4   rR   rR     s"    
 !Xzz|Hr3   c                     U (       d&  [         R                  [        R                  / / / 5      $ U S   nU SS  H  nX-  nM	     U$ )z
product of tensors
r   re   N)r  r  r   r  )r   r   txs      r4   
tensor_mulr    sG       B33	!AeD Hr3   c                ,   [        U R                  S S9nU Vs/ s H  o"S   PM	     snu  p4pVU [        SS5      -  nU R                  X34XF4XT4Xe45      * [        SS5      -  nU R                  X34XE4XT4Xf45      [        SS5      -  n	Xx-   U	-   n
U
$ s  snf )z{
replace Riemann tensor with an equivalent expression

``R(m,n,p,q) -> 2/3*R(m,n,p,q) - 1/3*R(m,q,n,p) + 1/3*R(m,p,n,q)``

c                    U S   $ r   r2   rD   s    r4   rF   (riemann_cyclic_replace.<locals>.<lambda>  s    !A$r3   rH   r   rA   r  re   )r   rJ   r   r  )t_rrJ   rE   rg  rk   r  qt0r'  t2t3s              r4   riemann_cyclic_replacer    s     #((/D $%1A$%JA!	Xa^	B

 
 !uaUA5
9	9(1a.	HB			qeQE1%	8!Q	GB	2BI &s   Bc           
        U R                  5       n [        U [        [        45      (       a  U /nOU R                  nU Vs/ s H  o"R                  5       PM     nnU VVs/ s H  oD Vs/ s H  n[        U5      PM     snPM      nnnU Vs/ s H  n[        U6 PM     nn[        U6 R                  SS9n	U	(       d  U	$ [        U	5      $ s  snf s  snf s  snnf s  snf )a  
Replace each Riemann tensor with an equivalent expression
satisfying the cyclic identity.

This trick is discussed in the reference guide to Cadabra.

Examples
========

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorHead, riemann_cyclic, TensorSymmetry
>>> Lorentz = TensorIndexType('Lorentz', dummy_name='L')
>>> i, j, k, l = tensor_indices('i,j,k,l', Lorentz)
>>> R = TensorHead('R', [Lorentz]*4, TensorSymmetry.riemann())
>>> t = R(i,j,k,l)*(R(-i,-j,-k,-l) - 2*R(-i,-k,-j,-l))
>>> riemann_cyclic(t)
0
Fr  )r  r   r  r  r  r   r  r  r  r  rR   )
r
  r  rE   a1r  r  a2r   a3r  s
             r4   riemann_cyclicr    s    $ 
B"w'((tww!	"T'')TB	"<>	?Bq
2"!"%
2BB	?"$	%"Q*a."B	%	"				&B	| 
#
2	?	%s$    C	 	C)C>CCCc                T   S nU R                   n0 nU R                    H  n[        U[        5      (       d  M  XT;   a  M!  UR                  n/ n[	        [        U5      5       H  nXh   UL d  M  UR                  U5        M     [        U5      S:  a  [        SU-  5      e[        U5      S:X  d  M  XtU'   M     / n	/ n
/ nU R                   GHY  u  ppX>   U;  a  M  X:X  a  U
R                  U/5        M*  XCU      nXCU      nUU;  a  M@  UR                  U5      UR                  U5      :X  a  [        eXCU      nUUS   :X  a  X4OX4u  nnU	R                  5       nU	 H  nUS   U:X  ab  US   U:X  aF  UR                  [        U5      5      nUR                  U5        U
R                  UUS USU -   5        OUR                  U5          O4US   U:X  d  My  UR                  SU5          O   UR                  UU/5        U Vs/ s H  nUU;  d  M  UPM     n	nU" U	5      n	GM\     / nU	 H  nU H  nUR                  U5        M     M     U
 H  nU H  nUR                  U5        M     M     [	        [        U5      5       Vs/ s H  nUU;  d  M  UPM     nnXU4$ s  snf s  snf )z
Returns ``(lines, traces, rest)`` for an index type,
where ``lines`` is the list of list of positions of a matrix line,
``traces`` is the list of list of traced matrix lines,
``rest`` is the rest of the elements of the tensor.
c                   SnU[        U 5      :  Gaa  X   nUS   nUS   nSnU(       Ga2  Sn[        US-   [        U 5      5       GH	  nU[        U 5      :  a    OX   S   U:X  a0  SnUR                  X   SS  5        US   nU R                  U5        MP  X   S   U:X  a5  Sn[	        X   SS  5      U-   X'   X   nX   S   nU R                  U5        M  X   S   U:X  a9  SnUR                  [	        X   S S 5      5        US   nU R                  U5        M  X   S   U:X  d  M  SnX   S S U-   X'   X   nUS   nU R                  U5        GM     U(       a  GM2  US-  nU[        U 5      :  a  GMa  U $ )Nr   r   TFre   )rN   r   r^   r  reversed)r   rY   rE   xendxstarthitr   s          r4   _join_linesget_lines.<locals>._join_lines  s   #a&jAR5DqTFCq1uc!f-ACF{tAw$"ab* ua tAw&("'QR1A5D!"aa tBx4'"!$s)!45 ua tBx6)" tCRy1}D!"1a 9 . #> FAI #a&jJ r3   rA   z&at most two indices of type %s allowedre   r   r   N)r  r   r  rL   r   rN   rj   ri   r1  rm   rP  r~  mininsert)exr;  r  	argumentsdtr  rL   r   rY   linestracestraces1r>  r/  c0c1ta0ta1b0b1lines1linerk   rE   restr  s                             r4   	get_linesr+    s   'R I	BWW!X&&7mms;'(A~+ ) q6A:E
RSSq6Q;qE  EFG ..="8MM2$22S=99R=CIIbM)
 &% 23q6\"BDBx2~7b=

3t9-ANN4(MM$qr(T"1X"56KKOaBAr"  MM2r(#"7Fqaw&6F7E"K )L DAKKN   AKKN   S^,>,!A,D>$ 8 ?s   
J J 
J%J%c                N    [        U [        5      (       d  gU R                  5       $ Nr2   )r   r  r   r   s    r4   r   r   C  s!    a""r3   c                N    [        U [        5      (       d  gU R                  5       $ r-  )r   r  ru   r.  s    r4   ru   ru   I  s    a""==?r3   c                    [        U [        5      (       d  gU R                  5       nU R                  5       nU Vs/ s H  o3U;  d  M
  UPM     sn$ s  snf r-  )r   r  ru   r   )r   r^  rJ   rY   s       r4   r  r  N  sG    a""==?DD-t!}At---s   	AAc                `    [        U [        5      (       a  U R                  $ [        / / / / 5      $ r]   )r   r  rn  r>   r.  s    r4   ro  ro  U  s,    !X!!!2r2r**r3   c                    [        U [        5      (       a  [        R                  $ [        U [        5      (       a  U R
                  $ [        U [        5      (       a  [        S5      eU $ )Nz3no coefficient associated to this tensor expression)r   r  r   r  r  r'  r  ri   r.  s    r4   	get_coeffr3  [  sL    !Vuu!Www!XNOOHr3   c                R    [        U [        5      (       a  U R                  U5      $ U $ r]   )r   r  r  )r   r   s     r4   r  r  d  s%    !X  ##Hr3   c                    [        U [        5      (       d  U $ [        U [        [        45      (       aA  [	        U 5      R                  XS9nU R                  X2S9nUS   [        U5      S-
  :w  a  U* $ U$ [        5       e)r+  r  r   re   )	r   r  r  r  ro  r   r  rN   rP  )r   r   r   nimr  s        r4   r   r   i  s|     a""	A(	)	)!!$000L(((FR5CFQJ4K


r3   c                N    [        U [        5      (       d  U $ U R                  " U6 $ r]   )r   r  r  )r   r  s     r4   r  r  {  s%    a""..r3   c           	     f    [        U R                  [        [        [        [
        [        5      5      $ r]   )r   atomsr   r   r  r  r  r  s    r4   r  r    s    

4z?N[\\r3   c                   ^  U 4S jnU$ )Nc                   > [         [        [        [        0T   n[	        S U R
                   5       5      (       a  U" U R
                  6 $ U $ )Nc              3  B   #    U  H  n[        U[        5      v   M     g 7fr]   )r   r  )r  r   s     r4   r  <get_postprocessor.<locals>._postprocessor.<locals>.<genexpr>  s     :	1z!X&&	s   )r   r  r   r  r  r  )r  
tens_classr  s     r4   _postprocessor)get_postprocessor.<locals>._postprocessor  s?    7C1#6
:		:::tyy))Kr3   r2   )r  r?  s   ` r4   get_postprocessorrA    s     r3   r   rC   r   )kr   
__future__r   typingr   	functoolsr   mathr   abcr   r   collectionsr	   rP  r#  sympy.core.numbersr
   r   rS  r   sympy.combinatorics.tensor_canr   r   r   r   
sympy.corer   r   r   r   r   r   sympy.core.cacher   sympy.core.containersr   r   sympy.core.functionr   sympy.core.sortingr   sympy.core.symbolr   r   r   sympy.core.sympifyr    r!   sympy.core.operationsr"   sympy.external.gmpyr#   sympy.matricesr$   sympy.utilities.exceptionsr%   r&   r'   sympy.utilities.decoratorr(   r)   sympy.utilities.iterablesr*   r5   r9   r<   r>   r   r   r  r  r   rH  ry   r0  r   rV  rX  r;  r  r  r  r  r  r  r  r  r  r  r  rR   r  r  r  r+  r   ru   r  ro  r3  r  r   r  r  rA  "_constructor_postprocessor_mappingr2   r3   r4   <module>rX     s  > #    # #   2 +4 4 8 8 ( - , / 3 3 4 ) * 9 9 C *			h)k h)V	&s{ sj ":!; j jZ  k6e k6\	Z% Zz:A9U A9H  #:?,?,B ;"6
;_ ;_
;_|  #6,,0O5 O5dntS nbih iXaKX aKJDch DcL"W"H W"tUZ Upu unLk L^B"E B"J	Bup 
.+
 $/] 
c"#6 ( ( 2r3   