test_base.py 169 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683
  1. #
  2. # Authors: Travis Oliphant, Ed Schofield, Robert Cimrman, Nathan Bell, and others
  3. """ Test functions for sparse matrices. Each class in the "Matrix class
  4. based tests" section become subclasses of the classes in the "Generic
  5. tests" section. This is done by the functions in the "Tailored base
  6. class for generic tests" section.
  7. """
  8. from __future__ import division, print_function, absolute_import
  9. __usage__ = """
  10. Build sparse:
  11. python setup.py build
  12. Run tests if scipy is installed:
  13. python -c 'import scipy;scipy.sparse.test()'
  14. Run tests if sparse is not installed:
  15. python tests/test_base.py
  16. """
  17. import operator
  18. import contextlib
  19. import functools
  20. from distutils.version import LooseVersion
  21. import numpy as np
  22. from scipy._lib.six import xrange, zip as izip
  23. from numpy import (arange, zeros, array, dot, matrix, asmatrix, asarray,
  24. vstack, ndarray, transpose, diag, kron, inf, conjugate,
  25. int8, ComplexWarning)
  26. import random
  27. from numpy.testing import (assert_equal, assert_array_equal,
  28. assert_array_almost_equal, assert_almost_equal, assert_,
  29. assert_allclose)
  30. from pytest import raises as assert_raises
  31. from scipy._lib._numpy_compat import suppress_warnings
  32. import scipy.linalg
  33. import scipy.sparse as sparse
  34. from scipy.sparse import (csc_matrix, csr_matrix, dok_matrix,
  35. coo_matrix, lil_matrix, dia_matrix, bsr_matrix,
  36. eye, isspmatrix, SparseEfficiencyWarning, issparse)
  37. from scipy.sparse.sputils import supported_dtypes, isscalarlike, get_index_dtype
  38. from scipy.sparse.linalg import splu, expm, inv
  39. from scipy._lib._version import NumpyVersion
  40. from scipy._lib.decorator import decorator
  41. import pytest
  42. def assert_in(member, collection, msg=None):
  43. assert_(member in collection, msg=msg if msg is not None else "%r not found in %r" % (member, collection))
  44. def assert_array_equal_dtype(x, y, **kwargs):
  45. assert_(x.dtype == y.dtype)
  46. assert_array_equal(x, y, **kwargs)
  47. # Only test matmul operator (A @ B) when available (Python 3.5+)
  48. TEST_MATMUL = hasattr(operator, 'matmul')
  49. sup_complex = suppress_warnings()
  50. sup_complex.filter(ComplexWarning)
  51. def with_64bit_maxval_limit(maxval_limit=None, random=False, fixed_dtype=None,
  52. downcast_maxval=None, assert_32bit=False):
  53. """
  54. Monkeypatch the maxval threshold at which scipy.sparse switches to
  55. 64-bit index arrays, or make it (pseudo-)random.
  56. """
  57. if maxval_limit is None:
  58. maxval_limit = 10
  59. if assert_32bit:
  60. def new_get_index_dtype(arrays=(), maxval=None, check_contents=False):
  61. tp = get_index_dtype(arrays, maxval, check_contents)
  62. assert_equal(np.iinfo(tp).max, np.iinfo(np.int32).max)
  63. assert_(tp == np.int32 or tp == np.intc)
  64. return tp
  65. elif fixed_dtype is not None:
  66. def new_get_index_dtype(arrays=(), maxval=None, check_contents=False):
  67. return fixed_dtype
  68. elif random:
  69. counter = np.random.RandomState(seed=1234)
  70. def new_get_index_dtype(arrays=(), maxval=None, check_contents=False):
  71. return (np.int32, np.int64)[counter.randint(2)]
  72. else:
  73. def new_get_index_dtype(arrays=(), maxval=None, check_contents=False):
  74. dtype = np.int32
  75. if maxval is not None:
  76. if maxval > maxval_limit:
  77. dtype = np.int64
  78. for arr in arrays:
  79. arr = np.asarray(arr)
  80. if arr.dtype > np.int32:
  81. if check_contents:
  82. if arr.size == 0:
  83. # a bigger type not needed
  84. continue
  85. elif np.issubdtype(arr.dtype, np.integer):
  86. maxval = arr.max()
  87. minval = arr.min()
  88. if minval >= -maxval_limit and maxval <= maxval_limit:
  89. # a bigger type not needed
  90. continue
  91. dtype = np.int64
  92. return dtype
  93. if downcast_maxval is not None:
  94. def new_downcast_intp_index(arr):
  95. if arr.max() > downcast_maxval:
  96. raise AssertionError("downcast limited")
  97. return arr.astype(np.intp)
  98. @decorator
  99. def deco(func, *a, **kw):
  100. backup = []
  101. modules = [scipy.sparse.bsr, scipy.sparse.coo, scipy.sparse.csc,
  102. scipy.sparse.csr, scipy.sparse.dia, scipy.sparse.dok,
  103. scipy.sparse.lil, scipy.sparse.sputils,
  104. scipy.sparse.compressed, scipy.sparse.construct]
  105. try:
  106. for mod in modules:
  107. backup.append((mod, 'get_index_dtype',
  108. getattr(mod, 'get_index_dtype', None)))
  109. setattr(mod, 'get_index_dtype', new_get_index_dtype)
  110. if downcast_maxval is not None:
  111. backup.append((mod, 'downcast_intp_index',
  112. getattr(mod, 'downcast_intp_index', None)))
  113. setattr(mod, 'downcast_intp_index', new_downcast_intp_index)
  114. return func(*a, **kw)
  115. finally:
  116. for mod, name, oldfunc in backup:
  117. if oldfunc is not None:
  118. setattr(mod, name, oldfunc)
  119. return deco
  120. def todense(a):
  121. if isinstance(a, np.ndarray) or isscalarlike(a):
  122. return a
  123. return a.todense()
  124. class BinopTester(object):
  125. # Custom type to test binary operations on sparse matrices.
  126. def __add__(self, mat):
  127. return "matrix on the right"
  128. def __mul__(self, mat):
  129. return "matrix on the right"
  130. def __sub__(self, mat):
  131. return "matrix on the right"
  132. def __radd__(self, mat):
  133. return "matrix on the left"
  134. def __rmul__(self, mat):
  135. return "matrix on the left"
  136. def __rsub__(self, mat):
  137. return "matrix on the left"
  138. def __matmul__(self, mat):
  139. return "matrix on the right"
  140. def __rmatmul__(self, mat):
  141. return "matrix on the left"
  142. class BinopTester_with_shape(object):
  143. # Custom type to test binary operations on sparse matrices
  144. # with object which has shape attribute.
  145. def __init__(self,shape):
  146. self._shape = shape
  147. def shape(self):
  148. return self._shape
  149. def ndim(self):
  150. return len(self._shape)
  151. def __add__(self, mat):
  152. return "matrix on the right"
  153. def __mul__(self, mat):
  154. return "matrix on the right"
  155. def __sub__(self, mat):
  156. return "matrix on the right"
  157. def __radd__(self, mat):
  158. return "matrix on the left"
  159. def __rmul__(self, mat):
  160. return "matrix on the left"
  161. def __rsub__(self, mat):
  162. return "matrix on the left"
  163. def __matmul__(self, mat):
  164. return "matrix on the right"
  165. def __rmatmul__(self, mat):
  166. return "matrix on the left"
  167. #------------------------------------------------------------------------------
  168. # Generic tests
  169. #------------------------------------------------------------------------------
  170. # TODO check that spmatrix( ... , copy=X ) is respected
  171. # TODO test prune
  172. # TODO test has_sorted_indices
  173. class _TestCommon(object):
  174. """test common functionality shared by all sparse formats"""
  175. math_dtypes = supported_dtypes
  176. @classmethod
  177. def init_class(cls):
  178. # Canonical data.
  179. cls.dat = matrix([[1,0,0,2],[3,0,1,0],[0,2,0,0]],'d')
  180. cls.datsp = cls.spmatrix(cls.dat)
  181. # Some sparse and dense matrices with data for every supported
  182. # dtype.
  183. # This set union is a workaround for numpy#6295, which means that
  184. # two np.int64 dtypes don't hash to the same value.
  185. cls.checked_dtypes = set(supported_dtypes).union(cls.math_dtypes)
  186. cls.dat_dtypes = {}
  187. cls.datsp_dtypes = {}
  188. for dtype in cls.checked_dtypes:
  189. cls.dat_dtypes[dtype] = cls.dat.astype(dtype)
  190. cls.datsp_dtypes[dtype] = cls.spmatrix(cls.dat.astype(dtype))
  191. # Check that the original data is equivalent to the
  192. # corresponding dat_dtypes & datsp_dtypes.
  193. assert_equal(cls.dat, cls.dat_dtypes[np.float64])
  194. assert_equal(cls.datsp.todense(),
  195. cls.datsp_dtypes[np.float64].todense())
  196. def test_bool(self):
  197. def check(dtype):
  198. datsp = self.datsp_dtypes[dtype]
  199. assert_raises(ValueError, bool, datsp)
  200. assert_(self.spmatrix([1]))
  201. assert_(not self.spmatrix([0]))
  202. if isinstance(self, TestDOK):
  203. pytest.skip("Cannot create a rank <= 2 DOK matrix.")
  204. for dtype in self.checked_dtypes:
  205. check(dtype)
  206. def test_bool_rollover(self):
  207. # bool's underlying dtype is 1 byte, check that it does not
  208. # rollover True -> False at 256.
  209. dat = np.matrix([[True, False]])
  210. datsp = self.spmatrix(dat)
  211. for _ in range(10):
  212. datsp = datsp + datsp
  213. dat = dat + dat
  214. assert_array_equal(dat, datsp.todense())
  215. def test_eq(self):
  216. sup = suppress_warnings()
  217. sup.filter(SparseEfficiencyWarning)
  218. @sup
  219. @sup_complex
  220. def check(dtype):
  221. dat = self.dat_dtypes[dtype]
  222. datsp = self.datsp_dtypes[dtype]
  223. dat2 = dat.copy()
  224. dat2[:,0] = 0
  225. datsp2 = self.spmatrix(dat2)
  226. datbsr = bsr_matrix(dat)
  227. datcsr = csr_matrix(dat)
  228. datcsc = csc_matrix(dat)
  229. datlil = lil_matrix(dat)
  230. # sparse/sparse
  231. assert_array_equal_dtype(dat == dat2, (datsp == datsp2).todense())
  232. # mix sparse types
  233. assert_array_equal_dtype(dat == dat2, (datbsr == datsp2).todense())
  234. assert_array_equal_dtype(dat == dat2, (datcsr == datsp2).todense())
  235. assert_array_equal_dtype(dat == dat2, (datcsc == datsp2).todense())
  236. assert_array_equal_dtype(dat == dat2, (datlil == datsp2).todense())
  237. # sparse/dense
  238. assert_array_equal_dtype(dat == datsp2, datsp2 == dat)
  239. # sparse/scalar
  240. assert_array_equal_dtype(dat == 0, (datsp == 0).todense())
  241. assert_array_equal_dtype(dat == 1, (datsp == 1).todense())
  242. assert_array_equal_dtype(dat == np.nan,
  243. (datsp == np.nan).todense())
  244. if not isinstance(self, (TestBSR, TestCSC, TestCSR)):
  245. pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.")
  246. for dtype in self.checked_dtypes:
  247. check(dtype)
  248. def test_ne(self):
  249. sup = suppress_warnings()
  250. sup.filter(SparseEfficiencyWarning)
  251. @sup
  252. @sup_complex
  253. def check(dtype):
  254. dat = self.dat_dtypes[dtype]
  255. datsp = self.datsp_dtypes[dtype]
  256. dat2 = dat.copy()
  257. dat2[:,0] = 0
  258. datsp2 = self.spmatrix(dat2)
  259. datbsr = bsr_matrix(dat)
  260. datcsc = csc_matrix(dat)
  261. datcsr = csr_matrix(dat)
  262. datlil = lil_matrix(dat)
  263. # sparse/sparse
  264. assert_array_equal_dtype(dat != dat2, (datsp != datsp2).todense())
  265. # mix sparse types
  266. assert_array_equal_dtype(dat != dat2, (datbsr != datsp2).todense())
  267. assert_array_equal_dtype(dat != dat2, (datcsc != datsp2).todense())
  268. assert_array_equal_dtype(dat != dat2, (datcsr != datsp2).todense())
  269. assert_array_equal_dtype(dat != dat2, (datlil != datsp2).todense())
  270. # sparse/dense
  271. assert_array_equal_dtype(dat != datsp2, datsp2 != dat)
  272. # sparse/scalar
  273. assert_array_equal_dtype(dat != 0, (datsp != 0).todense())
  274. assert_array_equal_dtype(dat != 1, (datsp != 1).todense())
  275. assert_array_equal_dtype(0 != dat, (0 != datsp).todense())
  276. assert_array_equal_dtype(1 != dat, (1 != datsp).todense())
  277. assert_array_equal_dtype(dat != np.nan,
  278. (datsp != np.nan).todense())
  279. if not isinstance(self, (TestBSR, TestCSC, TestCSR)):
  280. pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.")
  281. for dtype in self.checked_dtypes:
  282. check(dtype)
  283. def test_lt(self):
  284. sup = suppress_warnings()
  285. sup.filter(SparseEfficiencyWarning)
  286. @sup
  287. @sup_complex
  288. def check(dtype):
  289. # data
  290. dat = self.dat_dtypes[dtype]
  291. datsp = self.datsp_dtypes[dtype]
  292. dat2 = dat.copy()
  293. dat2[:,0] = 0
  294. datsp2 = self.spmatrix(dat2)
  295. datcomplex = dat.astype(complex)
  296. datcomplex[:,0] = 1 + 1j
  297. datspcomplex = self.spmatrix(datcomplex)
  298. datbsr = bsr_matrix(dat)
  299. datcsc = csc_matrix(dat)
  300. datcsr = csr_matrix(dat)
  301. datlil = lil_matrix(dat)
  302. # sparse/sparse
  303. assert_array_equal_dtype(dat < dat2, (datsp < datsp2).todense())
  304. assert_array_equal_dtype(datcomplex < dat2,
  305. (datspcomplex < datsp2).todense())
  306. # mix sparse types
  307. assert_array_equal_dtype(dat < dat2, (datbsr < datsp2).todense())
  308. assert_array_equal_dtype(dat < dat2, (datcsc < datsp2).todense())
  309. assert_array_equal_dtype(dat < dat2, (datcsr < datsp2).todense())
  310. assert_array_equal_dtype(dat < dat2, (datlil < datsp2).todense())
  311. assert_array_equal_dtype(dat2 < dat, (datsp2 < datbsr).todense())
  312. assert_array_equal_dtype(dat2 < dat, (datsp2 < datcsc).todense())
  313. assert_array_equal_dtype(dat2 < dat, (datsp2 < datcsr).todense())
  314. assert_array_equal_dtype(dat2 < dat, (datsp2 < datlil).todense())
  315. # sparse/dense
  316. assert_array_equal_dtype(dat < dat2, datsp < dat2)
  317. assert_array_equal_dtype(datcomplex < dat2, datspcomplex < dat2)
  318. # sparse/scalar
  319. assert_array_equal_dtype((datsp < 2).todense(), dat < 2)
  320. assert_array_equal_dtype((datsp < 1).todense(), dat < 1)
  321. assert_array_equal_dtype((datsp < 0).todense(), dat < 0)
  322. assert_array_equal_dtype((datsp < -1).todense(), dat < -1)
  323. assert_array_equal_dtype((datsp < -2).todense(), dat < -2)
  324. with np.errstate(invalid='ignore'):
  325. assert_array_equal_dtype((datsp < np.nan).todense(),
  326. dat < np.nan)
  327. assert_array_equal_dtype((2 < datsp).todense(), 2 < dat)
  328. assert_array_equal_dtype((1 < datsp).todense(), 1 < dat)
  329. assert_array_equal_dtype((0 < datsp).todense(), 0 < dat)
  330. assert_array_equal_dtype((-1 < datsp).todense(), -1 < dat)
  331. assert_array_equal_dtype((-2 < datsp).todense(), -2 < dat)
  332. # data
  333. dat = self.dat_dtypes[dtype]
  334. datsp = self.datsp_dtypes[dtype]
  335. dat2 = dat.copy()
  336. dat2[:,0] = 0
  337. datsp2 = self.spmatrix(dat2)
  338. # dense rhs
  339. assert_array_equal_dtype(dat < datsp2, datsp < dat2)
  340. if not isinstance(self, (TestBSR, TestCSC, TestCSR)):
  341. pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.")
  342. for dtype in self.checked_dtypes:
  343. check(dtype)
  344. def test_gt(self):
  345. sup = suppress_warnings()
  346. sup.filter(SparseEfficiencyWarning)
  347. @sup
  348. @sup_complex
  349. def check(dtype):
  350. dat = self.dat_dtypes[dtype]
  351. datsp = self.datsp_dtypes[dtype]
  352. dat2 = dat.copy()
  353. dat2[:,0] = 0
  354. datsp2 = self.spmatrix(dat2)
  355. datcomplex = dat.astype(complex)
  356. datcomplex[:,0] = 1 + 1j
  357. datspcomplex = self.spmatrix(datcomplex)
  358. datbsr = bsr_matrix(dat)
  359. datcsc = csc_matrix(dat)
  360. datcsr = csr_matrix(dat)
  361. datlil = lil_matrix(dat)
  362. # sparse/sparse
  363. assert_array_equal_dtype(dat > dat2, (datsp > datsp2).todense())
  364. assert_array_equal_dtype(datcomplex > dat2,
  365. (datspcomplex > datsp2).todense())
  366. # mix sparse types
  367. assert_array_equal_dtype(dat > dat2, (datbsr > datsp2).todense())
  368. assert_array_equal_dtype(dat > dat2, (datcsc > datsp2).todense())
  369. assert_array_equal_dtype(dat > dat2, (datcsr > datsp2).todense())
  370. assert_array_equal_dtype(dat > dat2, (datlil > datsp2).todense())
  371. assert_array_equal_dtype(dat2 > dat, (datsp2 > datbsr).todense())
  372. assert_array_equal_dtype(dat2 > dat, (datsp2 > datcsc).todense())
  373. assert_array_equal_dtype(dat2 > dat, (datsp2 > datcsr).todense())
  374. assert_array_equal_dtype(dat2 > dat, (datsp2 > datlil).todense())
  375. # sparse/dense
  376. assert_array_equal_dtype(dat > dat2, datsp > dat2)
  377. assert_array_equal_dtype(datcomplex > dat2, datspcomplex > dat2)
  378. # sparse/scalar
  379. assert_array_equal_dtype((datsp > 2).todense(), dat > 2)
  380. assert_array_equal_dtype((datsp > 1).todense(), dat > 1)
  381. assert_array_equal_dtype((datsp > 0).todense(), dat > 0)
  382. assert_array_equal_dtype((datsp > -1).todense(), dat > -1)
  383. assert_array_equal_dtype((datsp > -2).todense(), dat > -2)
  384. with np.errstate(invalid='ignore'):
  385. assert_array_equal_dtype((datsp > np.nan).todense(),
  386. dat > np.nan)
  387. assert_array_equal_dtype((2 > datsp).todense(), 2 > dat)
  388. assert_array_equal_dtype((1 > datsp).todense(), 1 > dat)
  389. assert_array_equal_dtype((0 > datsp).todense(), 0 > dat)
  390. assert_array_equal_dtype((-1 > datsp).todense(), -1 > dat)
  391. assert_array_equal_dtype((-2 > datsp).todense(), -2 > dat)
  392. # data
  393. dat = self.dat_dtypes[dtype]
  394. datsp = self.datsp_dtypes[dtype]
  395. dat2 = dat.copy()
  396. dat2[:,0] = 0
  397. datsp2 = self.spmatrix(dat2)
  398. # dense rhs
  399. assert_array_equal_dtype(dat > datsp2, datsp > dat2)
  400. if not isinstance(self, (TestBSR, TestCSC, TestCSR)):
  401. pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.")
  402. for dtype in self.checked_dtypes:
  403. check(dtype)
  404. def test_le(self):
  405. sup = suppress_warnings()
  406. sup.filter(SparseEfficiencyWarning)
  407. @sup
  408. @sup_complex
  409. def check(dtype):
  410. dat = self.dat_dtypes[dtype]
  411. datsp = self.datsp_dtypes[dtype]
  412. dat2 = dat.copy()
  413. dat2[:,0] = 0
  414. datsp2 = self.spmatrix(dat2)
  415. datcomplex = dat.astype(complex)
  416. datcomplex[:,0] = 1 + 1j
  417. datspcomplex = self.spmatrix(datcomplex)
  418. datbsr = bsr_matrix(dat)
  419. datcsc = csc_matrix(dat)
  420. datcsr = csr_matrix(dat)
  421. datlil = lil_matrix(dat)
  422. # sparse/sparse
  423. assert_array_equal_dtype(dat <= dat2, (datsp <= datsp2).todense())
  424. assert_array_equal_dtype(datcomplex <= dat2,
  425. (datspcomplex <= datsp2).todense())
  426. # mix sparse types
  427. assert_array_equal_dtype((datbsr <= datsp2).todense(), dat <= dat2)
  428. assert_array_equal_dtype((datcsc <= datsp2).todense(), dat <= dat2)
  429. assert_array_equal_dtype((datcsr <= datsp2).todense(), dat <= dat2)
  430. assert_array_equal_dtype((datlil <= datsp2).todense(), dat <= dat2)
  431. assert_array_equal_dtype((datsp2 <= datbsr).todense(), dat2 <= dat)
  432. assert_array_equal_dtype((datsp2 <= datcsc).todense(), dat2 <= dat)
  433. assert_array_equal_dtype((datsp2 <= datcsr).todense(), dat2 <= dat)
  434. assert_array_equal_dtype((datsp2 <= datlil).todense(), dat2 <= dat)
  435. # sparse/dense
  436. assert_array_equal_dtype(datsp <= dat2, dat <= dat2)
  437. assert_array_equal_dtype(datspcomplex <= dat2, datcomplex <= dat2)
  438. # sparse/scalar
  439. assert_array_equal_dtype((datsp <= 2).todense(), dat <= 2)
  440. assert_array_equal_dtype((datsp <= 1).todense(), dat <= 1)
  441. assert_array_equal_dtype((datsp <= -1).todense(), dat <= -1)
  442. assert_array_equal_dtype((datsp <= -2).todense(), dat <= -2)
  443. assert_array_equal_dtype((2 <= datsp).todense(), 2 <= dat)
  444. assert_array_equal_dtype((1 <= datsp).todense(), 1 <= dat)
  445. assert_array_equal_dtype((-1 <= datsp).todense(), -1 <= dat)
  446. assert_array_equal_dtype((-2 <= datsp).todense(), -2 <= dat)
  447. # data
  448. dat = self.dat_dtypes[dtype]
  449. datsp = self.datsp_dtypes[dtype]
  450. dat2 = dat.copy()
  451. dat2[:,0] = 0
  452. datsp2 = self.spmatrix(dat2)
  453. # dense rhs
  454. assert_array_equal_dtype(dat <= datsp2, datsp <= dat2)
  455. if not isinstance(self, (TestBSR, TestCSC, TestCSR)):
  456. pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.")
  457. for dtype in self.checked_dtypes:
  458. check(dtype)
  459. def test_ge(self):
  460. sup = suppress_warnings()
  461. sup.filter(SparseEfficiencyWarning)
  462. @sup
  463. @sup_complex
  464. def check(dtype):
  465. dat = self.dat_dtypes[dtype]
  466. datsp = self.datsp_dtypes[dtype]
  467. dat2 = dat.copy()
  468. dat2[:,0] = 0
  469. datsp2 = self.spmatrix(dat2)
  470. datcomplex = dat.astype(complex)
  471. datcomplex[:,0] = 1 + 1j
  472. datspcomplex = self.spmatrix(datcomplex)
  473. datbsr = bsr_matrix(dat)
  474. datcsc = csc_matrix(dat)
  475. datcsr = csr_matrix(dat)
  476. datlil = lil_matrix(dat)
  477. # sparse/sparse
  478. assert_array_equal_dtype(dat >= dat2, (datsp >= datsp2).todense())
  479. assert_array_equal_dtype(datcomplex >= dat2,
  480. (datspcomplex >= datsp2).todense())
  481. # mix sparse types
  482. assert_array_equal_dtype((datbsr >= datsp2).todense(), dat >= dat2)
  483. assert_array_equal_dtype((datcsc >= datsp2).todense(), dat >= dat2)
  484. assert_array_equal_dtype((datcsr >= datsp2).todense(), dat >= dat2)
  485. assert_array_equal_dtype((datlil >= datsp2).todense(), dat >= dat2)
  486. assert_array_equal_dtype((datsp2 >= datbsr).todense(), dat2 >= dat)
  487. assert_array_equal_dtype((datsp2 >= datcsc).todense(), dat2 >= dat)
  488. assert_array_equal_dtype((datsp2 >= datcsr).todense(), dat2 >= dat)
  489. assert_array_equal_dtype((datsp2 >= datlil).todense(), dat2 >= dat)
  490. # sparse/dense
  491. assert_array_equal_dtype(datsp >= dat2, dat >= dat2)
  492. assert_array_equal_dtype(datspcomplex >= dat2, datcomplex >= dat2)
  493. # sparse/scalar
  494. assert_array_equal_dtype((datsp >= 2).todense(), dat >= 2)
  495. assert_array_equal_dtype((datsp >= 1).todense(), dat >= 1)
  496. assert_array_equal_dtype((datsp >= -1).todense(), dat >= -1)
  497. assert_array_equal_dtype((datsp >= -2).todense(), dat >= -2)
  498. assert_array_equal_dtype((2 >= datsp).todense(), 2 >= dat)
  499. assert_array_equal_dtype((1 >= datsp).todense(), 1 >= dat)
  500. assert_array_equal_dtype((-1 >= datsp).todense(), -1 >= dat)
  501. assert_array_equal_dtype((-2 >= datsp).todense(), -2 >= dat)
  502. # dense data
  503. dat = self.dat_dtypes[dtype]
  504. datsp = self.datsp_dtypes[dtype]
  505. dat2 = dat.copy()
  506. dat2[:,0] = 0
  507. datsp2 = self.spmatrix(dat2)
  508. # dense rhs
  509. assert_array_equal_dtype(dat >= datsp2, datsp >= dat2)
  510. if not isinstance(self, (TestBSR, TestCSC, TestCSR)):
  511. pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.")
  512. for dtype in self.checked_dtypes:
  513. check(dtype)
  514. def test_empty(self):
  515. # create empty matrices
  516. assert_equal(self.spmatrix((3,3)).todense(), np.zeros((3,3)))
  517. assert_equal(self.spmatrix((3,3)).nnz, 0)
  518. assert_equal(self.spmatrix((3,3)).count_nonzero(), 0)
  519. def test_count_nonzero(self):
  520. expected = np.count_nonzero(self.datsp.toarray())
  521. assert_equal(self.datsp.count_nonzero(), expected)
  522. assert_equal(self.datsp.T.count_nonzero(), expected)
  523. def test_invalid_shapes(self):
  524. assert_raises(ValueError, self.spmatrix, (-1,3))
  525. assert_raises(ValueError, self.spmatrix, (3,-1))
  526. assert_raises(ValueError, self.spmatrix, (-1,-1))
  527. def test_repr(self):
  528. repr(self.datsp)
  529. def test_str(self):
  530. str(self.datsp)
  531. def test_empty_arithmetic(self):
  532. # Test manipulating empty matrices. Fails in SciPy SVN <= r1768
  533. shape = (5, 5)
  534. for mytype in [np.dtype('int32'), np.dtype('float32'),
  535. np.dtype('float64'), np.dtype('complex64'),
  536. np.dtype('complex128')]:
  537. a = self.spmatrix(shape, dtype=mytype)
  538. b = a + a
  539. c = 2 * a
  540. d = a * a.tocsc()
  541. e = a * a.tocsr()
  542. f = a * a.tocoo()
  543. for m in [a,b,c,d,e,f]:
  544. assert_equal(m.A, a.A*a.A)
  545. # These fail in all revisions <= r1768:
  546. assert_equal(m.dtype,mytype)
  547. assert_equal(m.A.dtype,mytype)
  548. def test_abs(self):
  549. A = matrix([[-1, 0, 17],[0, -5, 0],[1, -4, 0],[0,0,0]],'d')
  550. assert_equal(abs(A),abs(self.spmatrix(A)).todense())
  551. def test_elementwise_power(self):
  552. A = matrix([[-4, -3, -2],[-1, 0, 1],[2, 3, 4]], 'd')
  553. assert_equal(np.power(A, 2), self.spmatrix(A).power(2).todense())
  554. #it's element-wise power function, input has to be a scalar
  555. assert_raises(NotImplementedError, self.spmatrix(A).power, A)
  556. def test_neg(self):
  557. A = matrix([[-1, 0, 17], [0, -5, 0], [1, -4, 0], [0, 0, 0]], 'd')
  558. assert_equal(-A, (-self.spmatrix(A)).todense())
  559. # see gh-5843
  560. A = matrix([[True, False, False], [False, False, True]])
  561. assert_raises(NotImplementedError, self.spmatrix(A).__neg__)
  562. def test_real(self):
  563. D = matrix([[1 + 3j, 2 - 4j]])
  564. A = self.spmatrix(D)
  565. assert_equal(A.real.todense(),D.real)
  566. def test_imag(self):
  567. D = matrix([[1 + 3j, 2 - 4j]])
  568. A = self.spmatrix(D)
  569. assert_equal(A.imag.todense(),D.imag)
  570. def test_diagonal(self):
  571. # Does the matrix's .diagonal() method work?
  572. mats = []
  573. mats.append([[1,0,2]])
  574. mats.append([[1],[0],[2]])
  575. mats.append([[0,1],[0,2],[0,3]])
  576. mats.append([[0,0,1],[0,0,2],[0,3,0]])
  577. mats.append(kron(mats[0],[[1,2]]))
  578. mats.append(kron(mats[0],[[1],[2]]))
  579. mats.append(kron(mats[1],[[1,2],[3,4]]))
  580. mats.append(kron(mats[2],[[1,2],[3,4]]))
  581. mats.append(kron(mats[3],[[1,2],[3,4]]))
  582. mats.append(kron(mats[3],[[1,2,3,4]]))
  583. for m in mats:
  584. rows, cols = array(m).shape
  585. sparse_mat = self.spmatrix(m)
  586. for k in range(-rows + 1, cols):
  587. assert_equal(sparse_mat.diagonal(k=k), diag(m, k=k))
  588. assert_raises(ValueError, sparse_mat.diagonal, -rows)
  589. assert_raises(ValueError, sparse_mat.diagonal, cols)
  590. # Test all-zero matrix.
  591. assert_equal(self.spmatrix((40, 16130)).diagonal(), np.zeros(40))
  592. def test_reshape(self):
  593. # This first example is taken from the lil_matrix reshaping test.
  594. x = self.spmatrix([[1, 0, 7], [0, 0, 0], [0, 3, 0], [0, 0, 5]])
  595. for order in ['C', 'F']:
  596. for s in [(12, 1), (1, 12)]:
  597. assert_array_equal(x.reshape(s, order=order).todense(),
  598. x.todense().reshape(s, order=order))
  599. # This example is taken from the stackoverflow answer at
  600. # https://stackoverflow.com/q/16511879
  601. x = self.spmatrix([[0, 10, 0, 0], [0, 0, 0, 0], [0, 20, 30, 40]])
  602. y = x.reshape((2, 6)) # Default order is 'C'
  603. desired = [[0, 10, 0, 0, 0, 0], [0, 0, 0, 20, 30, 40]]
  604. assert_array_equal(y.A, desired)
  605. # Reshape with negative indexes
  606. y = x.reshape((2, -1))
  607. assert_array_equal(y.A, desired)
  608. y = x.reshape((-1, 6))
  609. assert_array_equal(y.A, desired)
  610. assert_raises(ValueError, x.reshape, (-1, -1))
  611. # Reshape with star args
  612. y = x.reshape(2, 6)
  613. assert_array_equal(y.A, desired)
  614. assert_raises(TypeError, x.reshape, 2, 6, not_an_arg=1)
  615. # Reshape with same size is noop unless copy=True
  616. y = x.reshape((3, 4))
  617. assert_(y is x)
  618. y = x.reshape((3, 4), copy=True)
  619. assert_(y is not x)
  620. # Ensure reshape did not alter original size
  621. assert_array_equal(x.shape, (3, 4))
  622. # Reshape in place
  623. x.shape = (2, 6)
  624. assert_array_equal(x.A, desired)
  625. @pytest.mark.slow
  626. def test_setdiag_comprehensive(self):
  627. def dense_setdiag(a, v, k):
  628. v = np.asarray(v)
  629. if k >= 0:
  630. n = min(a.shape[0], a.shape[1] - k)
  631. if v.ndim != 0:
  632. n = min(n, len(v))
  633. v = v[:n]
  634. i = np.arange(0, n)
  635. j = np.arange(k, k + n)
  636. a[i,j] = v
  637. elif k < 0:
  638. dense_setdiag(a.T, v, -k)
  639. def check_setdiag(a, b, k):
  640. # Check setting diagonal using a scalar, a vector of
  641. # correct length, and too short or too long vectors
  642. for r in [-1, len(np.diag(a, k)), 2, 30]:
  643. if r < 0:
  644. v = int(np.random.randint(1, 20, size=1))
  645. else:
  646. v = np.random.randint(1, 20, size=r)
  647. dense_setdiag(a, v, k)
  648. with suppress_warnings() as sup:
  649. sup.filter(SparseEfficiencyWarning, "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  650. b.setdiag(v, k)
  651. # check that dense_setdiag worked
  652. d = np.diag(a, k)
  653. if np.asarray(v).ndim == 0:
  654. assert_array_equal(d, v, err_msg="%s %d" % (msg, r))
  655. else:
  656. n = min(len(d), len(v))
  657. assert_array_equal(d[:n], v[:n], err_msg="%s %d" % (msg, r))
  658. # check that sparse setdiag worked
  659. assert_array_equal(b.A, a, err_msg="%s %d" % (msg, r))
  660. # comprehensive test
  661. np.random.seed(1234)
  662. shapes = [(0,5), (5,0), (1,5), (5,1), (5,5)]
  663. for dtype in [np.int8, np.float64]:
  664. for m,n in shapes:
  665. ks = np.arange(-m+1, n-1)
  666. for k in ks:
  667. msg = repr((dtype, m, n, k))
  668. a = np.zeros((m, n), dtype=dtype)
  669. b = self.spmatrix((m, n), dtype=dtype)
  670. check_setdiag(a, b, k)
  671. # check overwriting etc
  672. for k2 in np.random.choice(ks, size=min(len(ks), 5)):
  673. check_setdiag(a, b, k2)
  674. def test_setdiag(self):
  675. # simple test cases
  676. m = self.spmatrix(np.eye(3))
  677. values = [3, 2, 1]
  678. with suppress_warnings() as sup:
  679. sup.filter(SparseEfficiencyWarning,
  680. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  681. assert_raises(ValueError, m.setdiag, values, k=4)
  682. m.setdiag(values)
  683. assert_array_equal(m.diagonal(), values)
  684. m.setdiag(values, k=1)
  685. assert_array_equal(m.A, np.array([[3, 3, 0],
  686. [0, 2, 2],
  687. [0, 0, 1]]))
  688. m.setdiag(values, k=-2)
  689. assert_array_equal(m.A, np.array([[3, 3, 0],
  690. [0, 2, 2],
  691. [3, 0, 1]]))
  692. m.setdiag((9,), k=2)
  693. assert_array_equal(m.A[0,2], 9)
  694. m.setdiag((9,), k=-2)
  695. assert_array_equal(m.A[2,0], 9)
  696. def test_nonzero(self):
  697. A = array([[1, 0, 1],[0, 1, 1],[0, 0, 1]])
  698. Asp = self.spmatrix(A)
  699. A_nz = set([tuple(ij) for ij in transpose(A.nonzero())])
  700. Asp_nz = set([tuple(ij) for ij in transpose(Asp.nonzero())])
  701. assert_equal(A_nz, Asp_nz)
  702. def test_numpy_nonzero(self):
  703. # See gh-5987
  704. A = array([[1, 0, 1], [0, 1, 1], [0, 0, 1]])
  705. Asp = self.spmatrix(A)
  706. A_nz = set([tuple(ij) for ij in transpose(np.nonzero(A))])
  707. Asp_nz = set([tuple(ij) for ij in transpose(np.nonzero(Asp))])
  708. assert_equal(A_nz, Asp_nz)
  709. def test_getrow(self):
  710. assert_array_equal(self.datsp.getrow(1).todense(), self.dat[1,:])
  711. assert_array_equal(self.datsp.getrow(-1).todense(), self.dat[-1,:])
  712. def test_getcol(self):
  713. assert_array_equal(self.datsp.getcol(1).todense(), self.dat[:,1])
  714. assert_array_equal(self.datsp.getcol(-1).todense(), self.dat[:,-1])
  715. def test_sum(self):
  716. np.random.seed(1234)
  717. dat_1 = np.matrix([[0, 1, 2],
  718. [3, -4, 5],
  719. [-6, 7, 9]])
  720. dat_2 = np.random.rand(5, 5)
  721. dat_3 = np.array([[]])
  722. dat_4 = np.zeros((40, 40))
  723. dat_5 = sparse.rand(5, 5, density=1e-2).A
  724. matrices = [dat_1, dat_2, dat_3, dat_4, dat_5]
  725. def check(dtype, j):
  726. dat = np.matrix(matrices[j], dtype=dtype)
  727. datsp = self.spmatrix(dat, dtype=dtype)
  728. with np.errstate(over='ignore'):
  729. assert_array_almost_equal(dat.sum(), datsp.sum())
  730. assert_equal(dat.sum().dtype, datsp.sum().dtype)
  731. assert_(np.isscalar(datsp.sum(axis=None)))
  732. assert_array_almost_equal(dat.sum(axis=None),
  733. datsp.sum(axis=None))
  734. assert_equal(dat.sum(axis=None).dtype,
  735. datsp.sum(axis=None).dtype)
  736. assert_array_almost_equal(dat.sum(axis=0), datsp.sum(axis=0))
  737. assert_equal(dat.sum(axis=0).dtype, datsp.sum(axis=0).dtype)
  738. assert_array_almost_equal(dat.sum(axis=1), datsp.sum(axis=1))
  739. assert_equal(dat.sum(axis=1).dtype, datsp.sum(axis=1).dtype)
  740. assert_array_almost_equal(dat.sum(axis=-2), datsp.sum(axis=-2))
  741. assert_equal(dat.sum(axis=-2).dtype, datsp.sum(axis=-2).dtype)
  742. assert_array_almost_equal(dat.sum(axis=-1), datsp.sum(axis=-1))
  743. assert_equal(dat.sum(axis=-1).dtype, datsp.sum(axis=-1).dtype)
  744. for dtype in self.checked_dtypes:
  745. for j in range(len(matrices)):
  746. check(dtype, j)
  747. def test_sum_invalid_params(self):
  748. out = np.asmatrix(np.zeros((1, 3)))
  749. dat = np.matrix([[0, 1, 2],
  750. [3, -4, 5],
  751. [-6, 7, 9]])
  752. datsp = self.spmatrix(dat)
  753. assert_raises(ValueError, datsp.sum, axis=3)
  754. assert_raises(TypeError, datsp.sum, axis=(0, 1))
  755. assert_raises(TypeError, datsp.sum, axis=1.5)
  756. assert_raises(ValueError, datsp.sum, axis=1, out=out)
  757. def test_sum_dtype(self):
  758. dat = np.matrix([[0, 1, 2],
  759. [3, -4, 5],
  760. [-6, 7, 9]])
  761. datsp = self.spmatrix(dat)
  762. def check(dtype):
  763. dat_mean = dat.mean(dtype=dtype)
  764. datsp_mean = datsp.mean(dtype=dtype)
  765. assert_array_almost_equal(dat_mean, datsp_mean)
  766. assert_equal(dat_mean.dtype, datsp_mean.dtype)
  767. for dtype in self.checked_dtypes:
  768. check(dtype)
  769. def test_sum_out(self):
  770. dat = np.matrix([[0, 1, 2],
  771. [3, -4, 5],
  772. [-6, 7, 9]])
  773. datsp = self.spmatrix(dat)
  774. dat_out = np.matrix(0)
  775. datsp_out = np.matrix(0)
  776. dat.sum(out=dat_out)
  777. datsp.sum(out=datsp_out)
  778. assert_array_almost_equal(dat_out, datsp_out)
  779. dat_out = np.asmatrix(np.zeros((3, 1)))
  780. datsp_out = np.asmatrix(np.zeros((3, 1)))
  781. dat.sum(axis=1, out=dat_out)
  782. datsp.sum(axis=1, out=datsp_out)
  783. assert_array_almost_equal(dat_out, datsp_out)
  784. def test_numpy_sum(self):
  785. # See gh-5987
  786. dat = np.matrix([[0, 1, 2],
  787. [3, -4, 5],
  788. [-6, 7, 9]])
  789. datsp = self.spmatrix(dat)
  790. dat_mean = np.sum(dat)
  791. datsp_mean = np.sum(datsp)
  792. assert_array_almost_equal(dat_mean, datsp_mean)
  793. assert_equal(dat_mean.dtype, datsp_mean.dtype)
  794. def test_mean(self):
  795. def check(dtype):
  796. dat = np.matrix([[0, 1, 2],
  797. [3, -4, 5],
  798. [-6, 7, 9]], dtype=dtype)
  799. datsp = self.spmatrix(dat, dtype=dtype)
  800. assert_array_almost_equal(dat.mean(), datsp.mean())
  801. assert_equal(dat.mean().dtype, datsp.mean().dtype)
  802. assert_(np.isscalar(datsp.mean(axis=None)))
  803. assert_array_almost_equal(dat.mean(axis=None), datsp.mean(axis=None))
  804. assert_equal(dat.mean(axis=None).dtype, datsp.mean(axis=None).dtype)
  805. assert_array_almost_equal(dat.mean(axis=0), datsp.mean(axis=0))
  806. assert_equal(dat.mean(axis=0).dtype, datsp.mean(axis=0).dtype)
  807. assert_array_almost_equal(dat.mean(axis=1), datsp.mean(axis=1))
  808. assert_equal(dat.mean(axis=1).dtype, datsp.mean(axis=1).dtype)
  809. assert_array_almost_equal(dat.mean(axis=-2), datsp.mean(axis=-2))
  810. assert_equal(dat.mean(axis=-2).dtype, datsp.mean(axis=-2).dtype)
  811. assert_array_almost_equal(dat.mean(axis=-1), datsp.mean(axis=-1))
  812. assert_equal(dat.mean(axis=-1).dtype, datsp.mean(axis=-1).dtype)
  813. for dtype in self.checked_dtypes:
  814. check(dtype)
  815. def test_mean_invalid_params(self):
  816. out = np.asmatrix(np.zeros((1, 3)))
  817. dat = np.matrix([[0, 1, 2],
  818. [3, -4, 5],
  819. [-6, 7, 9]])
  820. datsp = self.spmatrix(dat)
  821. assert_raises(ValueError, datsp.mean, axis=3)
  822. assert_raises(TypeError, datsp.mean, axis=(0, 1))
  823. assert_raises(TypeError, datsp.mean, axis=1.5)
  824. assert_raises(ValueError, datsp.mean, axis=1, out=out)
  825. def test_mean_dtype(self):
  826. dat = np.matrix([[0, 1, 2],
  827. [3, -4, 5],
  828. [-6, 7, 9]])
  829. datsp = self.spmatrix(dat)
  830. def check(dtype):
  831. dat_mean = dat.mean(dtype=dtype)
  832. datsp_mean = datsp.mean(dtype=dtype)
  833. assert_array_almost_equal(dat_mean, datsp_mean)
  834. assert_equal(dat_mean.dtype, datsp_mean.dtype)
  835. for dtype in self.checked_dtypes:
  836. check(dtype)
  837. def test_mean_out(self):
  838. dat = np.matrix([[0, 1, 2],
  839. [3, -4, 5],
  840. [-6, 7, 9]])
  841. datsp = self.spmatrix(dat)
  842. dat_out = np.matrix(0)
  843. datsp_out = np.matrix(0)
  844. dat.mean(out=dat_out)
  845. datsp.mean(out=datsp_out)
  846. assert_array_almost_equal(dat_out, datsp_out)
  847. dat_out = np.asmatrix(np.zeros((3, 1)))
  848. datsp_out = np.asmatrix(np.zeros((3, 1)))
  849. dat.mean(axis=1, out=dat_out)
  850. datsp.mean(axis=1, out=datsp_out)
  851. assert_array_almost_equal(dat_out, datsp_out)
  852. def test_numpy_mean(self):
  853. # See gh-5987
  854. dat = np.matrix([[0, 1, 2],
  855. [3, -4, 5],
  856. [-6, 7, 9]])
  857. datsp = self.spmatrix(dat)
  858. dat_mean = np.mean(dat)
  859. datsp_mean = np.mean(datsp)
  860. assert_array_almost_equal(dat_mean, datsp_mean)
  861. assert_equal(dat_mean.dtype, datsp_mean.dtype)
  862. def test_expm(self):
  863. M = array([[1, 0, 2], [0, 0, 3], [-4, 5, 6]], float)
  864. sM = self.spmatrix(M, shape=(3,3), dtype=float)
  865. Mexp = scipy.linalg.expm(M)
  866. N = array([[3., 0., 1.], [0., 2., 0.], [0., 0., 0.]])
  867. sN = self.spmatrix(N, shape=(3,3), dtype=float)
  868. Nexp = scipy.linalg.expm(N)
  869. with suppress_warnings() as sup:
  870. sup.filter(SparseEfficiencyWarning, "splu requires CSC matrix format")
  871. sup.filter(SparseEfficiencyWarning,
  872. "spsolve is more efficient when sparse b is in the CSC matrix format")
  873. sup.filter(SparseEfficiencyWarning,
  874. "spsolve requires A be CSC or CSR matrix format")
  875. sMexp = expm(sM).todense()
  876. sNexp = expm(sN).todense()
  877. assert_array_almost_equal((sMexp - Mexp), zeros((3, 3)))
  878. assert_array_almost_equal((sNexp - Nexp), zeros((3, 3)))
  879. def test_inv(self):
  880. def check(dtype):
  881. M = array([[1, 0, 2], [0, 0, 3], [-4, 5, 6]], dtype)
  882. with suppress_warnings() as sup:
  883. sup.filter(SparseEfficiencyWarning,
  884. "spsolve requires A be CSC or CSR matrix format")
  885. sup.filter(SparseEfficiencyWarning,
  886. "spsolve is more efficient when sparse b is in the CSC matrix format")
  887. sup.filter(SparseEfficiencyWarning,
  888. "splu requires CSC matrix format")
  889. sM = self.spmatrix(M, shape=(3,3), dtype=dtype)
  890. sMinv = inv(sM)
  891. assert_array_almost_equal(sMinv.dot(sM).todense(), np.eye(3))
  892. assert_raises(TypeError, inv, M)
  893. for dtype in [float]:
  894. check(dtype)
  895. @sup_complex
  896. def test_from_array(self):
  897. A = array([[1,0,0],[2,3,4],[0,5,0],[0,0,0]])
  898. assert_array_equal(self.spmatrix(A).toarray(), A)
  899. A = array([[1.0 + 3j, 0, 0],
  900. [0, 2.0 + 5, 0],
  901. [0, 0, 0]])
  902. assert_array_equal(self.spmatrix(A).toarray(), A)
  903. assert_array_equal(self.spmatrix(A, dtype='int16').toarray(), A.astype('int16'))
  904. @sup_complex
  905. def test_from_matrix(self):
  906. A = matrix([[1,0,0],[2,3,4],[0,5,0],[0,0,0]])
  907. assert_array_equal(self.spmatrix(A).todense(), A)
  908. A = matrix([[1.0 + 3j, 0, 0],
  909. [0, 2.0 + 5, 0],
  910. [0, 0, 0]])
  911. assert_array_equal(self.spmatrix(A).toarray(), A)
  912. assert_array_equal(self.spmatrix(A, dtype='int16').toarray(), A.astype('int16'))
  913. @sup_complex
  914. def test_from_list(self):
  915. A = [[1,0,0],[2,3,4],[0,5,0],[0,0,0]]
  916. assert_array_equal(self.spmatrix(A).todense(), A)
  917. A = [[1.0 + 3j, 0, 0],
  918. [0, 2.0 + 5, 0],
  919. [0, 0, 0]]
  920. assert_array_equal(self.spmatrix(A).toarray(), array(A))
  921. assert_array_equal(self.spmatrix(A, dtype='int16').todense(), array(A).astype('int16'))
  922. @sup_complex
  923. def test_from_sparse(self):
  924. D = array([[1,0,0],[2,3,4],[0,5,0],[0,0,0]])
  925. S = csr_matrix(D)
  926. assert_array_equal(self.spmatrix(S).toarray(), D)
  927. S = self.spmatrix(D)
  928. assert_array_equal(self.spmatrix(S).toarray(), D)
  929. D = array([[1.0 + 3j, 0, 0],
  930. [0, 2.0 + 5, 0],
  931. [0, 0, 0]])
  932. S = csr_matrix(D)
  933. assert_array_equal(self.spmatrix(S).toarray(), D)
  934. assert_array_equal(self.spmatrix(S, dtype='int16').toarray(), D.astype('int16'))
  935. S = self.spmatrix(D)
  936. assert_array_equal(self.spmatrix(S).toarray(), D)
  937. assert_array_equal(self.spmatrix(S, dtype='int16').toarray(), D.astype('int16'))
  938. # def test_array(self):
  939. # """test array(A) where A is in sparse format"""
  940. # assert_equal( array(self.datsp), self.dat )
  941. def test_todense(self):
  942. # Check C- or F-contiguous (default).
  943. chk = self.datsp.todense()
  944. assert_array_equal(chk, self.dat)
  945. assert_(chk.flags.c_contiguous != chk.flags.f_contiguous)
  946. # Check C-contiguous (with arg).
  947. chk = self.datsp.todense(order='C')
  948. assert_array_equal(chk, self.dat)
  949. assert_(chk.flags.c_contiguous)
  950. assert_(not chk.flags.f_contiguous)
  951. # Check F-contiguous (with arg).
  952. chk = self.datsp.todense(order='F')
  953. assert_array_equal(chk, self.dat)
  954. assert_(not chk.flags.c_contiguous)
  955. assert_(chk.flags.f_contiguous)
  956. # Check with out argument (array).
  957. out = np.zeros(self.datsp.shape, dtype=self.datsp.dtype)
  958. chk = self.datsp.todense(out=out)
  959. assert_array_equal(self.dat, out)
  960. assert_array_equal(self.dat, chk)
  961. assert_(chk.base is out)
  962. # Check with out array (matrix).
  963. out = np.asmatrix(np.zeros(self.datsp.shape, dtype=self.datsp.dtype))
  964. chk = self.datsp.todense(out=out)
  965. assert_array_equal(self.dat, out)
  966. assert_array_equal(self.dat, chk)
  967. assert_(chk is out)
  968. a = matrix([1.,2.,3.])
  969. dense_dot_dense = a * self.dat
  970. check = a * self.datsp.todense()
  971. assert_array_equal(dense_dot_dense, check)
  972. b = matrix([1.,2.,3.,4.]).T
  973. dense_dot_dense = self.dat * b
  974. check2 = self.datsp.todense() * b
  975. assert_array_equal(dense_dot_dense, check2)
  976. # Check bool data works.
  977. spbool = self.spmatrix(self.dat, dtype=bool)
  978. matbool = self.dat.astype(bool)
  979. assert_array_equal(spbool.todense(), matbool)
  980. def test_toarray(self):
  981. # Check C- or F-contiguous (default).
  982. dat = asarray(self.dat)
  983. chk = self.datsp.toarray()
  984. assert_array_equal(chk, dat)
  985. assert_(chk.flags.c_contiguous != chk.flags.f_contiguous)
  986. # Check C-contiguous (with arg).
  987. chk = self.datsp.toarray(order='C')
  988. assert_array_equal(chk, dat)
  989. assert_(chk.flags.c_contiguous)
  990. assert_(not chk.flags.f_contiguous)
  991. # Check F-contiguous (with arg).
  992. chk = self.datsp.toarray(order='F')
  993. assert_array_equal(chk, dat)
  994. assert_(not chk.flags.c_contiguous)
  995. assert_(chk.flags.f_contiguous)
  996. # Check with output arg.
  997. out = np.zeros(self.datsp.shape, dtype=self.datsp.dtype)
  998. self.datsp.toarray(out=out)
  999. assert_array_equal(chk, dat)
  1000. # Check that things are fine when we don't initialize with zeros.
  1001. out[...] = 1.
  1002. self.datsp.toarray(out=out)
  1003. assert_array_equal(chk, dat)
  1004. a = array([1.,2.,3.])
  1005. dense_dot_dense = dot(a, dat)
  1006. check = dot(a, self.datsp.toarray())
  1007. assert_array_equal(dense_dot_dense, check)
  1008. b = array([1.,2.,3.,4.])
  1009. dense_dot_dense = dot(dat, b)
  1010. check2 = dot(self.datsp.toarray(), b)
  1011. assert_array_equal(dense_dot_dense, check2)
  1012. # Check bool data works.
  1013. spbool = self.spmatrix(self.dat, dtype=bool)
  1014. arrbool = dat.astype(bool)
  1015. assert_array_equal(spbool.toarray(), arrbool)
  1016. @sup_complex
  1017. def test_astype(self):
  1018. D = array([[2.0 + 3j, 0, 0],
  1019. [0, 4.0 + 5j, 0],
  1020. [0, 0, 0]])
  1021. S = self.spmatrix(D)
  1022. for x in supported_dtypes:
  1023. # Check correctly casted
  1024. D_casted = D.astype(x)
  1025. for copy in (True, False):
  1026. S_casted = S.astype(x, copy=copy)
  1027. assert_equal(S_casted.dtype, D_casted.dtype) # correct type
  1028. assert_equal(S_casted.toarray(), D_casted) # correct values
  1029. assert_equal(S_casted.format, S.format) # format preserved
  1030. # Check correctly copied
  1031. assert_(S_casted.astype(x, copy=False) is S_casted)
  1032. S_copied = S_casted.astype(x, copy=True)
  1033. assert_(S_copied is not S_casted)
  1034. def check_equal_but_not_same_array_attribute(attribute):
  1035. a = getattr(S_casted, attribute)
  1036. b = getattr(S_copied, attribute)
  1037. assert_array_equal(a, b)
  1038. assert_(a is not b)
  1039. i = (0,) * b.ndim
  1040. b_i = b[i]
  1041. b[i] = not b[i]
  1042. assert_(a[i] != b[i])
  1043. b[i] = b_i
  1044. if S_casted.format in ('csr', 'csc', 'bsr'):
  1045. for attribute in ('indices', 'indptr', 'data'):
  1046. check_equal_but_not_same_array_attribute(attribute)
  1047. elif S_casted.format == 'coo':
  1048. for attribute in ('row', 'col', 'data'):
  1049. check_equal_but_not_same_array_attribute(attribute)
  1050. elif S_casted.format == 'dia':
  1051. for attribute in ('offsets', 'data'):
  1052. check_equal_but_not_same_array_attribute(attribute)
  1053. def test_asfptype(self):
  1054. A = self.spmatrix(arange(6,dtype='int32').reshape(2,3))
  1055. assert_equal(A.dtype, np.dtype('int32'))
  1056. assert_equal(A.asfptype().dtype, np.dtype('float64'))
  1057. assert_equal(A.asfptype().format, A.format)
  1058. assert_equal(A.astype('int16').asfptype().dtype, np.dtype('float32'))
  1059. assert_equal(A.astype('complex128').asfptype().dtype, np.dtype('complex128'))
  1060. B = A.asfptype()
  1061. C = B.asfptype()
  1062. assert_(B is C)
  1063. def test_mul_scalar(self):
  1064. def check(dtype):
  1065. dat = self.dat_dtypes[dtype]
  1066. datsp = self.datsp_dtypes[dtype]
  1067. assert_array_equal(dat*2,(datsp*2).todense())
  1068. assert_array_equal(dat*17.3,(datsp*17.3).todense())
  1069. for dtype in self.math_dtypes:
  1070. check(dtype)
  1071. def test_rmul_scalar(self):
  1072. def check(dtype):
  1073. dat = self.dat_dtypes[dtype]
  1074. datsp = self.datsp_dtypes[dtype]
  1075. assert_array_equal(2*dat,(2*datsp).todense())
  1076. assert_array_equal(17.3*dat,(17.3*datsp).todense())
  1077. for dtype in self.math_dtypes:
  1078. check(dtype)
  1079. def test_add(self):
  1080. def check(dtype):
  1081. dat = self.dat_dtypes[dtype]
  1082. datsp = self.datsp_dtypes[dtype]
  1083. a = dat.copy()
  1084. a[0,2] = 2.0
  1085. b = datsp
  1086. c = b + a
  1087. assert_array_equal(c, b.todense() + a)
  1088. c = b + b.tocsr()
  1089. assert_array_equal(c.todense(),
  1090. b.todense() + b.todense())
  1091. # test broadcasting
  1092. c = b + a[0]
  1093. assert_array_equal(c, b.todense() + a[0])
  1094. for dtype in self.math_dtypes:
  1095. check(dtype)
  1096. def test_radd(self):
  1097. def check(dtype):
  1098. dat = self.dat_dtypes[dtype]
  1099. datsp = self.datsp_dtypes[dtype]
  1100. a = dat.copy()
  1101. a[0,2] = 2.0
  1102. b = datsp
  1103. c = a + b
  1104. assert_array_equal(c, a + b.todense())
  1105. for dtype in self.math_dtypes:
  1106. check(dtype)
  1107. def test_sub(self):
  1108. def check(dtype):
  1109. dat = self.dat_dtypes[dtype]
  1110. datsp = self.datsp_dtypes[dtype]
  1111. assert_array_equal((datsp - datsp).todense(),[[0,0,0,0],[0,0,0,0],[0,0,0,0]])
  1112. assert_array_equal((datsp - 0).todense(), dat)
  1113. A = self.spmatrix(matrix([[1,0,0,4],[-1,0,0,0],[0,8,0,-5]],'d'))
  1114. assert_array_equal((datsp - A).todense(),dat - A.todense())
  1115. assert_array_equal((A - datsp).todense(),A.todense() - dat)
  1116. # test broadcasting
  1117. assert_array_equal(datsp - dat[0], dat - dat[0])
  1118. for dtype in self.math_dtypes:
  1119. if dtype == np.dtype('bool'):
  1120. # boolean array subtraction deprecated in 1.9.0
  1121. continue
  1122. check(dtype)
  1123. def test_rsub(self):
  1124. def check(dtype):
  1125. dat = self.dat_dtypes[dtype]
  1126. datsp = self.datsp_dtypes[dtype]
  1127. assert_array_equal((dat - datsp),[[0,0,0,0],[0,0,0,0],[0,0,0,0]])
  1128. assert_array_equal((datsp - dat),[[0,0,0,0],[0,0,0,0],[0,0,0,0]])
  1129. assert_array_equal((0 - datsp).todense(), -dat)
  1130. A = self.spmatrix(matrix([[1,0,0,4],[-1,0,0,0],[0,8,0,-5]],'d'))
  1131. assert_array_equal((dat - A),dat - A.todense())
  1132. assert_array_equal((A - dat),A.todense() - dat)
  1133. assert_array_equal(A.todense() - datsp,A.todense() - dat)
  1134. assert_array_equal(datsp - A.todense(),dat - A.todense())
  1135. # test broadcasting
  1136. assert_array_equal(dat[0] - datsp, dat[0] - dat)
  1137. for dtype in self.math_dtypes:
  1138. if dtype == np.dtype('bool'):
  1139. # boolean array subtraction deprecated in 1.9.0
  1140. continue
  1141. check(dtype)
  1142. def test_add0(self):
  1143. def check(dtype):
  1144. dat = self.dat_dtypes[dtype]
  1145. datsp = self.datsp_dtypes[dtype]
  1146. # Adding 0 to a sparse matrix
  1147. assert_array_equal((datsp + 0).todense(), dat)
  1148. # use sum (which takes 0 as a starting value)
  1149. sumS = sum([k * datsp for k in range(1, 3)])
  1150. sumD = sum([k * dat for k in range(1, 3)])
  1151. assert_almost_equal(sumS.todense(), sumD)
  1152. for dtype in self.math_dtypes:
  1153. check(dtype)
  1154. def test_elementwise_multiply(self):
  1155. # real/real
  1156. A = array([[4,0,9],[2,-3,5]])
  1157. B = array([[0,7,0],[0,-4,0]])
  1158. Asp = self.spmatrix(A)
  1159. Bsp = self.spmatrix(B)
  1160. assert_almost_equal(Asp.multiply(Bsp).todense(), A*B) # sparse/sparse
  1161. assert_almost_equal(Asp.multiply(B).todense(), A*B) # sparse/dense
  1162. # complex/complex
  1163. C = array([[1-2j,0+5j,-1+0j],[4-3j,-3+6j,5]])
  1164. D = array([[5+2j,7-3j,-2+1j],[0-1j,-4+2j,9]])
  1165. Csp = self.spmatrix(C)
  1166. Dsp = self.spmatrix(D)
  1167. assert_almost_equal(Csp.multiply(Dsp).todense(), C*D) # sparse/sparse
  1168. assert_almost_equal(Csp.multiply(D).todense(), C*D) # sparse/dense
  1169. # real/complex
  1170. assert_almost_equal(Asp.multiply(Dsp).todense(), A*D) # sparse/sparse
  1171. assert_almost_equal(Asp.multiply(D).todense(), A*D) # sparse/dense
  1172. def test_elementwise_multiply_broadcast(self):
  1173. A = array([4])
  1174. B = array([[-9]])
  1175. C = array([1,-1,0])
  1176. D = array([[7,9,-9]])
  1177. E = array([[3],[2],[1]])
  1178. F = array([[8,6,3],[-4,3,2],[6,6,6]])
  1179. G = [1, 2, 3]
  1180. H = np.ones((3, 4))
  1181. J = H.T
  1182. K = array([[0]])
  1183. L = array([[[1,2],[0,1]]])
  1184. # Some arrays can't be cast as spmatrices (A,C,L) so leave
  1185. # them out.
  1186. Bsp = self.spmatrix(B)
  1187. Dsp = self.spmatrix(D)
  1188. Esp = self.spmatrix(E)
  1189. Fsp = self.spmatrix(F)
  1190. Hsp = self.spmatrix(H)
  1191. Hspp = self.spmatrix(H[0,None])
  1192. Jsp = self.spmatrix(J)
  1193. Jspp = self.spmatrix(J[:,0,None])
  1194. Ksp = self.spmatrix(K)
  1195. matrices = [A, B, C, D, E, F, G, H, J, K, L]
  1196. spmatrices = [Bsp, Dsp, Esp, Fsp, Hsp, Hspp, Jsp, Jspp, Ksp]
  1197. # sparse/sparse
  1198. for i in spmatrices:
  1199. for j in spmatrices:
  1200. try:
  1201. dense_mult = np.multiply(i.todense(), j.todense())
  1202. except ValueError:
  1203. assert_raises(ValueError, i.multiply, j)
  1204. continue
  1205. sp_mult = i.multiply(j)
  1206. assert_almost_equal(sp_mult.todense(), dense_mult)
  1207. # sparse/dense
  1208. for i in spmatrices:
  1209. for j in matrices:
  1210. try:
  1211. dense_mult = np.multiply(i.todense(), j)
  1212. except TypeError:
  1213. continue
  1214. except ValueError:
  1215. assert_raises(ValueError, i.multiply, j)
  1216. continue
  1217. sp_mult = i.multiply(j)
  1218. if isspmatrix(sp_mult):
  1219. assert_almost_equal(sp_mult.todense(), dense_mult)
  1220. else:
  1221. assert_almost_equal(sp_mult, dense_mult)
  1222. def test_elementwise_divide(self):
  1223. expected = [[1,np.nan,np.nan,1],
  1224. [1,np.nan,1,np.nan],
  1225. [np.nan,1,np.nan,np.nan]]
  1226. assert_array_equal(todense(self.datsp / self.datsp),expected)
  1227. denom = self.spmatrix(matrix([[1,0,0,4],[-1,0,0,0],[0,8,0,-5]],'d'))
  1228. expected = [[1,np.nan,np.nan,0.5],
  1229. [-3,np.nan,inf,np.nan],
  1230. [np.nan,0.25,np.nan,0]]
  1231. assert_array_equal(todense(self.datsp / denom), expected)
  1232. # complex
  1233. A = array([[1-2j,0+5j,-1+0j],[4-3j,-3+6j,5]])
  1234. B = array([[5+2j,7-3j,-2+1j],[0-1j,-4+2j,9]])
  1235. Asp = self.spmatrix(A)
  1236. Bsp = self.spmatrix(B)
  1237. assert_almost_equal(todense(Asp / Bsp), A/B)
  1238. # integer
  1239. A = array([[1,2,3],[-3,2,1]])
  1240. B = array([[0,1,2],[0,-2,3]])
  1241. Asp = self.spmatrix(A)
  1242. Bsp = self.spmatrix(B)
  1243. with np.errstate(divide='ignore'):
  1244. assert_array_equal(todense(Asp / Bsp), A / B)
  1245. # mismatching sparsity patterns
  1246. A = array([[0,1],[1,0]])
  1247. B = array([[1,0],[1,0]])
  1248. Asp = self.spmatrix(A)
  1249. Bsp = self.spmatrix(B)
  1250. with np.errstate(divide='ignore', invalid='ignore'):
  1251. assert_array_equal(np.array(todense(Asp / Bsp)), A / B)
  1252. def test_pow(self):
  1253. A = matrix([[1,0,2,0],[0,3,4,0],[0,5,0,0],[0,6,7,8]])
  1254. B = self.spmatrix(A)
  1255. for exponent in [0,1,2,3]:
  1256. assert_array_equal((B**exponent).todense(),A**exponent)
  1257. # invalid exponents
  1258. for exponent in [-1, 2.2, 1 + 3j]:
  1259. assert_raises(Exception, B.__pow__, exponent)
  1260. # nonsquare matrix
  1261. B = self.spmatrix(A[:3,:])
  1262. assert_raises(Exception, B.__pow__, 1)
  1263. def test_rmatvec(self):
  1264. M = self.spmatrix(matrix([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]]))
  1265. assert_array_almost_equal([1,2,3,4]*M, dot([1,2,3,4], M.toarray()))
  1266. row = matrix([[1,2,3,4]])
  1267. assert_array_almost_equal(row*M, row*M.todense())
  1268. def test_small_multiplication(self):
  1269. # test that A*x works for x with shape () (1,) (1,1) and (1,0)
  1270. A = self.spmatrix([[1],[2],[3]])
  1271. assert_(isspmatrix(A * array(1)))
  1272. assert_equal((A * array(1)).todense(), [[1],[2],[3]])
  1273. assert_equal(A * array([1]), array([1,2,3]))
  1274. assert_equal(A * array([[1]]), array([[1],[2],[3]]))
  1275. assert_equal(A * np.ones((1,0)), np.ones((3,0)))
  1276. def test_binop_custom_type(self):
  1277. # Non-regression test: previously, binary operations would raise
  1278. # NotImplementedError instead of returning NotImplemented
  1279. # (https://docs.python.org/library/constants.html#NotImplemented)
  1280. # so overloading Custom + matrix etc. didn't work.
  1281. A = self.spmatrix([[1], [2], [3]])
  1282. B = BinopTester()
  1283. assert_equal(A + B, "matrix on the left")
  1284. assert_equal(A - B, "matrix on the left")
  1285. assert_equal(A * B, "matrix on the left")
  1286. assert_equal(B + A, "matrix on the right")
  1287. assert_equal(B - A, "matrix on the right")
  1288. assert_equal(B * A, "matrix on the right")
  1289. if TEST_MATMUL:
  1290. assert_equal(eval('A @ B'), "matrix on the left")
  1291. assert_equal(eval('B @ A'), "matrix on the right")
  1292. def test_binop_custom_type_with_shape(self):
  1293. A = self.spmatrix([[1], [2], [3]])
  1294. B = BinopTester_with_shape((3,1))
  1295. assert_equal(A + B, "matrix on the left")
  1296. assert_equal(A - B, "matrix on the left")
  1297. assert_equal(A * B, "matrix on the left")
  1298. assert_equal(B + A, "matrix on the right")
  1299. assert_equal(B - A, "matrix on the right")
  1300. assert_equal(B * A, "matrix on the right")
  1301. if TEST_MATMUL:
  1302. assert_equal(eval('A @ B'), "matrix on the left")
  1303. assert_equal(eval('B @ A'), "matrix on the right")
  1304. def test_matmul(self):
  1305. if not TEST_MATMUL:
  1306. pytest.skip("matmul is only tested in Python 3.5+")
  1307. M = self.spmatrix(matrix([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]]))
  1308. B = self.spmatrix(matrix([[0,1],[1,0],[0,2]],'d'))
  1309. col = matrix([1,2,3]).T
  1310. # check matrix-vector
  1311. assert_array_almost_equal(operator.matmul(M, col),
  1312. M.todense() * col)
  1313. # check matrix-matrix
  1314. assert_array_almost_equal(operator.matmul(M, B).todense(),
  1315. (M * B).todense())
  1316. assert_array_almost_equal(operator.matmul(M.todense(), B),
  1317. (M * B).todense())
  1318. assert_array_almost_equal(operator.matmul(M, B.todense()),
  1319. (M * B).todense())
  1320. # check error on matrix-scalar
  1321. assert_raises(ValueError, operator.matmul, M, 1)
  1322. assert_raises(ValueError, operator.matmul, 1, M)
  1323. def test_matvec(self):
  1324. M = self.spmatrix(matrix([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]]))
  1325. col = matrix([1,2,3]).T
  1326. assert_array_almost_equal(M * col, M.todense() * col)
  1327. # check result dimensions (ticket #514)
  1328. assert_equal((M * array([1,2,3])).shape,(4,))
  1329. assert_equal((M * array([[1],[2],[3]])).shape,(4,1))
  1330. assert_equal((M * matrix([[1],[2],[3]])).shape,(4,1))
  1331. # check result type
  1332. assert_(isinstance(M * array([1,2,3]), ndarray))
  1333. assert_(isinstance(M * matrix([1,2,3]).T, matrix))
  1334. # ensure exception is raised for improper dimensions
  1335. bad_vecs = [array([1,2]), array([1,2,3,4]), array([[1],[2]]),
  1336. matrix([1,2,3]), matrix([[1],[2]])]
  1337. for x in bad_vecs:
  1338. assert_raises(ValueError, M.__mul__, x)
  1339. # Should this be supported or not?!
  1340. # flat = array([1,2,3])
  1341. # assert_array_almost_equal(M*flat, M.todense()*flat)
  1342. # Currently numpy dense matrices promote the result to a 1x3 matrix,
  1343. # whereas sparse matrices leave the result as a rank-1 array. Which
  1344. # is preferable?
  1345. # Note: the following command does not work. Both NumPy matrices
  1346. # and spmatrices should raise exceptions!
  1347. # assert_array_almost_equal(M*[1,2,3], M.todense()*[1,2,3])
  1348. # The current relationship between sparse matrix products and array
  1349. # products is as follows:
  1350. assert_array_almost_equal(M*array([1,2,3]), dot(M.A,[1,2,3]))
  1351. assert_array_almost_equal(M*[[1],[2],[3]], asmatrix(dot(M.A,[1,2,3])).T)
  1352. # Note that the result of M * x is dense if x has a singleton dimension.
  1353. # Currently M.matvec(asarray(col)) is rank-1, whereas M.matvec(col)
  1354. # is rank-2. Is this desirable?
  1355. def test_matmat_sparse(self):
  1356. a = matrix([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]])
  1357. a2 = array([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]])
  1358. b = matrix([[0,1],[1,0],[0,2]],'d')
  1359. asp = self.spmatrix(a)
  1360. bsp = self.spmatrix(b)
  1361. assert_array_almost_equal((asp*bsp).todense(), a*b)
  1362. assert_array_almost_equal(asp*b, a*b)
  1363. assert_array_almost_equal(a*bsp, a*b)
  1364. assert_array_almost_equal(a2*bsp, a*b)
  1365. # Now try performing cross-type multplication:
  1366. csp = bsp.tocsc()
  1367. c = b
  1368. assert_array_almost_equal((asp*csp).todense(), a*c)
  1369. assert_array_almost_equal(asp*c, a*c)
  1370. assert_array_almost_equal(a*csp, a*c)
  1371. assert_array_almost_equal(a2*csp, a*c)
  1372. csp = bsp.tocsr()
  1373. assert_array_almost_equal((asp*csp).todense(), a*c)
  1374. assert_array_almost_equal(asp*c, a*c)
  1375. assert_array_almost_equal(a*csp, a*c)
  1376. assert_array_almost_equal(a2*csp, a*c)
  1377. csp = bsp.tocoo()
  1378. assert_array_almost_equal((asp*csp).todense(), a*c)
  1379. assert_array_almost_equal(asp*c, a*c)
  1380. assert_array_almost_equal(a*csp, a*c)
  1381. assert_array_almost_equal(a2*csp, a*c)
  1382. # Test provided by Andy Fraser, 2006-03-26
  1383. L = 30
  1384. frac = .3
  1385. random.seed(0) # make runs repeatable
  1386. A = zeros((L,2))
  1387. for i in xrange(L):
  1388. for j in xrange(2):
  1389. r = random.random()
  1390. if r < frac:
  1391. A[i,j] = r/frac
  1392. A = self.spmatrix(A)
  1393. B = A*A.T
  1394. assert_array_almost_equal(B.todense(), A.todense() * A.T.todense())
  1395. assert_array_almost_equal(B.todense(), A.todense() * A.todense().T)
  1396. # check dimension mismatch 2x2 times 3x2
  1397. A = self.spmatrix([[1,2],[3,4]])
  1398. B = self.spmatrix([[1,2],[3,4],[5,6]])
  1399. assert_raises(ValueError, A.__mul__, B)
  1400. def test_matmat_dense(self):
  1401. a = matrix([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]])
  1402. asp = self.spmatrix(a)
  1403. # check both array and matrix types
  1404. bs = [array([[1,2],[3,4],[5,6]]), matrix([[1,2],[3,4],[5,6]])]
  1405. for b in bs:
  1406. result = asp*b
  1407. assert_(isinstance(result, type(b)))
  1408. assert_equal(result.shape, (4,2))
  1409. assert_equal(result, dot(a,b))
  1410. def test_sparse_format_conversions(self):
  1411. A = sparse.kron([[1,0,2],[0,3,4],[5,0,0]], [[1,2],[0,3]])
  1412. D = A.todense()
  1413. A = self.spmatrix(A)
  1414. for format in ['bsr','coo','csc','csr','dia','dok','lil']:
  1415. a = A.asformat(format)
  1416. assert_equal(a.format,format)
  1417. assert_array_equal(a.todense(), D)
  1418. b = self.spmatrix(D+3j).asformat(format)
  1419. assert_equal(b.format,format)
  1420. assert_array_equal(b.todense(), D+3j)
  1421. c = eval(format + '_matrix')(A)
  1422. assert_equal(c.format,format)
  1423. assert_array_equal(c.todense(), D)
  1424. for format in ['array', 'dense']:
  1425. a = A.asformat(format)
  1426. assert_array_equal(a, D)
  1427. b = self.spmatrix(D+3j).asformat(format)
  1428. assert_array_equal(b, D+3j)
  1429. def test_tobsr(self):
  1430. x = array([[1,0,2,0],[0,0,0,0],[0,0,4,5]])
  1431. y = array([[0,1,2],[3,0,5]])
  1432. A = kron(x,y)
  1433. Asp = self.spmatrix(A)
  1434. for format in ['bsr']:
  1435. fn = getattr(Asp, 'to' + format)
  1436. for X in [1, 2, 3, 6]:
  1437. for Y in [1, 2, 3, 4, 6, 12]:
  1438. assert_equal(fn(blocksize=(X,Y)).todense(), A)
  1439. def test_transpose(self):
  1440. dat_1 = self.dat
  1441. dat_2 = np.array([[]])
  1442. matrices = [dat_1, dat_2]
  1443. def check(dtype, j):
  1444. dat = np.matrix(matrices[j], dtype=dtype)
  1445. datsp = self.spmatrix(dat)
  1446. a = datsp.transpose()
  1447. b = dat.transpose()
  1448. assert_array_equal(a.todense(), b)
  1449. assert_array_equal(a.transpose().todense(), dat)
  1450. assert_equal(a.dtype, b.dtype)
  1451. # See gh-5987
  1452. empty = self.spmatrix((3, 4))
  1453. assert_array_equal(np.transpose(empty).todense(),
  1454. np.transpose(zeros((3, 4))))
  1455. assert_array_equal(empty.T.todense(), zeros((4, 3)))
  1456. assert_raises(ValueError, empty.transpose, axes=0)
  1457. for dtype in self.checked_dtypes:
  1458. for j in range(len(matrices)):
  1459. check(dtype, j)
  1460. def test_add_dense(self):
  1461. def check(dtype):
  1462. dat = self.dat_dtypes[dtype]
  1463. datsp = self.datsp_dtypes[dtype]
  1464. # adding a dense matrix to a sparse matrix
  1465. sum1 = dat + datsp
  1466. assert_array_equal(sum1, dat + dat)
  1467. sum2 = datsp + dat
  1468. assert_array_equal(sum2, dat + dat)
  1469. for dtype in self.math_dtypes:
  1470. check(dtype)
  1471. def test_sub_dense(self):
  1472. # subtracting a dense matrix to/from a sparse matrix
  1473. def check(dtype):
  1474. dat = self.dat_dtypes[dtype]
  1475. datsp = self.datsp_dtypes[dtype]
  1476. # Behavior is different for bool.
  1477. if dat.dtype == bool:
  1478. sum1 = dat - datsp
  1479. assert_array_equal(sum1, dat - dat)
  1480. sum2 = datsp - dat
  1481. assert_array_equal(sum2, dat - dat)
  1482. else:
  1483. # Manually add to avoid upcasting from scalar
  1484. # multiplication.
  1485. sum1 = (dat + dat + dat) - datsp
  1486. assert_array_equal(sum1, dat + dat)
  1487. sum2 = (datsp + datsp + datsp) - dat
  1488. assert_array_equal(sum2, dat + dat)
  1489. for dtype in self.math_dtypes:
  1490. if (dtype == np.dtype('bool')) and (
  1491. NumpyVersion(np.__version__) >= '1.9.0.dev'):
  1492. # boolean array subtraction deprecated in 1.9.0
  1493. continue
  1494. check(dtype)
  1495. def test_maximum_minimum(self):
  1496. A_dense = np.array([[1, 0, 3], [0, 4, 5], [0, 0, 0]])
  1497. B_dense = np.array([[1, 1, 2], [0, 3, 6], [1, -1, 0]])
  1498. A_dense_cpx = np.array([[1, 0, 3], [0, 4+2j, 5], [0, 1j, -1j]])
  1499. def check(dtype, dtype2, btype):
  1500. if np.issubdtype(dtype, np.complexfloating):
  1501. A = self.spmatrix(A_dense_cpx.astype(dtype))
  1502. else:
  1503. A = self.spmatrix(A_dense.astype(dtype))
  1504. if btype == 'scalar':
  1505. B = dtype2.type(1)
  1506. elif btype == 'scalar2':
  1507. B = dtype2.type(-1)
  1508. elif btype == 'dense':
  1509. B = B_dense.astype(dtype2)
  1510. elif btype == 'sparse':
  1511. B = self.spmatrix(B_dense.astype(dtype2))
  1512. else:
  1513. raise ValueError()
  1514. with suppress_warnings() as sup:
  1515. sup.filter(SparseEfficiencyWarning,
  1516. "Taking maximum .minimum. with > 0 .< 0. number results to a dense matrix")
  1517. max_s = A.maximum(B)
  1518. min_s = A.minimum(B)
  1519. max_d = np.maximum(todense(A), todense(B))
  1520. assert_array_equal(todense(max_s), max_d)
  1521. assert_equal(max_s.dtype, max_d.dtype)
  1522. min_d = np.minimum(todense(A), todense(B))
  1523. assert_array_equal(todense(min_s), min_d)
  1524. assert_equal(min_s.dtype, min_d.dtype)
  1525. for dtype in self.math_dtypes:
  1526. for dtype2 in [np.int8, np.float_, np.complex_]:
  1527. for btype in ['scalar', 'scalar2', 'dense', 'sparse']:
  1528. check(np.dtype(dtype), np.dtype(dtype2), btype)
  1529. def test_copy(self):
  1530. # Check whether the copy=True and copy=False keywords work
  1531. A = self.datsp
  1532. # check that copy preserves format
  1533. assert_equal(A.copy().format, A.format)
  1534. assert_equal(A.__class__(A,copy=True).format, A.format)
  1535. assert_equal(A.__class__(A,copy=False).format, A.format)
  1536. assert_equal(A.copy().todense(), A.todense())
  1537. assert_equal(A.__class__(A,copy=True).todense(), A.todense())
  1538. assert_equal(A.__class__(A,copy=False).todense(), A.todense())
  1539. # check that XXX_matrix.toXXX() works
  1540. toself = getattr(A,'to' + A.format)
  1541. assert_equal(toself().format, A.format)
  1542. assert_equal(toself(copy=True).format, A.format)
  1543. assert_equal(toself(copy=False).format, A.format)
  1544. assert_equal(toself().todense(), A.todense())
  1545. assert_equal(toself(copy=True).todense(), A.todense())
  1546. assert_equal(toself(copy=False).todense(), A.todense())
  1547. # check whether the data is copied?
  1548. # TODO: deal with non-indexable types somehow
  1549. B = A.copy()
  1550. try:
  1551. B[0,0] += 1
  1552. assert_(B[0,0] != A[0,0])
  1553. except NotImplementedError:
  1554. # not all sparse matrices can be indexed
  1555. pass
  1556. except TypeError:
  1557. # not all sparse matrices can be indexed
  1558. pass
  1559. # test that __iter__ is compatible with NumPy matrix
  1560. def test_iterator(self):
  1561. B = np.matrix(np.arange(50).reshape(5, 10))
  1562. A = self.spmatrix(B)
  1563. for x, y in zip(A, B):
  1564. assert_equal(x.todense(), y)
  1565. def test_size_zero_matrix_arithmetic(self):
  1566. # Test basic matrix arithmetic with shapes like (0,0), (10,0),
  1567. # (0, 3), etc.
  1568. mat = np.matrix([])
  1569. a = mat.reshape((0, 0))
  1570. b = mat.reshape((0, 1))
  1571. c = mat.reshape((0, 5))
  1572. d = mat.reshape((1, 0))
  1573. e = mat.reshape((5, 0))
  1574. f = np.matrix(np.ones([5, 5]))
  1575. asp = self.spmatrix(a)
  1576. bsp = self.spmatrix(b)
  1577. csp = self.spmatrix(c)
  1578. dsp = self.spmatrix(d)
  1579. esp = self.spmatrix(e)
  1580. fsp = self.spmatrix(f)
  1581. # matrix product.
  1582. assert_array_equal(asp.dot(asp).A, np.dot(a, a).A)
  1583. assert_array_equal(bsp.dot(dsp).A, np.dot(b, d).A)
  1584. assert_array_equal(dsp.dot(bsp).A, np.dot(d, b).A)
  1585. assert_array_equal(csp.dot(esp).A, np.dot(c, e).A)
  1586. assert_array_equal(csp.dot(fsp).A, np.dot(c, f).A)
  1587. assert_array_equal(esp.dot(csp).A, np.dot(e, c).A)
  1588. assert_array_equal(dsp.dot(csp).A, np.dot(d, c).A)
  1589. assert_array_equal(fsp.dot(esp).A, np.dot(f, e).A)
  1590. # bad matrix products
  1591. assert_raises(ValueError, dsp.dot, e)
  1592. assert_raises(ValueError, asp.dot, d)
  1593. # elemente-wise multiplication
  1594. assert_array_equal(asp.multiply(asp).A, np.multiply(a, a).A)
  1595. assert_array_equal(bsp.multiply(bsp).A, np.multiply(b, b).A)
  1596. assert_array_equal(dsp.multiply(dsp).A, np.multiply(d, d).A)
  1597. assert_array_equal(asp.multiply(a).A, np.multiply(a, a).A)
  1598. assert_array_equal(bsp.multiply(b).A, np.multiply(b, b).A)
  1599. assert_array_equal(dsp.multiply(d).A, np.multiply(d, d).A)
  1600. assert_array_equal(asp.multiply(6).A, np.multiply(a, 6).A)
  1601. assert_array_equal(bsp.multiply(6).A, np.multiply(b, 6).A)
  1602. assert_array_equal(dsp.multiply(6).A, np.multiply(d, 6).A)
  1603. # bad element-wise multiplication
  1604. assert_raises(ValueError, asp.multiply, c)
  1605. assert_raises(ValueError, esp.multiply, c)
  1606. # Addition
  1607. assert_array_equal(asp.__add__(asp).A, a.__add__(a).A)
  1608. assert_array_equal(bsp.__add__(bsp).A, b.__add__(b).A)
  1609. assert_array_equal(dsp.__add__(dsp).A, d.__add__(d).A)
  1610. # bad addition
  1611. assert_raises(ValueError, asp.__add__, dsp)
  1612. assert_raises(ValueError, bsp.__add__, asp)
  1613. def test_size_zero_conversions(self):
  1614. mat = np.matrix([])
  1615. a = mat.reshape((0, 0))
  1616. b = mat.reshape((0, 5))
  1617. c = mat.reshape((5, 0))
  1618. for m in [a, b, c]:
  1619. spm = self.spmatrix(m)
  1620. assert_array_equal(spm.tocoo().A, m)
  1621. assert_array_equal(spm.tocsr().A, m)
  1622. assert_array_equal(spm.tocsc().A, m)
  1623. assert_array_equal(spm.tolil().A, m)
  1624. assert_array_equal(spm.todok().A, m)
  1625. assert_array_equal(spm.tobsr().A, m)
  1626. def test_pickle(self):
  1627. import pickle
  1628. sup = suppress_warnings()
  1629. sup.filter(SparseEfficiencyWarning)
  1630. @sup
  1631. def check():
  1632. datsp = self.datsp.copy()
  1633. for protocol in range(pickle.HIGHEST_PROTOCOL):
  1634. sploaded = pickle.loads(pickle.dumps(datsp, protocol=protocol))
  1635. assert_equal(datsp.shape, sploaded.shape)
  1636. assert_array_equal(datsp.toarray(), sploaded.toarray())
  1637. assert_equal(datsp.format, sploaded.format)
  1638. for key, val in datsp.__dict__.items():
  1639. if isinstance(val, np.ndarray):
  1640. assert_array_equal(val, sploaded.__dict__[key])
  1641. else:
  1642. assert_(val == sploaded.__dict__[key])
  1643. check()
  1644. def test_unary_ufunc_overrides(self):
  1645. def check(name):
  1646. if name == "sign":
  1647. pytest.skip("sign conflicts with comparison op "
  1648. "support on Numpy")
  1649. if self.spmatrix in (dok_matrix, lil_matrix):
  1650. pytest.skip("Unary ops not implemented for dok/lil")
  1651. ufunc = getattr(np, name)
  1652. X = self.spmatrix(np.arange(20).reshape(4, 5) / 20.)
  1653. X0 = ufunc(X.toarray())
  1654. X2 = ufunc(X)
  1655. assert_array_equal(X2.toarray(), X0)
  1656. for name in ["sin", "tan", "arcsin", "arctan", "sinh", "tanh",
  1657. "arcsinh", "arctanh", "rint", "sign", "expm1", "log1p",
  1658. "deg2rad", "rad2deg", "floor", "ceil", "trunc", "sqrt",
  1659. "abs"]:
  1660. check(name)
  1661. def test_resize(self):
  1662. # resize(shape) resizes the matrix in-place
  1663. D = np.array([[1, 0, 3, 4],
  1664. [2, 0, 0, 0],
  1665. [3, 0, 0, 0]])
  1666. S = self.spmatrix(D)
  1667. assert_(S.resize((3, 2)) is None)
  1668. assert_array_equal(S.A, [[1, 0],
  1669. [2, 0],
  1670. [3, 0]])
  1671. S.resize((2, 2))
  1672. assert_array_equal(S.A, [[1, 0],
  1673. [2, 0]])
  1674. S.resize((3, 2))
  1675. assert_array_equal(S.A, [[1, 0],
  1676. [2, 0],
  1677. [0, 0]])
  1678. S.resize((3, 3))
  1679. assert_array_equal(S.A, [[1, 0, 0],
  1680. [2, 0, 0],
  1681. [0, 0, 0]])
  1682. # test no-op
  1683. S.resize((3, 3))
  1684. assert_array_equal(S.A, [[1, 0, 0],
  1685. [2, 0, 0],
  1686. [0, 0, 0]])
  1687. # test *args
  1688. S.resize(3, 2)
  1689. assert_array_equal(S.A, [[1, 0],
  1690. [2, 0],
  1691. [0, 0]])
  1692. for bad_shape in [1, (-1, 2), (2, -1), (1, 2, 3)]:
  1693. assert_raises(ValueError, S.resize, bad_shape)
  1694. class _TestInplaceArithmetic(object):
  1695. @pytest.mark.skipif(NumpyVersion(np.__version__) < "1.13.0",
  1696. reason="numpy version doesn't respect array priority")
  1697. def test_inplace_dense(self):
  1698. a = np.ones((3, 4))
  1699. b = self.spmatrix(a)
  1700. x = a.copy()
  1701. y = a.copy()
  1702. x += a
  1703. y += b
  1704. assert_array_equal(x, y)
  1705. x = a.copy()
  1706. y = a.copy()
  1707. x -= a
  1708. y -= b
  1709. assert_array_equal(x, y)
  1710. # This is matrix product, from __rmul__
  1711. assert_raises(ValueError, operator.imul, x, b)
  1712. x = a.copy()
  1713. y = a.copy()
  1714. x = x.dot(a.T)
  1715. y *= b.T
  1716. assert_array_equal(x, y)
  1717. # Matrix (non-elementwise) floor division is not defined
  1718. assert_raises(TypeError, operator.ifloordiv, x, b)
  1719. def test_imul_scalar(self):
  1720. def check(dtype):
  1721. dat = self.dat_dtypes[dtype]
  1722. datsp = self.datsp_dtypes[dtype]
  1723. # Avoid implicit casting.
  1724. if np.can_cast(type(2), dtype, casting='same_kind'):
  1725. a = datsp.copy()
  1726. a *= 2
  1727. b = dat.copy()
  1728. b *= 2
  1729. assert_array_equal(b, a.todense())
  1730. if np.can_cast(type(17.3), dtype, casting='same_kind'):
  1731. a = datsp.copy()
  1732. a *= 17.3
  1733. b = dat.copy()
  1734. b *= 17.3
  1735. assert_array_equal(b, a.todense())
  1736. for dtype in self.math_dtypes:
  1737. check(dtype)
  1738. def test_idiv_scalar(self):
  1739. def check(dtype):
  1740. dat = self.dat_dtypes[dtype]
  1741. datsp = self.datsp_dtypes[dtype]
  1742. if np.can_cast(type(2), dtype, casting='same_kind'):
  1743. a = datsp.copy()
  1744. a /= 2
  1745. b = dat.copy()
  1746. b /= 2
  1747. assert_array_equal(b, a.todense())
  1748. if np.can_cast(type(17.3), dtype, casting='same_kind'):
  1749. a = datsp.copy()
  1750. a /= 17.3
  1751. b = dat.copy()
  1752. b /= 17.3
  1753. assert_array_equal(b, a.todense())
  1754. for dtype in self.math_dtypes:
  1755. # /= should only be used with float dtypes to avoid implicit
  1756. # casting.
  1757. if not np.can_cast(dtype, np.int_):
  1758. check(dtype)
  1759. def test_inplace_success(self):
  1760. # Inplace ops should work even if a specialized version is not
  1761. # implemented, falling back to x = x <op> y
  1762. a = self.spmatrix(np.eye(5))
  1763. b = self.spmatrix(np.eye(5))
  1764. bp = self.spmatrix(np.eye(5))
  1765. b += a
  1766. bp = bp + a
  1767. assert_allclose(b.A, bp.A)
  1768. b *= a
  1769. bp = bp * a
  1770. assert_allclose(b.A, bp.A)
  1771. b -= a
  1772. bp = bp - a
  1773. assert_allclose(b.A, bp.A)
  1774. assert_raises(TypeError, operator.ifloordiv, a, b)
  1775. class _TestGetSet(object):
  1776. def test_getelement(self):
  1777. def check(dtype):
  1778. D = array([[1,0,0],
  1779. [4,3,0],
  1780. [0,2,0],
  1781. [0,0,0]], dtype=dtype)
  1782. A = self.spmatrix(D)
  1783. M,N = D.shape
  1784. for i in range(-M, M):
  1785. for j in range(-N, N):
  1786. assert_equal(A[i,j], D[i,j])
  1787. for ij in [(0,3),(-1,3),(4,0),(4,3),(4,-1), (1, 2, 3)]:
  1788. assert_raises((IndexError, TypeError), A.__getitem__, ij)
  1789. for dtype in supported_dtypes:
  1790. check(np.dtype(dtype))
  1791. def test_setelement(self):
  1792. def check(dtype):
  1793. A = self.spmatrix((3,4), dtype=dtype)
  1794. with suppress_warnings() as sup:
  1795. sup.filter(SparseEfficiencyWarning,
  1796. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  1797. A[0, 0] = dtype.type(0) # bug 870
  1798. A[1, 2] = dtype.type(4.0)
  1799. A[0, 1] = dtype.type(3)
  1800. A[2, 0] = dtype.type(2.0)
  1801. A[0,-1] = dtype.type(8)
  1802. A[-1,-2] = dtype.type(7)
  1803. A[0, 1] = dtype.type(5)
  1804. if dtype != np.bool_:
  1805. assert_array_equal(A.todense(),[[0,5,0,8],[0,0,4,0],[2,0,7,0]])
  1806. for ij in [(0,4),(-1,4),(3,0),(3,4),(3,-1)]:
  1807. assert_raises(IndexError, A.__setitem__, ij, 123.0)
  1808. for v in [[1,2,3], array([1,2,3])]:
  1809. assert_raises(ValueError, A.__setitem__, (0,0), v)
  1810. if (not np.issubdtype(dtype, np.complexfloating) and
  1811. dtype != np.bool_):
  1812. for v in [3j]:
  1813. assert_raises(TypeError, A.__setitem__, (0,0), v)
  1814. for dtype in supported_dtypes:
  1815. check(np.dtype(dtype))
  1816. def test_negative_index_assignment(self):
  1817. # Regression test for github issue 4428.
  1818. def check(dtype):
  1819. A = self.spmatrix((3, 10), dtype=dtype)
  1820. with suppress_warnings() as sup:
  1821. sup.filter(SparseEfficiencyWarning,
  1822. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  1823. A[0, -4] = 1
  1824. assert_equal(A[0, -4], 1)
  1825. for dtype in self.math_dtypes:
  1826. check(np.dtype(dtype))
  1827. def test_scalar_assign_2(self):
  1828. n, m = (5, 10)
  1829. def _test_set(i, j, nitems):
  1830. msg = "%r ; %r ; %r" % (i, j, nitems)
  1831. A = self.spmatrix((n, m))
  1832. with suppress_warnings() as sup:
  1833. sup.filter(SparseEfficiencyWarning,
  1834. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  1835. A[i, j] = 1
  1836. assert_almost_equal(A.sum(), nitems, err_msg=msg)
  1837. assert_almost_equal(A[i, j], 1, err_msg=msg)
  1838. # [i,j]
  1839. for i, j in [(2, 3), (-1, 8), (-1, -2), (array(-1), -2), (-1, array(-2)),
  1840. (array(-1), array(-2))]:
  1841. _test_set(i, j, 1)
  1842. def test_index_scalar_assign(self):
  1843. A = self.spmatrix((5, 5))
  1844. B = np.zeros((5, 5))
  1845. with suppress_warnings() as sup:
  1846. sup.filter(SparseEfficiencyWarning,
  1847. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  1848. for C in [A, B]:
  1849. C[0,1] = 1
  1850. C[3,0] = 4
  1851. C[3,0] = 9
  1852. assert_array_equal(A.toarray(), B)
  1853. class _TestSolve(object):
  1854. def test_solve(self):
  1855. # Test whether the lu_solve command segfaults, as reported by Nils
  1856. # Wagner for a 64-bit machine, 02 March 2005 (EJS)
  1857. n = 20
  1858. np.random.seed(0) # make tests repeatable
  1859. A = zeros((n,n), dtype=complex)
  1860. x = np.random.rand(n)
  1861. y = np.random.rand(n-1)+1j*np.random.rand(n-1)
  1862. r = np.random.rand(n)
  1863. for i in range(len(x)):
  1864. A[i,i] = x[i]
  1865. for i in range(len(y)):
  1866. A[i,i+1] = y[i]
  1867. A[i+1,i] = conjugate(y[i])
  1868. A = self.spmatrix(A)
  1869. with suppress_warnings() as sup:
  1870. sup.filter(SparseEfficiencyWarning, "splu requires CSC matrix format")
  1871. x = splu(A).solve(r)
  1872. assert_almost_equal(A*x,r)
  1873. class _TestSlicing(object):
  1874. def test_dtype_preservation(self):
  1875. assert_equal(self.spmatrix((1,10), dtype=np.int16)[0,1:5].dtype, np.int16)
  1876. assert_equal(self.spmatrix((1,10), dtype=np.int32)[0,1:5].dtype, np.int32)
  1877. assert_equal(self.spmatrix((1,10), dtype=np.float32)[0,1:5].dtype, np.float32)
  1878. assert_equal(self.spmatrix((1,10), dtype=np.float64)[0,1:5].dtype, np.float64)
  1879. def test_get_horiz_slice(self):
  1880. B = asmatrix(arange(50.).reshape(5,10))
  1881. A = self.spmatrix(B)
  1882. assert_array_equal(B[1,:], A[1,:].todense())
  1883. assert_array_equal(B[1,2:5], A[1,2:5].todense())
  1884. C = matrix([[1, 2, 1], [4, 0, 6], [0, 0, 0], [0, 0, 1]])
  1885. D = self.spmatrix(C)
  1886. assert_array_equal(C[1, 1:3], D[1, 1:3].todense())
  1887. # Now test slicing when a row contains only zeros
  1888. E = matrix([[1, 2, 1], [4, 0, 0], [0, 0, 0], [0, 0, 1]])
  1889. F = self.spmatrix(E)
  1890. assert_array_equal(E[1, 1:3], F[1, 1:3].todense())
  1891. assert_array_equal(E[2, -2:], F[2, -2:].A)
  1892. # The following should raise exceptions:
  1893. assert_raises(IndexError, A.__getitem__, (slice(None), 11))
  1894. assert_raises(IndexError, A.__getitem__, (6, slice(3, 7)))
  1895. def test_get_vert_slice(self):
  1896. B = asmatrix(arange(50.).reshape(5,10))
  1897. A = self.spmatrix(B)
  1898. assert_array_equal(B[2:5,0], A[2:5,0].todense())
  1899. assert_array_equal(B[:,1], A[:,1].todense())
  1900. C = matrix([[1, 2, 1], [4, 0, 6], [0, 0, 0], [0, 0, 1]])
  1901. D = self.spmatrix(C)
  1902. assert_array_equal(C[1:3, 1], D[1:3, 1].todense())
  1903. assert_array_equal(C[:, 2], D[:, 2].todense())
  1904. # Now test slicing when a column contains only zeros
  1905. E = matrix([[1, 0, 1], [4, 0, 0], [0, 0, 0], [0, 0, 1]])
  1906. F = self.spmatrix(E)
  1907. assert_array_equal(E[:, 1], F[:, 1].todense())
  1908. assert_array_equal(E[-2:, 2], F[-2:, 2].todense())
  1909. # The following should raise exceptions:
  1910. assert_raises(IndexError, A.__getitem__, (slice(None), 11))
  1911. assert_raises(IndexError, A.__getitem__, (6, slice(3, 7)))
  1912. def test_get_slices(self):
  1913. B = asmatrix(arange(50.).reshape(5,10))
  1914. A = self.spmatrix(B)
  1915. assert_array_equal(A[2:5,0:3].todense(), B[2:5,0:3])
  1916. assert_array_equal(A[1:,:-1].todense(), B[1:,:-1])
  1917. assert_array_equal(A[:-1,1:].todense(), B[:-1,1:])
  1918. # Now test slicing when a column contains only zeros
  1919. E = matrix([[1, 0, 1], [4, 0, 0], [0, 0, 0], [0, 0, 1]])
  1920. F = self.spmatrix(E)
  1921. assert_array_equal(E[1:2, 1:2], F[1:2, 1:2].todense())
  1922. assert_array_equal(E[:, 1:], F[:, 1:].todense())
  1923. def test_non_unit_stride_2d_indexing(self):
  1924. # Regression test -- used to silently ignore the stride.
  1925. v0 = np.random.rand(50, 50)
  1926. try:
  1927. v = self.spmatrix(v0)[0:25:2, 2:30:3]
  1928. except ValueError:
  1929. # if unsupported
  1930. raise pytest.skip("feature not implemented")
  1931. assert_array_equal(v.todense(),
  1932. v0[0:25:2, 2:30:3])
  1933. def test_slicing_2(self):
  1934. B = asmatrix(arange(50).reshape(5,10))
  1935. A = self.spmatrix(B)
  1936. # [i,j]
  1937. assert_equal(A[2,3], B[2,3])
  1938. assert_equal(A[-1,8], B[-1,8])
  1939. assert_equal(A[-1,-2],B[-1,-2])
  1940. assert_equal(A[array(-1),-2],B[-1,-2])
  1941. assert_equal(A[-1,array(-2)],B[-1,-2])
  1942. assert_equal(A[array(-1),array(-2)],B[-1,-2])
  1943. # [i,1:2]
  1944. assert_equal(A[2,:].todense(), B[2,:])
  1945. assert_equal(A[2,5:-2].todense(),B[2,5:-2])
  1946. assert_equal(A[array(2),5:-2].todense(),B[2,5:-2])
  1947. # [1:2,j]
  1948. assert_equal(A[:,2].todense(), B[:,2])
  1949. assert_equal(A[3:4,9].todense(), B[3:4,9])
  1950. assert_equal(A[1:4,-5].todense(),B[1:4,-5])
  1951. assert_equal(A[2:-1,3].todense(),B[2:-1,3])
  1952. assert_equal(A[2:-1,array(3)].todense(),B[2:-1,3])
  1953. # [1:2,1:2]
  1954. assert_equal(A[1:2,1:2].todense(),B[1:2,1:2])
  1955. assert_equal(A[4:,3:].todense(), B[4:,3:])
  1956. assert_equal(A[:4,:5].todense(), B[:4,:5])
  1957. assert_equal(A[2:-1,:5].todense(),B[2:-1,:5])
  1958. # [i]
  1959. assert_equal(A[1,:].todense(), B[1,:])
  1960. assert_equal(A[-2,:].todense(),B[-2,:])
  1961. assert_equal(A[array(-2),:].todense(),B[-2,:])
  1962. # [1:2]
  1963. assert_equal(A[1:4].todense(), B[1:4])
  1964. assert_equal(A[1:-2].todense(),B[1:-2])
  1965. # Check bug reported by Robert Cimrman:
  1966. # http://thread.gmane.org/gmane.comp.python.scientific.devel/7986 (dead link)
  1967. s = slice(int8(2),int8(4),None)
  1968. assert_equal(A[s,:].todense(), B[2:4,:])
  1969. assert_equal(A[:,s].todense(), B[:,2:4])
  1970. def test_slicing_3(self):
  1971. B = asmatrix(arange(50).reshape(5,10))
  1972. A = self.spmatrix(B)
  1973. s_ = np.s_
  1974. slices = [s_[:2], s_[1:2], s_[3:], s_[3::2],
  1975. s_[8:3:-1], s_[4::-2], s_[:5:-1],
  1976. 0, 1, s_[:], s_[1:5], -1, -2, -5,
  1977. array(-1), np.int8(-3)]
  1978. def check_1(a):
  1979. x = A[a]
  1980. y = B[a]
  1981. if y.shape == ():
  1982. assert_equal(x, y, repr(a))
  1983. else:
  1984. if x.size == 0 and y.size == 0:
  1985. pass
  1986. else:
  1987. assert_array_equal(x.todense(), y, repr(a))
  1988. for j, a in enumerate(slices):
  1989. check_1(a)
  1990. def check_2(a, b):
  1991. # Indexing np.matrix with 0-d arrays seems to be broken,
  1992. # as they seem not to be treated as scalars.
  1993. # https://github.com/numpy/numpy/issues/3110
  1994. if isinstance(a, np.ndarray):
  1995. ai = int(a)
  1996. else:
  1997. ai = a
  1998. if isinstance(b, np.ndarray):
  1999. bi = int(b)
  2000. else:
  2001. bi = b
  2002. x = A[a, b]
  2003. y = B[ai, bi]
  2004. if y.shape == ():
  2005. assert_equal(x, y, repr((a, b)))
  2006. else:
  2007. if x.size == 0 and y.size == 0:
  2008. pass
  2009. else:
  2010. assert_array_equal(x.todense(), y, repr((a, b)))
  2011. for i, a in enumerate(slices):
  2012. for j, b in enumerate(slices):
  2013. check_2(a, b)
  2014. def test_ellipsis_slicing(self):
  2015. b = asmatrix(arange(50).reshape(5,10))
  2016. a = self.spmatrix(b)
  2017. assert_array_equal(a[...].A, b[...].A)
  2018. assert_array_equal(a[...,].A, b[...,].A)
  2019. assert_array_equal(a[1, ...].A, b[1, ...].A)
  2020. assert_array_equal(a[..., 1].A, b[..., 1].A)
  2021. assert_array_equal(a[1:, ...].A, b[1:, ...].A)
  2022. assert_array_equal(a[..., 1:].A, b[..., 1:].A)
  2023. assert_array_equal(a[1:, 1, ...].A, b[1:, 1, ...].A)
  2024. assert_array_equal(a[1, ..., 1:].A, b[1, ..., 1:].A)
  2025. # These return ints
  2026. assert_equal(a[1, 1, ...], b[1, 1, ...])
  2027. assert_equal(a[1, ..., 1], b[1, ..., 1])
  2028. @pytest.mark.skipif(NumpyVersion(np.__version__) >= '1.9.0.dev', reason="")
  2029. def test_multiple_ellipsis_slicing(self):
  2030. b = asmatrix(arange(50).reshape(5,10))
  2031. a = self.spmatrix(b)
  2032. assert_array_equal(a[..., ...].A, b[..., ...].A)
  2033. assert_array_equal(a[..., ..., ...].A, b[..., ..., ...].A)
  2034. assert_array_equal(a[1, ..., ...].A, b[1, ..., ...].A)
  2035. assert_array_equal(a[1:, ..., ...].A, b[1:, ..., ...].A)
  2036. assert_array_equal(a[..., ..., 1:].A, b[..., ..., 1:].A)
  2037. # Bug in NumPy's slicing
  2038. assert_array_equal(a[..., ..., 1].A, b[..., ..., 1].A.reshape((5,1)))
  2039. class _TestSlicingAssign(object):
  2040. def test_slice_scalar_assign(self):
  2041. A = self.spmatrix((5, 5))
  2042. B = np.zeros((5, 5))
  2043. with suppress_warnings() as sup:
  2044. sup.filter(SparseEfficiencyWarning,
  2045. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2046. for C in [A, B]:
  2047. C[0:1,1] = 1
  2048. C[3:0,0] = 4
  2049. C[3:4,0] = 9
  2050. C[0,4:] = 1
  2051. C[3::-1,4:] = 9
  2052. assert_array_equal(A.toarray(), B)
  2053. def test_slice_assign_2(self):
  2054. n, m = (5, 10)
  2055. def _test_set(i, j):
  2056. msg = "i=%r; j=%r" % (i, j)
  2057. A = self.spmatrix((n, m))
  2058. with suppress_warnings() as sup:
  2059. sup.filter(SparseEfficiencyWarning,
  2060. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2061. A[i, j] = 1
  2062. B = np.zeros((n, m))
  2063. B[i, j] = 1
  2064. assert_array_almost_equal(A.todense(), B, err_msg=msg)
  2065. # [i,1:2]
  2066. for i, j in [(2, slice(3)), (2, slice(None, 10, 4)), (2, slice(5, -2)),
  2067. (array(2), slice(5, -2))]:
  2068. _test_set(i, j)
  2069. def test_self_self_assignment(self):
  2070. # Tests whether a row of one lil_matrix can be assigned to
  2071. # another.
  2072. B = self.spmatrix((4,3))
  2073. with suppress_warnings() as sup:
  2074. sup.filter(SparseEfficiencyWarning,
  2075. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2076. B[0,0] = 2
  2077. B[1,2] = 7
  2078. B[2,1] = 3
  2079. B[3,0] = 10
  2080. A = B / 10
  2081. B[0,:] = A[0,:]
  2082. assert_array_equal(A[0,:].A, B[0,:].A)
  2083. A = B / 10
  2084. B[:,:] = A[:1,:1]
  2085. assert_array_equal(np.zeros((4,3)) + A[0,0], B.A)
  2086. A = B / 10
  2087. B[:-1,0] = A[0,:].T
  2088. assert_array_equal(A[0,:].A.T, B[:-1,0].A)
  2089. def test_slice_assignment(self):
  2090. B = self.spmatrix((4,3))
  2091. expected = array([[10,0,0],
  2092. [0,0,6],
  2093. [0,14,0],
  2094. [0,0,0]])
  2095. block = [[1,0],[0,4]]
  2096. with suppress_warnings() as sup:
  2097. sup.filter(SparseEfficiencyWarning,
  2098. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2099. B[0,0] = 5
  2100. B[1,2] = 3
  2101. B[2,1] = 7
  2102. B[:,:] = B+B
  2103. assert_array_equal(B.todense(),expected)
  2104. B[:2,:2] = csc_matrix(array(block))
  2105. assert_array_equal(B.todense()[:2,:2],block)
  2106. def test_sparsity_modifying_assignment(self):
  2107. B = self.spmatrix((4,3))
  2108. with suppress_warnings() as sup:
  2109. sup.filter(SparseEfficiencyWarning,
  2110. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2111. B[0,0] = 5
  2112. B[1,2] = 3
  2113. B[2,1] = 7
  2114. B[3,0] = 10
  2115. B[:3] = csr_matrix(np.eye(3))
  2116. expected = array([[1,0,0],[0,1,0],[0,0,1],[10,0,0]])
  2117. assert_array_equal(B.toarray(), expected)
  2118. def test_set_slice(self):
  2119. A = self.spmatrix((5,10))
  2120. B = matrix(zeros((5,10), float))
  2121. s_ = np.s_
  2122. slices = [s_[:2], s_[1:2], s_[3:], s_[3::2],
  2123. s_[8:3:-1], s_[4::-2], s_[:5:-1],
  2124. 0, 1, s_[:], s_[1:5], -1, -2, -5,
  2125. array(-1), np.int8(-3)]
  2126. with suppress_warnings() as sup:
  2127. sup.filter(SparseEfficiencyWarning,
  2128. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2129. for j, a in enumerate(slices):
  2130. A[a] = j
  2131. B[a] = j
  2132. assert_array_equal(A.todense(), B, repr(a))
  2133. for i, a in enumerate(slices):
  2134. for j, b in enumerate(slices):
  2135. A[a,b] = 10*i + 1000*(j+1)
  2136. B[a,b] = 10*i + 1000*(j+1)
  2137. assert_array_equal(A.todense(), B, repr((a, b)))
  2138. A[0, 1:10:2] = xrange(1,10,2)
  2139. B[0, 1:10:2] = xrange(1,10,2)
  2140. assert_array_equal(A.todense(), B)
  2141. A[1:5:2,0] = np.array(range(1,5,2))[:,None]
  2142. B[1:5:2,0] = np.array(range(1,5,2))[:,None]
  2143. assert_array_equal(A.todense(), B)
  2144. # The next commands should raise exceptions
  2145. assert_raises(ValueError, A.__setitem__, (0, 0), list(range(100)))
  2146. assert_raises(ValueError, A.__setitem__, (0, 0), arange(100))
  2147. assert_raises(ValueError, A.__setitem__, (0, slice(None)),
  2148. list(range(100)))
  2149. assert_raises(ValueError, A.__setitem__, (slice(None), 1),
  2150. list(range(100)))
  2151. assert_raises(ValueError, A.__setitem__, (slice(None), 1), A.copy())
  2152. assert_raises(ValueError, A.__setitem__,
  2153. ([[1, 2, 3], [0, 3, 4]], [1, 2, 3]), [1, 2, 3, 4])
  2154. assert_raises(ValueError, A.__setitem__,
  2155. ([[1, 2, 3], [0, 3, 4], [4, 1, 3]],
  2156. [[1, 2, 4], [0, 1, 3]]), [2, 3, 4])
  2157. class _TestFancyIndexing(object):
  2158. """Tests fancy indexing features. The tests for any matrix formats
  2159. that implement these features should derive from this class.
  2160. """
  2161. def test_bad_index(self):
  2162. A = self.spmatrix(np.zeros([5, 5]))
  2163. assert_raises((IndexError, ValueError, TypeError), A.__getitem__, "foo")
  2164. assert_raises((IndexError, ValueError, TypeError), A.__getitem__, (2, "foo"))
  2165. assert_raises((IndexError, ValueError), A.__getitem__,
  2166. ([1, 2, 3], [1, 2, 3, 4]))
  2167. def test_fancy_indexing(self):
  2168. B = asmatrix(arange(50).reshape(5,10))
  2169. A = self.spmatrix(B)
  2170. # [i]
  2171. assert_equal(A[[1,3]].todense(), B[[1,3]])
  2172. # [i,[1,2]]
  2173. assert_equal(A[3,[1,3]].todense(), B[3,[1,3]])
  2174. assert_equal(A[-1,[2,-5]].todense(),B[-1,[2,-5]])
  2175. assert_equal(A[array(-1),[2,-5]].todense(),B[-1,[2,-5]])
  2176. assert_equal(A[-1,array([2,-5])].todense(),B[-1,[2,-5]])
  2177. assert_equal(A[array(-1),array([2,-5])].todense(),B[-1,[2,-5]])
  2178. # [1:2,[1,2]]
  2179. assert_equal(A[:,[2,8,3,-1]].todense(),B[:,[2,8,3,-1]])
  2180. assert_equal(A[3:4,[9]].todense(), B[3:4,[9]])
  2181. assert_equal(A[1:4,[-1,-5]].todense(), B[1:4,[-1,-5]])
  2182. assert_equal(A[1:4,array([-1,-5])].todense(), B[1:4,[-1,-5]])
  2183. # [[1,2],j]
  2184. assert_equal(A[[1,3],3].todense(), B[[1,3],3])
  2185. assert_equal(A[[2,-5],-4].todense(), B[[2,-5],-4])
  2186. assert_equal(A[array([2,-5]),-4].todense(), B[[2,-5],-4])
  2187. assert_equal(A[[2,-5],array(-4)].todense(), B[[2,-5],-4])
  2188. assert_equal(A[array([2,-5]),array(-4)].todense(), B[[2,-5],-4])
  2189. # [[1,2],1:2]
  2190. assert_equal(A[[1,3],:].todense(), B[[1,3],:])
  2191. assert_equal(A[[2,-5],8:-1].todense(),B[[2,-5],8:-1])
  2192. assert_equal(A[array([2,-5]),8:-1].todense(),B[[2,-5],8:-1])
  2193. # [[1,2],[1,2]]
  2194. assert_equal(todense(A[[1,3],[2,4]]), B[[1,3],[2,4]])
  2195. assert_equal(todense(A[[-1,-3],[2,-4]]), B[[-1,-3],[2,-4]])
  2196. assert_equal(todense(A[array([-1,-3]),[2,-4]]), B[[-1,-3],[2,-4]])
  2197. assert_equal(todense(A[[-1,-3],array([2,-4])]), B[[-1,-3],[2,-4]])
  2198. assert_equal(todense(A[array([-1,-3]),array([2,-4])]), B[[-1,-3],[2,-4]])
  2199. # [[[1],[2]],[1,2]]
  2200. assert_equal(A[[[1],[3]],[2,4]].todense(), B[[[1],[3]],[2,4]])
  2201. assert_equal(A[[[-1],[-3],[-2]],[2,-4]].todense(),B[[[-1],[-3],[-2]],[2,-4]])
  2202. assert_equal(A[array([[-1],[-3],[-2]]),[2,-4]].todense(),B[[[-1],[-3],[-2]],[2,-4]])
  2203. assert_equal(A[[[-1],[-3],[-2]],array([2,-4])].todense(),B[[[-1],[-3],[-2]],[2,-4]])
  2204. assert_equal(A[array([[-1],[-3],[-2]]),array([2,-4])].todense(),B[[[-1],[-3],[-2]],[2,-4]])
  2205. # [[1,2]]
  2206. assert_equal(A[[1,3]].todense(), B[[1,3]])
  2207. assert_equal(A[[-1,-3]].todense(),B[[-1,-3]])
  2208. assert_equal(A[array([-1,-3])].todense(),B[[-1,-3]])
  2209. # [[1,2],:][:,[1,2]]
  2210. assert_equal(A[[1,3],:][:,[2,4]].todense(), B[[1,3],:][:,[2,4]])
  2211. assert_equal(A[[-1,-3],:][:,[2,-4]].todense(), B[[-1,-3],:][:,[2,-4]])
  2212. assert_equal(A[array([-1,-3]),:][:,array([2,-4])].todense(), B[[-1,-3],:][:,[2,-4]])
  2213. # [:,[1,2]][[1,2],:]
  2214. assert_equal(A[:,[1,3]][[2,4],:].todense(), B[:,[1,3]][[2,4],:])
  2215. assert_equal(A[:,[-1,-3]][[2,-4],:].todense(), B[:,[-1,-3]][[2,-4],:])
  2216. assert_equal(A[:,array([-1,-3])][array([2,-4]),:].todense(), B[:,[-1,-3]][[2,-4],:])
  2217. # Check bug reported by Robert Cimrman:
  2218. # http://thread.gmane.org/gmane.comp.python.scientific.devel/7986 (dead link)
  2219. s = slice(int8(2),int8(4),None)
  2220. assert_equal(A[s,:].todense(), B[2:4,:])
  2221. assert_equal(A[:,s].todense(), B[:,2:4])
  2222. # Regression for gh-4917: index with tuple of 2D arrays
  2223. i = np.array([[1]], dtype=int)
  2224. assert_equal(A[i,i].todense(), B[i,i])
  2225. # Regression for gh-4917: index with tuple of empty nested lists
  2226. assert_equal(A[[[]], [[]]].todense(), B[[[]], [[]]])
  2227. def test_fancy_indexing_randomized(self):
  2228. np.random.seed(1234) # make runs repeatable
  2229. NUM_SAMPLES = 50
  2230. M = 6
  2231. N = 4
  2232. D = np.asmatrix(np.random.rand(M,N))
  2233. D = np.multiply(D, D > 0.5)
  2234. I = np.random.randint(-M + 1, M, size=NUM_SAMPLES)
  2235. J = np.random.randint(-N + 1, N, size=NUM_SAMPLES)
  2236. S = self.spmatrix(D)
  2237. SIJ = S[I,J]
  2238. if isspmatrix(SIJ):
  2239. SIJ = SIJ.todense()
  2240. assert_equal(SIJ, D[I,J])
  2241. I_bad = I + M
  2242. J_bad = J - N
  2243. assert_raises(IndexError, S.__getitem__, (I_bad,J))
  2244. assert_raises(IndexError, S.__getitem__, (I,J_bad))
  2245. def test_fancy_indexing_boolean(self):
  2246. np.random.seed(1234) # make runs repeatable
  2247. B = asmatrix(arange(50).reshape(5,10))
  2248. A = self.spmatrix(B)
  2249. I = np.array(np.random.randint(0, 2, size=5), dtype=bool)
  2250. J = np.array(np.random.randint(0, 2, size=10), dtype=bool)
  2251. X = np.array(np.random.randint(0, 2, size=(5, 10)), dtype=bool)
  2252. assert_equal(todense(A[I]), B[I])
  2253. assert_equal(todense(A[:,J]), B[:, J])
  2254. assert_equal(todense(A[X]), B[X])
  2255. assert_equal(todense(A[B > 9]), B[B > 9])
  2256. I = np.array([True, False, True, True, False])
  2257. J = np.array([False, True, True, False, True,
  2258. False, False, False, False, False])
  2259. assert_equal(todense(A[I, J]), B[I, J])
  2260. Z1 = np.zeros((6, 11), dtype=bool)
  2261. Z2 = np.zeros((6, 11), dtype=bool)
  2262. Z2[0,-1] = True
  2263. Z3 = np.zeros((6, 11), dtype=bool)
  2264. Z3[-1,0] = True
  2265. assert_equal(A[Z1], np.array([]))
  2266. assert_raises(IndexError, A.__getitem__, Z2)
  2267. assert_raises(IndexError, A.__getitem__, Z3)
  2268. assert_raises((IndexError, ValueError), A.__getitem__, (X, 1))
  2269. def test_fancy_indexing_sparse_boolean(self):
  2270. np.random.seed(1234) # make runs repeatable
  2271. B = asmatrix(arange(50).reshape(5,10))
  2272. A = self.spmatrix(B)
  2273. X = np.array(np.random.randint(0, 2, size=(5, 10)), dtype=bool)
  2274. Xsp = csr_matrix(X)
  2275. assert_equal(todense(A[Xsp]), B[X])
  2276. assert_equal(todense(A[A > 9]), B[B > 9])
  2277. Z = np.array(np.random.randint(0, 2, size=(5, 11)), dtype=bool)
  2278. Y = np.array(np.random.randint(0, 2, size=(6, 10)), dtype=bool)
  2279. Zsp = csr_matrix(Z)
  2280. Ysp = csr_matrix(Y)
  2281. assert_raises(IndexError, A.__getitem__, Zsp)
  2282. assert_raises(IndexError, A.__getitem__, Ysp)
  2283. assert_raises((IndexError, ValueError), A.__getitem__, (Xsp, 1))
  2284. def test_fancy_indexing_regression_3087(self):
  2285. mat = self.spmatrix(array([[1, 0, 0], [0,1,0], [1,0,0]]))
  2286. desired_cols = np.ravel(mat.sum(0)) > 0
  2287. assert_equal(mat[:, desired_cols].A, [[1, 0], [0, 1], [1, 0]])
  2288. def test_fancy_indexing_seq_assign(self):
  2289. mat = self.spmatrix(array([[1, 0], [0, 1]]))
  2290. assert_raises(ValueError, mat.__setitem__, (0, 0), np.array([1,2]))
  2291. def test_fancy_indexing_empty(self):
  2292. B = asmatrix(arange(50).reshape(5,10))
  2293. B[1,:] = 0
  2294. B[:,2] = 0
  2295. B[3,6] = 0
  2296. A = self.spmatrix(B)
  2297. K = np.array([False, False, False, False, False])
  2298. assert_equal(todense(A[K]), B[K])
  2299. K = np.array([], dtype=int)
  2300. assert_equal(todense(A[K]), B[K])
  2301. assert_equal(todense(A[K,K]), B[K,K])
  2302. J = np.array([0, 1, 2, 3, 4], dtype=int)[:,None]
  2303. assert_equal(todense(A[K,J]), B[K,J])
  2304. assert_equal(todense(A[J,K]), B[J,K])
  2305. @contextlib.contextmanager
  2306. def check_remains_sorted(X):
  2307. """Checks that sorted indices property is retained through an operation
  2308. """
  2309. if not hasattr(X, 'has_sorted_indices') or not X.has_sorted_indices:
  2310. yield
  2311. return
  2312. yield
  2313. indices = X.indices.copy()
  2314. X.has_sorted_indices = False
  2315. X.sort_indices()
  2316. assert_array_equal(indices, X.indices,
  2317. 'Expected sorted indices, found unsorted')
  2318. class _TestFancyIndexingAssign(object):
  2319. def test_bad_index_assign(self):
  2320. A = self.spmatrix(np.zeros([5, 5]))
  2321. assert_raises((IndexError, ValueError, TypeError), A.__setitem__, "foo", 2)
  2322. assert_raises((IndexError, ValueError, TypeError), A.__setitem__, (2, "foo"), 5)
  2323. def test_fancy_indexing_set(self):
  2324. n, m = (5, 10)
  2325. def _test_set_slice(i, j):
  2326. A = self.spmatrix((n, m))
  2327. B = asmatrix(np.zeros((n, m)))
  2328. with suppress_warnings() as sup:
  2329. sup.filter(SparseEfficiencyWarning,
  2330. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2331. B[i, j] = 1
  2332. with check_remains_sorted(A):
  2333. A[i, j] = 1
  2334. assert_array_almost_equal(A.todense(), B)
  2335. # [1:2,1:2]
  2336. for i, j in [((2, 3, 4), slice(None, 10, 4)),
  2337. (np.arange(3), slice(5, -2)),
  2338. (slice(2, 5), slice(5, -2))]:
  2339. _test_set_slice(i, j)
  2340. for i, j in [(np.arange(3), np.arange(3)), ((0, 3, 4), (1, 2, 4))]:
  2341. _test_set_slice(i, j)
  2342. def test_fancy_assignment_dtypes(self):
  2343. def check(dtype):
  2344. A = self.spmatrix((5, 5), dtype=dtype)
  2345. with suppress_warnings() as sup:
  2346. sup.filter(SparseEfficiencyWarning,
  2347. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2348. A[[0,1],[0,1]] = dtype.type(1)
  2349. assert_equal(A.sum(), dtype.type(1)*2)
  2350. A[0:2,0:2] = dtype.type(1.0)
  2351. assert_equal(A.sum(), dtype.type(1)*4)
  2352. A[2,2] = dtype.type(1.0)
  2353. assert_equal(A.sum(), dtype.type(1)*4 + dtype.type(1))
  2354. for dtype in supported_dtypes:
  2355. check(np.dtype(dtype))
  2356. def test_sequence_assignment(self):
  2357. A = self.spmatrix((4,3))
  2358. B = self.spmatrix(eye(3,4))
  2359. i0 = [0,1,2]
  2360. i1 = (0,1,2)
  2361. i2 = array(i0)
  2362. with suppress_warnings() as sup:
  2363. sup.filter(SparseEfficiencyWarning,
  2364. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2365. with check_remains_sorted(A):
  2366. A[0,i0] = B[i0,0].T
  2367. A[1,i1] = B[i1,1].T
  2368. A[2,i2] = B[i2,2].T
  2369. assert_array_equal(A.todense(),B.T.todense())
  2370. # column slice
  2371. A = self.spmatrix((2,3))
  2372. with check_remains_sorted(A):
  2373. A[1,1:3] = [10,20]
  2374. assert_array_equal(A.todense(), [[0,0,0],[0,10,20]])
  2375. # row slice
  2376. A = self.spmatrix((3,2))
  2377. with check_remains_sorted(A):
  2378. A[1:3,1] = [[10],[20]]
  2379. assert_array_equal(A.todense(), [[0,0],[0,10],[0,20]])
  2380. # both slices
  2381. A = self.spmatrix((3,3))
  2382. B = asmatrix(np.zeros((3,3)))
  2383. with check_remains_sorted(A):
  2384. for C in [A, B]:
  2385. C[[0,1,2], [0,1,2]] = [4,5,6]
  2386. assert_array_equal(A.toarray(), B)
  2387. # both slices (2)
  2388. A = self.spmatrix((4, 3))
  2389. with check_remains_sorted(A):
  2390. A[(1, 2, 3), (0, 1, 2)] = [1, 2, 3]
  2391. assert_almost_equal(A.sum(), 6)
  2392. B = asmatrix(np.zeros((4, 3)))
  2393. B[(1, 2, 3), (0, 1, 2)] = [1, 2, 3]
  2394. assert_array_equal(A.todense(), B)
  2395. def test_fancy_assign_empty(self):
  2396. B = asmatrix(arange(50).reshape(5,10))
  2397. B[1,:] = 0
  2398. B[:,2] = 0
  2399. B[3,6] = 0
  2400. A = self.spmatrix(B)
  2401. K = np.array([False, False, False, False, False])
  2402. A[K] = 42
  2403. assert_equal(todense(A), B)
  2404. K = np.array([], dtype=int)
  2405. A[K] = 42
  2406. assert_equal(todense(A), B)
  2407. A[K,K] = 42
  2408. assert_equal(todense(A), B)
  2409. J = np.array([0, 1, 2, 3, 4], dtype=int)[:,None]
  2410. A[K,J] = 42
  2411. assert_equal(todense(A), B)
  2412. A[J,K] = 42
  2413. assert_equal(todense(A), B)
  2414. class _TestFancyMultidim(object):
  2415. def test_fancy_indexing_ndarray(self):
  2416. sets = [
  2417. (np.array([[1], [2], [3]]), np.array([3, 4, 2])),
  2418. (np.array([[1], [2], [3]]), np.array([[3, 4, 2]])),
  2419. (np.array([[1, 2, 3]]), np.array([[3], [4], [2]])),
  2420. (np.array([1, 2, 3]), np.array([[3], [4], [2]])),
  2421. (np.array([[1, 2, 3], [3, 4, 2]]),
  2422. np.array([[5, 6, 3], [2, 3, 1]]))
  2423. ]
  2424. # These inputs generate 3-D outputs
  2425. # (np.array([[[1], [2], [3]], [[3], [4], [2]]]),
  2426. # np.array([[[5], [6], [3]], [[2], [3], [1]]])),
  2427. for I, J in sets:
  2428. np.random.seed(1234)
  2429. D = np.asmatrix(np.random.rand(5, 7))
  2430. S = self.spmatrix(D)
  2431. SIJ = S[I,J]
  2432. if isspmatrix(SIJ):
  2433. SIJ = SIJ.todense()
  2434. assert_equal(SIJ, D[I,J])
  2435. I_bad = I + 5
  2436. J_bad = J + 7
  2437. assert_raises(IndexError, S.__getitem__, (I_bad,J))
  2438. assert_raises(IndexError, S.__getitem__, (I,J_bad))
  2439. # This would generate 3-D arrays -- not supported
  2440. assert_raises(IndexError, S.__getitem__, ([I, I], slice(None)))
  2441. assert_raises(IndexError, S.__getitem__, (slice(None), [J, J]))
  2442. class _TestFancyMultidimAssign(object):
  2443. def test_fancy_assign_ndarray(self):
  2444. np.random.seed(1234)
  2445. D = np.asmatrix(np.random.rand(5, 7))
  2446. S = self.spmatrix(D)
  2447. X = np.random.rand(2, 3)
  2448. I = np.array([[1, 2, 3], [3, 4, 2]])
  2449. J = np.array([[5, 6, 3], [2, 3, 1]])
  2450. with check_remains_sorted(S):
  2451. S[I,J] = X
  2452. D[I,J] = X
  2453. assert_equal(S.todense(), D)
  2454. I_bad = I + 5
  2455. J_bad = J + 7
  2456. C = [1, 2, 3]
  2457. with check_remains_sorted(S):
  2458. S[I,J] = C
  2459. D[I,J] = C
  2460. assert_equal(S.todense(), D)
  2461. with check_remains_sorted(S):
  2462. S[I,J] = 3
  2463. D[I,J] = 3
  2464. assert_equal(S.todense(), D)
  2465. assert_raises(IndexError, S.__setitem__, (I_bad,J), C)
  2466. assert_raises(IndexError, S.__setitem__, (I,J_bad), C)
  2467. def test_fancy_indexing_multidim_set(self):
  2468. n, m = (5, 10)
  2469. def _test_set_slice(i, j):
  2470. A = self.spmatrix((n, m))
  2471. with check_remains_sorted(A), suppress_warnings() as sup:
  2472. sup.filter(SparseEfficiencyWarning,
  2473. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  2474. A[i, j] = 1
  2475. B = asmatrix(np.zeros((n, m)))
  2476. B[i, j] = 1
  2477. assert_array_almost_equal(A.todense(), B)
  2478. # [[[1, 2], [1, 2]], [1, 2]]
  2479. for i, j in [(np.array([[1, 2], [1, 3]]), [1, 3]),
  2480. (np.array([0, 4]), [[0, 3], [1, 2]]),
  2481. ([[1, 2, 3], [0, 2, 4]], [[0, 4, 3], [4, 1, 2]])]:
  2482. _test_set_slice(i, j)
  2483. def test_fancy_assign_list(self):
  2484. np.random.seed(1234)
  2485. D = np.asmatrix(np.random.rand(5, 7))
  2486. S = self.spmatrix(D)
  2487. X = np.random.rand(2, 3)
  2488. I = [[1, 2, 3], [3, 4, 2]]
  2489. J = [[5, 6, 3], [2, 3, 1]]
  2490. S[I,J] = X
  2491. D[I,J] = X
  2492. assert_equal(S.todense(), D)
  2493. I_bad = [[ii + 5 for ii in i] for i in I]
  2494. J_bad = [[jj + 7 for jj in j] for j in J]
  2495. C = [1, 2, 3]
  2496. S[I,J] = C
  2497. D[I,J] = C
  2498. assert_equal(S.todense(), D)
  2499. S[I,J] = 3
  2500. D[I,J] = 3
  2501. assert_equal(S.todense(), D)
  2502. assert_raises(IndexError, S.__setitem__, (I_bad,J), C)
  2503. assert_raises(IndexError, S.__setitem__, (I,J_bad), C)
  2504. def test_fancy_assign_slice(self):
  2505. np.random.seed(1234)
  2506. D = np.asmatrix(np.random.rand(5, 7))
  2507. S = self.spmatrix(D)
  2508. I = [[1, 2, 3], [3, 4, 2]]
  2509. J = [[5, 6, 3], [2, 3, 1]]
  2510. I_bad = [[ii + 5 for ii in i] for i in I]
  2511. J_bad = [[jj + 7 for jj in j] for j in J]
  2512. C = [1, 2, 3, 4, 5, 6, 7]
  2513. assert_raises(IndexError, S.__setitem__, (I_bad, slice(None)), C)
  2514. assert_raises(IndexError, S.__setitem__, (slice(None), J_bad), C)
  2515. class _TestArithmetic(object):
  2516. """
  2517. Test real/complex arithmetic
  2518. """
  2519. def __arith_init(self):
  2520. # these can be represented exactly in FP (so arithmetic should be exact)
  2521. self.__A = matrix([[-1.5, 6.5, 0, 2.25, 0, 0],
  2522. [3.125, -7.875, 0.625, 0, 0, 0],
  2523. [0, 0, -0.125, 1.0, 0, 0],
  2524. [0, 0, 8.375, 0, 0, 0]],'float64')
  2525. self.__B = matrix([[0.375, 0, 0, 0, -5, 2.5],
  2526. [14.25, -3.75, 0, 0, -0.125, 0],
  2527. [0, 7.25, 0, 0, 0, 0],
  2528. [18.5, -0.0625, 0, 0, 0, 0]],'complex128')
  2529. self.__B.imag = matrix([[1.25, 0, 0, 0, 6, -3.875],
  2530. [2.25, 4.125, 0, 0, 0, 2.75],
  2531. [0, 4.125, 0, 0, 0, 0],
  2532. [-0.0625, 0, 0, 0, 0, 0]],'float64')
  2533. # fractions are all x/16ths
  2534. assert_array_equal((self.__A*16).astype('int32'),16*self.__A)
  2535. assert_array_equal((self.__B.real*16).astype('int32'),16*self.__B.real)
  2536. assert_array_equal((self.__B.imag*16).astype('int32'),16*self.__B.imag)
  2537. self.__Asp = self.spmatrix(self.__A)
  2538. self.__Bsp = self.spmatrix(self.__B)
  2539. def test_add_sub(self):
  2540. self.__arith_init()
  2541. # basic tests
  2542. assert_array_equal((self.__Asp+self.__Bsp).todense(),self.__A+self.__B)
  2543. # check conversions
  2544. for x in supported_dtypes:
  2545. A = self.__A.astype(x)
  2546. Asp = self.spmatrix(A)
  2547. for y in supported_dtypes:
  2548. if not np.issubdtype(y, np.complexfloating):
  2549. B = self.__B.real.astype(y)
  2550. else:
  2551. B = self.__B.astype(y)
  2552. Bsp = self.spmatrix(B)
  2553. # addition
  2554. D1 = A + B
  2555. S1 = Asp + Bsp
  2556. assert_equal(S1.dtype,D1.dtype)
  2557. assert_array_equal(S1.todense(),D1)
  2558. assert_array_equal(Asp + B,D1) # check sparse + dense
  2559. assert_array_equal(A + Bsp,D1) # check dense + sparse
  2560. # subtraction
  2561. if (np.dtype('bool') in [x, y]) and (
  2562. NumpyVersion(np.__version__) >= '1.9.0.dev'):
  2563. # boolean array subtraction deprecated in 1.9.0
  2564. continue
  2565. D1 = A - B
  2566. S1 = Asp - Bsp
  2567. assert_equal(S1.dtype,D1.dtype)
  2568. assert_array_equal(S1.todense(),D1)
  2569. assert_array_equal(Asp - B,D1) # check sparse - dense
  2570. assert_array_equal(A - Bsp,D1) # check dense - sparse
  2571. def test_mu(self):
  2572. self.__arith_init()
  2573. # basic tests
  2574. assert_array_equal((self.__Asp*self.__Bsp.T).todense(),self.__A*self.__B.T)
  2575. for x in supported_dtypes:
  2576. A = self.__A.astype(x)
  2577. Asp = self.spmatrix(A)
  2578. for y in supported_dtypes:
  2579. if np.issubdtype(y, np.complexfloating):
  2580. B = self.__B.astype(y)
  2581. else:
  2582. B = self.__B.real.astype(y)
  2583. Bsp = self.spmatrix(B)
  2584. D1 = A * B.T
  2585. S1 = Asp * Bsp.T
  2586. assert_allclose(S1.todense(), D1,
  2587. atol=1e-14*abs(D1).max())
  2588. assert_equal(S1.dtype,D1.dtype)
  2589. class _TestMinMax(object):
  2590. def test_minmax(self):
  2591. for dtype in [np.float32, np.float64, np.int32, np.int64, np.complex128]:
  2592. D = np.arange(20, dtype=dtype).reshape(5,4)
  2593. X = self.spmatrix(D)
  2594. assert_equal(X.min(), 0)
  2595. assert_equal(X.max(), 19)
  2596. assert_equal(X.min().dtype, dtype)
  2597. assert_equal(X.max().dtype, dtype)
  2598. D *= -1
  2599. X = self.spmatrix(D)
  2600. assert_equal(X.min(), -19)
  2601. assert_equal(X.max(), 0)
  2602. D += 5
  2603. X = self.spmatrix(D)
  2604. assert_equal(X.min(), -14)
  2605. assert_equal(X.max(), 5)
  2606. # try a fully dense matrix
  2607. X = self.spmatrix(np.arange(1, 10).reshape(3, 3))
  2608. assert_equal(X.min(), 1)
  2609. assert_equal(X.min().dtype, X.dtype)
  2610. X = -X
  2611. assert_equal(X.max(), -1)
  2612. # and a fully sparse matrix
  2613. Z = self.spmatrix(np.zeros(1))
  2614. assert_equal(Z.min(), 0)
  2615. assert_equal(Z.max(), 0)
  2616. assert_equal(Z.max().dtype, Z.dtype)
  2617. # another test
  2618. D = np.arange(20, dtype=float).reshape(5,4)
  2619. D[0:2, :] = 0
  2620. X = self.spmatrix(D)
  2621. assert_equal(X.min(), 0)
  2622. assert_equal(X.max(), 19)
  2623. # zero-size matrices
  2624. for D in [np.zeros((0, 0)), np.zeros((0, 10)), np.zeros((10, 0))]:
  2625. X = self.spmatrix(D)
  2626. assert_raises(ValueError, X.min)
  2627. assert_raises(ValueError, X.max)
  2628. def test_minmax_axis(self):
  2629. D = np.matrix(np.arange(50).reshape(5,10))
  2630. # completely empty rows, leaving some completely full:
  2631. D[1, :] = 0
  2632. # empty at end for reduceat:
  2633. D[:, 9] = 0
  2634. # partial rows/cols:
  2635. D[3, 3] = 0
  2636. # entries on either side of 0:
  2637. D[2, 2] = -1
  2638. X = self.spmatrix(D)
  2639. axes = [-2, -1, 0, 1]
  2640. for axis in axes:
  2641. assert_array_equal(X.max(axis=axis).A, D.max(axis=axis).A)
  2642. assert_array_equal(X.min(axis=axis).A, D.min(axis=axis).A)
  2643. # full matrix
  2644. D = np.matrix(np.arange(1, 51).reshape(10, 5))
  2645. X = self.spmatrix(D)
  2646. for axis in axes:
  2647. assert_array_equal(X.max(axis=axis).A, D.max(axis=axis).A)
  2648. assert_array_equal(X.min(axis=axis).A, D.min(axis=axis).A)
  2649. # empty matrix
  2650. D = np.matrix(np.zeros((10, 5)))
  2651. X = self.spmatrix(D)
  2652. for axis in axes:
  2653. assert_array_equal(X.max(axis=axis).A, D.max(axis=axis).A)
  2654. assert_array_equal(X.min(axis=axis).A, D.min(axis=axis).A)
  2655. axes_even = [0, -2]
  2656. axes_odd = [1, -1]
  2657. # zero-size matrices
  2658. D = np.zeros((0, 10))
  2659. X = self.spmatrix(D)
  2660. for axis in axes_even:
  2661. assert_raises(ValueError, X.min, axis=axis)
  2662. assert_raises(ValueError, X.max, axis=axis)
  2663. for axis in axes_odd:
  2664. assert_array_equal(np.zeros((0, 1)), X.min(axis=axis).A)
  2665. assert_array_equal(np.zeros((0, 1)), X.max(axis=axis).A)
  2666. D = np.zeros((10, 0))
  2667. X = self.spmatrix(D)
  2668. for axis in axes_odd:
  2669. assert_raises(ValueError, X.min, axis=axis)
  2670. assert_raises(ValueError, X.max, axis=axis)
  2671. for axis in axes_even:
  2672. assert_array_equal(np.zeros((1, 0)), X.min(axis=axis).A)
  2673. assert_array_equal(np.zeros((1, 0)), X.max(axis=axis).A)
  2674. def test_minmax_invalid_params(self):
  2675. dat = np.matrix([[0, 1, 2],
  2676. [3, -4, 5],
  2677. [-6, 7, 9]])
  2678. datsp = self.spmatrix(dat)
  2679. for fname in ('min', 'max'):
  2680. func = getattr(datsp, fname)
  2681. assert_raises(ValueError, func, axis=3)
  2682. assert_raises(TypeError, func, axis=(0, 1))
  2683. assert_raises(TypeError, func, axis=1.5)
  2684. assert_raises(ValueError, func, axis=1, out=1)
  2685. def test_numpy_minmax(self):
  2686. # See gh-5987
  2687. # xref gh-7460 in 'numpy'
  2688. from scipy.sparse import data
  2689. dat = np.matrix([[0, 1, 2],
  2690. [3, -4, 5],
  2691. [-6, 7, 9]])
  2692. datsp = self.spmatrix(dat)
  2693. # We are only testing sparse matrices who have
  2694. # implemented 'min' and 'max' because they are
  2695. # the ones with the compatibility issues with
  2696. # the 'numpy' implementation.
  2697. if isinstance(datsp, data._minmax_mixin):
  2698. assert_array_equal(np.min(datsp), np.min(dat))
  2699. assert_array_equal(np.max(datsp), np.max(dat))
  2700. def test_argmax(self):
  2701. D1 = np.array([
  2702. [-1, 5, 2, 3],
  2703. [0, 0, -1, -2],
  2704. [-1, -2, -3, -4],
  2705. [1, 2, 3, 4],
  2706. [1, 2, 0, 0],
  2707. ])
  2708. D2 = D1.transpose()
  2709. for D in [D1, D2]:
  2710. mat = csr_matrix(D)
  2711. assert_equal(mat.argmax(), np.argmax(D))
  2712. assert_equal(mat.argmin(), np.argmin(D))
  2713. assert_equal(mat.argmax(axis=0),
  2714. np.asmatrix(np.argmax(D, axis=0)))
  2715. assert_equal(mat.argmin(axis=0),
  2716. np.asmatrix(np.argmin(D, axis=0)))
  2717. assert_equal(mat.argmax(axis=1),
  2718. np.asmatrix(np.argmax(D, axis=1).reshape(-1, 1)))
  2719. assert_equal(mat.argmin(axis=1),
  2720. np.asmatrix(np.argmin(D, axis=1).reshape(-1, 1)))
  2721. D1 = np.empty((0, 5))
  2722. D2 = np.empty((5, 0))
  2723. for axis in [None, 0]:
  2724. mat = self.spmatrix(D1)
  2725. assert_raises(ValueError, mat.argmax, axis=axis)
  2726. assert_raises(ValueError, mat.argmin, axis=axis)
  2727. for axis in [None, 1]:
  2728. mat = self.spmatrix(D2)
  2729. assert_raises(ValueError, mat.argmax, axis=axis)
  2730. assert_raises(ValueError, mat.argmin, axis=axis)
  2731. class _TestGetNnzAxis(object):
  2732. def test_getnnz_axis(self):
  2733. dat = np.matrix([[0, 2],
  2734. [3, 5],
  2735. [-6, 9]])
  2736. bool_dat = dat.astype(bool).A
  2737. datsp = self.spmatrix(dat)
  2738. accepted_return_dtypes = (np.int32, np.int64)
  2739. assert_array_equal(bool_dat.sum(axis=None), datsp.getnnz(axis=None))
  2740. assert_array_equal(bool_dat.sum(), datsp.getnnz())
  2741. assert_array_equal(bool_dat.sum(axis=0), datsp.getnnz(axis=0))
  2742. assert_in(datsp.getnnz(axis=0).dtype, accepted_return_dtypes)
  2743. assert_array_equal(bool_dat.sum(axis=1), datsp.getnnz(axis=1))
  2744. assert_in(datsp.getnnz(axis=1).dtype, accepted_return_dtypes)
  2745. assert_array_equal(bool_dat.sum(axis=-2), datsp.getnnz(axis=-2))
  2746. assert_in(datsp.getnnz(axis=-2).dtype, accepted_return_dtypes)
  2747. assert_array_equal(bool_dat.sum(axis=-1), datsp.getnnz(axis=-1))
  2748. assert_in(datsp.getnnz(axis=-1).dtype, accepted_return_dtypes)
  2749. assert_raises(ValueError, datsp.getnnz, axis=2)
  2750. #------------------------------------------------------------------------------
  2751. # Tailored base class for generic tests
  2752. #------------------------------------------------------------------------------
  2753. def _possibly_unimplemented(cls, require=True):
  2754. """
  2755. Construct a class that either runs tests as usual (require=True),
  2756. or each method skips if it encounters a common error.
  2757. """
  2758. if require:
  2759. return cls
  2760. else:
  2761. def wrap(fc):
  2762. @functools.wraps(fc)
  2763. def wrapper(*a, **kw):
  2764. try:
  2765. return fc(*a, **kw)
  2766. except (NotImplementedError, TypeError, ValueError,
  2767. IndexError, AttributeError):
  2768. raise pytest.skip("feature not implemented")
  2769. return wrapper
  2770. new_dict = dict(cls.__dict__)
  2771. for name, func in cls.__dict__.items():
  2772. if name.startswith('test_'):
  2773. new_dict[name] = wrap(func)
  2774. return type(cls.__name__ + "NotImplemented",
  2775. cls.__bases__,
  2776. new_dict)
  2777. def sparse_test_class(getset=True, slicing=True, slicing_assign=True,
  2778. fancy_indexing=True, fancy_assign=True,
  2779. fancy_multidim_indexing=True, fancy_multidim_assign=True,
  2780. minmax=True, nnz_axis=True):
  2781. """
  2782. Construct a base class, optionally converting some of the tests in
  2783. the suite to check that the feature is not implemented.
  2784. """
  2785. bases = (_TestCommon,
  2786. _possibly_unimplemented(_TestGetSet, getset),
  2787. _TestSolve,
  2788. _TestInplaceArithmetic,
  2789. _TestArithmetic,
  2790. _possibly_unimplemented(_TestSlicing, slicing),
  2791. _possibly_unimplemented(_TestSlicingAssign, slicing_assign),
  2792. _possibly_unimplemented(_TestFancyIndexing, fancy_indexing),
  2793. _possibly_unimplemented(_TestFancyIndexingAssign,
  2794. fancy_assign),
  2795. _possibly_unimplemented(_TestFancyMultidim,
  2796. fancy_indexing and fancy_multidim_indexing),
  2797. _possibly_unimplemented(_TestFancyMultidimAssign,
  2798. fancy_multidim_assign and fancy_assign),
  2799. _possibly_unimplemented(_TestMinMax, minmax),
  2800. _possibly_unimplemented(_TestGetNnzAxis, nnz_axis))
  2801. # check that test names do not clash
  2802. names = {}
  2803. for cls in bases:
  2804. for name in cls.__dict__:
  2805. if not name.startswith('test_'):
  2806. continue
  2807. old_cls = names.get(name)
  2808. if old_cls is not None:
  2809. raise ValueError("Test class %s overloads test %s defined in %s" % (
  2810. cls.__name__, name, old_cls.__name__))
  2811. names[name] = cls
  2812. return type("TestBase", bases, {})
  2813. #------------------------------------------------------------------------------
  2814. # Matrix class based tests
  2815. #------------------------------------------------------------------------------
  2816. class TestCSR(sparse_test_class()):
  2817. @classmethod
  2818. def spmatrix(cls, *args, **kwargs):
  2819. with suppress_warnings() as sup:
  2820. sup.filter(SparseEfficiencyWarning,
  2821. "Changing the sparsity structure of a csr_matrix is expensive")
  2822. return csr_matrix(*args, **kwargs)
  2823. math_dtypes = [np.bool_, np.int_, np.float_, np.complex_]
  2824. def test_constructor1(self):
  2825. b = matrix([[0,4,0],
  2826. [3,0,0],
  2827. [0,2,0]],'d')
  2828. bsp = csr_matrix(b)
  2829. assert_array_almost_equal(bsp.data,[4,3,2])
  2830. assert_array_equal(bsp.indices,[1,0,1])
  2831. assert_array_equal(bsp.indptr,[0,1,2,3])
  2832. assert_equal(bsp.getnnz(),3)
  2833. assert_equal(bsp.getformat(),'csr')
  2834. assert_array_equal(bsp.todense(),b)
  2835. def test_constructor2(self):
  2836. b = zeros((6,6),'d')
  2837. b[3,4] = 5
  2838. bsp = csr_matrix(b)
  2839. assert_array_almost_equal(bsp.data,[5])
  2840. assert_array_equal(bsp.indices,[4])
  2841. assert_array_equal(bsp.indptr,[0,0,0,0,1,1,1])
  2842. assert_array_almost_equal(bsp.todense(),b)
  2843. def test_constructor3(self):
  2844. b = matrix([[1,0],
  2845. [0,2],
  2846. [3,0]],'d')
  2847. bsp = csr_matrix(b)
  2848. assert_array_almost_equal(bsp.data,[1,2,3])
  2849. assert_array_equal(bsp.indices,[0,1,0])
  2850. assert_array_equal(bsp.indptr,[0,1,2,3])
  2851. assert_array_almost_equal(bsp.todense(),b)
  2852. ### currently disabled
  2853. ## def test_constructor4(self):
  2854. ## """try using int64 indices"""
  2855. ## data = arange( 6 ) + 1
  2856. ## col = array( [1, 2, 1, 0, 0, 2], dtype='int64' )
  2857. ## ptr = array( [0, 2, 4, 6], dtype='int64' )
  2858. ##
  2859. ## a = csr_matrix( (data, col, ptr), shape = (3,3) )
  2860. ##
  2861. ## b = matrix([[0,1,2],
  2862. ## [4,3,0],
  2863. ## [5,0,6]],'d')
  2864. ##
  2865. ## assert_equal(a.indptr.dtype,numpy.dtype('int64'))
  2866. ## assert_equal(a.indices.dtype,numpy.dtype('int64'))
  2867. ## assert_array_equal(a.todense(),b)
  2868. def test_constructor4(self):
  2869. # using (data, ij) format
  2870. row = array([2, 3, 1, 3, 0, 1, 3, 0, 2, 1, 2])
  2871. col = array([0, 1, 0, 0, 1, 1, 2, 2, 2, 2, 1])
  2872. data = array([6., 10., 3., 9., 1., 4.,
  2873. 11., 2., 8., 5., 7.])
  2874. ij = vstack((row,col))
  2875. csr = csr_matrix((data,ij),(4,3))
  2876. assert_array_equal(arange(12).reshape(4,3),csr.todense())
  2877. def test_constructor5(self):
  2878. # infer dimensions from arrays
  2879. indptr = array([0,1,3,3])
  2880. indices = array([0,5,1,2])
  2881. data = array([1,2,3,4])
  2882. csr = csr_matrix((data, indices, indptr))
  2883. assert_array_equal(csr.shape,(3,6))
  2884. def test_constructor6(self):
  2885. # infer dimensions and dtype from lists
  2886. indptr = [0, 1, 3, 3]
  2887. indices = [0, 5, 1, 2]
  2888. data = [1, 2, 3, 4]
  2889. csr = csr_matrix((data, indices, indptr))
  2890. assert_array_equal(csr.shape, (3,6))
  2891. assert_(np.issubdtype(csr.dtype, np.signedinteger))
  2892. def test_sort_indices(self):
  2893. data = arange(5)
  2894. indices = array([7, 2, 1, 5, 4])
  2895. indptr = array([0, 3, 5])
  2896. asp = csr_matrix((data, indices, indptr), shape=(2,10))
  2897. bsp = asp.copy()
  2898. asp.sort_indices()
  2899. assert_array_equal(asp.indices,[1, 2, 7, 4, 5])
  2900. assert_array_equal(asp.todense(),bsp.todense())
  2901. def test_eliminate_zeros(self):
  2902. data = array([1, 0, 0, 0, 2, 0, 3, 0])
  2903. indices = array([1, 2, 3, 4, 5, 6, 7, 8])
  2904. indptr = array([0, 3, 8])
  2905. asp = csr_matrix((data, indices, indptr), shape=(2,10))
  2906. bsp = asp.copy()
  2907. asp.eliminate_zeros()
  2908. assert_array_equal(asp.nnz, 3)
  2909. assert_array_equal(asp.data,[1, 2, 3])
  2910. assert_array_equal(asp.todense(),bsp.todense())
  2911. def test_ufuncs(self):
  2912. X = csr_matrix(np.arange(20).reshape(4, 5) / 20.)
  2913. for f in ["sin", "tan", "arcsin", "arctan", "sinh", "tanh",
  2914. "arcsinh", "arctanh", "rint", "sign", "expm1", "log1p",
  2915. "deg2rad", "rad2deg", "floor", "ceil", "trunc", "sqrt"]:
  2916. assert_equal(hasattr(csr_matrix, f), True)
  2917. X2 = getattr(X, f)()
  2918. assert_equal(X.shape, X2.shape)
  2919. assert_array_equal(X.indices, X2.indices)
  2920. assert_array_equal(X.indptr, X2.indptr)
  2921. assert_array_equal(X2.toarray(), getattr(np, f)(X.toarray()))
  2922. def test_unsorted_arithmetic(self):
  2923. data = arange(5)
  2924. indices = array([7, 2, 1, 5, 4])
  2925. indptr = array([0, 3, 5])
  2926. asp = csr_matrix((data, indices, indptr), shape=(2,10))
  2927. data = arange(6)
  2928. indices = array([8, 1, 5, 7, 2, 4])
  2929. indptr = array([0, 2, 6])
  2930. bsp = csr_matrix((data, indices, indptr), shape=(2,10))
  2931. assert_equal((asp + bsp).todense(), asp.todense() + bsp.todense())
  2932. def test_fancy_indexing_broadcast(self):
  2933. # broadcasting indexing mode is supported
  2934. I = np.array([[1], [2], [3]])
  2935. J = np.array([3, 4, 2])
  2936. np.random.seed(1234)
  2937. D = np.asmatrix(np.random.rand(5, 7))
  2938. S = self.spmatrix(D)
  2939. SIJ = S[I,J]
  2940. if isspmatrix(SIJ):
  2941. SIJ = SIJ.todense()
  2942. assert_equal(SIJ, D[I,J])
  2943. def test_has_sorted_indices(self):
  2944. "Ensure has_sorted_indices memoizes sorted state for sort_indices"
  2945. sorted_inds = np.array([0, 1])
  2946. unsorted_inds = np.array([1, 0])
  2947. data = np.array([1, 1])
  2948. indptr = np.array([0, 2])
  2949. M = csr_matrix((data, sorted_inds, indptr)).copy()
  2950. assert_equal(True, M.has_sorted_indices)
  2951. M = csr_matrix((data, unsorted_inds, indptr)).copy()
  2952. assert_equal(False, M.has_sorted_indices)
  2953. # set by sorting
  2954. M.sort_indices()
  2955. assert_equal(True, M.has_sorted_indices)
  2956. assert_array_equal(M.indices, sorted_inds)
  2957. M = csr_matrix((data, unsorted_inds, indptr)).copy()
  2958. # set manually (although underlyingly unsorted)
  2959. M.has_sorted_indices = True
  2960. assert_equal(True, M.has_sorted_indices)
  2961. assert_array_equal(M.indices, unsorted_inds)
  2962. # ensure sort bypassed when has_sorted_indices == True
  2963. M.sort_indices()
  2964. assert_array_equal(M.indices, unsorted_inds)
  2965. def test_has_canonical_format(self):
  2966. "Ensure has_canonical_format memoizes state for sum_duplicates"
  2967. M = csr_matrix((np.array([2]), np.array([0]), np.array([0, 1])))
  2968. assert_equal(True, M.has_canonical_format)
  2969. indices = np.array([0, 0]) # contains duplicate
  2970. data = np.array([1, 1])
  2971. indptr = np.array([0, 2])
  2972. M = csr_matrix((data, indices, indptr)).copy()
  2973. assert_equal(False, M.has_canonical_format)
  2974. # set by deduplicating
  2975. M.sum_duplicates()
  2976. assert_equal(True, M.has_canonical_format)
  2977. assert_equal(1, len(M.indices))
  2978. M = csr_matrix((data, indices, indptr)).copy()
  2979. # set manually (although underlyingly duplicated)
  2980. M.has_canonical_format = True
  2981. assert_equal(True, M.has_canonical_format)
  2982. assert_equal(2, len(M.indices)) # unaffected content
  2983. # ensure deduplication bypassed when has_canonical_format == True
  2984. M.sum_duplicates()
  2985. assert_equal(2, len(M.indices)) # unaffected content
  2986. def test_scalar_idx_dtype(self):
  2987. # Check that index dtype takes into account all parameters
  2988. # passed to sparsetools, including the scalar ones
  2989. indptr = np.zeros(2, dtype=np.int32)
  2990. indices = np.zeros(0, dtype=np.int32)
  2991. vals = np.zeros(0)
  2992. a = csr_matrix((vals, indices, indptr), shape=(1, 2**31-1))
  2993. b = csr_matrix((vals, indices, indptr), shape=(1, 2**31))
  2994. ij = np.zeros((2, 0), dtype=np.int32)
  2995. c = csr_matrix((vals, ij), shape=(1, 2**31-1))
  2996. d = csr_matrix((vals, ij), shape=(1, 2**31))
  2997. e = csr_matrix((1, 2**31-1))
  2998. f = csr_matrix((1, 2**31))
  2999. assert_equal(a.indptr.dtype, np.int32)
  3000. assert_equal(b.indptr.dtype, np.int64)
  3001. assert_equal(c.indptr.dtype, np.int32)
  3002. assert_equal(d.indptr.dtype, np.int64)
  3003. assert_equal(e.indptr.dtype, np.int32)
  3004. assert_equal(f.indptr.dtype, np.int64)
  3005. # These shouldn't fail
  3006. for x in [a, b, c, d, e, f]:
  3007. x + x
  3008. TestCSR.init_class()
  3009. class TestCSC(sparse_test_class()):
  3010. @classmethod
  3011. def spmatrix(cls, *args, **kwargs):
  3012. with suppress_warnings() as sup:
  3013. sup.filter(SparseEfficiencyWarning,
  3014. "Changing the sparsity structure of a csc_matrix is expensive")
  3015. return csc_matrix(*args, **kwargs)
  3016. math_dtypes = [np.bool_, np.int_, np.float_, np.complex_]
  3017. def test_constructor1(self):
  3018. b = matrix([[1,0,0,0],[0,0,1,0],[0,2,0,3]],'d')
  3019. bsp = csc_matrix(b)
  3020. assert_array_almost_equal(bsp.data,[1,2,1,3])
  3021. assert_array_equal(bsp.indices,[0,2,1,2])
  3022. assert_array_equal(bsp.indptr,[0,1,2,3,4])
  3023. assert_equal(bsp.getnnz(),4)
  3024. assert_equal(bsp.shape,b.shape)
  3025. assert_equal(bsp.getformat(),'csc')
  3026. def test_constructor2(self):
  3027. b = zeros((6,6),'d')
  3028. b[2,4] = 5
  3029. bsp = csc_matrix(b)
  3030. assert_array_almost_equal(bsp.data,[5])
  3031. assert_array_equal(bsp.indices,[2])
  3032. assert_array_equal(bsp.indptr,[0,0,0,0,0,1,1])
  3033. def test_constructor3(self):
  3034. b = matrix([[1,0],[0,0],[0,2]],'d')
  3035. bsp = csc_matrix(b)
  3036. assert_array_almost_equal(bsp.data,[1,2])
  3037. assert_array_equal(bsp.indices,[0,2])
  3038. assert_array_equal(bsp.indptr,[0,1,2])
  3039. def test_constructor4(self):
  3040. # using (data, ij) format
  3041. row = array([2, 3, 1, 3, 0, 1, 3, 0, 2, 1, 2])
  3042. col = array([0, 1, 0, 0, 1, 1, 2, 2, 2, 2, 1])
  3043. data = array([6., 10., 3., 9., 1., 4.,
  3044. 11., 2., 8., 5., 7.])
  3045. ij = vstack((row,col))
  3046. csc = csc_matrix((data,ij),(4,3))
  3047. assert_array_equal(arange(12).reshape(4,3),csc.todense())
  3048. def test_constructor5(self):
  3049. # infer dimensions from arrays
  3050. indptr = array([0,1,3,3])
  3051. indices = array([0,5,1,2])
  3052. data = array([1,2,3,4])
  3053. csc = csc_matrix((data, indices, indptr))
  3054. assert_array_equal(csc.shape,(6,3))
  3055. def test_constructor6(self):
  3056. # infer dimensions and dtype from lists
  3057. indptr = [0, 1, 3, 3]
  3058. indices = [0, 5, 1, 2]
  3059. data = [1, 2, 3, 4]
  3060. csc = csc_matrix((data, indices, indptr))
  3061. assert_array_equal(csc.shape,(6,3))
  3062. assert_(np.issubdtype(csc.dtype, np.signedinteger))
  3063. def test_eliminate_zeros(self):
  3064. data = array([1, 0, 0, 0, 2, 0, 3, 0])
  3065. indices = array([1, 2, 3, 4, 5, 6, 7, 8])
  3066. indptr = array([0, 3, 8])
  3067. asp = csc_matrix((data, indices, indptr), shape=(10,2))
  3068. bsp = asp.copy()
  3069. asp.eliminate_zeros()
  3070. assert_array_equal(asp.nnz, 3)
  3071. assert_array_equal(asp.data,[1, 2, 3])
  3072. assert_array_equal(asp.todense(),bsp.todense())
  3073. def test_sort_indices(self):
  3074. data = arange(5)
  3075. row = array([7, 2, 1, 5, 4])
  3076. ptr = [0, 3, 5]
  3077. asp = csc_matrix((data, row, ptr), shape=(10,2))
  3078. bsp = asp.copy()
  3079. asp.sort_indices()
  3080. assert_array_equal(asp.indices,[1, 2, 7, 4, 5])
  3081. assert_array_equal(asp.todense(),bsp.todense())
  3082. def test_ufuncs(self):
  3083. X = csc_matrix(np.arange(21).reshape(7, 3) / 21.)
  3084. for f in ["sin", "tan", "arcsin", "arctan", "sinh", "tanh",
  3085. "arcsinh", "arctanh", "rint", "sign", "expm1", "log1p",
  3086. "deg2rad", "rad2deg", "floor", "ceil", "trunc", "sqrt"]:
  3087. assert_equal(hasattr(csr_matrix, f), True)
  3088. X2 = getattr(X, f)()
  3089. assert_equal(X.shape, X2.shape)
  3090. assert_array_equal(X.indices, X2.indices)
  3091. assert_array_equal(X.indptr, X2.indptr)
  3092. assert_array_equal(X2.toarray(), getattr(np, f)(X.toarray()))
  3093. def test_unsorted_arithmetic(self):
  3094. data = arange(5)
  3095. indices = array([7, 2, 1, 5, 4])
  3096. indptr = array([0, 3, 5])
  3097. asp = csc_matrix((data, indices, indptr), shape=(10,2))
  3098. data = arange(6)
  3099. indices = array([8, 1, 5, 7, 2, 4])
  3100. indptr = array([0, 2, 6])
  3101. bsp = csc_matrix((data, indices, indptr), shape=(10,2))
  3102. assert_equal((asp + bsp).todense(), asp.todense() + bsp.todense())
  3103. def test_fancy_indexing_broadcast(self):
  3104. # broadcasting indexing mode is supported
  3105. I = np.array([[1], [2], [3]])
  3106. J = np.array([3, 4, 2])
  3107. np.random.seed(1234)
  3108. D = np.asmatrix(np.random.rand(5, 7))
  3109. S = self.spmatrix(D)
  3110. SIJ = S[I,J]
  3111. if isspmatrix(SIJ):
  3112. SIJ = SIJ.todense()
  3113. assert_equal(SIJ, D[I,J])
  3114. def test_scalar_idx_dtype(self):
  3115. # Check that index dtype takes into account all parameters
  3116. # passed to sparsetools, including the scalar ones
  3117. indptr = np.zeros(2, dtype=np.int32)
  3118. indices = np.zeros(0, dtype=np.int32)
  3119. vals = np.zeros(0)
  3120. a = csc_matrix((vals, indices, indptr), shape=(2**31-1, 1))
  3121. b = csc_matrix((vals, indices, indptr), shape=(2**31, 1))
  3122. ij = np.zeros((2, 0), dtype=np.int32)
  3123. c = csc_matrix((vals, ij), shape=(2**31-1, 1))
  3124. d = csc_matrix((vals, ij), shape=(2**31, 1))
  3125. e = csr_matrix((1, 2**31-1))
  3126. f = csr_matrix((1, 2**31))
  3127. assert_equal(a.indptr.dtype, np.int32)
  3128. assert_equal(b.indptr.dtype, np.int64)
  3129. assert_equal(c.indptr.dtype, np.int32)
  3130. assert_equal(d.indptr.dtype, np.int64)
  3131. assert_equal(e.indptr.dtype, np.int32)
  3132. assert_equal(f.indptr.dtype, np.int64)
  3133. # These shouldn't fail
  3134. for x in [a, b, c, d, e, f]:
  3135. x + x
  3136. TestCSC.init_class()
  3137. class TestDOK(sparse_test_class(minmax=False, nnz_axis=False)):
  3138. spmatrix = dok_matrix
  3139. math_dtypes = [np.int_, np.float_, np.complex_]
  3140. def test_mult(self):
  3141. A = dok_matrix((10,10))
  3142. A[0,3] = 10
  3143. A[5,6] = 20
  3144. D = A*A.T
  3145. E = A*A.H
  3146. assert_array_equal(D.A, E.A)
  3147. def test_add_nonzero(self):
  3148. A = self.spmatrix((3,2))
  3149. A[0,1] = -10
  3150. A[2,0] = 20
  3151. A = A + 10
  3152. B = matrix([[10, 0], [10, 10], [30, 10]])
  3153. assert_array_equal(A.todense(), B)
  3154. A = A + 1j
  3155. B = B + 1j
  3156. assert_array_equal(A.todense(), B)
  3157. def test_dok_divide_scalar(self):
  3158. A = self.spmatrix((3,2))
  3159. A[0,1] = -10
  3160. A[2,0] = 20
  3161. assert_array_equal((A/1j).todense(), A.todense()/1j)
  3162. assert_array_equal((A/9).todense(), A.todense()/9)
  3163. def test_convert(self):
  3164. # Test provided by Andrew Straw. Fails in SciPy <= r1477.
  3165. (m, n) = (6, 7)
  3166. a = dok_matrix((m, n))
  3167. # set a few elements, but none in the last column
  3168. a[2,1] = 1
  3169. a[0,2] = 2
  3170. a[3,1] = 3
  3171. a[1,5] = 4
  3172. a[4,3] = 5
  3173. a[4,2] = 6
  3174. # assert that the last column is all zeros
  3175. assert_array_equal(a.toarray()[:,n-1], zeros(m,))
  3176. # make sure it still works for CSC format
  3177. csc = a.tocsc()
  3178. assert_array_equal(csc.toarray()[:,n-1], zeros(m,))
  3179. # now test CSR
  3180. (m, n) = (n, m)
  3181. b = a.transpose()
  3182. assert_equal(b.shape, (m, n))
  3183. # assert that the last row is all zeros
  3184. assert_array_equal(b.toarray()[m-1,:], zeros(n,))
  3185. # make sure it still works for CSR format
  3186. csr = b.tocsr()
  3187. assert_array_equal(csr.toarray()[m-1,:], zeros(n,))
  3188. def test_ctor(self):
  3189. # Empty ctor
  3190. assert_raises(TypeError, dok_matrix)
  3191. # Dense ctor
  3192. b = matrix([[1,0,0,0],[0,0,1,0],[0,2,0,3]],'d')
  3193. A = dok_matrix(b)
  3194. assert_equal(b.dtype, A.dtype)
  3195. assert_equal(A.todense(), b)
  3196. # Sparse ctor
  3197. c = csr_matrix(b)
  3198. assert_equal(A.todense(), c.todense())
  3199. data = [[0, 1, 2], [3, 0, 0]]
  3200. d = dok_matrix(data, dtype=np.float32)
  3201. assert_equal(d.dtype, np.float32)
  3202. da = d.toarray()
  3203. assert_equal(da.dtype, np.float32)
  3204. assert_array_equal(da, data)
  3205. def test_ticket1160(self):
  3206. # Regression test for ticket #1160.
  3207. a = dok_matrix((3,3))
  3208. a[0,0] = 0
  3209. # This assert would fail, because the above assignment would
  3210. # incorrectly call __set_item__ even though the value was 0.
  3211. assert_((0,0) not in a.keys(), "Unexpected entry (0,0) in keys")
  3212. # Slice assignments were also affected.
  3213. b = dok_matrix((3,3))
  3214. b[:,0] = 0
  3215. assert_(len(b.keys()) == 0, "Unexpected entries in keys")
  3216. TestDOK.init_class()
  3217. class TestLIL(sparse_test_class(minmax=False)):
  3218. spmatrix = lil_matrix
  3219. math_dtypes = [np.int_, np.float_, np.complex_]
  3220. def test_dot(self):
  3221. A = matrix(zeros((10,10)))
  3222. A[0,3] = 10
  3223. A[5,6] = 20
  3224. B = lil_matrix((10,10))
  3225. B[0,3] = 10
  3226. B[5,6] = 20
  3227. assert_array_equal(A * A.T, (B * B.T).todense())
  3228. assert_array_equal(A * A.H, (B * B.H).todense())
  3229. def test_scalar_mul(self):
  3230. x = lil_matrix((3,3))
  3231. x[0,0] = 2
  3232. x = x*2
  3233. assert_equal(x[0,0],4)
  3234. x = x*0
  3235. assert_equal(x[0,0],0)
  3236. def test_inplace_ops(self):
  3237. A = lil_matrix([[0,2,3],[4,0,6]])
  3238. B = lil_matrix([[0,1,0],[0,2,3]])
  3239. data = {'add': (B,A + B),
  3240. 'sub': (B,A - B),
  3241. 'mul': (3,A * 3)}
  3242. for op,(other,expected) in data.items():
  3243. result = A.copy()
  3244. getattr(result, '__i%s__' % op)(other)
  3245. assert_array_equal(result.todense(), expected.todense())
  3246. # Ticket 1604.
  3247. A = lil_matrix((1,3), dtype=np.dtype('float64'))
  3248. B = array([0.1,0.1,0.1])
  3249. A[0,:] += B
  3250. assert_array_equal(A[0,:].toarray().squeeze(), B)
  3251. def test_lil_iteration(self):
  3252. row_data = [[1,2,3],[4,5,6]]
  3253. B = lil_matrix(array(row_data))
  3254. for r,row in enumerate(B):
  3255. assert_array_equal(row.todense(),array(row_data[r],ndmin=2))
  3256. def test_lil_from_csr(self):
  3257. # Tests whether a lil_matrix can be constructed from a
  3258. # csr_matrix.
  3259. B = lil_matrix((10,10))
  3260. B[0,3] = 10
  3261. B[5,6] = 20
  3262. B[8,3] = 30
  3263. B[3,8] = 40
  3264. B[8,9] = 50
  3265. C = B.tocsr()
  3266. D = lil_matrix(C)
  3267. assert_array_equal(C.A, D.A)
  3268. def test_fancy_indexing_lil(self):
  3269. M = asmatrix(arange(25).reshape(5,5))
  3270. A = lil_matrix(M)
  3271. assert_equal(A[array([1,2,3]),2:3].todense(), M[array([1,2,3]),2:3])
  3272. def test_point_wise_multiply(self):
  3273. l = lil_matrix((4,3))
  3274. l[0,0] = 1
  3275. l[1,1] = 2
  3276. l[2,2] = 3
  3277. l[3,1] = 4
  3278. m = lil_matrix((4,3))
  3279. m[0,0] = 1
  3280. m[0,1] = 2
  3281. m[2,2] = 3
  3282. m[3,1] = 4
  3283. m[3,2] = 4
  3284. assert_array_equal(l.multiply(m).todense(),
  3285. m.multiply(l).todense())
  3286. assert_array_equal(l.multiply(m).todense(),
  3287. [[1,0,0],
  3288. [0,0,0],
  3289. [0,0,9],
  3290. [0,16,0]])
  3291. def test_lil_multiply_removal(self):
  3292. # Ticket #1427.
  3293. a = lil_matrix(np.ones((3,3)))
  3294. a *= 2.
  3295. a[0, :] = 0
  3296. TestLIL.init_class()
  3297. class TestCOO(sparse_test_class(getset=False,
  3298. slicing=False, slicing_assign=False,
  3299. fancy_indexing=False, fancy_assign=False)):
  3300. spmatrix = coo_matrix
  3301. math_dtypes = [np.int_, np.float_, np.complex_]
  3302. def test_constructor1(self):
  3303. # unsorted triplet format
  3304. row = array([2, 3, 1, 3, 0, 1, 3, 0, 2, 1, 2])
  3305. col = array([0, 1, 0, 0, 1, 1, 2, 2, 2, 2, 1])
  3306. data = array([6., 10., 3., 9., 1., 4.,
  3307. 11., 2., 8., 5., 7.])
  3308. coo = coo_matrix((data,(row,col)),(4,3))
  3309. assert_array_equal(arange(12).reshape(4,3),coo.todense())
  3310. def test_constructor2(self):
  3311. # unsorted triplet format with duplicates (which are summed)
  3312. row = array([0,1,2,2,2,2,0,0,2,2])
  3313. col = array([0,2,0,2,1,1,1,0,0,2])
  3314. data = array([2,9,-4,5,7,0,-1,2,1,-5])
  3315. coo = coo_matrix((data,(row,col)),(3,3))
  3316. mat = matrix([[4,-1,0],[0,0,9],[-3,7,0]])
  3317. assert_array_equal(mat,coo.todense())
  3318. def test_constructor3(self):
  3319. # empty matrix
  3320. coo = coo_matrix((4,3))
  3321. assert_array_equal(coo.shape,(4,3))
  3322. assert_array_equal(coo.row,[])
  3323. assert_array_equal(coo.col,[])
  3324. assert_array_equal(coo.data,[])
  3325. assert_array_equal(coo.todense(),zeros((4,3)))
  3326. def test_constructor4(self):
  3327. # from dense matrix
  3328. mat = array([[0,1,0,0],
  3329. [7,0,3,0],
  3330. [0,4,0,0]])
  3331. coo = coo_matrix(mat)
  3332. assert_array_equal(coo.todense(),mat)
  3333. # upgrade rank 1 arrays to row matrix
  3334. mat = array([0,1,0,0])
  3335. coo = coo_matrix(mat)
  3336. assert_array_equal(coo.todense(),mat.reshape(1,-1))
  3337. @pytest.mark.xfail(run=False, reason='COO does not have a __getitem__')
  3338. def test_iterator(self):
  3339. pass
  3340. def test_todia_all_zeros(self):
  3341. zeros = [[0, 0]]
  3342. dia = coo_matrix(zeros).todia()
  3343. assert_array_equal(dia.A, zeros)
  3344. def test_sum_duplicates(self):
  3345. coo = coo_matrix((4,3))
  3346. coo.sum_duplicates()
  3347. coo = coo_matrix(([1,2], ([1,0], [1,0])))
  3348. coo.sum_duplicates()
  3349. assert_array_equal(coo.A, [[2,0],[0,1]])
  3350. coo = coo_matrix(([1,2], ([1,1], [1,1])))
  3351. coo.sum_duplicates()
  3352. assert_array_equal(coo.A, [[0,0],[0,3]])
  3353. assert_array_equal(coo.row, [1])
  3354. assert_array_equal(coo.col, [1])
  3355. assert_array_equal(coo.data, [3])
  3356. def test_todok_duplicates(self):
  3357. coo = coo_matrix(([1,1,1,1], ([0,2,2,0], [0,1,1,0])))
  3358. dok = coo.todok()
  3359. assert_array_equal(dok.A, coo.A)
  3360. def test_eliminate_zeros(self):
  3361. data = array([1, 0, 0, 0, 2, 0, 3, 0])
  3362. row = array([0, 0, 0, 1, 1, 1, 1, 1])
  3363. col = array([1, 2, 3, 4, 5, 6, 7, 8])
  3364. asp = coo_matrix((data, (row, col)), shape=(2,10))
  3365. bsp = asp.copy()
  3366. asp.eliminate_zeros()
  3367. assert_((asp.data != 0).all())
  3368. assert_array_equal(asp.A, bsp.A)
  3369. def test_reshape_copy(self):
  3370. arr = [[0, 10, 0, 0], [0, 0, 0, 0], [0, 20, 30, 40]]
  3371. new_shape = (2, 6)
  3372. x = coo_matrix(arr)
  3373. y = x.reshape(new_shape)
  3374. assert_(y.data is x.data)
  3375. y = x.reshape(new_shape, copy=False)
  3376. assert_(y.data is x.data)
  3377. y = x.reshape(new_shape, copy=True)
  3378. assert_(not np.may_share_memory(y.data, x.data))
  3379. def test_large_dimensions_reshape(self):
  3380. # Test that reshape is immune to integer overflow when number of elements
  3381. # exceeds 2^31-1
  3382. mat1 = coo_matrix(([1], ([3000000], [1000])), (3000001, 1001))
  3383. mat2 = coo_matrix(([1], ([1000], [3000000])), (1001, 3000001))
  3384. # assert_array_equal is slow for big matrices because it expects dense
  3385. # Using __ne__ and nnz instead
  3386. assert_((mat1.reshape((1001, 3000001), order='C') != mat2).nnz == 0)
  3387. assert_((mat2.reshape((3000001, 1001), order='F') != mat1).nnz == 0)
  3388. TestCOO.init_class()
  3389. class TestDIA(sparse_test_class(getset=False, slicing=False, slicing_assign=False,
  3390. fancy_indexing=False, fancy_assign=False,
  3391. minmax=False, nnz_axis=False)):
  3392. spmatrix = dia_matrix
  3393. math_dtypes = [np.int_, np.float_, np.complex_]
  3394. def test_constructor1(self):
  3395. D = matrix([[1, 0, 3, 0],
  3396. [1, 2, 0, 4],
  3397. [0, 2, 3, 0],
  3398. [0, 0, 3, 4]])
  3399. data = np.array([[1,2,3,4]]).repeat(3,axis=0)
  3400. offsets = np.array([0,-1,2])
  3401. assert_equal(dia_matrix((data,offsets), shape=(4,4)).todense(), D)
  3402. @pytest.mark.xfail(run=False, reason='DIA does not have a __getitem__')
  3403. def test_iterator(self):
  3404. pass
  3405. @with_64bit_maxval_limit(3)
  3406. def test_setdiag_dtype(self):
  3407. m = dia_matrix(np.eye(3))
  3408. assert_equal(m.offsets.dtype, np.int32)
  3409. m.setdiag((3,), k=2)
  3410. assert_equal(m.offsets.dtype, np.int32)
  3411. m = dia_matrix(np.eye(4))
  3412. assert_equal(m.offsets.dtype, np.int64)
  3413. m.setdiag((3,), k=3)
  3414. assert_equal(m.offsets.dtype, np.int64)
  3415. @pytest.mark.skip(reason='DIA stores extra zeros')
  3416. def test_getnnz_axis(self):
  3417. pass
  3418. TestDIA.init_class()
  3419. class TestBSR(sparse_test_class(getset=False,
  3420. slicing=False, slicing_assign=False,
  3421. fancy_indexing=False, fancy_assign=False,
  3422. nnz_axis=False)):
  3423. spmatrix = bsr_matrix
  3424. math_dtypes = [np.int_, np.float_, np.complex_]
  3425. def test_constructor1(self):
  3426. # check native BSR format constructor
  3427. indptr = array([0,2,2,4])
  3428. indices = array([0,2,2,3])
  3429. data = zeros((4,2,3))
  3430. data[0] = array([[0, 1, 2],
  3431. [3, 0, 5]])
  3432. data[1] = array([[0, 2, 4],
  3433. [6, 0, 10]])
  3434. data[2] = array([[0, 4, 8],
  3435. [12, 0, 20]])
  3436. data[3] = array([[0, 5, 10],
  3437. [15, 0, 25]])
  3438. A = kron([[1,0,2,0],[0,0,0,0],[0,0,4,5]], [[0,1,2],[3,0,5]])
  3439. Asp = bsr_matrix((data,indices,indptr),shape=(6,12))
  3440. assert_equal(Asp.todense(),A)
  3441. # infer shape from arrays
  3442. Asp = bsr_matrix((data,indices,indptr))
  3443. assert_equal(Asp.todense(),A)
  3444. def test_constructor2(self):
  3445. # construct from dense
  3446. # test zero mats
  3447. for shape in [(1,1), (5,1), (1,10), (10,4), (3,7), (2,1)]:
  3448. A = zeros(shape)
  3449. assert_equal(bsr_matrix(A).todense(),A)
  3450. A = zeros((4,6))
  3451. assert_equal(bsr_matrix(A,blocksize=(2,2)).todense(),A)
  3452. assert_equal(bsr_matrix(A,blocksize=(2,3)).todense(),A)
  3453. A = kron([[1,0,2,0],[0,0,0,0],[0,0,4,5]], [[0,1,2],[3,0,5]])
  3454. assert_equal(bsr_matrix(A).todense(),A)
  3455. assert_equal(bsr_matrix(A,shape=(6,12)).todense(),A)
  3456. assert_equal(bsr_matrix(A,blocksize=(1,1)).todense(),A)
  3457. assert_equal(bsr_matrix(A,blocksize=(2,3)).todense(),A)
  3458. assert_equal(bsr_matrix(A,blocksize=(2,6)).todense(),A)
  3459. assert_equal(bsr_matrix(A,blocksize=(2,12)).todense(),A)
  3460. assert_equal(bsr_matrix(A,blocksize=(3,12)).todense(),A)
  3461. assert_equal(bsr_matrix(A,blocksize=(6,12)).todense(),A)
  3462. A = kron([[1,0,2,0],[0,1,0,0],[0,0,0,0]], [[0,1,2],[3,0,5]])
  3463. assert_equal(bsr_matrix(A,blocksize=(2,3)).todense(),A)
  3464. def test_constructor3(self):
  3465. # construct from coo-like (data,(row,col)) format
  3466. arg = ([1,2,3], ([0,1,1], [0,0,1]))
  3467. A = array([[1,0],[2,3]])
  3468. assert_equal(bsr_matrix(arg, blocksize=(2,2)).todense(), A)
  3469. def test_constructor4(self):
  3470. # regression test for gh-6292: bsr_matrix((data, indices, indptr)) was
  3471. # trying to compare an int to a None
  3472. n = 8
  3473. data = np.ones((n, n, 1), dtype=np.int8)
  3474. indptr = np.array([0, n], dtype=np.int32)
  3475. indices = np.arange(n, dtype=np.int32)
  3476. bsr_matrix((data, indices, indptr), blocksize=(n, 1), copy=False)
  3477. def test_bsr_tocsr(self):
  3478. # check native conversion from BSR to CSR
  3479. indptr = array([0, 2, 2, 4])
  3480. indices = array([0, 2, 2, 3])
  3481. data = zeros((4, 2, 3))
  3482. data[0] = array([[0, 1, 2],
  3483. [3, 0, 5]])
  3484. data[1] = array([[0, 2, 4],
  3485. [6, 0, 10]])
  3486. data[2] = array([[0, 4, 8],
  3487. [12, 0, 20]])
  3488. data[3] = array([[0, 5, 10],
  3489. [15, 0, 25]])
  3490. A = kron([[1, 0, 2, 0], [0, 0, 0, 0], [0, 0, 4, 5]],
  3491. [[0, 1, 2], [3, 0, 5]])
  3492. Absr = bsr_matrix((data, indices, indptr), shape=(6, 12))
  3493. Acsr = Absr.tocsr()
  3494. Acsr_via_coo = Absr.tocoo().tocsr()
  3495. assert_equal(Acsr.todense(), A)
  3496. assert_equal(Acsr.todense(), Acsr_via_coo.todense())
  3497. def test_eliminate_zeros(self):
  3498. data = kron([1, 0, 0, 0, 2, 0, 3, 0], [[1,1],[1,1]]).T
  3499. data = data.reshape(-1,2,2)
  3500. indices = array([1, 2, 3, 4, 5, 6, 7, 8])
  3501. indptr = array([0, 3, 8])
  3502. asp = bsr_matrix((data, indices, indptr), shape=(4,20))
  3503. bsp = asp.copy()
  3504. asp.eliminate_zeros()
  3505. assert_array_equal(asp.nnz, 3*4)
  3506. assert_array_equal(asp.todense(),bsp.todense())
  3507. def test_bsr_matvec(self):
  3508. A = bsr_matrix(arange(2*3*4*5).reshape(2*4,3*5), blocksize=(4,5))
  3509. x = arange(A.shape[1]).reshape(-1,1)
  3510. assert_equal(A*x, A.todense()*x)
  3511. def test_bsr_matvecs(self):
  3512. A = bsr_matrix(arange(2*3*4*5).reshape(2*4,3*5), blocksize=(4,5))
  3513. x = arange(A.shape[1]*6).reshape(-1,6)
  3514. assert_equal(A*x, A.todense()*x)
  3515. @pytest.mark.xfail(run=False, reason='BSR does not have a __getitem__')
  3516. def test_iterator(self):
  3517. pass
  3518. @pytest.mark.xfail(run=False, reason='BSR does not have a __setitem__')
  3519. def test_setdiag(self):
  3520. pass
  3521. def test_resize_blocked(self):
  3522. # test resize() with non-(1,1) blocksize
  3523. D = np.array([[1, 0, 3, 4],
  3524. [2, 0, 0, 0],
  3525. [3, 0, 0, 0]])
  3526. S = self.spmatrix(D, blocksize=(1, 2))
  3527. assert_(S.resize((3, 2)) is None)
  3528. assert_array_equal(S.A, [[1, 0],
  3529. [2, 0],
  3530. [3, 0]])
  3531. S.resize((2, 2))
  3532. assert_array_equal(S.A, [[1, 0],
  3533. [2, 0]])
  3534. S.resize((3, 2))
  3535. assert_array_equal(S.A, [[1, 0],
  3536. [2, 0],
  3537. [0, 0]])
  3538. S.resize((3, 4))
  3539. assert_array_equal(S.A, [[1, 0, 0, 0],
  3540. [2, 0, 0, 0],
  3541. [0, 0, 0, 0]])
  3542. assert_raises(ValueError, S.resize, (2, 3))
  3543. @pytest.mark.xfail(run=False, reason='BSR does not have a __setitem__')
  3544. def test_setdiag_comprehensive(self):
  3545. pass
  3546. def test_scalar_idx_dtype(self):
  3547. # Check that index dtype takes into account all parameters
  3548. # passed to sparsetools, including the scalar ones
  3549. indptr = np.zeros(2, dtype=np.int32)
  3550. indices = np.zeros(0, dtype=np.int32)
  3551. vals = np.zeros((0, 1, 1))
  3552. a = bsr_matrix((vals, indices, indptr), shape=(1, 2**31-1))
  3553. b = bsr_matrix((vals, indices, indptr), shape=(1, 2**31))
  3554. c = bsr_matrix((1, 2**31-1))
  3555. d = bsr_matrix((1, 2**31))
  3556. assert_equal(a.indptr.dtype, np.int32)
  3557. assert_equal(b.indptr.dtype, np.int64)
  3558. assert_equal(c.indptr.dtype, np.int32)
  3559. assert_equal(d.indptr.dtype, np.int64)
  3560. try:
  3561. vals2 = np.zeros((0, 1, 2**31-1))
  3562. vals3 = np.zeros((0, 1, 2**31))
  3563. e = bsr_matrix((vals2, indices, indptr), shape=(1, 2**31-1))
  3564. f = bsr_matrix((vals3, indices, indptr), shape=(1, 2**31))
  3565. assert_equal(e.indptr.dtype, np.int32)
  3566. assert_equal(f.indptr.dtype, np.int64)
  3567. except (MemoryError, ValueError):
  3568. # May fail on 32-bit Python
  3569. e = 0
  3570. f = 0
  3571. # These shouldn't fail
  3572. for x in [a, b, c, d, e, f]:
  3573. x + x
  3574. TestBSR.init_class()
  3575. #------------------------------------------------------------------------------
  3576. # Tests for non-canonical representations (with duplicates, unsorted indices)
  3577. #------------------------------------------------------------------------------
  3578. def _same_sum_duplicate(data, *inds, **kwargs):
  3579. """Duplicates entries to produce the same matrix"""
  3580. indptr = kwargs.pop('indptr', None)
  3581. if np.issubdtype(data.dtype, np.bool_) or \
  3582. np.issubdtype(data.dtype, np.unsignedinteger):
  3583. if indptr is None:
  3584. return (data,) + inds
  3585. else:
  3586. return (data,) + inds + (indptr,)
  3587. zeros_pos = (data == 0).nonzero()
  3588. # duplicate data
  3589. data = data.repeat(2, axis=0)
  3590. data[::2] -= 1
  3591. data[1::2] = 1
  3592. # don't spoil all explicit zeros
  3593. if zeros_pos[0].size > 0:
  3594. pos = tuple(p[0] for p in zeros_pos)
  3595. pos1 = (2*pos[0],) + pos[1:]
  3596. pos2 = (2*pos[0]+1,) + pos[1:]
  3597. data[pos1] = 0
  3598. data[pos2] = 0
  3599. inds = tuple(indices.repeat(2) for indices in inds)
  3600. if indptr is None:
  3601. return (data,) + inds
  3602. else:
  3603. return (data,) + inds + (indptr * 2,)
  3604. class _NonCanonicalMixin(object):
  3605. def spmatrix(self, D, sorted_indices=False, **kwargs):
  3606. """Replace D with a non-canonical equivalent: containing
  3607. duplicate elements and explicit zeros"""
  3608. construct = super(_NonCanonicalMixin, self).spmatrix
  3609. M = construct(D, **kwargs)
  3610. zero_pos = (M.A == 0).nonzero()
  3611. has_zeros = (zero_pos[0].size > 0)
  3612. if has_zeros:
  3613. k = zero_pos[0].size//2
  3614. with suppress_warnings() as sup:
  3615. sup.filter(SparseEfficiencyWarning,
  3616. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  3617. M = self._insert_explicit_zero(M, zero_pos[0][k], zero_pos[1][k])
  3618. arg1 = self._arg1_for_noncanonical(M, sorted_indices)
  3619. if 'shape' not in kwargs:
  3620. kwargs['shape'] = M.shape
  3621. NC = construct(arg1, **kwargs)
  3622. # check that result is valid
  3623. if NC.dtype in [np.float32, np.complex64]:
  3624. # For single-precision floats, the differences between M and NC
  3625. # that are introduced by the extra operations involved in the
  3626. # construction of NC necessitate a more lenient tolerance level
  3627. # than the default.
  3628. rtol = 1e-05
  3629. else:
  3630. rtol = 1e-07
  3631. assert_allclose(NC.A, M.A, rtol=rtol)
  3632. # check that at least one explicit zero
  3633. if has_zeros:
  3634. assert_((NC.data == 0).any())
  3635. # TODO check that NC has duplicates (which are not explicit zeros)
  3636. return NC
  3637. @pytest.mark.skip(reason='bool(matrix) counts explicit zeros')
  3638. def test_bool(self):
  3639. pass
  3640. @pytest.mark.skip(reason='getnnz-axis counts explicit zeros')
  3641. def test_getnnz_axis(self):
  3642. pass
  3643. @pytest.mark.skip(reason='nnz counts explicit zeros')
  3644. def test_empty(self):
  3645. pass
  3646. class _NonCanonicalCompressedMixin(_NonCanonicalMixin):
  3647. def _arg1_for_noncanonical(self, M, sorted_indices=False):
  3648. """Return non-canonical constructor arg1 equivalent to M"""
  3649. data, indices, indptr = _same_sum_duplicate(M.data, M.indices,
  3650. indptr=M.indptr)
  3651. if not sorted_indices:
  3652. for start, stop in izip(indptr, indptr[1:]):
  3653. indices[start:stop] = indices[start:stop][::-1].copy()
  3654. data[start:stop] = data[start:stop][::-1].copy()
  3655. return data, indices, indptr
  3656. def _insert_explicit_zero(self, M, i, j):
  3657. M[i,j] = 0
  3658. return M
  3659. class _NonCanonicalCSMixin(_NonCanonicalCompressedMixin):
  3660. def test_getelement(self):
  3661. def check(dtype, sorted_indices):
  3662. D = array([[1,0,0],
  3663. [4,3,0],
  3664. [0,2,0],
  3665. [0,0,0]], dtype=dtype)
  3666. A = self.spmatrix(D, sorted_indices=sorted_indices)
  3667. M,N = D.shape
  3668. for i in range(-M, M):
  3669. for j in range(-N, N):
  3670. assert_equal(A[i,j], D[i,j])
  3671. for ij in [(0,3),(-1,3),(4,0),(4,3),(4,-1), (1, 2, 3)]:
  3672. assert_raises((IndexError, TypeError), A.__getitem__, ij)
  3673. for dtype in supported_dtypes:
  3674. for sorted_indices in [False, True]:
  3675. check(np.dtype(dtype), sorted_indices)
  3676. def test_setitem_sparse(self):
  3677. D = np.eye(3)
  3678. A = self.spmatrix(D)
  3679. B = self.spmatrix([[1,2,3]])
  3680. D[1,:] = B.toarray()
  3681. with suppress_warnings() as sup:
  3682. sup.filter(SparseEfficiencyWarning,
  3683. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  3684. A[1,:] = B
  3685. assert_array_equal(A.toarray(), D)
  3686. D[:,2] = B.toarray().ravel()
  3687. with suppress_warnings() as sup:
  3688. sup.filter(SparseEfficiencyWarning,
  3689. "Changing the sparsity structure of a cs[cr]_matrix is expensive")
  3690. A[:,2] = B.T
  3691. assert_array_equal(A.toarray(), D)
  3692. @pytest.mark.xfail(run=False, reason='inverse broken with non-canonical matrix')
  3693. def test_inv(self):
  3694. pass
  3695. @pytest.mark.xfail(run=False, reason='solve broken with non-canonical matrix')
  3696. def test_solve(self):
  3697. pass
  3698. class TestCSRNonCanonical(_NonCanonicalCSMixin, TestCSR):
  3699. pass
  3700. class TestCSCNonCanonical(_NonCanonicalCSMixin, TestCSC):
  3701. pass
  3702. class TestBSRNonCanonical(_NonCanonicalCompressedMixin, TestBSR):
  3703. def _insert_explicit_zero(self, M, i, j):
  3704. x = M.tocsr()
  3705. x[i,j] = 0
  3706. return x.tobsr(blocksize=M.blocksize)
  3707. @pytest.mark.xfail(run=False, reason='diagonal broken with non-canonical BSR')
  3708. def test_diagonal(self):
  3709. pass
  3710. @pytest.mark.xfail(run=False, reason='expm broken with non-canonical BSR')
  3711. def test_expm(self):
  3712. pass
  3713. class TestCOONonCanonical(_NonCanonicalMixin, TestCOO):
  3714. def _arg1_for_noncanonical(self, M, sorted_indices=None):
  3715. """Return non-canonical constructor arg1 equivalent to M"""
  3716. data, row, col = _same_sum_duplicate(M.data, M.row, M.col)
  3717. return data, (row, col)
  3718. def _insert_explicit_zero(self, M, i, j):
  3719. M.data = np.r_[M.data.dtype.type(0), M.data]
  3720. M.row = np.r_[M.row.dtype.type(i), M.row]
  3721. M.col = np.r_[M.col.dtype.type(j), M.col]
  3722. return M
  3723. def test_setdiag_noncanonical(self):
  3724. m = self.spmatrix(np.eye(3))
  3725. m.sum_duplicates()
  3726. m.setdiag([3, 2], k=1)
  3727. m.sum_duplicates()
  3728. assert_(np.all(np.diff(m.col) >= 0))
  3729. def cases_64bit():
  3730. TEST_CLASSES = [TestBSR, TestCOO, TestCSC, TestCSR, TestDIA,
  3731. # lil/dok->other conversion operations have get_index_dtype
  3732. TestDOK, TestLIL
  3733. ]
  3734. # The following features are missing, so skip the tests:
  3735. SKIP_TESTS = {
  3736. 'test_expm': 'expm for 64-bit indices not available',
  3737. 'test_inv': 'linsolve for 64-bit indices not available',
  3738. 'test_solve': 'linsolve for 64-bit indices not available',
  3739. 'test_scalar_idx_dtype': 'test implemented in base class',
  3740. 'test_large_dimensions_reshape': 'test actually requires 64-bit to work',
  3741. }
  3742. for cls in TEST_CLASSES:
  3743. for method_name in sorted(dir(cls)):
  3744. method = getattr(cls, method_name)
  3745. if (method_name.startswith('test_') and
  3746. not getattr(method, 'slow', False)):
  3747. marks = []
  3748. msg = SKIP_TESTS.get(method_name)
  3749. if bool(msg):
  3750. marks += [pytest.mark.skip(reason=msg)]
  3751. if LooseVersion(pytest.__version__) >= LooseVersion("3.6.0"):
  3752. markers = getattr(method, 'pytestmark', [])
  3753. for mark in markers:
  3754. if mark.name in ('skipif', 'skip', 'xfail', 'xslow'):
  3755. marks.append(mark)
  3756. else:
  3757. for mname in ['skipif', 'skip', 'xfail', 'xslow']:
  3758. if hasattr(method, mname):
  3759. marks += [getattr(method, mname)]
  3760. yield pytest.param(cls, method_name, marks=marks)
  3761. class Test64Bit(object):
  3762. MAT_CLASSES = [bsr_matrix, coo_matrix, csc_matrix, csr_matrix, dia_matrix]
  3763. def _create_some_matrix(self, mat_cls, m, n):
  3764. return mat_cls(np.random.rand(m, n))
  3765. def _compare_index_dtype(self, m, dtype):
  3766. dtype = np.dtype(dtype)
  3767. if isinstance(m, csc_matrix) or isinstance(m, csr_matrix) \
  3768. or isinstance(m, bsr_matrix):
  3769. return (m.indices.dtype == dtype) and (m.indptr.dtype == dtype)
  3770. elif isinstance(m, coo_matrix):
  3771. return (m.row.dtype == dtype) and (m.col.dtype == dtype)
  3772. elif isinstance(m, dia_matrix):
  3773. return (m.offsets.dtype == dtype)
  3774. else:
  3775. raise ValueError("matrix %r has no integer indices" % (m,))
  3776. def test_decorator_maxval_limit(self):
  3777. # Test that the with_64bit_maxval_limit decorator works
  3778. @with_64bit_maxval_limit(maxval_limit=10)
  3779. def check(mat_cls):
  3780. m = mat_cls(np.random.rand(10, 1))
  3781. assert_(self._compare_index_dtype(m, np.int32))
  3782. m = mat_cls(np.random.rand(11, 1))
  3783. assert_(self._compare_index_dtype(m, np.int64))
  3784. for mat_cls in self.MAT_CLASSES:
  3785. check(mat_cls)
  3786. def test_decorator_maxval_random(self):
  3787. # Test that the with_64bit_maxval_limit decorator works (2)
  3788. @with_64bit_maxval_limit(random=True)
  3789. def check(mat_cls):
  3790. seen_32 = False
  3791. seen_64 = False
  3792. for k in range(100):
  3793. m = self._create_some_matrix(mat_cls, 9, 9)
  3794. seen_32 = seen_32 or self._compare_index_dtype(m, np.int32)
  3795. seen_64 = seen_64 or self._compare_index_dtype(m, np.int64)
  3796. if seen_32 and seen_64:
  3797. break
  3798. else:
  3799. raise AssertionError("both 32 and 64 bit indices not seen")
  3800. for mat_cls in self.MAT_CLASSES:
  3801. check(mat_cls)
  3802. def _check_resiliency(self, cls, method_name, **kw):
  3803. # Resiliency test, to check that sparse matrices deal reasonably
  3804. # with varying index data types.
  3805. @with_64bit_maxval_limit(**kw)
  3806. def check(cls, method_name):
  3807. instance = cls()
  3808. if hasattr(instance, 'setup_method'):
  3809. instance.setup_method()
  3810. try:
  3811. getattr(instance, method_name)()
  3812. finally:
  3813. if hasattr(instance, 'teardown_method'):
  3814. instance.teardown_method()
  3815. check(cls, method_name)
  3816. @pytest.mark.parametrize('cls,method_name', cases_64bit())
  3817. def test_resiliency_limit_10(self, cls, method_name):
  3818. self._check_resiliency(cls, method_name, maxval_limit=10)
  3819. @pytest.mark.parametrize('cls,method_name', cases_64bit())
  3820. def test_resiliency_random(self, cls, method_name):
  3821. # bsr_matrix.eliminate_zeros relies on csr_matrix constructor
  3822. # not making copies of index arrays --- this is not
  3823. # necessarily true when we pick the index data type randomly
  3824. self._check_resiliency(cls, method_name, random=True)
  3825. @pytest.mark.parametrize('cls,method_name', cases_64bit())
  3826. def test_resiliency_all_32(self, cls, method_name):
  3827. self._check_resiliency(cls, method_name, fixed_dtype=np.int32)
  3828. @pytest.mark.parametrize('cls,method_name', cases_64bit())
  3829. def test_resiliency_all_64(self, cls, method_name):
  3830. self._check_resiliency(cls, method_name, fixed_dtype=np.int64)
  3831. @pytest.mark.parametrize('cls,method_name', cases_64bit())
  3832. def test_no_64(self, cls, method_name):
  3833. self._check_resiliency(cls, method_name, assert_32bit=True)
  3834. def test_downcast_intp(self):
  3835. # Check that bincount and ufunc.reduceat intp downcasts are
  3836. # dealt with. The point here is to trigger points in the code
  3837. # that can fail on 32-bit systems when using 64-bit indices,
  3838. # due to use of functions that only work with intp-size
  3839. # indices.
  3840. @with_64bit_maxval_limit(fixed_dtype=np.int64,
  3841. downcast_maxval=1)
  3842. def check_limited():
  3843. # These involve indices larger than `downcast_maxval`
  3844. a = csc_matrix([[1, 2], [3, 4], [5, 6]])
  3845. assert_raises(AssertionError, a.getnnz, axis=1)
  3846. assert_raises(AssertionError, a.sum, axis=0)
  3847. a = csr_matrix([[1, 2, 3], [3, 4, 6]])
  3848. assert_raises(AssertionError, a.getnnz, axis=0)
  3849. a = coo_matrix([[1, 2, 3], [3, 4, 5]])
  3850. assert_raises(AssertionError, a.getnnz, axis=0)
  3851. @with_64bit_maxval_limit(fixed_dtype=np.int64)
  3852. def check_unlimited():
  3853. # These involve indices larger than `downcast_maxval`
  3854. a = csc_matrix([[1, 2], [3, 4], [5, 6]])
  3855. a.getnnz(axis=1)
  3856. a.sum(axis=0)
  3857. a = csr_matrix([[1, 2, 3], [3, 4, 6]])
  3858. a.getnnz(axis=0)
  3859. a = coo_matrix([[1, 2, 3], [3, 4, 5]])
  3860. a.getnnz(axis=0)
  3861. check_limited()
  3862. check_unlimited()