K ij~dZddlmZddlmZddlmZddlmZm Z m Z m Z ddl m Z ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZdd lmZmZed k7rd d gZ Gd de!Z"ddl#m$Z$ddl%m&Z&y)a Module for the DDM class. The DDM class is an internal representation used by DomainMatrix. The letters DDM stand for Dense Domain Matrix. A DDM instance represents a matrix using elements from a polynomial Domain (e.g. ZZ, QQ, ...) in a dense-matrix representation. Basic usage: >>> from sympy import ZZ, QQ >>> from sympy.polys.matrices.ddm import DDM >>> A = DDM([[ZZ(0), ZZ(1)], [ZZ(-1), ZZ(0)]], (2, 2), ZZ) >>> A.shape (2, 2) >>> A [[0, 1], [-1, 0]] >>> type(A) >>> A @ A [[-1, 0], [0, -1]] The ddm_* functions are designed to operate on DDM as well as on an ordinary list of lists: >>> from sympy.polys.matrices.dense import ddm_idet >>> ddm_idet(A, QQ) 1 >>> ddm_idet([[0, 1], [-1, 0]], QQ) 1 >>> A [[-1, 0], [0, -1]] Note that ddm_idet modifies the input matrix in-place. It is recommended to use the DDM.det method as a friendlier interface to this instead which takes care of copying the matrix: >>> B = DDM([[ZZ(0), ZZ(1)], [ZZ(-1), ZZ(0)]], (2, 2), ZZ) >>> B.det() 1 Normally DDM would not be used directly and is just part of the internal representation of DomainMatrix which adds further functionality including e.g. unifying domains. The dense format used by DDM is a list of lists of elements e.g. the 2x2 identity matrix is like [[1, 0], [0, 1]]. The DDM class itself is a subclass of list and its list items are plain lists. Elements are accessed as e.g. ddm[i][j] where ddm[i] gives the ith row and ddm[i][j] gets the element in the jth column of that row. Subclassing list makes e.g. iteration and indexing very efficient. We do not override __getitem__ because it would lose that benefit. The core routines are implemented by the ddm_* functions defined in dense.py. Those functions are intended to be able to operate on a raw list-of-lists representation of matrices with most functions operating in-place. The DDM class takes care of copying etc and also stores a Domain object associated with its elements. This makes it possible to implement things like A + B with domain checking and also shape checking so that the list of lists representation is friendlier. )chain) GROUND_TYPES)doctest_depends_on)DMBadInputError DMDomainErrorDMNonSquareMatrixError DMShapeError)QQ) ddm_transposeddm_iaddddm_isubddm_inegddm_imul ddm_irmul ddm_imatmul ddm_irref ddm_irref_denddm_idetddm_iinv ddm_ilu_split ddm_ilu_solveddm_berk)ddm_lllddm_lll_transformflintz DDM.to_dfmzDDM.to_dfm_or_ddmceZdZdZdZdZdZfdZdZdZ dZ d Z e d Z e d Zd Zd Ze dZdZdZdZe dZdZe dZdZe dZdZdZdZdZedgdZedgdZ dZ!d Z"d!Z#fd"Z$d#Z%e d$Z&e d%Z'e d&Z(d'Z)d(Z*d)Z+d*Z,d+Z-d,Z.d-Z/d.Z0e d/Z1d0Z2d1Z3d2Z4d3Z5d4Z6d5Z7d6Z8d7Z9d8Z:d9Z;d:Zd=Z?d>Z@d?ZAdSd@ZBdAZCdBZDdCZEdDZFdEZGdFZHdGZIdHZJdIZKdJZLdKZMdLZNdMZOdNZPeQdOdPfdQZReQdOdPfdRZSxZTS)TDDMzDense matrix based on polys domain elements This is a list subclass and is a wrapper for a list of lists that supports basic matrix arithmetic +, -, *, **. denseFTcbt|trtd|Ds td|\}t ||k7st fd|Dr tdt ||Dcgc]}|jc}|f|_ ||_ |_ ||_ ycc}w)Nc3>K|]}t|tuywN)typelist.0rows ^/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/polys/matrices/ddm.py zDDM.__init__..rs2Y493D2Ysz rowslist must be a list of listsc3:K|]}t|k7ywr")len)r&r'ns r(r)zDDM.__init__..us$GsSX]$GszInconsistent row-list/shape) isinstancer$allrr+anysuper__init__copyshaperowscolsdomain)selfrowslistr3r6mir, __class__s @r(r1z DDM.__init__qs8T*s2YPX2Y/Y!"DE E1 x=A $Gh$G!G!"?@ @ H5q!&&(56V    6s/B,c|||Sr")r7r:js r(getitemz DDM.getitem~sAwqzc||||<yr"r=)r7r:r>values r(setitemz DDM.setitemsQ r@c||Dcgc]}|| }}t|}|rt|dn#tt|jd|}t|||f|jScc}w)Nrr)r+ranger3rr6)r7slice1slice2r'ddmr4r5s r( extract_slicezDDM.extract_slicesj&*6l3ss6{333x!s3q6{s5A+?+G'H3t dkk224s A.cg}|D])}||}|j|Dcgc]}|| c}+t|t|t|f|jScc}wr")appendrr+r6)r7r4r5rHr:rowir>s r(extractz DDM.extractsa 0A7D JJ.AQ. / 03TCI. <</s A c||||S)a Create a :class:`DDM` from a list of lists. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.ddm import DDM >>> A = DDM.from_list([[ZZ(0), ZZ(1)], [ZZ(-1), ZZ(0)]], (2, 2), ZZ) >>> A [[0, 1], [-1, 0]] >>> A == DDM([[ZZ(0), ZZ(1)], [ZZ(-1), ZZ(0)]], (2, 2), ZZ) True See Also ======== from_list_flat r=)clsr8r3r6s r( from_listz DDM.from_lists*8UF++r@c"|jSr")r2)rOothers r(from_ddmz DDM.from_ddmszz|r@c2|Dcgc]}|dd c}Scc}w)a Convert to a list of lists. Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.ddm import DDM >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> A.to_list() [[1, 2], [3, 4]] See Also ======== to_list_flat sympy.polys.matrices.domainmatrix.DomainMatrix.to_list Nr=r7r's r(to_listz DDM.to_lists&#''3A'''s c:g}|D]}|j||S)a Convert to a flat list of elements. Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.ddm import DDM >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> A.to_list_flat() [1, 2, 3, 4] >>> A == DDM.from_list_flat(A.to_list_flat(), A.shape, A.domain) True See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.to_list_flat extend)r7flatr's r( to_list_flatzDDM.to_list_flats)( C KK   r@ct|tusJ|\}}t|||zk(s tdt |Dcgc]}|||z|dz|z}}||||Scc}w)a Create a :class:`DDM` from a flat list of elements. Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.ddm import DDM >>> A = DDM.from_list_flat([1, 2, 3, 4], (2, 2), QQ) >>> A [[1, 2], [3, 4]] >>> A == DDM.from_list_flat(A.to_list_flat(), A.shape, A.domain) True See Also ======== to_list_flat sympy.polys.matrices.domainmatrix.DomainMatrix.from_list_flat zInconsistent flat-list shaper)r#r$r+rrE)rOrZr3r6r4r5r:lols r(from_list_flatzDDM.from_list_flatsy,DzT!!! dD T$Y&!"@A A05d <1tAdFAaC:&<<3v&&=sA#c,tj|Sr")r from_iterabler7s r(flatiterz DDM.flatiters""4((r@c:g}|D]}|j||Sr"rX)r7itemsr's r(rZzDDM.flats' C LL   r@c>|jjS)a@ Convert to a flat list of nonzero elements and data. Explanation =========== This is used to operate on a list of the elements of a matrix and then reconstruct a matrix using :meth:`from_flat_nz`. Zero elements are included in the list but that may change in the future. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> elements, data = A.to_flat_nz() >>> elements [1, 2, 3, 4] >>> A == DDM.from_flat_nz(elements, data, A.domain) True See Also ======== from_flat_nz sympy.polys.matrices.sdm.SDM.to_flat_nz sympy.polys.matrices.domainmatrix.DomainMatrix.to_flat_nz )to_sdm to_flat_nzras r(rgzDDM.to_flat_nzs<{{}''))r@cLtj|||jS)aF Reconstruct a :class:`DDM` after calling :meth:`to_flat_nz`. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> elements, data = A.to_flat_nz() >>> elements [1, 2, 3, 4] >>> A == DDM.from_flat_nz(elements, data, A.domain) True See Also ======== to_flat_nz sympy.polys.matrices.sdm.SDM.from_flat_nz sympy.polys.matrices.domainmatrix.DomainMatrix.from_flat_nz )SDM from_flat_nzto_ddm)rOelementsdatar6s r(rjzDDM.from_flat_nz s"0$7>>@@r@ci}t|D].\}}t|Dcic] \}}|s || }}}|s*|||<0|Scc}}w)a Convert to a dictionary of dictionaries (dod) format. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> A.to_dod() {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}} See Also ======== from_dod sympy.polys.matrices.sdm.SDM.to_dod sympy.polys.matrices.domainmatrix.DomainMatrix.to_dod  enumerate)r7dodr:r'r>es r(to_dodz DDM.to_dod:sY(o FAs#,S>741aQ1Q37C7A  8s AAc|\}}t|Dcgc]}|jg|z}}|jD]%\}} | jD] \} } | ||| <'t|||Scc}w)a Create a :class:`DDM` from a dictionary of dictionaries (dod) format. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> dod = {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}} >>> A = DDM.from_dod(dod, (2, 2), QQ) >>> A [[1, 2], [3, 4]] See Also ======== to_dod sympy.polys.matrices.sdm.SDM.from_dod sympy.polys.matrices.domainmatrix.DomainMatrix.from_dod rEzerordr) rOrqr3r6r4r5_r]r:r'r>elements r(from_dodz DDM.from_dodUs, d-24[9 }t#99iik $FAs!iik $ 7#Aq  $ $3v&& :sA1cji}t|D]"\}}t|D]\}}|s ||||f<$|S)a Convert :class:`DDM` to dictionary of keys (dok) format. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> A.to_dok() {(0, 0): 1, (0, 1): 2, (1, 0): 3, (1, 1): 4} See Also ======== from_dok sympy.polys.matrices.sdm.SDM.to_dok sympy.polys.matrices.domainmatrix.DomainMatrix.to_dok ro)r7dokr:r'r>rxs r(to_dokz DDM.to_dokrsN(o (FAs'n ( 7 'C1I ( ( r@c|\}}t|Dcgc]}|jg|z}}|jD]\\}} } | ||| <t|||Scc}w)a Create a :class:`DDM` from a dictionary of keys (dok) format. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> dok = {(0, 0): 1, (0, 1): 2, (1, 0): 3, (1, 1): 4} >>> A = DDM.from_dok(dok, (2, 2), QQ) >>> A [[1, 2], [3, 4]] See Also ======== to_dok sympy.polys.matrices.sdm.SDM.from_dok sympy.polys.matrices.domainmatrix.DomainMatrix.from_dok ru) rOr{r3r6r4r5rwr]r:r>rxs r(from_dokz DDM.from_doksm, d-24[9 }t#99"yy{ OFQGCF1I 3v&&:sAc#FK|D]}td|Ed{y7w)a Iterate over the non-zero values of the matrix. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[QQ(1), QQ(0)], [QQ(3), QQ(4)]], (2, 2), QQ) >>> list(A.iter_values()) [1, 3, 4] See Also ======== iter_items to_list_flat sympy.polys.matrices.domainmatrix.DomainMatrix.iter_values N)filterrUs r( iter_valueszDDM.iter_valuess*( )CdC( ( ( ) (s !!c#nKt|D]#\}}t|D]\}}|s ||f|f%yw)a Iterate over indices and values of nonzero elements of the matrix. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[QQ(1), QQ(0)], [QQ(3), QQ(4)]], (2, 2), QQ) >>> list(A.iter_items()) [((0, 0), 1), ((1, 0), 3), ((1, 1), 4)] See Also ======== iter_values to_dok sympy.polys.matrices.domainmatrix.DomainMatrix.iter_items Nro)r7r:r'r>rxs r( iter_itemszDDM.iter_itemssG( o *FAs'n * 7a&'/) * *s%5 5c|S)au Convert to a :class:`DDM`. This just returns ``self`` but exists to parallel the corresponding method in other matrix types like :class:`~.SDM`. See Also ======== to_sdm to_dfm to_dfm_or_ddm sympy.polys.matrices.sdm.SDM.to_ddm sympy.polys.matrices.domainmatrix.DomainMatrix.to_ddm r=ras r(rkz DDM.to_ddms  r@cXtj||j|jS)a Convert to a :class:`~.SDM`. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> A.to_sdm() {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}} >>> type(A.to_sdm()) See Also ======== SDM sympy.polys.matrices.sdm.SDM.to_ddm )rirPr3r6ras r(rfz DDM.to_sdms*}}T4::t{{;;r@r) ground_typescVtt||j|jS)a Convert to :class:`~.DDM` to :class:`~.DFM`. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> A.to_dfm() [[1, 2], [3, 4]] >>> type(A.to_dfm()) See Also ======== DFM sympy.polys.matrices._dfm.DFM.to_ddm )DFMr$r3r6ras r(to_dfmz DDM.to_dfms,4:tzz4;;77r@cdtj|jr|jS|S)a Convert to :class:`~.DFM` if possible or otherwise return self. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy import QQ >>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ) >>> A.to_dfm_or_ddm() [[1, 2], [3, 4]] >>> type(A.to_dfm_or_ddm()) See Also ======== to_dfm to_ddm sympy.polys.matrices.domainmatrix.DomainMatrix.to_dfm_or_ddm )r_supports_domainr6rras r( to_dfm_or_ddmzDDM.to_dfm_or_ddms'.    ,;;=  r@c |j}||k(r|jS|Dcgc]"}|Dcgc]}|j||c}$}}}t||j|Scc}wcc}}wr")r6r2 convert_fromrr3)r7KKoldr'rrr4s r( convert_tozDDM.convert_to5sb{{ 999; BFG3#6Q4(6GG4Q''7Gs A-A( A-(A-c |Dcgc]$}ddjtt|z&}}ddj|zScc}w)Nz[%s], )joinmapstr)r7r'rowsstrs r(__str__z DDM.__str__<sC@DE6DIIc#sm44EE '***Fs)Act|j}tj|}|d|d|jd|j dS)N(r))r#__name__r$__repr__r3r6)r7rOr4s r(rz DDM.__repr__@s64j!!}}T"#&djj$++FFr@czt|tsyt| |xr|j|jk(S)NF)r-rr0__eq__r6)r7rRr;s r(rz DDM.__eq__Es1%%u%E$++*EFr@c&|j| Sr")r)r7rRs r(__ne__z DDM.__ne__Js;;u%%%r@c|j}|\}}t|Dcgc]}|g|z }}t|||Scc}wr")rvrEr)rOr3r6zr9r,rwr8s r(zerosz DDM.zerosMsE KK1%*1X.QC!G..8UF++/ ;c|j}|\}}t|Dcgc]}|g|z }}t|||Scc}wr")onerEr)rOr3r6rr9r,rwrowlists r(oneszDDM.onesTsEjj1&+Ah/C519//7E6**0rct|tr|\}}nt|tr|x}}|j}|j f|}t t ||D] }||||< |Sr")r-tupleintrrrEmin)rOsizer6r9r,rrHr:s r(eyezDDM.eye[sq dE "DAq c "LAjjiiA's1ay! ACF1I  r@cr|Dcgc]}|dd }}t||j|jScc}wr")rr3r6)r7r'copyrowss r(r2zDDM.copygs5&*+sCF++8TZZ55,s 4cz|j\}}|r t|}ngg|z}t|||f|jSr")r3r rr6)r7r4r5ddmTs r( transposez DDM.transposeks>ZZ d  &D4$;D4$t{{33r@cPt|tstS|j|Sr")r-rNotImplementedaddabs r(__add__z DDM.__add__s!S!! !uuQxr@cPt|tstS|j|Sr")r-rrsubrs r(__sub__z DDM.__sub__xrr@c"|jSr")negrs r(__neg__z DDM.__neg__}s uuwr@cL||jvr|j|StSr"r6mulrrs r(__mul__z DDM.__mul__ =558O! !r@cL||jvr|j|StSr"rrs r(__rmul__z DDM.__rmul__rr@cPt|tr|j|StSr")r-rmatmulrrs r( __matmul__zDDM.__matmul__s a 88A; ! !r@c|j|jk7r*d|jd|d|j}t|||k7r*d|jd|d|j}t|y)NzDomain mismatch:  zShape mismatch: )r6rr3r )rOroprashapebshapemsgs r(_checkz DDM._checks] 88qxx 122qxxHC$ $ V 01QWWECs# # r@c|j|d||j|j|j}t|||S)za + b+)rr3r2r rrcs r(rzDDM.add7 CAGGQWW- FFHAr@c|j|d||j|j|j}t|||S)za - b-)rr3r2rrs r(rzDDM.subrr@c<|j}t||S)z-a)r2rrs r(rzDDM.negs FFH r@c>|j}t|||Sr")r2rrs r(rzDDM.muls FFHAr@c>|j}t|||Sr")r2rrs r(rmulzDDM.rmuls FFH!Qr@c|j\}}|j\}}|j|d||||j||f|j}t ||||S)za @ b (matrix product)*)r3rrr6r)rrr9oo2r,rs r(rz DDM.matmulsYww1A CAr" GGQFAHH %Aq!r@c P|j|jk(sJ|j|jk(sJt||Dcgc]'\}}t||Dcgc] \}}||z c}})}}}}}t||j|jScc}}wcc}}}}wr")r3r6zipr)rraibiaijbijrs r(mul_elementwisezDDM.mul_elementwisesww!''!!!xx188###CFq!9 M MRB 4HCcCi 4 M M1aggqxx((5 MsB B.B B cPt|j}|j\}}|j}|D]U}|j\}}||k(sJ|j|k(sJ||z }t |D]\} } || j | Wt |||f|jS)a Horizontally stacks :py:class:`~.DDM` matrices. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import DDM >>> A = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) >>> B = DDM([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ) >>> A.hstack(B) [[1, 2, 5, 6], [3, 4, 7, 8]] >>> C = DDM([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ) >>> A.hstack(B, C) [[1, 2, 5, 6, 9, 10], [3, 4, 7, 8, 11, 12]] )r$r2r3r6rprYr) ABAnewr4r5r6BkBkrowsBkcolsr:Bkis r(hstackz DDM.hstacks$AFFH~WW d $BXXNFFT> !>99& && FND#B- $3Qs# $ $4$qxx00r@c@t|j}|j\}}|j}|D]M}|j\}}||k(sJ|j|k(sJ||z }|j |jOt |||f|jS)aVertically stacks :py:class:`~.DDM` matrices. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import DDM >>> A = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) >>> B = DDM([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ) >>> A.vstack(B) [[1, 2], [3, 4], [5, 6], [7, 8]] >>> C = DDM([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ) >>> A.vstack(B, C) [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]] )r$r2r3r6rYr) rrrr4r5r6rrrs r(vstackz DDM.vstacks$AFFH~WW d #BXXNFFT> !>99& && FND KK " #4$qxx00r@c ~|Dcgc]}tt||}}t||j|Scc}wr")r$rrr3)r7funcr6r'rls r( applyfuncz DDM.applyfunc s8489SDT3(998TZZ00:s:c&td|DS)zNumber of non-zero entries in :py:class:`~.DDM` matrix. See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.nnz c3NK|]}ttt|ywr")sumrboolr%s r(r)zDDM.nnz..s433s4~&4s#%)rrs r(nnzzDDM.nnzs4!444r@c>|jjS)aStrongly connected components of a square matrix *a*. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import DDM >>> A = DDM([[ZZ(1), ZZ(0)], [ZZ(0), ZZ(1)]], (2, 2), ZZ) >>> A.scc() [[0], [1]] See also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.scc )rfsccrs r(rzDDM.sccs$xxz~~r@cJtj||jS)a|Returns a square diagonal matrix with *values* on the diagonal. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import DDM >>> DDM.diag([ZZ(1), ZZ(2), ZZ(3)], ZZ) [[1, 0, 0], [0, 2, 0], [0, 0, 3]] See also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.diag )ridiagrk)rOvaluesr6s r(rzDDM.diag-s"xx'..00r@c|j}|j}|jxs |j}t ||}||fS)a"Reduced-row echelon form of a and list of pivots. See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.rref Higher level interface to this function. sympy.polys.matrices.dense.ddm_irref The underlying algorithm. )_partial_pivot)r2r6 is_RealFieldis_ComplexFieldr)rrr partial_pivotpivotss r(rrefzDDM.rref@sB FFH HH;!*;*; 1];&yr@cb|j}|j}t||\}}|||fS)a:Reduced-row echelon form of a with denominator and list of pivots See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.rref_den Higher level interface to this function. sympy.polys.matrices.dense.ddm_irref_den The underlying algorithm. )r2r6r)rrrdenomrs r(rref_denz DDM.rref_denQs5 FFH HH%a+ v%r@cJ|j\}}|j|S)zReturns a basis for the nullspace of a. The domain of the matrix must be a field. See Also ======== rref sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace )r nullspace_from_rref)rr rs r( nullspacez DDM.nullspaceas$vvx f''//r@c|j\}}|j}|Gg}d}t|D]5}||}t|dz|D]}||s |}|j|57|s&|j ||t t|fS|d|d} g} g} t|D]x}||vr| j|t|Dcgc]}||k(r| n |j } }t|D]\} }| |xx|| |zcc<| j| zt| t| |f|}|| fScc}w)a9Compute the nullspace of a matrix from its rref. The domain of the matrix can be any domain. Returns a tuple (basis, nonpivots). See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace The higher level interface to this function. rr) r3r6rErKrr$rvrprr+)rrr9r,r last_pivotr:rr> pivot_valbasis nonpivotsveciijj basis_ddms r(rzDDM.nullspace_from_rrefosmww1 HH >FJ1X qTz!|Q/A!u%&  a(  EE!QKeAh0 0aDO  q AF{   Q cZ|jjjSr")rf particularrkrs r(rzDDM.particulars xxz$$&--//r@c|j\}}||k7r td|j}|j}t ||}|S)zDeterminant of a Determinant of non-square matrix)r3r r2r6r)rr9r,rrdetas r(detzDDM.detsFww1 6()KL L FFH HH1~ r@c|j\}}||k7r td|j}|j}t ||||S)z Inverse of ar)r3r r2r6r)rr9r,ainvrs r(invzDDM.invsGww1 6()KL Lvvx HHq! r@c|j\}}|j}|j}|j||}t |||}|||fS)zL, U decomposition of a)r3r6r2rr)rr9r,rULswapss r(luzDDM.lusLww1 HH FFH EE!QKaA&!U{r@c |j\}}|j |j tt |}d}t t ||D] t fdt |Dr$d}t ||D]} |  jk7s|}n|dk(rV||k7r" | |c |< |<||||c||<||< | }t |dz|D]r} | }|dkDr |dz |dz n j} t dz|D]/} j| || z || |zz |  || <1| | <t|dz } |fS)a& Private method for Phase 1 of fraction-free LU decomposition. Performs row operations and elimination to compute U and permutation indices. Returns: LU : decomposition as a single matrix. perm (list): Permutation indices for row swaps. rc3HK|]}|jk(ywr")rv)r&r:rLUr>s r(r)zDDM._fflu..s";!2a58qvv%;"rr) r3r6r2r$rErr.rvrexquo)r7r4r5permrank pivot_rowr:pivot multiplier denominatorkrr*r>s @@@r(_ffluz DDM._fflusZZ d KK YY[E$K s4' A;uT{;;I4& a58qvv% !I  BD *,Y-D'4"Y-.29otDz+T DOtHQKE4!8T* &U1X 8lDdis r(ffluzDDM.fflusZZ d KK**,4 JJd|Q 't_ EAruuAaDH  JJd|Q ' A$h1t8tAw!&& A$q'!Qq1ud+%Ad1gAaDGffAaDG % Q FA$h1t8q$ AeeAaDG  JJd|Q ' 19d1gAaDG UUq$ A1q5!a%1Q47*BAaDG  !Qzr@c  |j\ }|j |j |jt ||f } j s t d fd}t|D]}tt | D]\}|||}| jk7s||||z |||<t D]!} ||xx||| ||zzcc<#^| ks}|||}| jk7s j|||< jt tt | |fS)a4 QR decomposition for DDM. Returns: - Q: Orthogonal matrix as a DDM. - R: Upper triangular matrix as a DDM. See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.qr The higher-level interface to this function. z,QR decomposition requires a field (e.g. QQ).cRjfdtDS)Nc3@K|]}||zywr"r=)r&r3Qr:r>s r(r)z+DDM.qr....As&%MAad1g!Q&7%Ms)rrE)r:r>rr?r4s``r(zDDM.qr..As%Mt%M Mr@) r3r6r2rris_FieldrrErvrrM) r7r5Rdot_colsr>r:dot_iir3dot_jjrr?r4s @@@r(qrzDDM.qr*sLZZ d KK IIK JJD$. 2zz NO OMt $A3q$<( 5!!QQVV#&q!nv5AaDG"4[5!Q1Q47QqT!W#445  54x!!QQVV#eeAaDG $ IIeDk5T4#9 :!t r@c0|j\}}|j\}}|j|d||||jjs t d|j \}}}|j ||f|j} t| ||||| S)zx where a*x = blu_solvezlu_solve requires a field)r3rr6rArr'rr) rrr9r,m2rr%r$r&xs r(rHz DDM.lu_solveTsww1A J1b)xx   ;< <ddf 1e GGQFAHH %aAua(r@c|j}|j\}}||k7r tdt||}t |dzDcgc] }||d }}|Scc}w)z.Coefficients of characteristic polynomial of azCharpoly of non-square matrixrr)r6r3r rrE)rrr9r,rr:coeffss r(charpolyz DDM.charpolyasc HHww1 6()HI Iq!n%*1Q3Z0#a&)00 1sAct|jjtfd|jDS)z@ Says whether this matrix has all zero entries. c3(K|] }|k( ywr"r=)r&Mijrvs r(r)z%DDM.is_zero_matrix..ps:33$;:s)r6rvr.rbr7rvs @r(is_zero_matrixzDDM.is_zero_matrixks+{{:$--/:::r@cj|jjtfdt|DS)z~ Says whether this matrix is upper-triangular. True can be returned even if the matrix is not square. c3BK|]\}}|d|D] }|k( ywr"r=r&r:MirPrvs r(r)zDDM.is_upper..xs+N51br"1vN3$;N;Nsr6rvr.rprQs @r(is_upperz DDM.is_upperrs) {{NIdONNNr@cj|jjtfdt|DS)z~ Says whether this matrix is lower-triangular. True can be returned even if the matrix is not square. c3HK|]\}}||dzdD] }|k( yw)rNr=rUs r(r)zDDM.is_lower..s/P51br!A#$xP3$;P;Pr+rWrQs @r(is_lowerz DDM.is_lowerzs) {{PIdOPPPr@cF|jxr|jS)zv Says whether this matrix is diagonal. True can be returned even if the matrix is not square. )rXr[ras r( is_diagonalzDDM.is_diagonals }}24==?2r@c||j\}}tt||Dcgc] }||| c}Scc}w)zQ Returns a list of the elements from the diagonal of the matrix. )r3rEr)r7r9r,r:s r(diagonalz DDM.diagonals8zz1$)#a)$45qQ 555s9ct||SN)delta)rrrds r(lllzDDM.lllsq&&r@ct||Src)rres r( lll_transformzDDM.lll_transforms %00r@r")Ur __module__ __qualname____doc__fmtis_DFMis_DDMr1r?rCrIrM classmethodrPrSrVr[r^rbrZrgrjrsryr|r~rrrkrfrrrrrrrrrrrr2rrrrrrrrrrrrrrrrrrrrrr r rrrrr"r'r4r;rFrHrMrRrXr[r]r_r rfrh __classcell__)r;s@r(rrfs C F F 3 =,,,(*2''8) *@AA26''86''6).*2$<.gY/808.gY/04(+G G &,, ++   64  " " " $$   ) 1D1B15 (11$" 0.&`0 1f4l(T ;OQ361X' "!Qx1r@r)ri)rN)'rk itertoolsrsympy.external.gmpyrsympy.utilities.decoratorr exceptionsrrr r sympy.polys.domainsr rr r rrrrrrrrrrrrrfrr__doctest_skip__r$rsdmridfmrr=r@r(rysk>~,8#    ",7$&9:n1$n1b!r@