K i%dZddlmZmZmZmZmZddlmZddl m Z ddl m Z ddl mZddlmZmZmZdd lmZdd lmZe d k7rd d gZGddeZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%y)z Module for the SDM class. )addnegpossubmul) defaultdict) GROUND_TYPES)doctest_depends_on)_strongly_connected_components)DMBadInputError DMDomainError DMShapeError)QQ)DDMflintz SDM.to_dfmzSDM.to_dfm_or_ddmceZdZdZdZdZdZfdZdZdZ dZ dZ d Z d Z ed Zd Zed ZedZdZdZedZdZedZdZedZdZedZdZdZdZdZe dgdZ!e dgdZ"ed Z#ed!Z$ed"Z%edLd#Z&d$Z'd%Z(d&Z)d'Z*d(Z+d)Z,d*Z-d+Z.d,Z/d-Z0d.Z1d/Z2d0Z3d1Z4d2Z5d3Z6d4Z7d5Z8d6Z9d7Z:d8Z;d9Zd<Z?dLd=Z@d>ZAd?ZBd@ZCdAZDdBZEdCZFdDZGdEZHdFZIdGZJeKdHdIfdJZLeKdHdIfdKZMxZNS)MSDMaSparse matrix based on polys domain elements This is a dict subclass and is a wrapper for a dict of dicts that supports basic matrix arithmetic +, -, *, **. In order to create a new :py:class:`~.SDM`, a dict of dicts mapping non-zero elements to their corresponding row and column in the matrix is needed. We also need to specify the shape and :py:class:`~.Domain` of our :py:class:`~.SDM` object. We declare a 2x2 :py:class:`~.SDM` matrix belonging to QQ domain as shown below. The 2x2 Matrix in the example is .. math:: A = \left[\begin{array}{ccc} 0 & \frac{1}{2} \\ 0 & 0 \end{array} \right] >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> elemsdict = {0:{1:QQ(1, 2)}} >>> A = SDM(elemsdict, (2, 2), QQ) >>> A {0: {1: 1/2}} We can manipulate :py:class:`~.SDM` the same way as a Matrix class >>> from sympy import ZZ >>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) >>> B = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ) >>> A + B {0: {0: 3, 1: 2}, 1: {0: 1, 1: 4}} Multiplication >>> A*B {0: {1: 8}, 1: {0: 3}} >>> A*ZZ(2) {0: {1: 4}, 1: {0: 2}} sparseFct|||x|_x\|_|_\||_t fd|Ds tdt fd|jDs tdy)Nc3>K|]}d|cxkxrkncywrN).0rms ^/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/polys/matrices/sdm.py zSDM.__init__..Ss,!1:A::,szRow out of rangec3LK|]}|D]}d|cxkxrkncywrr)rrowcns rrzSDM.__init__..Us'D#D11:A::D:Ds!$zColumn out of range) super__init__shaperowscolsdomainallr values)self elemsdictr%r(rr" __class__s @@rr$z SDM.__init__Nsu #388 8)TY DAq ,t,,!"45 5DDD!"78 8Ec6 |||S#t$r|j\}}| |cxkr|kr^n t d| |cxkr|krEn t d |||z||zcYS#t$r|jjcYcYSwxYwt dwxYwNzindex out of range)KeyErrorr%r(zero IndexError)r+ijrr"s rgetitemz SDM.getitemXs 771:  7::DAqrQ{{ !!566 !"rQ{{ !!566 ,A;q1u--,;;+++,!!566 7s. A B A%"B%B BB  BcN|j\}}| |cxkr|kr%n td| |cxkr|kstdtd||z||z}}|r ||||<y|j|d}| ||=|s||=yyy#t$r ||i||<YywxYw#t$rYywxYwr0)r%r3r1get)r+r4r5valuerr"rowis rsetitemz SDM.setitemeszz1a ! 12 2"#a ! 12 2!,12 21ua!e1  %"Q 88At$D$Q  G   %e*Q % s$B7BBB B$#B$c|j\}}t||}t||}i}|jD]X\}} ||vs | jD cic]\} } | |vs |j| | } } } | sE| ||j|<Z|j |t |t |f|j Scc} } wN)r%rangeitemsindexnewlenr() r+slice1slice2rr"ricisdmr4r r5es r extract_slicezSDM.extract_slicezszz1 1Xf  1Xf jjl +FAsBw25))+I$!Qbrxx{A~II'*C $  + xxc"gs2w/== Js  C )C c|r|r|s0|jt|t|f|jS|j\}}| t |cxkrt |cxkr|kst dt d| t |cxkrt |cxkr|kst dt dtt}tt}t|D]\}}|||zj|t|D]\} } || |zj| t|} t|} |} i}| | jzD]U}| |}i}| |jzD]} || }|| D]} ||| < |s9||D]}|j||<W|j|t|t|f|jS)NzRow index out of rangezColumn index out of range)zerosrBr(r%minmaxr3rlist enumerateappendsetkeyscopyrA)r+r&r'rr"rowmapcolmapi2i1j2j1rowsetcolsetsdm1sdm2row1row2row1_j1s rextractz SDM.extracts$::s4y#d)4dkkB Bzz1c$i03t90q056 6156 6c$i03t90q089 9189 9T"T"o &FB 26N ! !" % &o &FB 26N ! !" % &VV499;& +B8DDtyy{* 'r( *'B&DH' ' *+B#yy{DH+ +xxs4y#d)4dkkBBr.cg}|jD]B\}}djd|jD}|j|d|dDddj|zS)N, c30K|]\}}|d|yw)z: Nr)rr5elems rrzSDM.__str__..s Q'!TQ!5 Qsz: {}z{%s})r?joinrP)r+rowsstrr4r elemsstrs r__str__z SDM.__str__sajjl 7FAsyy QSYY[ QQH NNH5 6 7 '***r.ct|j}tj|}|d|d|jd|j dS)N(rc))type__name__dict__repr__r%r()r+clsr&s rrqz SDM.__repr__s64j!!}}T"#&djj$++FFr.c||||S)a Parameters ========== sdm: A dict of dicts for non-zero elements in SDM shape: tuple representing dimension of SDM domain: Represents :py:class:`~.Domain` of SDM Returns ======= An :py:class:`~.SDM` object Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> elemsdict = {0:{1: QQ(2)}} >>> A = SDM.new(elemsdict, (2, 2), QQ) >>> A {0: {1: 2}} r)rrrGr%r(s rrAzSDM.news63v&&r.c|jDcic]\}}||j}}}|j||j|jScc}}w)aT Returns the copy of a :py:class:`~.SDM` object Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> elemsdict = {0:{1:QQ(2)}, 1:{}} >>> A = SDM(elemsdict, (2, 2), QQ) >>> B = A.copy() >>> B {0: {1: 2}, 1: {}} )r?rSrAr%r()Ar4AiAcs rrSzSDM.copysK )* 2uq"al 2 2uuR!((++3sAc |\} t|k(rt fdDs td fd fdt|D}|Dcic] \}}|s || }}}||||Scc}}w)a" Create :py:class:`~.SDM` object from a list of lists. Parameters ========== ddm: list of lists containing domain elements shape: Dimensions of :py:class:`~.SDM` matrix domain: Represents :py:class:`~.Domain` of :py:class:`~.SDM` object Returns ======= :py:class:`~.SDM` containing elements of ddm Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> ddm = [[QQ(1, 2), QQ(0)], [QQ(0), QQ(3, 4)]] >>> A = SDM.from_list(ddm, (2, 2), QQ) >>> A {0: {0: 1/2}, 1: {1: 3/4}} See Also ======== to_list from_list_flat from_dok from_ddm c3:K|]}t|k(ywr=)rB)rr r"s rrz SDM.from_list..s%Cc#h!m%CszInconsistent row-list/shapec`tDcic]}||s |||c}Scc}wr=)r>)r4r5ddmr"s rzSDM.from_list..s/qGASVAYAc!fQiKGGs + +c32K|]}||fywr=r)rr4getrows rrz SDM.from_list..s2A!VAY2s)rBr)r r>) rrr{r%r(rirowsr4r rGr~r"s ` @@r from_listz SDM.from_listswN1CA #%Cs%C"C!"?@ @G2q2$)1&!SSq#v113v&&2s  A2 A2cP|j||j|jS)a1 Create :py:class:`~.SDM` from a :py:class:`~.DDM`. Examples ======== >>> from sympy.polys.matrices.ddm import DDM >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> ddm = DDM( [[QQ(1, 2), 0], [0, QQ(3, 4)]], (2, 2), QQ) >>> A = SDM.from_ddm(ddm) >>> A {0: {0: 1/2}, 1: {1: 3/4}} >>> SDM.from_ddm(ddm).to_ddm() == ddm True See Also ======== to_ddm from_list from_list_flat from_dok )rr%r()rrr{s rfrom_ddmz SDM.from_ddms4}}S#))SZZ88r.c|j\}}|jj}t|Dcgc]}|g|z }}|j D]%\}}|j D] \}} | |||<'|Scc}w)aL Convert a :py:class:`~.SDM` object to a list of lists. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> elemsdict = {0:{1:QQ(2)}, 1:{}} >>> A = SDM(elemsdict, (2, 2), QQ) >>> A.to_list() [[0, 2], [0, 0]] )r%r(r2r>r?) Mrr"r2_r{r4r r5rHs rto_listz SDM.to_list5s ww1xx}}#(8,avz,,ggi FAs  1Aq    -s A<c|j\}}|jj}|g||zz}|jD](\}}|jD]\}}||||z|z<*|S)a Convert :py:class:`~.SDM` to a flat list. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0:{1:QQ(2)}, 1:{0: QQ(3)}}, (2, 2), QQ) >>> A.to_list_flat() [0, 2, 3, 0] >>> A == A.from_list_flat(A.to_list_flat(), A.shape, A.domain) True See Also ======== from_list_flat to_list to_dok to_ddm )r%r(r2r?) rrr"r2flatr4r r5rHs r to_list_flatzSDM.to_list_flatMsx.ww1xx}}vQggi "FAs  "1 !QqS1W  " " r.c|\}}t|||zk7r tdtt}t |D]\}}|s t ||\} } ||| | <!||||S)a Create :py:class:`~.SDM` from a flat list of elements. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM.from_list_flat([QQ(0), QQ(2), QQ(0), QQ(0)], (2, 2), QQ) >>> A {0: {1: 2}} >>> A == A.from_list_flat(A.to_list_flat(), A.shape, A.domain) True See Also ======== to_list_flat from_list from_dok from_ddm zInconsistent flat-list shape)rBr rrprOdivmod) rrelementsr%r(rr"rGinjelementr4r5s rfrom_list_flatzSDM.from_list_flatls{01 x=AE !!"@A A$%h/ $LCc1~1#Aq  $3v&&r.c|j}t|}t|j}||jf}||fS)aq Convert :class:`SDM` 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 modified matrix with elements in the same positions using :meth:`from_flat_nz`. Zero elements are omitted from the list. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0:{1:QQ(2)}, 1:{0: QQ(3)}}, (2, 2), QQ) >>> elements, data = A.to_flat_nz() >>> elements [2, 3] >>> A == A.from_flat_nz(elements, data, A.domain) True See Also ======== from_flat_nz to_list_flat sympy.polys.matrices.ddm.DDM.to_flat_nz sympy.polys.matrices.domainmatrix.DomainMatrix.to_flat_nz )to_doktuplerNr*r%)rdokindicesrdatas r to_flat_nzzSDM.to_flat_nzs@>hhj* %!~r.c\|\}}tt||}|j|||S)aE Reconstruct a :class:`~.SDM` after calling :meth:`to_flat_nz`. See :meth:`to_flat_nz` for explanation. See Also ======== to_flat_nz from_list_flat sympy.polys.matrices.ddm.DDM.from_flat_nz sympy.polys.matrices.domainmatrix.DomainMatrix.from_flat_nz )rpzipfrom_dok)rrrrr(rr%rs r from_flat_nzzSDM.from_flat_nzs13w)*||C//r.cr|jDcic]\}}||jc}}Scc}}w)a Convert to dictionary of dictionaries (dod) format. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0: {1: QQ(2)}, 1: {0: QQ(3)}}, (2, 2), QQ) >>> A.to_dod() {0: {1: 2}, 1: {0: 3}} See Also ======== from_dod sympy.polys.matrices.domainmatrix.DomainMatrix.to_dod )r?rS)rr4r s rto_dodz SDM.to_dods,&-.GGI6&!S388: 666s3ctt}|jD](\}}|jD]\}}|s ||||<*||||S)a Create :py:class:`~.SDM` from dictionary of dictionaries (dod) format. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> dod = {0: {1: QQ(2)}, 1: {0: QQ(3)}} >>> A = SDM.from_dod(dod, (2, 2), QQ) >>> A {0: {1: 2}, 1: {0: 3}} >>> A == SDM.from_dod(A.to_dod(), A.shape, A.domain) True See Also ======== to_dod sympy.polys.matrices.domainmatrix.DomainMatrix.to_dod rrpr?) rrdodr%r(rGr4r r5rHs rfrom_dodz SDM.from_dodsa.$iik "FAs  "1 !CF1I " "3v&&r.c |jDcic]"\}}|jD] \}}||f| $c}}}}Scc}}}}w)a Convert to dictionary of keys (dok) format. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0: {1: QQ(2)}, 1: {0: QQ(3)}}, (2, 2), QQ) >>> A.to_dok() {(0, 1): 2, (1, 0): 3} See Also ======== from_dok to_list to_list_flat to_ddm r?rr4r r5rHs rrz SDM.to_doksC*)* JJfaciikJdaA JJJJs'A ctt}|jD]\\}}}|s ||||<||||S)a  Create :py:class:`~.SDM` from dictionary of keys (dok) format. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> dok = {(0, 1): QQ(2), (1, 0): QQ(3)} >>> A = SDM.from_dok(dok, (2, 2), QQ) >>> A {0: {1: 2}, 1: {0: 3}} >>> A == SDM.from_dok(A.to_dok(), A.shape, A.domain) True See Also ======== to_dok from_list from_list_flat from_ddm r)rrrr%r(rGr4r5rHs rrz SDM.from_doksL2$ IFQAAq  3v&&r.c#jK|jD]}|jEd{y7w)a< Iterate over the nonzero values of a :py:class:`~.SDM` matrix. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0: {1: QQ(2)}, 1: {0: QQ(3)}}, (2, 2), QQ) >>> list(A.iter_values()) [2, 3] N)r*)rr s r iter_valueszSDM.iter_values/s/88: $Czz| # # $ #s '313c#|K|jD]%\}}|jD] \}}||f|f'yw)a Iterate over indices and values of the nonzero elements. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0: {1: QQ(2)}, 1: {0: QQ(3)}}, (2, 2), QQ) >>> list(A.iter_items()) [((0, 1), 2), ((1, 0), 3)] See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.iter_items Nrrs r iter_itemszSDM.iter_items@sG$ggi FAs  1!fai  s:<c`t|j|j|jS)a2 Convert a :py:class:`~.SDM` object to a :py:class:`~.DDM` object Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ) >>> A.to_ddm() [[0, 2], [0, 0]] )rrr%r(rs rto_ddmz SDM.to_ddmVs!199;22r.c|S)zE Convert to :py:class:`~.SDM` format (returns self). rrs rto_sdmz SDM.to_sdmfs r.r) ground_typesc>|jjS)a Convert a :py:class:`~.SDM` object to a :py:class:`~.DFM` object Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ) >>> A.to_dfm() [[0, 2], [0, 0]] See Also ======== to_ddm to_dfm_or_ddm sympy.polys.matrices.domainmatrix.DomainMatrix.to_dfm )rto_dfmrs rrz SDM.to_dfmls*xxz  ""r.c>|jjS)a3 Convert to :py:class:`~.DFM` if possible, else :py:class:`~.DDM`. Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ) >>> A.to_dfm_or_ddm() [[0, 2], [0, 0]] >>> type(A.to_dfm_or_ddm()) # depends on the ground types See Also ======== to_ddm to_dfm sympy.polys.matrices.domainmatrix.DomainMatrix.to_dfm_or_ddm )r to_dfm_or_ddmrs rrzSDM.to_dfm_or_ddms.xxz''))r.c|i||S)a Returns a :py:class:`~.SDM` of size shape, belonging to the specified domain In the example below we declare a matrix A where, .. math:: A := \left[\begin{array}{ccc} 0 & 0 & 0 \\ 0 & 0 & 0 \end{array} \right] >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM.zeros((2, 3), QQ) >>> A {} r)rrr%r(s rrKz SDM.zeross*2uf%%r.c|j}|\}}ttt||g|z}t|Dcic]}||j }}||||Scc}wr=)onerprr>rS) rrr%r(rrr"r r4rGs roneszSDM.onessdjj13uQx#q)*&+Ah/q#((*}//3v&&0sA%ct|tr||}}n|\}}|j}tt ||Dcic]}|||i }}||||f|Scc}w)aO Returns a identity :py:class:`~.SDM` matrix of dimensions size x size, belonging to the specified domain Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> I = SDM.eye((2, 2), QQ) >>> I {0: {0: 1}, 1: {1: 1}} ) isinstanceintrr>rL)rrr%r(r&r'rr4rGs reyezSDM.eyesg" eS !$DJD$jj$)#dD/$:;qq1c({;;3t f--TQAq1a&y>>3v&&?s AAcrt|}|j||jddd|jS)a$ Returns the transpose of a :py:class:`~.SDM` matrix Examples ======== >>> from sympy.polys.matrices.sdm import SDM >>> from sympy import QQ >>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ) >>> A.transpose() {1: {0: 2}} N) sdm_transposerAr%r()rMTs r transposez SDM.transposes11 uuR211r.ct|tstS|j|jk7r%t d|jd|j|j |S)NMatrix size mismatch: z + )rrNotImplementedr%rrruBs r__add__z SDM.__add__G!S!! ! WW !''177ST TuuQxr.ct|tstS|j|jk7r%t d|jd|j|j |S)Nrz - )rrrr%rrrs r__sub__z SDM.__sub__rr.c"|jSr=)rrus r__neg__z SDM.__neg__s uuwr.ct|tr|j|S||jvr|j |St S)zA * B)rrmatmulr(rrrs r__mul__z SDM.__mul__s8 a 88A;  !((]558O! !r.cL||jvr|j|StSr=)r(rmulr)abs r__rmul__z SDM.__rmul__s! =66!9 ! !r.c|j|jk7rt|j\}}|j\}}||k7rtt |||j||}|j |||f|jS)a Performs matrix multiplication of two SDM matrices Parameters ========== A, B: SDM to multiply Returns ======= SDM SDM after multiplication Raises ====== DomainError If domain of A does not match with that of B Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) >>> B = SDM({0:{0:ZZ(2), 1:ZZ(3)}, 1:{0:ZZ(4)}}, (2, 2), ZZ) >>> A.matmul(B) {0: {0: 8}, 1: {0: 2, 1: 3}} )r(rr%r sdm_matmulrA)rurrr"n2oCs rrz SDM.matmul ssB 88qxx  ww1A 7  q!QXXq! ,uuQA))r.cpt|fd}|j||j|jS)a. Multiplies each element of A with a scalar b Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) >>> A.mul(ZZ(3)) {0: {1: 6}, 1: {0: 3}} c|zSr=raijrs rr|zSDM.mul..Es Ar. unop_dictrAr%r(rurCsdms ` rrzSDM.mul7s--.uuT177AHH--r.cpt|fd}|j||j|jS)Nc|zSr=rrs rr|zSDM.rmul..Is #r.rrs ` rrzSDM.rmulHs+-.uuT177AHH--r.c*|j|jk7rt|j|jk7rt|jjfd}t ||t ||}|j||j|jS)NcSr=r)rHr2s rr|z%SDM.mul_elementwise..Rs$r.)r(rr%rr2 binop_dictrrA)rurfzerorr2s @rmul_elementwisezSDM.mul_elementwiseLsn 88qxx   77agg  xx}}!QUE2uuT177AHH--r.ct||ttt}|j||j|j S)ak Adds two :py:class:`~.SDM` matrices Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) >>> B = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ) >>> A.add(B) {0: {0: 3, 1: 2}, 1: {0: 1, 1: 4}} )rrrrAr%r(rurrs rrzSDM.addV1 !QS#.uuT177AHH--r.ct||ttt}|j ||j |j S)as Subtracts two :py:class:`~.SDM` matrices Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) >>> B = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ) >>> A.sub(B) {0: {0: -3, 1: 2}, 1: {0: 1, 1: -4}} )rrrrrAr%r(rs rrzSDM.subirr.cpt|t}|j||j|jS)a2 Returns the negative of a :py:class:`~.SDM` matrix Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) >>> A.neg() {0: {1: -2}, 1: {0: -1}} )rrrAr%r()rurs rrzSDM.neg|s+C uuT177AHH--r.c|jk(r|jSt|fd}|j||jS)aN Converts the :py:class:`~.Domain` of a :py:class:`~.SDM` matrix to K Examples ======== >>> from sympy import ZZ, QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) >>> A.convert_to(QQ) {0: {1: 2}, 1: {0: 1}} c(j|Sr=) convert_from)rHKKolds rr|z SDM.convert_to..sANN1d$;r.)r(rSrrAr%)rurAkrs ` @r convert_tozSDM.convert_tosDxx 9668O q; <uuR!$$r.cPttt|jS)ayNumber of non-zero elements in the :py:class:`~.SDM` matrix. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) >>> A.nnz() 2 See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.nnz )summaprBr*rs rnnzzSDM.nnzs"3sAHHJ'((r.c |j\}}||k(sJt|}|Dcic]}|t|j|g }}t ||Scc}w)a{Strongly connected components of a square matrix *A*. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0: ZZ(2)}, 1:{1:ZZ(1)}}, (2, 2), ZZ) >>> A.scc() [[0], [1]] See also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.scc )r%r>rNr8r )rur&r'VrEmaps rscczSDM.sccs_"WW dt|| $K/01!4a %%11-a662s#Acrt|\}}}|j||j|j|fS)a_ Returns reduced-row echelon form and list of pivots for the :py:class:`~.SDM` Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(2), 1:QQ(4)}}, (2, 2), QQ) >>> A.rref() ({0: {0: 1, 1: 2}}, [0]) ) sdm_irrefrAr%r()rurpivotsrs rrrefzSDM.rrefs3!| 61uuQ*F22r.c|j}t||\}}}|j||j|j}|||fS)a] Returns reduced-row echelon form (RREF) with denominator and pivots. Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(2), 1:QQ(4)}}, (2, 2), QQ) >>> A.rref_den() ({0: {0: 1, 1: 2}}, 1, [0]) )r( sdm_rref_denrAr%)rur A_rref_sdmdenomrA_rrefs rrref_denz SDM.rref_densG HH$0A$6! E6z177AHH5uf$$r.cZ|jjjS)a> Returns inverse of a matrix A Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) >>> A.inv() {0: {0: -2, 1: 1}, 1: {0: 3/2, 1: -1/2}} )rinvrrs rr zSDM.invs# $$&--//r.c>|jjS)a Returns determinant of A Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) >>> A.det() -2 )rdetrs rr zSDM.dets* $$&&r.c|jj\}}}|j||j||fS)a` Returns LU decomposition for a matrix A Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) >>> A.lu() ({0: {0: 1}, 1: {0: 3, 1: 1}}, {0: {0: 1, 1: 2}, 1: {1: -2}}, []) )rlur)ruLUswapss rrzSDM.lus8hhjmmo 1ezz!}ajjmU22r.c|jj\}}|j}|j}||fS)z QR decomposition for SDM (Sparse Domain Matrix). Returns: - Q: Orthogonal matrix as a SDM. - R: Upper triangular matrix as a SDM. )rqrr)r+ddm_qddm_rQRs rrzSDM.qr,s;{{}'') u LLN LLN!t r.cz|j|jj|jS)an Uses LU decomposition to solve Ax = b, Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) >>> b = SDM({0:{0:QQ(1)}, 1:{0:QQ(2)}}, (2, 1), QQ) >>> A.lu_solve(b) {1: {0: 1/2}} )rrlu_solve)rurs rrz SDM.lu_solve9s* zz!((*--ahhj9::r.c|jj\}}}}|j}|j}|j}|j}||||fS)z Fraction free LU decomposition of SDM. Uses DDM implementation. See Also ======== sympy.polys.matrices.ddm.DDM.fflu )rfflur) r+ddm_pddm_lddm_dddm_uPrDrs rrzSDM.ffluKs^&*%7%7%9%>%>%@"ueU LLN LLN LLN LLN!Qzr.c|jd}|jj}t|\}}}t |||||\}}t t |}t||f}|j|||j|fS)a Nullspace of a :py:class:`~.SDM` matrix A. The domain of the matrix must be a field. It is better to use the :meth:`~.DomainMatrix.nullspace` method rather than this method which is otherwise no longer used. Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0: QQ(2), 1: QQ(4)}}, (2, 2), QQ) >>> A.nullspace() ({0: {0: -2, 1: 1}}, [1]) See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace The preferred way to get the nullspace of a matrix. r ) r%r(rrsdm_nullspace_from_rrefrprOrBrA) runcolsrrrnzcolsr nonpivotsr%s r nullspacez SDM.nullspace]s{4 hhll%aL66.q#uffM 9 1 QuuQqxx()33r.c8|j\}}|j}|'ttt|j }|s(|j ||f|tt|fSt||k(r|jd|f|gfS|d|d}|j|rJt|}tt}|jD]3\}} | jD]\} } || j|| f5g} g} t|D]C} | |vr| j| | |i}|| D]\}} | |||<| j|Et!t#| }|j%|t| |f|}|| fS)a\ Returns nullspace for a :py:class:`~.SDM` matrix ``A`` in RREF. The domain of the matrix can be any domain. The matrix must already be in reduced row echelon form (RREF). Examples ======== >>> from sympy import QQ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0: QQ(2), 1: QQ(4)}}, (2, 2), QQ) >>> A_rref, pivots = A.rref() >>> A_null, nonpivots = A_rref.nullspace_from_rref(pivots) >>> A_null {0: {0: -2, 1: 1}} >>> pivots [0] >>> nonpivots [1] See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace The higher-level function that would usually be called instead of calling this one directly. sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace_from_rref The higher-level direct equivalent of this function. sympy.polys.matrices.ddm.DDM.nullspace_from_rref The equivalent function for dense :py:class:`~.DDM` matrices. r)r%r(sortedrrLr*rrNr>rBrKis_zerorQrr?rPrprOrA)rurrr"r pivot_val pivots_set nonzero_colsr4rvr5Aijbasisr'veciprGA_nulls rnullspace_from_rrefzSDM.nullspace_from_rrefsJww1 HH >CQXXZ01F55!Q#T%(^3 3 [A 77Aq61%r) )aDO 99Y'''[ #4( WWY 1EAr((* 13Q&&3x0 1 1 q AJ   Q i.C'? 'C#&$F2J ' LL  9U#$sSZOQ/ ""r.c|jd}t|\}}}t|||}|rd|ini}|j|d|dz f|jS)Nr r)r%rsdm_particular_from_rrefrAr()rur%rrr&r!reps r particularzSDM.particularsY %aL66 $Qv 6qebuuS1eAg,11r.ct|j}|j\}}|j}|D]}|j\}}||k(sJ|j|k(sJ|j D]@\} } |j | d} | ix|| <} | j D] \} } | | | |z<B||z }|j |||f|jS)aHorizontally stacks :py:class:`~.SDM` matrices. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}, (2, 2), ZZ) >>> B = SDM({0: {0: ZZ(5), 1: ZZ(6)}, 1: {0: ZZ(7), 1: ZZ(8)}}, (2, 2), ZZ) >>> A.hstack(B) {0: {0: 1, 1: 2, 2: 5, 3: 6}, 1: {0: 3, 1: 4, 2: 7, 3: 8}} >>> C = SDM({0: {0: ZZ(9), 1: ZZ(10)}, 1: {0: ZZ(11), 1: ZZ(12)}}, (2, 2), ZZ) >>> A.hstack(B, C) {0: {0: 1, 1: 2, 2: 5, 3: 6, 4: 9, 5: 10}, 1: {0: 3, 1: 4, 2: 7, 3: 8, 4: 11, 5: 12}} N)rprSr%r(r?r8rA)rurAnewr&r'r(BkBkrowsBkcolsr4Bkirvr5Bkijs rhstackz SDM.hstacks$AFFH~WW d BXXNFFT> !>99& &&((* (3XXa&:#%%DGb"yy{(GAt#'Bq4xL(  ( FND uuTD$<22r.cNt|j}|j\}}|j}|D]N}|j\}}||k(sJ|j|k(sJ|j D] \} } | || |z<||z }P|j |||f|jS)aVertically stacks :py:class:`~.SDM` matrices. Examples ======== >>> from sympy import ZZ >>> from sympy.polys.matrices.sdm import SDM >>> A = SDM({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}, (2, 2), ZZ) >>> B = SDM({0: {0: ZZ(5), 1: ZZ(6)}, 1: {0: ZZ(7), 1: ZZ(8)}}, (2, 2), ZZ) >>> A.vstack(B) {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}, 2: {0: 5, 1: 6}, 3: {0: 7, 1: 8}} >>> C = SDM({0: {0: ZZ(9), 1: ZZ(10)}, 1: {0: ZZ(11), 1: ZZ(12)}}, (2, 2), ZZ) >>> A.vstack(B, C) {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}, 2: {0: 5, 1: 6}, 3: {0: 7, 1: 8}, 4: {0: 9, 1: 10}, 5: {0: 11, 1: 12}} )rprSr%r(r?rA) rurr:r&r'r(r;r<r=r4r>s rvstackz SDM.vstacks$AFFH~WW d BXXNFFT> !>99& &&((* %3!$QX % FND uuTD$<22r.c|jDcic]0\}}||jDcic]\}}|||c}}2}}}}}|j||j|Scc}}wcc}}}}wr=)r?rAr%)r+funcr(r4r r5rHrGs r applyfuncz SDM.applyfunc#scEIZZ\RR61cq#))+6$!Q1d1g:66RRxxTZZ007RsA3 A-A3 -A3 c|j}|j\}}t|||}|jg|dzz}|j D] \}}|||< |S)a Returns the coefficients of the characteristic polynomial of the :py:class:`~.SDM` matrix. These elements will be domain elements. The domain of the elements will be same as domain of the :py:class:`~.SDM`. Examples ======== >>> from sympy import QQ, Symbol >>> from sympy.polys.matrices.sdm import SDM >>> from sympy.polys import Poly >>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) >>> A.charpoly() [1, -5, -2] We can create a polynomial using the coefficients using :py:class:`~.Poly` >>> x = Symbol('x') >>> p = Poly(A.charpoly(), x, domain=A.domain) >>> p Poly(x**2 - 5*x - 2, x, domain='QQ') r )r(r%sdm_berkr2r?)rurr"rpdictplistr4pis rcharpolyz SDM.charpoly'sc2 HHww1Aq!AE"[[] EArE!H  r.c| S)z@ Says whether this matrix has all zero entries. rr+s ris_zero_matrixzSDM.is_zero_matrixHs xr.cBtd|jDS)z~ Says whether this matrix is upper-triangular. True can be returned even if the matrix is not square. c3:K|]\}}|D] }||k ywr=rrr4r r5s rrzSDM.is_upper..S$BfacB16B6Br)r?rMs ris_upperz SDM.is_upperN B BBBr.cBtd|jDS)z~ Says whether this matrix is lower-triangular. True can be returned even if the matrix is not square. c3:K|]\}}|D] }||k\ ywr=rrQs rrzSDM.is_lower..ZrRrSrTrMs ris_lowerz SDM.is_lowerUrVr.cBtd|jDS)zv Says whether this matrix is diagonal. True can be returned even if the matrix is not square. c3:K|]\}}|D] }||k( ywr=rrQs rrz"SDM.is_diagonal..arRrSrTrMs r is_diagonalzSDM.is_diagonal\rVr.c|j\}}|jj}|jDcgc]\}}||ks |j ||c}}Scc}}w)z? Returns the diagonal of the matrix as a list. )r%r(r2r?r8)r+rr"r2r4r s rrz SDM.diagonalcsOzz1{{/3zz|EVQq1u4 EEEs AAc^|jj|jS)zQ Returns the LLL-reduced basis for the :py:class:`~.SDM` matrix. delta)rlllr)rurbs rrczSDM.lllks( $$5$188::r.c|jj|\}}|j|jfS)zJ Returns the LLL-reduced basis and transformation matrix. ra)r lll_transformr)rurbreduced transforms rrezSDM.lll_transformqs>__.<<5<I~~!1!1!333r.r=)Oro __module__ __qualname____doc__fmtis_DFMis_DDMr$r6r;rIrarjrq classmethodrArSrrrrrrrrrrrrrrrr rrrKrrrrrrrrrrrrrrrrrrrrr r r rrrrr(r4r8r@rBrErKrNrUrYr\rrrcre __classcell__)r-s@rrrsg.` C F F9 7$* >$CL+G ''8,&,','\9960>''B#J00$7*'':K.''<$" ,3  gY/#0#,gY/*0*0&&,''..0'' 2$"" (*T."...&.&.$%()&7.3$%(0"'.3$ ;$$ 4DU#n2#3J3B1B CCCF1X; "!Qx4r.rcXt|t|}}i}||zD]}||||} } i} t| t| } } | | zD]}|| || |}|s|| |<| | z D]}|| |}|s|| |<| | z D]}|| |}|s|| |<| s| ||<||z D]9}||} i} | jD]\}}||}|s|| |<| s5| ||<;||z D]9}||} i} | jD]\}}||}|s|| |<| s5| ||<;|Sr=)rQr?)rurfabfafbAnzBnzrr4rvBiCiAnziBnzir5Cijr/Bijs rrrys1vs1vC A 3Y1qtB Wc"gd AbeRU#C1  ARU)C1  ARU)C1  AaD#&3Y qT hhj FAsS'C1  AaD3Y qT hhj FAsS'C1  AaD Hr.ci}|jD]7\}}i}|jD]\}}||}|s|||<|s3|||<9|Sr=r) rufrr4rvrvr5r/r{s rrrsh A2 hhj FAsC&C1  AaD Hr.ci}|jD]&\}}|jD]\}} ||||<(|S#t$r ||i||<Y'wxYwr=)r?r1)rrr4Mir5Mijs rrrsp B!2hhj !FAs !1a !! I !C1 !s>AAcz|jfdjjzDS)Nc34K|]}||zywr=r)rr5rurs rrzsdm_dotvec..s:1!:s)rrR)rurrs`` r sdm_dotvecrs) 55:affh&9: ::r.cdi}|jD]\}}t|||}|s|||<|Sr=)r?r)rurrrr4rvrws r sdm_matvecmulrsA A2 Aq ! AaD Hr.c|jrt|||||Si}t|}|jD]\}}i} t|} | |zD]e} || } || jD]H\} }| j | d}|"|| |zz}|r|| | <*| j | <| |z}|sD|| | <Jg| s| ||<|Sr=)is_EXRAWsdm_matmul_exrawrQr?r8pop)rurrrrrB_knzr4rvrwAi_knzkAikr5Bkjrzs rrrs" zz1aA.. A FE2 R% $AQ%CA$**, $3ffQo?c /C #1q )C #1 $ $ AaD%& Hr.c F|j}i}t|}|jD]\}} tt} t| } | |zD]|} | | } || z|k(r3|| jD]\}}| |j | |zCt |D],}| |j | || j||z.~| |z D]4} || | z}||k7st |D]}| |j |6i}| jD]\}}|j|}|s|||< |s|||<|jD]\} }|jD]\}}||z|k7st |D]}|j|ij| |} | |k(s+|j|i}|j||| |zz}||k7r |||<|||<e|j|d|r|||<|j|d|Sr=) r2rQr?rrNrPr>r8rr)rurrrrr2rrr4rvCi_listrrrr5rzAikrwCij_listrzr;s rrrsX 66D A FE2d#R% ?AQ%CczT!djjl1FAsAJ%%cCi01q?AAJ%%cAaDHHQ,=&=>? ?% ,A"Q%>> from sympy import QQ >>> from sympy.polys.matrices.sdm import sdm_irref >>> A = {0: {0: QQ(1), 1: QQ(2)}, 1: {0: QQ(3), 1: QQ(4)}} >>> Arref, pivots, _ = sdm_irref(A) >>> Arref {0: {0: 1}, 1: {1: 1}} >>> pivots [0, 1] The analogous calculation with :py:class:`~.MutableDenseMatrix` would be >>> from sympy import Matrix >>> M = Matrix([[1, 2], [3, 4]]) >>> Mrref, pivots = M.rref() >>> Mrref Matrix([ [1, 0], [0, 1]]) >>> pivots (0, 1) Notes ===== The cost of this algorithm is determined purely by the nonzero elements of the matrix. No part of the cost of any step in this algorithm depends on the number of rows or columns in the matrix. No step depends even on the number of nonzero rows apart from the primary loop over those rows. The implementation is much faster than ddm_rref for sparse matrices. In fact at the time of writing it is also (slightly) faster than the dense implementation even if the input is a fully dense matrix so it seems to be faster in all cases. The elements of the matrix should support exact division with ``/``. For example elements of any domain that is a field (e.g. ``QQ``) should be fine. No attempt is made to handle inexact arithmetic. See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.rref The higher-level function that would normally be used to call this routine. sympy.polys.matrices.dense.ddm_irref The dense equivalent of this routine. sdm_rref_den Fraction-free version of this routine. c3<K|]}|jywr=)rS)rrvs rrzsdm_irref..s3"BGGI3skeyrrr ) r*r*rLrQrrr?removerrBrOrp)ruArows pivot_row_mapreduced_pivotsnonreduced_pivotsnonzero_columnsrvr5r/AjAinzAjnzrrAijinvlrAkjAknzAklrr"p pivot2rowr!sr4r&rs rrr8sv 3 3 =E MUN"#&O  YY[$&88: IC.1Haf I I#SW, Aq!BQ%Cr7Dr7DD[ &1 1 & FF1I KKND[ ecBqEk)BqEFF1I   $  Ge a2w b A qEVOE !$$Q+ ,Aq!BQ%Cr7DD[ *1 1"&&q) * FF1I KKND[ 5ecBqEk)BqEFF1IAv'*11!4 52w!|""1%!((+) ,, r7a<   q !  ! !! $ .6#A&**1- .M VN%66 7F"+F"34$!QA4I4@O@U@U@WXX1q3A9Q<33XOX&, -M!  -D -  $ D  ((WJN53X -s02 L6?L6 L<) M6 MM MMc|si|jgfSt|dk(r8|j\}t|}||}d|j i||gfS|j r |j }n |j}tt|j\}}i}i} |j} | j} g} d} d}t|t}|D]}|jDcic] \}}|| vs ||}}}i}| |jzD]p}|j|}| | |}|jD]B\}}|j|}| ||z||<"|||zz}|r|||<2|j|Drt|}t|}| xs |j}||z D] }|| ||< ||z D] }|||z||<||zD])}|||z||z }|r|||<|j|+|s7t|}|j|}t| jD] \}}| |}||vr.|jD]\}}||z}| |||}|||<>|j|}t|}t|}||z D] }| ||z||<|||||||<"||z D]}|||z||<|||||||<!||zD]7}|||z|||zz }|r| |||}|||<'|j|9|r| j||||<t| }| j!||r|| |<n|||<|j#|s | |} n| |z} | || |} | }| |j} i|| } | jDcic]\}}|| }!}}t%| Dcgc] \}}|!||f}"}}tt|"\}#}$t|#}#t%|$D] \}}| ||#|<t't%|$}%|%| |#fScc}}wcc}}wcc}}w)a? Return the reduced row echelon form (RREF) of A with denominator. The RREF is computed using fraction-free Gauss-Jordan elimination. Explanation =========== The algorithm used is the fraction-free version of Gauss-Jordan elimination described as FFGJ in [1]_. Here it is modified to handle zero or missing pivots and to avoid redundant arithmetic. This implementation is also optimized for sparse matrices. The domain $K$ must support exact division (``K.exquo``) but does not need to be a field. This method is suitable for most exact rings and fields like :ref:`ZZ`, :ref:`QQ` and :ref:`QQ(a)`. In the case of :ref:`QQ` or :ref:`K(x)` it might be more efficient to clear denominators and use :ref:`ZZ` or :ref:`K[x]` instead. For inexact domains like :ref:`RR` and :ref:`CC` use ``ddm_irref`` instead. Examples ======== >>> from sympy.polys.matrices.sdm import sdm_rref_den >>> from sympy.polys.domains import ZZ >>> A = {0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}} >>> A_rref, den, pivots = sdm_rref_den(A, ZZ) >>> A_rref {0: {0: -2}, 1: {1: -2}} >>> den -2 >>> pivots [0, 1] See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.rref_den Higher-level interface to ``sdm_rref_den`` that would usually be used instead of calling this function directly. sympy.polys.matrices.sdm.sdm_rref_den The ``SDM`` method that uses this function. sdm_irref Computes RREF using field division. ddm_irref_den The dense version of this algorithm. References ========== .. [1] Fraction-free algorithms for linear and polynomial equations. George C. Nakos , Peter R. Turner , Robert M. Williams. https://dl.acm.org/doi/10.1145/271130.271133 r rNr)rrBr*rLrSis_Exactexquoquorr*r?rRrr8rQrNrPis_onerOrp)&rurrvr5r/rr rows_in_ordercol_to_row_reducedcol_to_row_unreducedrf unreduced A_rref_rowsrdivisorA_rows Ai_cancelrrAjk Aik_cancelAi_nz Ai_cancel_nzdrpkrrrrAk_nzr4 col_to_row row_to_colA_rref_rows_colrrrs& rrrs]z AEE2 Q1hhj GeBGGIaS)) zzF1779-.A} %%'G$))+IK EG Ms +F~$&88: BC'1Aaf B B RWWY& )A&&)C1!45B((* )3&]]1- %#&9IaL!+cCi!7J!'1 ! ! a( ) )&B9~ NQUU% "Aq\MBqE "% AqEAIBqE % AQ%!)il*C1q    GffQi.4467) +EBQB{!hhj FAs)C*#C1BqE  &&)CGEGEU] 21 1&!"Q%1BqE 2 U] 2be 1&!"Q%1BqE 2 U] BqEkC"Q%K/*#C1BqEFF1I $((,)*"2&S) +V  2 &'  #$% q !xx}}   %)E}~@ }@&?*>?J#-#3#3#5641a!Q$6J68A+8NOuq" 1 r*OOO&12NFF &\F6"26!9 i'(J uf $$[CD7Os3 QQ Q0Q#cttt|t|z }g}|D]=}||i}|j|dD]} || | ||| <|j |?||fS)z%Get nullspace from A which is in RREFr)r*rQr>r8rP) rurr%rr.r'rr5Kjr4s rr$r$ ss5<(3v;67I A W!!!R( %AqT!WHBvayM %   i<r.ci}t|D].\}}||j|dz d}|!||||z ||<0|S)z1Get a particular solution from A which is in RREFr N)rOr8)rur%rr!r4r5Ains rr6r6sX A&!!1dhhuQw% ?1a=AaD! Hr.c |j}|j}|dk(rd|iS|dk(r.d|i}|jdijd|x}r| |d<|jiittf\}}} } |j D]H\} } | j D]0\} }| r| r|| | dz | dz <| r || | dz <$| r ||| dz </|}2J| }t || |}|| | g}td|dzD]2} t| ||}|sn!t |||}|j| 4|r|ds|j|r|dst| |dz |}|ddd}i}tt|tt|t|z|dzD];} t t|| t|z dz}t |||x}s7||| <=|S)a\ Berkowitz algorithm for computing the characteristic polynomial. Explanation =========== The Berkowitz algorithm is a division-free algorithm for computing the characteristic polynomial of a matrix over any commutative ring using only arithmetic in the coefficient ring. This implementation is for sparse matrices represented in a dict-of-dicts format (like :class:`SDM`). Examples ======== >>> from sympy import Matrix >>> from sympy.polys.matrices.sdm import sdm_berk >>> from sympy.polys.domains import ZZ >>> M = {0: {0: ZZ(1), 1:ZZ(2)}, 1: {0:ZZ(3), 1:ZZ(4)}} >>> sdm_berk(M, 2, ZZ) {0: 1, 1: -5, 2: -2} >>> Matrix([[1, 2], [3, 4]]).charpoly() PurePoly(lambda**2 - 5*lambda - 2, lambda, domain='ZZ') See Also ======== sympy.polys.matrices.domainmatrix.DomainMatrix.charpoly The high-level interface to this function. sympy.polys.matrices.dense.ddm_berk The dense version of this function. References ========== .. [1] https://en.wikipedia.org/wiki/Samuelson%E2%80%93Berkowitz_algorithm rr r^rN)r2rr8rrpr?rr>rrPrrGrLrMrBrO)rr"rr2rrHM00rrrrur4rr5rAnCRCTvalsRAnCqTqTiTqis rrGrG#sJ 66D %%CAv3x aC%%2,""1d+ +3 +tE!HRT!22JAq!Q 2hhj FAsQ!!A#qs !A#!A#  . C Aq! B 1"rcNE 1ac]AsA& !S!$ dU  b   b  AaCA" $B$KE B 3q63s1vc%j0!A#6 7 )E1SZ<>2 3RA& &3 &BqE Ir.N)&rjoperatorrrrrr collectionsrsympy.external.gmpyr sympy.utilities.decoratorr sympy.utilities.iterablesr exceptionsr rrsympy.polys.domainsrr{r__doctest_skip__rprrrrrrrrrrr$r6rGrr.rrs -,#,8DDD"7$&9:]4$]4@++ \  ; ) X= @})@P%f  rr.