_interpolative_backend.py 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669
  1. #******************************************************************************
  2. # Copyright (C) 2013 Kenneth L. Ho
  3. #
  4. # Redistribution and use in source and binary forms, with or without
  5. # modification, are permitted provided that the following conditions are met:
  6. #
  7. # Redistributions of source code must retain the above copyright notice, this
  8. # list of conditions and the following disclaimer. Redistributions in binary
  9. # form must reproduce the above copyright notice, this list of conditions and
  10. # the following disclaimer in the documentation and/or other materials
  11. # provided with the distribution.
  12. #
  13. # None of the names of the copyright holders may be used to endorse or
  14. # promote products derived from this software without specific prior written
  15. # permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  21. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. # POSSIBILITY OF SUCH DAMAGE.
  28. #******************************************************************************
  29. """
  30. Direct wrappers for Fortran `id_dist` backend.
  31. """
  32. import scipy.linalg._interpolative as _id
  33. import numpy as np
  34. _RETCODE_ERROR = RuntimeError("nonzero return code")
  35. #------------------------------------------------------------------------------
  36. # id_rand.f
  37. #------------------------------------------------------------------------------
  38. def id_srand(n):
  39. """
  40. Generate standard uniform pseudorandom numbers via a very efficient lagged
  41. Fibonacci method.
  42. :param n:
  43. Number of pseudorandom numbers to generate.
  44. :type n: int
  45. :return:
  46. Pseudorandom numbers.
  47. :rtype: :class:`numpy.ndarray`
  48. """
  49. return _id.id_srand(n)
  50. def id_srandi(t):
  51. """
  52. Initialize seed values for :func:`id_srand` (any appropriately random
  53. numbers will do).
  54. :param t:
  55. Array of 55 seed values.
  56. :type t: :class:`numpy.ndarray`
  57. """
  58. t = np.asfortranarray(t)
  59. _id.id_srandi(t)
  60. def id_srando():
  61. """
  62. Reset seed values to their original values.
  63. """
  64. _id.id_srando()
  65. #------------------------------------------------------------------------------
  66. # idd_frm.f
  67. #------------------------------------------------------------------------------
  68. def idd_frm(n, w, x):
  69. """
  70. Transform real vector via a composition of Rokhlin's random transform,
  71. random subselection, and an FFT.
  72. In contrast to :func:`idd_sfrm`, this routine works best when the length of
  73. the transformed vector is the power-of-two integer output by
  74. :func:`idd_frmi`, or when the length is not specified but instead
  75. determined a posteriori from the output. The returned transformed vector is
  76. randomly permuted.
  77. :param n:
  78. Greatest power-of-two integer satisfying `n <= x.size` as obtained from
  79. :func:`idd_frmi`; `n` is also the length of the output vector.
  80. :type n: int
  81. :param w:
  82. Initialization array constructed by :func:`idd_frmi`.
  83. :type w: :class:`numpy.ndarray`
  84. :param x:
  85. Vector to be transformed.
  86. :type x: :class:`numpy.ndarray`
  87. :return:
  88. Transformed vector.
  89. :rtype: :class:`numpy.ndarray`
  90. """
  91. return _id.idd_frm(n, w, x)
  92. def idd_sfrm(l, n, w, x):
  93. """
  94. Transform real vector via a composition of Rokhlin's random transform,
  95. random subselection, and an FFT.
  96. In contrast to :func:`idd_frm`, this routine works best when the length of
  97. the transformed vector is known a priori.
  98. :param l:
  99. Length of transformed vector, satisfying `l <= n`.
  100. :type l: int
  101. :param n:
  102. Greatest power-of-two integer satisfying `n <= x.size` as obtained from
  103. :func:`idd_sfrmi`.
  104. :type n: int
  105. :param w:
  106. Initialization array constructed by :func:`idd_sfrmi`.
  107. :type w: :class:`numpy.ndarray`
  108. :param x:
  109. Vector to be transformed.
  110. :type x: :class:`numpy.ndarray`
  111. :return:
  112. Transformed vector.
  113. :rtype: :class:`numpy.ndarray`
  114. """
  115. return _id.idd_sfrm(l, n, w, x)
  116. def idd_frmi(m):
  117. """
  118. Initialize data for :func:`idd_frm`.
  119. :param m:
  120. Length of vector to be transformed.
  121. :type m: int
  122. :return:
  123. Greatest power-of-two integer `n` satisfying `n <= m`.
  124. :rtype: int
  125. :return:
  126. Initialization array to be used by :func:`idd_frm`.
  127. :rtype: :class:`numpy.ndarray`
  128. """
  129. return _id.idd_frmi(m)
  130. def idd_sfrmi(l, m):
  131. """
  132. Initialize data for :func:`idd_sfrm`.
  133. :param l:
  134. Length of output transformed vector.
  135. :type l: int
  136. :param m:
  137. Length of the vector to be transformed.
  138. :type m: int
  139. :return:
  140. Greatest power-of-two integer `n` satisfying `n <= m`.
  141. :rtype: int
  142. :return:
  143. Initialization array to be used by :func:`idd_sfrm`.
  144. :rtype: :class:`numpy.ndarray`
  145. """
  146. return _id.idd_sfrmi(l, m)
  147. #------------------------------------------------------------------------------
  148. # idd_id.f
  149. #------------------------------------------------------------------------------
  150. def iddp_id(eps, A):
  151. """
  152. Compute ID of a real matrix to a specified relative precision.
  153. :param eps:
  154. Relative precision.
  155. :type eps: float
  156. :param A:
  157. Matrix.
  158. :type A: :class:`numpy.ndarray`
  159. :return:
  160. Rank of ID.
  161. :rtype: int
  162. :return:
  163. Column index array.
  164. :rtype: :class:`numpy.ndarray`
  165. :return:
  166. Interpolation coefficients.
  167. :rtype: :class:`numpy.ndarray`
  168. """
  169. A = np.asfortranarray(A)
  170. k, idx, rnorms = _id.iddp_id(eps, A)
  171. n = A.shape[1]
  172. proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
  173. return k, idx, proj
  174. def iddr_id(A, k):
  175. """
  176. Compute ID of a real matrix to a specified rank.
  177. :param A:
  178. Matrix.
  179. :type A: :class:`numpy.ndarray`
  180. :param k:
  181. Rank of ID.
  182. :type k: int
  183. :return:
  184. Column index array.
  185. :rtype: :class:`numpy.ndarray`
  186. :return:
  187. Interpolation coefficients.
  188. :rtype: :class:`numpy.ndarray`
  189. """
  190. A = np.asfortranarray(A)
  191. idx, rnorms = _id.iddr_id(A, k)
  192. n = A.shape[1]
  193. proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
  194. return idx, proj
  195. def idd_reconid(B, idx, proj):
  196. """
  197. Reconstruct matrix from real ID.
  198. :param B:
  199. Skeleton matrix.
  200. :type B: :class:`numpy.ndarray`
  201. :param idx:
  202. Column index array.
  203. :type idx: :class:`numpy.ndarray`
  204. :param proj:
  205. Interpolation coefficients.
  206. :type proj: :class:`numpy.ndarray`
  207. :return:
  208. Reconstructed matrix.
  209. :rtype: :class:`numpy.ndarray`
  210. """
  211. B = np.asfortranarray(B)
  212. if proj.size > 0:
  213. return _id.idd_reconid(B, idx, proj)
  214. else:
  215. return B[:, np.argsort(idx)]
  216. def idd_reconint(idx, proj):
  217. """
  218. Reconstruct interpolation matrix from real ID.
  219. :param idx:
  220. Column index array.
  221. :type idx: :class:`numpy.ndarray`
  222. :param proj:
  223. Interpolation coefficients.
  224. :type proj: :class:`numpy.ndarray`
  225. :return:
  226. Interpolation matrix.
  227. :rtype: :class:`numpy.ndarray`
  228. """
  229. return _id.idd_reconint(idx, proj)
  230. def idd_copycols(A, k, idx):
  231. """
  232. Reconstruct skeleton matrix from real ID.
  233. :param A:
  234. Original matrix.
  235. :type A: :class:`numpy.ndarray`
  236. :param k:
  237. Rank of ID.
  238. :type k: int
  239. :param idx:
  240. Column index array.
  241. :type idx: :class:`numpy.ndarray`
  242. :return:
  243. Skeleton matrix.
  244. :rtype: :class:`numpy.ndarray`
  245. """
  246. A = np.asfortranarray(A)
  247. return _id.idd_copycols(A, k, idx)
  248. #------------------------------------------------------------------------------
  249. # idd_id2svd.f
  250. #------------------------------------------------------------------------------
  251. def idd_id2svd(B, idx, proj):
  252. """
  253. Convert real ID to SVD.
  254. :param B:
  255. Skeleton matrix.
  256. :type B: :class:`numpy.ndarray`
  257. :param idx:
  258. Column index array.
  259. :type idx: :class:`numpy.ndarray`
  260. :param proj:
  261. Interpolation coefficients.
  262. :type proj: :class:`numpy.ndarray`
  263. :return:
  264. Left singular vectors.
  265. :rtype: :class:`numpy.ndarray`
  266. :return:
  267. Right singular vectors.
  268. :rtype: :class:`numpy.ndarray`
  269. :return:
  270. Singular values.
  271. :rtype: :class:`numpy.ndarray`
  272. """
  273. B = np.asfortranarray(B)
  274. U, V, S, ier = _id.idd_id2svd(B, idx, proj)
  275. if ier:
  276. raise _RETCODE_ERROR
  277. return U, V, S
  278. #------------------------------------------------------------------------------
  279. # idd_snorm.f
  280. #------------------------------------------------------------------------------
  281. def idd_snorm(m, n, matvect, matvec, its=20):
  282. """
  283. Estimate spectral norm of a real matrix by the randomized power method.
  284. :param m:
  285. Matrix row dimension.
  286. :type m: int
  287. :param n:
  288. Matrix column dimension.
  289. :type n: int
  290. :param matvect:
  291. Function to apply the matrix transpose to a vector, with call signature
  292. `y = matvect(x)`, where `x` and `y` are the input and output vectors,
  293. respectively.
  294. :type matvect: function
  295. :param matvec:
  296. Function to apply the matrix to a vector, with call signature
  297. `y = matvec(x)`, where `x` and `y` are the input and output vectors,
  298. respectively.
  299. :type matvec: function
  300. :param its:
  301. Number of power method iterations.
  302. :type its: int
  303. :return:
  304. Spectral norm estimate.
  305. :rtype: float
  306. """
  307. snorm, v = _id.idd_snorm(m, n, matvect, matvec, its)
  308. return snorm
  309. def idd_diffsnorm(m, n, matvect, matvect2, matvec, matvec2, its=20):
  310. """
  311. Estimate spectral norm of the difference of two real matrices by the
  312. randomized power method.
  313. :param m:
  314. Matrix row dimension.
  315. :type m: int
  316. :param n:
  317. Matrix column dimension.
  318. :type n: int
  319. :param matvect:
  320. Function to apply the transpose of the first matrix to a vector, with
  321. call signature `y = matvect(x)`, where `x` and `y` are the input and
  322. output vectors, respectively.
  323. :type matvect: function
  324. :param matvect2:
  325. Function to apply the transpose of the second matrix to a vector, with
  326. call signature `y = matvect2(x)`, where `x` and `y` are the input and
  327. output vectors, respectively.
  328. :type matvect2: function
  329. :param matvec:
  330. Function to apply the first matrix to a vector, with call signature
  331. `y = matvec(x)`, where `x` and `y` are the input and output vectors,
  332. respectively.
  333. :type matvec: function
  334. :param matvec2:
  335. Function to apply the second matrix to a vector, with call signature
  336. `y = matvec2(x)`, where `x` and `y` are the input and output vectors,
  337. respectively.
  338. :type matvec2: function
  339. :param its:
  340. Number of power method iterations.
  341. :type its: int
  342. :return:
  343. Spectral norm estimate of matrix difference.
  344. :rtype: float
  345. """
  346. return _id.idd_diffsnorm(m, n, matvect, matvect2, matvec, matvec2, its)
  347. #------------------------------------------------------------------------------
  348. # idd_svd.f
  349. #------------------------------------------------------------------------------
  350. def iddr_svd(A, k):
  351. """
  352. Compute SVD of a real matrix to a specified rank.
  353. :param A:
  354. Matrix.
  355. :type A: :class:`numpy.ndarray`
  356. :param k:
  357. Rank of SVD.
  358. :type k: int
  359. :return:
  360. Left singular vectors.
  361. :rtype: :class:`numpy.ndarray`
  362. :return:
  363. Right singular vectors.
  364. :rtype: :class:`numpy.ndarray`
  365. :return:
  366. Singular values.
  367. :rtype: :class:`numpy.ndarray`
  368. """
  369. A = np.asfortranarray(A)
  370. U, V, S, ier = _id.iddr_svd(A, k)
  371. if ier:
  372. raise _RETCODE_ERROR
  373. return U, V, S
  374. def iddp_svd(eps, A):
  375. """
  376. Compute SVD of a real matrix to a specified relative precision.
  377. :param eps:
  378. Relative precision.
  379. :type eps: float
  380. :param A:
  381. Matrix.
  382. :type A: :class:`numpy.ndarray`
  383. :return:
  384. Left singular vectors.
  385. :rtype: :class:`numpy.ndarray`
  386. :return:
  387. Right singular vectors.
  388. :rtype: :class:`numpy.ndarray`
  389. :return:
  390. Singular values.
  391. :rtype: :class:`numpy.ndarray`
  392. """
  393. A = np.asfortranarray(A)
  394. m, n = A.shape
  395. k, iU, iV, iS, w, ier = _id.iddp_svd(eps, A)
  396. if ier:
  397. raise _RETCODE_ERROR
  398. U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
  399. V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
  400. S = w[iS-1:iS+k-1]
  401. return U, V, S
  402. #------------------------------------------------------------------------------
  403. # iddp_aid.f
  404. #------------------------------------------------------------------------------
  405. def iddp_aid(eps, A):
  406. """
  407. Compute ID of a real matrix to a specified relative precision using random
  408. sampling.
  409. :param eps:
  410. Relative precision.
  411. :type eps: float
  412. :param A:
  413. Matrix.
  414. :type A: :class:`numpy.ndarray`
  415. :return:
  416. Rank of ID.
  417. :rtype: int
  418. :return:
  419. Column index array.
  420. :rtype: :class:`numpy.ndarray`
  421. :return:
  422. Interpolation coefficients.
  423. :rtype: :class:`numpy.ndarray`
  424. """
  425. A = np.asfortranarray(A)
  426. m, n = A.shape
  427. n2, w = idd_frmi(m)
  428. proj = np.empty(n*(2*n2 + 1) + n2 + 1, order='F')
  429. k, idx, proj = _id.iddp_aid(eps, A, w, proj)
  430. proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
  431. return k, idx, proj
  432. def idd_estrank(eps, A):
  433. """
  434. Estimate rank of a real matrix to a specified relative precision using
  435. random sampling.
  436. The output rank is typically about 8 higher than the actual rank.
  437. :param eps:
  438. Relative precision.
  439. :type eps: float
  440. :param A:
  441. Matrix.
  442. :type A: :class:`numpy.ndarray`
  443. :return:
  444. Rank estimate.
  445. :rtype: int
  446. """
  447. A = np.asfortranarray(A)
  448. m, n = A.shape
  449. n2, w = idd_frmi(m)
  450. ra = np.empty(n*n2 + (n + 1)*(n2 + 1), order='F')
  451. k, ra = _id.idd_estrank(eps, A, w, ra)
  452. return k
  453. #------------------------------------------------------------------------------
  454. # iddp_asvd.f
  455. #------------------------------------------------------------------------------
  456. def iddp_asvd(eps, A):
  457. """
  458. Compute SVD of a real matrix to a specified relative precision using random
  459. sampling.
  460. :param eps:
  461. Relative precision.
  462. :type eps: float
  463. :param A:
  464. Matrix.
  465. :type A: :class:`numpy.ndarray`
  466. :return:
  467. Left singular vectors.
  468. :rtype: :class:`numpy.ndarray`
  469. :return:
  470. Right singular vectors.
  471. :rtype: :class:`numpy.ndarray`
  472. :return:
  473. Singular values.
  474. :rtype: :class:`numpy.ndarray`
  475. """
  476. A = np.asfortranarray(A)
  477. m, n = A.shape
  478. n2, winit = _id.idd_frmi(m)
  479. w = np.empty(
  480. max((min(m, n) + 1)*(3*m + 5*n + 1) + 25*min(m, n)**2,
  481. (2*n + 1)*(n2 + 1)),
  482. order='F')
  483. k, iU, iV, iS, w, ier = _id.iddp_asvd(eps, A, winit, w)
  484. if ier:
  485. raise _RETCODE_ERROR
  486. U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
  487. V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
  488. S = w[iS-1:iS+k-1]
  489. return U, V, S
  490. #------------------------------------------------------------------------------
  491. # iddp_rid.f
  492. #------------------------------------------------------------------------------
  493. def iddp_rid(eps, m, n, matvect):
  494. """
  495. Compute ID of a real matrix to a specified relative precision using random
  496. matrix-vector multiplication.
  497. :param eps:
  498. Relative precision.
  499. :type eps: float
  500. :param m:
  501. Matrix row dimension.
  502. :type m: int
  503. :param n:
  504. Matrix column dimension.
  505. :type n: int
  506. :param matvect:
  507. Function to apply the matrix transpose to a vector, with call signature
  508. `y = matvect(x)`, where `x` and `y` are the input and output vectors,
  509. respectively.
  510. :type matvect: function
  511. :return:
  512. Rank of ID.
  513. :rtype: int
  514. :return:
  515. Column index array.
  516. :rtype: :class:`numpy.ndarray`
  517. :return:
  518. Interpolation coefficients.
  519. :rtype: :class:`numpy.ndarray`
  520. """
  521. proj = np.empty(m + 1 + 2*n*(min(m, n) + 1), order='F')
  522. k, idx, proj, ier = _id.iddp_rid(eps, m, n, matvect, proj)
  523. if ier != 0:
  524. raise _RETCODE_ERROR
  525. proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
  526. return k, idx, proj
  527. def idd_findrank(eps, m, n, matvect):
  528. """
  529. Estimate rank of a real matrix to a specified relative precision using
  530. random matrix-vector multiplication.
  531. :param eps:
  532. Relative precision.
  533. :type eps: float
  534. :param m:
  535. Matrix row dimension.
  536. :type m: int
  537. :param n:
  538. Matrix column dimension.
  539. :type n: int
  540. :param matvect:
  541. Function to apply the matrix transpose to a vector, with call signature
  542. `y = matvect(x)`, where `x` and `y` are the input and output vectors,
  543. respectively.
  544. :type matvect: function
  545. :return:
  546. Rank estimate.
  547. :rtype: int
  548. """
  549. k, ra, ier = _id.idd_findrank(eps, m, n, matvect)
  550. if ier:
  551. raise _RETCODE_ERROR
  552. return k
  553. #------------------------------------------------------------------------------
  554. # iddp_rsvd.f
  555. #------------------------------------------------------------------------------
  556. def iddp_rsvd(eps, m, n, matvect, matvec):
  557. """
  558. Compute SVD of a real matrix to a specified relative precision using random
  559. matrix-vector multiplication.
  560. :param eps:
  561. Relative precision.
  562. :type eps: float
  563. :param m:
  564. Matrix row dimension.
  565. :type m: int
  566. :param n:
  567. Matrix column dimension.
  568. :type n: int
  569. :param matvect:
  570. Function to apply the matrix transpose to a vector, with call signature
  571. `y = matvect(x)`, where `x` and `y` are the input and output vectors,
  572. respectively.
  573. :type matvect: function
  574. :param matvec:
  575. Function to apply the matrix to a vector, with call signature
  576. `y = matvec(x)`, where `x` and `y` are the input and output vectors,
  577. respectively.
  578. :type matvec: function
  579. :return:
  580. Left singular vectors.
  581. :rtype: :class:`numpy.ndarray`
  582. :return:
  583. Right singular vectors.
  584. :rtype: :class:`numpy.ndarray`
  585. :return:
  586. Singular values.
  587. :rtype: :class:`numpy.ndarray`
  588. """
  589. k, iU, iV, iS, w, ier = _id.iddp_rsvd(eps, m, n, matvect, matvec)
  590. if ier:
  591. raise _RETCODE_ERROR
  592. U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
  593. V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
  594. S = w[iS-1:iS+k-1]
  595. return U, V, S
  596. #------------------------------------------------------------------------------
  597. # iddr_aid.f
  598. #------------------------------------------------------------------------------
  599. def iddr_aid(A, k):
  600. """
  601. Compute ID of a real matrix to a specified rank using random sampling.
  602. :param A:
  603. Matrix.
  604. :type A: :class:`numpy.ndarray`
  605. :param k:
  606. Rank of ID.
  607. :type k: int
  608. :return:
  609. Column index array.
  610. :rtype: :class:`numpy.ndarray`
  611. :return:
  612. Interpolation coefficients.
  613. :rtype: :class:`numpy.ndarray`
  614. """
  615. A = np.asfortranarray(A)
  616. m, n = A.shape
  617. w = iddr_aidi(m, n, k)
  618. idx, proj = _id.iddr_aid(A, k, w)
  619. if k == n:
  620. proj = np.empty((k, n-k), dtype='float64', order='F')
  621. else:
  622. proj = proj.reshape((k, n-k), order='F')
  623. return idx, proj
  624. def iddr_aidi(m, n, k):
  625. """
  626. Initialize array for :func:`iddr_aid`.
  627. :param m:
  628. Matrix row dimension.
  629. :type m: int
  630. :param n:
  631. Matrix column dimension.
  632. :type n: int
  633. :param k:
  634. Rank of ID.
  635. :type k: int
  636. :return:
  637. Initialization array to be used by :func:`iddr_aid`.
  638. :rtype: :class:`numpy.ndarray`
  639. """
  640. return _id.iddr_aidi(m, n, k)
  641. #------------------------------------------------------------------------------
  642. # iddr_asvd.f
  643. #------------------------------------------------------------------------------
  644. def iddr_asvd(A, k):
  645. """
  646. Compute SVD of a real matrix to a specified rank using random sampling.
  647. :param A:
  648. Matrix.
  649. :type A: :class:`numpy.ndarray`
  650. :param k:
  651. Rank of SVD.
  652. :type k: int
  653. :return:
  654. Left singular vectors.
  655. :rtype: :class:`numpy.ndarray`
  656. :return:
  657. Right singular vectors.
  658. :rtype: :class:`numpy.ndarray`
  659. :return:
  660. Singular values.
  661. :rtype: :class:`numpy.ndarray`
  662. """
  663. A = np.asfortranarray(A)
  664. m, n = A.shape
  665. w = np.empty((2*k + 28)*m + (6*k + 21)*n + 25*k**2 + 100, order='F')
  666. w_ = iddr_aidi(m, n, k)
  667. w[:w_.size] = w_
  668. U, V, S, ier = _id.iddr_asvd(A, k, w)
  669. if ier != 0:
  670. raise _RETCODE_ERROR
  671. return U, V, S
  672. #------------------------------------------------------------------------------
  673. # iddr_rid.f
  674. #------------------------------------------------------------------------------
  675. def iddr_rid(m, n, matvect, k):
  676. """
  677. Compute ID of a real matrix to a specified rank using random matrix-vector
  678. multiplication.
  679. :param m:
  680. Matrix row dimension.
  681. :type m: int
  682. :param n:
  683. Matrix column dimension.
  684. :type n: int
  685. :param matvect:
  686. Function to apply the matrix transpose to a vector, with call signature
  687. `y = matvect(x)`, where `x` and `y` are the input and output vectors,
  688. respectively.
  689. :type matvect: function
  690. :param k:
  691. Rank of ID.
  692. :type k: int
  693. :return:
  694. Column index array.
  695. :rtype: :class:`numpy.ndarray`
  696. :return:
  697. Interpolation coefficients.
  698. :rtype: :class:`numpy.ndarray`
  699. """
  700. idx, proj = _id.iddr_rid(m, n, matvect, k)
  701. proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
  702. return idx, proj
  703. #------------------------------------------------------------------------------
  704. # iddr_rsvd.f
  705. #------------------------------------------------------------------------------
  706. def iddr_rsvd(m, n, matvect, matvec, k):
  707. """
  708. Compute SVD of a real matrix to a specified rank using random matrix-vector
  709. multiplication.
  710. :param m:
  711. Matrix row dimension.
  712. :type m: int
  713. :param n:
  714. Matrix column dimension.
  715. :type n: int
  716. :param matvect:
  717. Function to apply the matrix transpose to a vector, with call signature
  718. `y = matvect(x)`, where `x` and `y` are the input and output vectors,
  719. respectively.
  720. :type matvect: function
  721. :param matvec:
  722. Function to apply the matrix to a vector, with call signature
  723. `y = matvec(x)`, where `x` and `y` are the input and output vectors,
  724. respectively.
  725. :type matvec: function
  726. :param k:
  727. Rank of SVD.
  728. :type k: int
  729. :return:
  730. Left singular vectors.
  731. :rtype: :class:`numpy.ndarray`
  732. :return:
  733. Right singular vectors.
  734. :rtype: :class:`numpy.ndarray`
  735. :return:
  736. Singular values.
  737. :rtype: :class:`numpy.ndarray`
  738. """
  739. U, V, S, ier = _id.iddr_rsvd(m, n, matvect, matvec, k)
  740. if ier != 0:
  741. raise _RETCODE_ERROR
  742. return U, V, S
  743. #------------------------------------------------------------------------------
  744. # idz_frm.f
  745. #------------------------------------------------------------------------------
  746. def idz_frm(n, w, x):
  747. """
  748. Transform complex vector via a composition of Rokhlin's random transform,
  749. random subselection, and an FFT.
  750. In contrast to :func:`idz_sfrm`, this routine works best when the length of
  751. the transformed vector is the power-of-two integer output by
  752. :func:`idz_frmi`, or when the length is not specified but instead
  753. determined a posteriori from the output. The returned transformed vector is
  754. randomly permuted.
  755. :param n:
  756. Greatest power-of-two integer satisfying `n <= x.size` as obtained from
  757. :func:`idz_frmi`; `n` is also the length of the output vector.
  758. :type n: int
  759. :param w:
  760. Initialization array constructed by :func:`idz_frmi`.
  761. :type w: :class:`numpy.ndarray`
  762. :param x:
  763. Vector to be transformed.
  764. :type x: :class:`numpy.ndarray`
  765. :return:
  766. Transformed vector.
  767. :rtype: :class:`numpy.ndarray`
  768. """
  769. return _id.idz_frm(n, w, x)
  770. def idz_sfrm(l, n, w, x):
  771. """
  772. Transform complex vector via a composition of Rokhlin's random transform,
  773. random subselection, and an FFT.
  774. In contrast to :func:`idz_frm`, this routine works best when the length of
  775. the transformed vector is known a priori.
  776. :param l:
  777. Length of transformed vector, satisfying `l <= n`.
  778. :type l: int
  779. :param n:
  780. Greatest power-of-two integer satisfying `n <= x.size` as obtained from
  781. :func:`idz_sfrmi`.
  782. :type n: int
  783. :param w:
  784. Initialization array constructed by :func:`idd_sfrmi`.
  785. :type w: :class:`numpy.ndarray`
  786. :param x:
  787. Vector to be transformed.
  788. :type x: :class:`numpy.ndarray`
  789. :return:
  790. Transformed vector.
  791. :rtype: :class:`numpy.ndarray`
  792. """
  793. return _id.idz_sfrm(l, n, w, x)
  794. def idz_frmi(m):
  795. """
  796. Initialize data for :func:`idz_frm`.
  797. :param m:
  798. Length of vector to be transformed.
  799. :type m: int
  800. :return:
  801. Greatest power-of-two integer `n` satisfying `n <= m`.
  802. :rtype: int
  803. :return:
  804. Initialization array to be used by :func:`idz_frm`.
  805. :rtype: :class:`numpy.ndarray`
  806. """
  807. return _id.idz_frmi(m)
  808. def idz_sfrmi(l, m):
  809. """
  810. Initialize data for :func:`idz_sfrm`.
  811. :param l:
  812. Length of output transformed vector.
  813. :type l: int
  814. :param m:
  815. Length of the vector to be transformed.
  816. :type m: int
  817. :return:
  818. Greatest power-of-two integer `n` satisfying `n <= m`.
  819. :rtype: int
  820. :return:
  821. Initialization array to be used by :func:`idz_sfrm`.
  822. :rtype: :class:`numpy.ndarray`
  823. """
  824. return _id.idz_sfrmi(l, m)
  825. #------------------------------------------------------------------------------
  826. # idz_id.f
  827. #------------------------------------------------------------------------------
  828. def idzp_id(eps, A):
  829. """
  830. Compute ID of a complex matrix to a specified relative precision.
  831. :param eps:
  832. Relative precision.
  833. :type eps: float
  834. :param A:
  835. Matrix.
  836. :type A: :class:`numpy.ndarray`
  837. :return:
  838. Rank of ID.
  839. :rtype: int
  840. :return:
  841. Column index array.
  842. :rtype: :class:`numpy.ndarray`
  843. :return:
  844. Interpolation coefficients.
  845. :rtype: :class:`numpy.ndarray`
  846. """
  847. A = np.asfortranarray(A)
  848. k, idx, rnorms = _id.idzp_id(eps, A)
  849. n = A.shape[1]
  850. proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
  851. return k, idx, proj
  852. def idzr_id(A, k):
  853. """
  854. Compute ID of a complex matrix to a specified rank.
  855. :param A:
  856. Matrix.
  857. :type A: :class:`numpy.ndarray`
  858. :param k:
  859. Rank of ID.
  860. :type k: int
  861. :return:
  862. Column index array.
  863. :rtype: :class:`numpy.ndarray`
  864. :return:
  865. Interpolation coefficients.
  866. :rtype: :class:`numpy.ndarray`
  867. """
  868. A = np.asfortranarray(A)
  869. idx, rnorms = _id.idzr_id(A, k)
  870. n = A.shape[1]
  871. proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
  872. return idx, proj
  873. def idz_reconid(B, idx, proj):
  874. """
  875. Reconstruct matrix from complex ID.
  876. :param B:
  877. Skeleton matrix.
  878. :type B: :class:`numpy.ndarray`
  879. :param idx:
  880. Column index array.
  881. :type idx: :class:`numpy.ndarray`
  882. :param proj:
  883. Interpolation coefficients.
  884. :type proj: :class:`numpy.ndarray`
  885. :return:
  886. Reconstructed matrix.
  887. :rtype: :class:`numpy.ndarray`
  888. """
  889. B = np.asfortranarray(B)
  890. if proj.size > 0:
  891. return _id.idz_reconid(B, idx, proj)
  892. else:
  893. return B[:, np.argsort(idx)]
  894. def idz_reconint(idx, proj):
  895. """
  896. Reconstruct interpolation matrix from complex ID.
  897. :param idx:
  898. Column index array.
  899. :type idx: :class:`numpy.ndarray`
  900. :param proj:
  901. Interpolation coefficients.
  902. :type proj: :class:`numpy.ndarray`
  903. :return:
  904. Interpolation matrix.
  905. :rtype: :class:`numpy.ndarray`
  906. """
  907. return _id.idz_reconint(idx, proj)
  908. def idz_copycols(A, k, idx):
  909. """
  910. Reconstruct skeleton matrix from complex ID.
  911. :param A:
  912. Original matrix.
  913. :type A: :class:`numpy.ndarray`
  914. :param k:
  915. Rank of ID.
  916. :type k: int
  917. :param idx:
  918. Column index array.
  919. :type idx: :class:`numpy.ndarray`
  920. :return:
  921. Skeleton matrix.
  922. :rtype: :class:`numpy.ndarray`
  923. """
  924. A = np.asfortranarray(A)
  925. return _id.idz_copycols(A, k, idx)
  926. #------------------------------------------------------------------------------
  927. # idz_id2svd.f
  928. #------------------------------------------------------------------------------
  929. def idz_id2svd(B, idx, proj):
  930. """
  931. Convert complex ID to SVD.
  932. :param B:
  933. Skeleton matrix.
  934. :type B: :class:`numpy.ndarray`
  935. :param idx:
  936. Column index array.
  937. :type idx: :class:`numpy.ndarray`
  938. :param proj:
  939. Interpolation coefficients.
  940. :type proj: :class:`numpy.ndarray`
  941. :return:
  942. Left singular vectors.
  943. :rtype: :class:`numpy.ndarray`
  944. :return:
  945. Right singular vectors.
  946. :rtype: :class:`numpy.ndarray`
  947. :return:
  948. Singular values.
  949. :rtype: :class:`numpy.ndarray`
  950. """
  951. B = np.asfortranarray(B)
  952. U, V, S, ier = _id.idz_id2svd(B, idx, proj)
  953. if ier:
  954. raise _RETCODE_ERROR
  955. return U, V, S
  956. #------------------------------------------------------------------------------
  957. # idz_snorm.f
  958. #------------------------------------------------------------------------------
  959. def idz_snorm(m, n, matveca, matvec, its=20):
  960. """
  961. Estimate spectral norm of a complex matrix by the randomized power method.
  962. :param m:
  963. Matrix row dimension.
  964. :type m: int
  965. :param n:
  966. Matrix column dimension.
  967. :type n: int
  968. :param matveca:
  969. Function to apply the matrix adjoint to a vector, with call signature
  970. `y = matveca(x)`, where `x` and `y` are the input and output vectors,
  971. respectively.
  972. :type matveca: function
  973. :param matvec:
  974. Function to apply the matrix to a vector, with call signature
  975. `y = matvec(x)`, where `x` and `y` are the input and output vectors,
  976. respectively.
  977. :type matvec: function
  978. :param its:
  979. Number of power method iterations.
  980. :type its: int
  981. :return:
  982. Spectral norm estimate.
  983. :rtype: float
  984. """
  985. snorm, v = _id.idz_snorm(m, n, matveca, matvec, its)
  986. return snorm
  987. def idz_diffsnorm(m, n, matveca, matveca2, matvec, matvec2, its=20):
  988. """
  989. Estimate spectral norm of the difference of two complex matrices by the
  990. randomized power method.
  991. :param m:
  992. Matrix row dimension.
  993. :type m: int
  994. :param n:
  995. Matrix column dimension.
  996. :type n: int
  997. :param matveca:
  998. Function to apply the adjoint of the first matrix to a vector, with
  999. call signature `y = matveca(x)`, where `x` and `y` are the input and
  1000. output vectors, respectively.
  1001. :type matveca: function
  1002. :param matveca2:
  1003. Function to apply the adjoint of the second matrix to a vector, with
  1004. call signature `y = matveca2(x)`, where `x` and `y` are the input and
  1005. output vectors, respectively.
  1006. :type matveca2: function
  1007. :param matvec:
  1008. Function to apply the first matrix to a vector, with call signature
  1009. `y = matvec(x)`, where `x` and `y` are the input and output vectors,
  1010. respectively.
  1011. :type matvec: function
  1012. :param matvec2:
  1013. Function to apply the second matrix to a vector, with call signature
  1014. `y = matvec2(x)`, where `x` and `y` are the input and output vectors,
  1015. respectively.
  1016. :type matvec2: function
  1017. :param its:
  1018. Number of power method iterations.
  1019. :type its: int
  1020. :return:
  1021. Spectral norm estimate of matrix difference.
  1022. :rtype: float
  1023. """
  1024. return _id.idz_diffsnorm(m, n, matveca, matveca2, matvec, matvec2, its)
  1025. #------------------------------------------------------------------------------
  1026. # idz_svd.f
  1027. #------------------------------------------------------------------------------
  1028. def idzr_svd(A, k):
  1029. """
  1030. Compute SVD of a complex matrix to a specified rank.
  1031. :param A:
  1032. Matrix.
  1033. :type A: :class:`numpy.ndarray`
  1034. :param k:
  1035. Rank of SVD.
  1036. :type k: int
  1037. :return:
  1038. Left singular vectors.
  1039. :rtype: :class:`numpy.ndarray`
  1040. :return:
  1041. Right singular vectors.
  1042. :rtype: :class:`numpy.ndarray`
  1043. :return:
  1044. Singular values.
  1045. :rtype: :class:`numpy.ndarray`
  1046. """
  1047. A = np.asfortranarray(A)
  1048. U, V, S, ier = _id.idzr_svd(A, k)
  1049. if ier:
  1050. raise _RETCODE_ERROR
  1051. return U, V, S
  1052. def idzp_svd(eps, A):
  1053. """
  1054. Compute SVD of a complex matrix to a specified relative precision.
  1055. :param eps:
  1056. Relative precision.
  1057. :type eps: float
  1058. :param A:
  1059. Matrix.
  1060. :type A: :class:`numpy.ndarray`
  1061. :return:
  1062. Left singular vectors.
  1063. :rtype: :class:`numpy.ndarray`
  1064. :return:
  1065. Right singular vectors.
  1066. :rtype: :class:`numpy.ndarray`
  1067. :return:
  1068. Singular values.
  1069. :rtype: :class:`numpy.ndarray`
  1070. """
  1071. A = np.asfortranarray(A)
  1072. m, n = A.shape
  1073. k, iU, iV, iS, w, ier = _id.idzp_svd(eps, A)
  1074. if ier:
  1075. raise _RETCODE_ERROR
  1076. U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
  1077. V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
  1078. S = w[iS-1:iS+k-1]
  1079. return U, V, S
  1080. #------------------------------------------------------------------------------
  1081. # idzp_aid.f
  1082. #------------------------------------------------------------------------------
  1083. def idzp_aid(eps, A):
  1084. """
  1085. Compute ID of a complex matrix to a specified relative precision using
  1086. random sampling.
  1087. :param eps:
  1088. Relative precision.
  1089. :type eps: float
  1090. :param A:
  1091. Matrix.
  1092. :type A: :class:`numpy.ndarray`
  1093. :return:
  1094. Rank of ID.
  1095. :rtype: int
  1096. :return:
  1097. Column index array.
  1098. :rtype: :class:`numpy.ndarray`
  1099. :return:
  1100. Interpolation coefficients.
  1101. :rtype: :class:`numpy.ndarray`
  1102. """
  1103. A = np.asfortranarray(A)
  1104. m, n = A.shape
  1105. n2, w = idz_frmi(m)
  1106. proj = np.empty(n*(2*n2 + 1) + n2 + 1, dtype='complex128', order='F')
  1107. k, idx, proj = _id.idzp_aid(eps, A, w, proj)
  1108. proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
  1109. return k, idx, proj
  1110. def idz_estrank(eps, A):
  1111. """
  1112. Estimate rank of a complex matrix to a specified relative precision using
  1113. random sampling.
  1114. The output rank is typically about 8 higher than the actual rank.
  1115. :param eps:
  1116. Relative precision.
  1117. :type eps: float
  1118. :param A:
  1119. Matrix.
  1120. :type A: :class:`numpy.ndarray`
  1121. :return:
  1122. Rank estimate.
  1123. :rtype: int
  1124. """
  1125. A = np.asfortranarray(A)
  1126. m, n = A.shape
  1127. n2, w = idz_frmi(m)
  1128. ra = np.empty(n*n2 + (n + 1)*(n2 + 1), dtype='complex128', order='F')
  1129. k, ra = _id.idz_estrank(eps, A, w, ra)
  1130. return k
  1131. #------------------------------------------------------------------------------
  1132. # idzp_asvd.f
  1133. #------------------------------------------------------------------------------
  1134. def idzp_asvd(eps, A):
  1135. """
  1136. Compute SVD of a complex matrix to a specified relative precision using
  1137. random sampling.
  1138. :param eps:
  1139. Relative precision.
  1140. :type eps: float
  1141. :param A:
  1142. Matrix.
  1143. :type A: :class:`numpy.ndarray`
  1144. :return:
  1145. Left singular vectors.
  1146. :rtype: :class:`numpy.ndarray`
  1147. :return:
  1148. Right singular vectors.
  1149. :rtype: :class:`numpy.ndarray`
  1150. :return:
  1151. Singular values.
  1152. :rtype: :class:`numpy.ndarray`
  1153. """
  1154. A = np.asfortranarray(A)
  1155. m, n = A.shape
  1156. n2, winit = _id.idz_frmi(m)
  1157. w = np.empty(
  1158. max((min(m, n) + 1)*(3*m + 5*n + 11) + 8*min(m, n)**2,
  1159. (2*n + 1)*(n2 + 1)),
  1160. dtype=np.complex128, order='F')
  1161. k, iU, iV, iS, w, ier = _id.idzp_asvd(eps, A, winit, w)
  1162. if ier:
  1163. raise _RETCODE_ERROR
  1164. U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
  1165. V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
  1166. S = w[iS-1:iS+k-1]
  1167. return U, V, S
  1168. #------------------------------------------------------------------------------
  1169. # idzp_rid.f
  1170. #------------------------------------------------------------------------------
  1171. def idzp_rid(eps, m, n, matveca):
  1172. """
  1173. Compute ID of a complex matrix to a specified relative precision using
  1174. random matrix-vector multiplication.
  1175. :param eps:
  1176. Relative precision.
  1177. :type eps: float
  1178. :param m:
  1179. Matrix row dimension.
  1180. :type m: int
  1181. :param n:
  1182. Matrix column dimension.
  1183. :type n: int
  1184. :param matveca:
  1185. Function to apply the matrix adjoint to a vector, with call signature
  1186. `y = matveca(x)`, where `x` and `y` are the input and output vectors,
  1187. respectively.
  1188. :type matveca: function
  1189. :return:
  1190. Rank of ID.
  1191. :rtype: int
  1192. :return:
  1193. Column index array.
  1194. :rtype: :class:`numpy.ndarray`
  1195. :return:
  1196. Interpolation coefficients.
  1197. :rtype: :class:`numpy.ndarray`
  1198. """
  1199. proj = np.empty(
  1200. m + 1 + 2*n*(min(m, n) + 1),
  1201. dtype=np.complex128, order='F')
  1202. k, idx, proj, ier = _id.idzp_rid(eps, m, n, matveca, proj)
  1203. if ier:
  1204. raise _RETCODE_ERROR
  1205. proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
  1206. return k, idx, proj
  1207. def idz_findrank(eps, m, n, matveca):
  1208. """
  1209. Estimate rank of a complex matrix to a specified relative precision using
  1210. random matrix-vector multiplication.
  1211. :param eps:
  1212. Relative precision.
  1213. :type eps: float
  1214. :param m:
  1215. Matrix row dimension.
  1216. :type m: int
  1217. :param n:
  1218. Matrix column dimension.
  1219. :type n: int
  1220. :param matveca:
  1221. Function to apply the matrix adjoint to a vector, with call signature
  1222. `y = matveca(x)`, where `x` and `y` are the input and output vectors,
  1223. respectively.
  1224. :type matveca: function
  1225. :return:
  1226. Rank estimate.
  1227. :rtype: int
  1228. """
  1229. k, ra, ier = _id.idz_findrank(eps, m, n, matveca)
  1230. if ier:
  1231. raise _RETCODE_ERROR
  1232. return k
  1233. #------------------------------------------------------------------------------
  1234. # idzp_rsvd.f
  1235. #------------------------------------------------------------------------------
  1236. def idzp_rsvd(eps, m, n, matveca, matvec):
  1237. """
  1238. Compute SVD of a complex matrix to a specified relative precision using
  1239. random matrix-vector multiplication.
  1240. :param eps:
  1241. Relative precision.
  1242. :type eps: float
  1243. :param m:
  1244. Matrix row dimension.
  1245. :type m: int
  1246. :param n:
  1247. Matrix column dimension.
  1248. :type n: int
  1249. :param matveca:
  1250. Function to apply the matrix adjoint to a vector, with call signature
  1251. `y = matveca(x)`, where `x` and `y` are the input and output vectors,
  1252. respectively.
  1253. :type matveca: function
  1254. :param matvec:
  1255. Function to apply the matrix to a vector, with call signature
  1256. `y = matvec(x)`, where `x` and `y` are the input and output vectors,
  1257. respectively.
  1258. :type matvec: function
  1259. :return:
  1260. Left singular vectors.
  1261. :rtype: :class:`numpy.ndarray`
  1262. :return:
  1263. Right singular vectors.
  1264. :rtype: :class:`numpy.ndarray`
  1265. :return:
  1266. Singular values.
  1267. :rtype: :class:`numpy.ndarray`
  1268. """
  1269. k, iU, iV, iS, w, ier = _id.idzp_rsvd(eps, m, n, matveca, matvec)
  1270. if ier:
  1271. raise _RETCODE_ERROR
  1272. U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
  1273. V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
  1274. S = w[iS-1:iS+k-1]
  1275. return U, V, S
  1276. #------------------------------------------------------------------------------
  1277. # idzr_aid.f
  1278. #------------------------------------------------------------------------------
  1279. def idzr_aid(A, k):
  1280. """
  1281. Compute ID of a complex matrix to a specified rank using random sampling.
  1282. :param A:
  1283. Matrix.
  1284. :type A: :class:`numpy.ndarray`
  1285. :param k:
  1286. Rank of ID.
  1287. :type k: int
  1288. :return:
  1289. Column index array.
  1290. :rtype: :class:`numpy.ndarray`
  1291. :return:
  1292. Interpolation coefficients.
  1293. :rtype: :class:`numpy.ndarray`
  1294. """
  1295. A = np.asfortranarray(A)
  1296. m, n = A.shape
  1297. w = idzr_aidi(m, n, k)
  1298. idx, proj = _id.idzr_aid(A, k, w)
  1299. if k == n:
  1300. proj = np.empty((k, n-k), dtype='complex128', order='F')
  1301. else:
  1302. proj = proj.reshape((k, n-k), order='F')
  1303. return idx, proj
  1304. def idzr_aidi(m, n, k):
  1305. """
  1306. Initialize array for :func:`idzr_aid`.
  1307. :param m:
  1308. Matrix row dimension.
  1309. :type m: int
  1310. :param n:
  1311. Matrix column dimension.
  1312. :type n: int
  1313. :param k:
  1314. Rank of ID.
  1315. :type k: int
  1316. :return:
  1317. Initialization array to be used by :func:`idzr_aid`.
  1318. :rtype: :class:`numpy.ndarray`
  1319. """
  1320. return _id.idzr_aidi(m, n, k)
  1321. #------------------------------------------------------------------------------
  1322. # idzr_asvd.f
  1323. #------------------------------------------------------------------------------
  1324. def idzr_asvd(A, k):
  1325. """
  1326. Compute SVD of a complex matrix to a specified rank using random sampling.
  1327. :param A:
  1328. Matrix.
  1329. :type A: :class:`numpy.ndarray`
  1330. :param k:
  1331. Rank of SVD.
  1332. :type k: int
  1333. :return:
  1334. Left singular vectors.
  1335. :rtype: :class:`numpy.ndarray`
  1336. :return:
  1337. Right singular vectors.
  1338. :rtype: :class:`numpy.ndarray`
  1339. :return:
  1340. Singular values.
  1341. :rtype: :class:`numpy.ndarray`
  1342. """
  1343. A = np.asfortranarray(A)
  1344. m, n = A.shape
  1345. w = np.empty(
  1346. (2*k + 22)*m + (6*k + 21)*n + 8*k**2 + 10*k + 90,
  1347. dtype='complex128', order='F')
  1348. w_ = idzr_aidi(m, n, k)
  1349. w[:w_.size] = w_
  1350. U, V, S, ier = _id.idzr_asvd(A, k, w)
  1351. if ier:
  1352. raise _RETCODE_ERROR
  1353. return U, V, S
  1354. #------------------------------------------------------------------------------
  1355. # idzr_rid.f
  1356. #------------------------------------------------------------------------------
  1357. def idzr_rid(m, n, matveca, k):
  1358. """
  1359. Compute ID of a complex matrix to a specified rank using random
  1360. matrix-vector multiplication.
  1361. :param m:
  1362. Matrix row dimension.
  1363. :type m: int
  1364. :param n:
  1365. Matrix column dimension.
  1366. :type n: int
  1367. :param matveca:
  1368. Function to apply the matrix adjoint to a vector, with call signature
  1369. `y = matveca(x)`, where `x` and `y` are the input and output vectors,
  1370. respectively.
  1371. :type matveca: function
  1372. :param k:
  1373. Rank of ID.
  1374. :type k: int
  1375. :return:
  1376. Column index array.
  1377. :rtype: :class:`numpy.ndarray`
  1378. :return:
  1379. Interpolation coefficients.
  1380. :rtype: :class:`numpy.ndarray`
  1381. """
  1382. idx, proj = _id.idzr_rid(m, n, matveca, k)
  1383. proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
  1384. return idx, proj
  1385. #------------------------------------------------------------------------------
  1386. # idzr_rsvd.f
  1387. #------------------------------------------------------------------------------
  1388. def idzr_rsvd(m, n, matveca, matvec, k):
  1389. """
  1390. Compute SVD of a complex matrix to a specified rank using random
  1391. matrix-vector multiplication.
  1392. :param m:
  1393. Matrix row dimension.
  1394. :type m: int
  1395. :param n:
  1396. Matrix column dimension.
  1397. :type n: int
  1398. :param matveca:
  1399. Function to apply the matrix adjoint to a vector, with call signature
  1400. `y = matveca(x)`, where `x` and `y` are the input and output vectors,
  1401. respectively.
  1402. :type matveca: function
  1403. :param matvec:
  1404. Function to apply the matrix to a vector, with call signature
  1405. `y = matvec(x)`, where `x` and `y` are the input and output vectors,
  1406. respectively.
  1407. :type matvec: function
  1408. :param k:
  1409. Rank of SVD.
  1410. :type k: int
  1411. :return:
  1412. Left singular vectors.
  1413. :rtype: :class:`numpy.ndarray`
  1414. :return:
  1415. Right singular vectors.
  1416. :rtype: :class:`numpy.ndarray`
  1417. :return:
  1418. Singular values.
  1419. :rtype: :class:`numpy.ndarray`
  1420. """
  1421. U, V, S, ier = _id.idzr_rsvd(m, n, matveca, matvec, k)
  1422. if ier:
  1423. raise _RETCODE_ERROR
  1424. return U, V, S