test_base.py 177 KB

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