_interpolative_backend.py 44 KB

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