K i"nddlmZddlmZddlmZddlmZddlm Z ddl m Z m Z m Z mZGdde Zy ) ) permutedims)Number)S)Symbol)sympify)TensorTensExprTensAddTensMulceZdZdZdZedZedZedZ dZ dZ dZ d Z d Zd Zed Zed ZdZy)PartialDerivativea Partial derivative for tensor expressions. Examples ======== >>> from sympy.tensor.tensor import TensorIndexType, TensorHead >>> from sympy.tensor.toperators import PartialDerivative >>> from sympy import symbols >>> L = TensorIndexType("L") >>> A = TensorHead("A", [L]) >>> B = TensorHead("B", [L]) >>> i, j, k = symbols("i j k") >>> expr = PartialDerivative(A(i), A(j)) >>> expr PartialDerivative(A(i), A(j)) The ``PartialDerivative`` object behaves like a tensorial expression: >>> expr.get_indices() [i, -j] Notice that the deriving variables have opposite valence than the printed one: ``A(j)`` is printed as covariant, but the index of the derivative is actually contravariant, i.e. ``-j``. Indices can be contracted: >>> expr = PartialDerivative(A(i), A(i)) >>> expr PartialDerivative(A(L_0), A(L_0)) >>> expr.get_indices() [L_0, -L_0] The method ``.get_indices()`` always returns all indices (even the contracted ones). If only uncontracted indices are needed, call ``.get_free_indices()``: >>> expr.get_free_indices() [] Nested partial derivatives are flattened: >>> expr = PartialDerivative(PartialDerivative(A(i), A(j)), A(k)) >>> expr PartialDerivative(A(i), A(j), A(k)) >>> expr.get_indices() [i, -j, -k] Replace a derivative with array values: >>> from sympy.abc import x, y >>> from sympy import sin, log >>> compA = [sin(x), log(x)*y**3] >>> compB = [x, y] >>> expr = PartialDerivative(A(i), B(j)) >>> expr.replace_with_arrays({A(i): compA, B(i): compB}) [[cos(x), 0], [y**3/x, 3*y**2*log(x)]] The returned array is indexed by `(i, -j)`. Be careful that other SymPy modules put the indices of the deriving variables before the indices of the derivand in the derivative result. For example: >>> expr.get_free_indices() [i, -j] >>> from sympy import Matrix, Array >>> Matrix(compA).diff(Matrix(compB)).reshape(2, 2) [[cos(x), y**3/x], [0, 3*y**2*log(x)]] >>> Array(compA).diff(Array(compB)) [[cos(x), y**3/x], [0, 3*y**2*log(x)]] These are the transpose of the result of ``PartialDerivative``, as the matrix and the array modules put the index `-j` before `i` in the derivative result. An array read with index order `(-j, i)` is indeed the transpose of the same array read with index order `(i, -j)`. By specifying the index order to ``.replace_with_arrays`` one can get a compatible expression: >>> expr.replace_with_arrays({A(i): compA, B(i): compB}, [-j, i]) [[cos(x), y**3/x], [0, 3*y**2*log(x)]] ct|tr|j|z}|j}|j t ||\}}}}t j|g|}||_||_ ||_ |SN) isinstancer variablesexpr _contract_indices_for_derivativerr __new___indices_free_dum)clsrrargsindicesfreedumobjs ]/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/tensor/toperators.pyrzPartialDerivative.__new__`sy d- .2I99D#&#G#G dGY$  gtSs*T*   c"tjSr)rOneselfs rcoeffzPartialDerivative.coeffqs uu rc|Srr"s rnocoeffzPartialDerivative.nocoeffus rc .g}|D]u}t|trA|j}|j|j |Dcic]}|| c}Tt|t se|j|wt j|g|zd\}}} } tdt|D]R}||} t| ts||j} ||j | Dcic]}|| c}||<T||| | fScc}wcc}w)NT)replace_indices) rrget_free_indicesappendxreplacerr _tensMul_contract_indicesrangelen) rrrvariables_opposite_valenceii_free_indiceskrrrrargs_i i_indicess rrz2PartialDerivative._contract_indices_for_derivativeys%%'" 5A!V$!"!3!3!5*11 >#BaArE#BCEAv&*11!4  5$+#D#D F/ /$G gtSq#d)$ GA!WF&&) G446 q'**9+EaArE+EFQ  G WdC''$C,Fs  D 0 D c |j|j|j\}}}}|j|}||_||_||_|Sr)rrrfuncrrr)r#hintsrrrrrs rdoitzPartialDerivative.doitsR#'#H#HTXTbTb#c gtSdii   rc V|j|j|j\}}}}|j|}||_||_||_|}|djstjSt|jtrf|jj|jjDcgc]-}|j|g|jj/c}}|St|jtrt|jdk(rg}t!|jj} t#t| D]t} tt%| | t&r |j| | g|jj} |j)t| d| | gz| | dzdzvtj*|}|S|j}|jD]"} |j|| j}$|Scc}w)Nrr*)rrrr8rrr free_symbolsrZerorr r_expand_partial_derivativer r0listr/rrr,fromiter) r#rrrrrresultatermsmulargsinddvs rr>z,PartialDerivative._expand_partial_derivatives#'#H#HTXTbTb#c gtSdii  Aw##66M ' *"SXX]]#[[--%/DIIa0#--0KKM%/0F8 3' *3==!Q&sxx}}- W.HC%ggcl&;VD&DIIgclCS]]C^^` Wwt}230518#'1D0E&GH H!))%0 OA!YYvq1LLNFO 9%/s92H&c|j}|jD]R}t|tr|j |}%|j r|j |}Ctj}T|Sr) rrrr _eval_partial_derivative _diff_wrt_eval_derivativerr=)r#rArGs r_perform_derivativez%PartialDerivative._perform_derivatives_ $A&(+88;;;#44Q7FVVF $ rc|jSr)rr"s r get_indiceszPartialDerivative.get_indicess }}rcbt|jd}|Dcgc]}|d c}Scc}w)Nc |dSNr*r&)xs rz4PartialDerivative.get_free_indices..s !r)keyr)sortedr)r#rr2s rr+z"PartialDerivative.get_free_indicess*djjn5"#!###s ,c|jj|}|jDcic] \}}| |  }}}|jDcgc]}|j|}}|j|g|Scc}}wcc}wr)rr-itemsrr8)r#replrr4rGmirroredr2rs r_replace_indicesz"PartialDerivative._replace_indicessyyy!!$''+zz|4tq!QBF4437>>BaQZZ)B Btyy* **5Bs A<Bc |jdS)Nrrr"s rrzPartialDerivative.exprsyy|rc |jddSrQr\r"s rrzPartialDerivative.variablessyy}rc ddlm}m}|jj |\}}|j D]|}|j |\}}|D cgc]} | }} t |D cgc]} | jc} \} }t|j} |||}t|j} | | z } t|t| D cgc]} | | z c} tt| z}|j}|d}dgtt|D cgc] } tdc} z}t| D] \} }| |d<|t!|xx|zcc<"| |vr3|j#| }||d|dzf}|j%|l|j'|||fScc} wcc} wcc} wcc} w)Nr*)derive_by_arraytensorcontractionr)arrayr_r`r _extract_datarzip as_coeff_Mulr0shaperr/r? as_mutableslice enumeratetupleindexpopr,)r#replacement_dictr_r`rravariable var_indices var_arrayr2 coeff_array dim_before dim_after dim_increasevarindex coeff_indexr$poss rrbzPartialDerivative._extract_datas=001AB )H%-%;%;>+;*O%P "KU[[)J#E95EEKK(I$z1L% BS'TQL(8'TW[\abn\oWp'pqE$$&E"1~H#eCL6I Jt JJK%k2 35!" AeK()U2) 3yG#mmXI.)%!SU< C x(+ ),~)4*O (U!Ks F7$F< G "GN)__name__ __module__ __qualname____doc__rpropertyr$r' classmethodrr:r>rLrNr+rZrrrbr&rrr r sTl"((,*X $+ rr N)sympyrsympy.core.numbersrsympy.core.singletonrsympy.core.symbolrsympy.core.sympifyrsympy.tensor.tensorrr r r r r&rrrs(%"$&BBwwr