test_laguerre.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. """Tests for laguerre module.
  2. """
  3. from functools import reduce
  4. import numpy as np
  5. import numpy.polynomial.laguerre as lag
  6. from numpy.polynomial.polynomial import polyval
  7. from numpy.testing import (
  8. assert_almost_equal, assert_raises, assert_equal, assert_,
  9. )
  10. L0 = np.array([1])/1
  11. L1 = np.array([1, -1])/1
  12. L2 = np.array([2, -4, 1])/2
  13. L3 = np.array([6, -18, 9, -1])/6
  14. L4 = np.array([24, -96, 72, -16, 1])/24
  15. L5 = np.array([120, -600, 600, -200, 25, -1])/120
  16. L6 = np.array([720, -4320, 5400, -2400, 450, -36, 1])/720
  17. Llist = [L0, L1, L2, L3, L4, L5, L6]
  18. def trim(x):
  19. return lag.lagtrim(x, tol=1e-6)
  20. class TestConstants:
  21. def test_lagdomain(self):
  22. assert_equal(lag.lagdomain, [0, 1])
  23. def test_lagzero(self):
  24. assert_equal(lag.lagzero, [0])
  25. def test_lagone(self):
  26. assert_equal(lag.lagone, [1])
  27. def test_lagx(self):
  28. assert_equal(lag.lagx, [1, -1])
  29. class TestArithmetic:
  30. x = np.linspace(-3, 3, 100)
  31. def test_lagadd(self):
  32. for i in range(5):
  33. for j in range(5):
  34. msg = f"At i={i}, j={j}"
  35. tgt = np.zeros(max(i, j) + 1)
  36. tgt[i] += 1
  37. tgt[j] += 1
  38. res = lag.lagadd([0]*i + [1], [0]*j + [1])
  39. assert_equal(trim(res), trim(tgt), err_msg=msg)
  40. def test_lagsub(self):
  41. for i in range(5):
  42. for j in range(5):
  43. msg = f"At i={i}, j={j}"
  44. tgt = np.zeros(max(i, j) + 1)
  45. tgt[i] += 1
  46. tgt[j] -= 1
  47. res = lag.lagsub([0]*i + [1], [0]*j + [1])
  48. assert_equal(trim(res), trim(tgt), err_msg=msg)
  49. def test_lagmulx(self):
  50. assert_equal(lag.lagmulx([0]), [0])
  51. assert_equal(lag.lagmulx([1]), [1, -1])
  52. for i in range(1, 5):
  53. ser = [0]*i + [1]
  54. tgt = [0]*(i - 1) + [-i, 2*i + 1, -(i + 1)]
  55. assert_almost_equal(lag.lagmulx(ser), tgt)
  56. def test_lagmul(self):
  57. # check values of result
  58. for i in range(5):
  59. pol1 = [0]*i + [1]
  60. val1 = lag.lagval(self.x, pol1)
  61. for j in range(5):
  62. msg = f"At i={i}, j={j}"
  63. pol2 = [0]*j + [1]
  64. val2 = lag.lagval(self.x, pol2)
  65. pol3 = lag.lagmul(pol1, pol2)
  66. val3 = lag.lagval(self.x, pol3)
  67. assert_(len(pol3) == i + j + 1, msg)
  68. assert_almost_equal(val3, val1*val2, err_msg=msg)
  69. def test_lagdiv(self):
  70. for i in range(5):
  71. for j in range(5):
  72. msg = f"At i={i}, j={j}"
  73. ci = [0]*i + [1]
  74. cj = [0]*j + [1]
  75. tgt = lag.lagadd(ci, cj)
  76. quo, rem = lag.lagdiv(tgt, ci)
  77. res = lag.lagadd(lag.lagmul(quo, ci), rem)
  78. assert_almost_equal(trim(res), trim(tgt), err_msg=msg)
  79. def test_lagpow(self):
  80. for i in range(5):
  81. for j in range(5):
  82. msg = f"At i={i}, j={j}"
  83. c = np.arange(i + 1)
  84. tgt = reduce(lag.lagmul, [c]*j, np.array([1]))
  85. res = lag.lagpow(c, j)
  86. assert_equal(trim(res), trim(tgt), err_msg=msg)
  87. class TestEvaluation:
  88. # coefficients of 1 + 2*x + 3*x**2
  89. c1d = np.array([9., -14., 6.])
  90. c2d = np.einsum('i,j->ij', c1d, c1d)
  91. c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
  92. # some random values in [-1, 1)
  93. x = np.random.random((3, 5))*2 - 1
  94. y = polyval(x, [1., 2., 3.])
  95. def test_lagval(self):
  96. #check empty input
  97. assert_equal(lag.lagval([], [1]).size, 0)
  98. #check normal input)
  99. x = np.linspace(-1, 1)
  100. y = [polyval(x, c) for c in Llist]
  101. for i in range(7):
  102. msg = f"At i={i}"
  103. tgt = y[i]
  104. res = lag.lagval(x, [0]*i + [1])
  105. assert_almost_equal(res, tgt, err_msg=msg)
  106. #check that shape is preserved
  107. for i in range(3):
  108. dims = [2]*i
  109. x = np.zeros(dims)
  110. assert_equal(lag.lagval(x, [1]).shape, dims)
  111. assert_equal(lag.lagval(x, [1, 0]).shape, dims)
  112. assert_equal(lag.lagval(x, [1, 0, 0]).shape, dims)
  113. def test_lagval2d(self):
  114. x1, x2, x3 = self.x
  115. y1, y2, y3 = self.y
  116. #test exceptions
  117. assert_raises(ValueError, lag.lagval2d, x1, x2[:2], self.c2d)
  118. #test values
  119. tgt = y1*y2
  120. res = lag.lagval2d(x1, x2, self.c2d)
  121. assert_almost_equal(res, tgt)
  122. #test shape
  123. z = np.ones((2, 3))
  124. res = lag.lagval2d(z, z, self.c2d)
  125. assert_(res.shape == (2, 3))
  126. def test_lagval3d(self):
  127. x1, x2, x3 = self.x
  128. y1, y2, y3 = self.y
  129. #test exceptions
  130. assert_raises(ValueError, lag.lagval3d, x1, x2, x3[:2], self.c3d)
  131. #test values
  132. tgt = y1*y2*y3
  133. res = lag.lagval3d(x1, x2, x3, self.c3d)
  134. assert_almost_equal(res, tgt)
  135. #test shape
  136. z = np.ones((2, 3))
  137. res = lag.lagval3d(z, z, z, self.c3d)
  138. assert_(res.shape == (2, 3))
  139. def test_laggrid2d(self):
  140. x1, x2, x3 = self.x
  141. y1, y2, y3 = self.y
  142. #test values
  143. tgt = np.einsum('i,j->ij', y1, y2)
  144. res = lag.laggrid2d(x1, x2, self.c2d)
  145. assert_almost_equal(res, tgt)
  146. #test shape
  147. z = np.ones((2, 3))
  148. res = lag.laggrid2d(z, z, self.c2d)
  149. assert_(res.shape == (2, 3)*2)
  150. def test_laggrid3d(self):
  151. x1, x2, x3 = self.x
  152. y1, y2, y3 = self.y
  153. #test values
  154. tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
  155. res = lag.laggrid3d(x1, x2, x3, self.c3d)
  156. assert_almost_equal(res, tgt)
  157. #test shape
  158. z = np.ones((2, 3))
  159. res = lag.laggrid3d(z, z, z, self.c3d)
  160. assert_(res.shape == (2, 3)*3)
  161. class TestIntegral:
  162. def test_lagint(self):
  163. # check exceptions
  164. assert_raises(TypeError, lag.lagint, [0], .5)
  165. assert_raises(ValueError, lag.lagint, [0], -1)
  166. assert_raises(ValueError, lag.lagint, [0], 1, [0, 0])
  167. assert_raises(ValueError, lag.lagint, [0], lbnd=[0])
  168. assert_raises(ValueError, lag.lagint, [0], scl=[0])
  169. assert_raises(TypeError, lag.lagint, [0], axis=.5)
  170. # test integration of zero polynomial
  171. for i in range(2, 5):
  172. k = [0]*(i - 2) + [1]
  173. res = lag.lagint([0], m=i, k=k)
  174. assert_almost_equal(res, [1, -1])
  175. # check single integration with integration constant
  176. for i in range(5):
  177. scl = i + 1
  178. pol = [0]*i + [1]
  179. tgt = [i] + [0]*i + [1/scl]
  180. lagpol = lag.poly2lag(pol)
  181. lagint = lag.lagint(lagpol, m=1, k=[i])
  182. res = lag.lag2poly(lagint)
  183. assert_almost_equal(trim(res), trim(tgt))
  184. # check single integration with integration constant and lbnd
  185. for i in range(5):
  186. scl = i + 1
  187. pol = [0]*i + [1]
  188. lagpol = lag.poly2lag(pol)
  189. lagint = lag.lagint(lagpol, m=1, k=[i], lbnd=-1)
  190. assert_almost_equal(lag.lagval(-1, lagint), i)
  191. # check single integration with integration constant and scaling
  192. for i in range(5):
  193. scl = i + 1
  194. pol = [0]*i + [1]
  195. tgt = [i] + [0]*i + [2/scl]
  196. lagpol = lag.poly2lag(pol)
  197. lagint = lag.lagint(lagpol, m=1, k=[i], scl=2)
  198. res = lag.lag2poly(lagint)
  199. assert_almost_equal(trim(res), trim(tgt))
  200. # check multiple integrations with default k
  201. for i in range(5):
  202. for j in range(2, 5):
  203. pol = [0]*i + [1]
  204. tgt = pol[:]
  205. for k in range(j):
  206. tgt = lag.lagint(tgt, m=1)
  207. res = lag.lagint(pol, m=j)
  208. assert_almost_equal(trim(res), trim(tgt))
  209. # check multiple integrations with defined k
  210. for i in range(5):
  211. for j in range(2, 5):
  212. pol = [0]*i + [1]
  213. tgt = pol[:]
  214. for k in range(j):
  215. tgt = lag.lagint(tgt, m=1, k=[k])
  216. res = lag.lagint(pol, m=j, k=list(range(j)))
  217. assert_almost_equal(trim(res), trim(tgt))
  218. # check multiple integrations with lbnd
  219. for i in range(5):
  220. for j in range(2, 5):
  221. pol = [0]*i + [1]
  222. tgt = pol[:]
  223. for k in range(j):
  224. tgt = lag.lagint(tgt, m=1, k=[k], lbnd=-1)
  225. res = lag.lagint(pol, m=j, k=list(range(j)), lbnd=-1)
  226. assert_almost_equal(trim(res), trim(tgt))
  227. # check multiple integrations with scaling
  228. for i in range(5):
  229. for j in range(2, 5):
  230. pol = [0]*i + [1]
  231. tgt = pol[:]
  232. for k in range(j):
  233. tgt = lag.lagint(tgt, m=1, k=[k], scl=2)
  234. res = lag.lagint(pol, m=j, k=list(range(j)), scl=2)
  235. assert_almost_equal(trim(res), trim(tgt))
  236. def test_lagint_axis(self):
  237. # check that axis keyword works
  238. c2d = np.random.random((3, 4))
  239. tgt = np.vstack([lag.lagint(c) for c in c2d.T]).T
  240. res = lag.lagint(c2d, axis=0)
  241. assert_almost_equal(res, tgt)
  242. tgt = np.vstack([lag.lagint(c) for c in c2d])
  243. res = lag.lagint(c2d, axis=1)
  244. assert_almost_equal(res, tgt)
  245. tgt = np.vstack([lag.lagint(c, k=3) for c in c2d])
  246. res = lag.lagint(c2d, k=3, axis=1)
  247. assert_almost_equal(res, tgt)
  248. class TestDerivative:
  249. def test_lagder(self):
  250. # check exceptions
  251. assert_raises(TypeError, lag.lagder, [0], .5)
  252. assert_raises(ValueError, lag.lagder, [0], -1)
  253. # check that zeroth derivative does nothing
  254. for i in range(5):
  255. tgt = [0]*i + [1]
  256. res = lag.lagder(tgt, m=0)
  257. assert_equal(trim(res), trim(tgt))
  258. # check that derivation is the inverse of integration
  259. for i in range(5):
  260. for j in range(2, 5):
  261. tgt = [0]*i + [1]
  262. res = lag.lagder(lag.lagint(tgt, m=j), m=j)
  263. assert_almost_equal(trim(res), trim(tgt))
  264. # check derivation with scaling
  265. for i in range(5):
  266. for j in range(2, 5):
  267. tgt = [0]*i + [1]
  268. res = lag.lagder(lag.lagint(tgt, m=j, scl=2), m=j, scl=.5)
  269. assert_almost_equal(trim(res), trim(tgt))
  270. def test_lagder_axis(self):
  271. # check that axis keyword works
  272. c2d = np.random.random((3, 4))
  273. tgt = np.vstack([lag.lagder(c) for c in c2d.T]).T
  274. res = lag.lagder(c2d, axis=0)
  275. assert_almost_equal(res, tgt)
  276. tgt = np.vstack([lag.lagder(c) for c in c2d])
  277. res = lag.lagder(c2d, axis=1)
  278. assert_almost_equal(res, tgt)
  279. class TestVander:
  280. # some random values in [-1, 1)
  281. x = np.random.random((3, 5))*2 - 1
  282. def test_lagvander(self):
  283. # check for 1d x
  284. x = np.arange(3)
  285. v = lag.lagvander(x, 3)
  286. assert_(v.shape == (3, 4))
  287. for i in range(4):
  288. coef = [0]*i + [1]
  289. assert_almost_equal(v[..., i], lag.lagval(x, coef))
  290. # check for 2d x
  291. x = np.array([[1, 2], [3, 4], [5, 6]])
  292. v = lag.lagvander(x, 3)
  293. assert_(v.shape == (3, 2, 4))
  294. for i in range(4):
  295. coef = [0]*i + [1]
  296. assert_almost_equal(v[..., i], lag.lagval(x, coef))
  297. def test_lagvander2d(self):
  298. # also tests lagval2d for non-square coefficient array
  299. x1, x2, x3 = self.x
  300. c = np.random.random((2, 3))
  301. van = lag.lagvander2d(x1, x2, [1, 2])
  302. tgt = lag.lagval2d(x1, x2, c)
  303. res = np.dot(van, c.flat)
  304. assert_almost_equal(res, tgt)
  305. # check shape
  306. van = lag.lagvander2d([x1], [x2], [1, 2])
  307. assert_(van.shape == (1, 5, 6))
  308. def test_lagvander3d(self):
  309. # also tests lagval3d for non-square coefficient array
  310. x1, x2, x3 = self.x
  311. c = np.random.random((2, 3, 4))
  312. van = lag.lagvander3d(x1, x2, x3, [1, 2, 3])
  313. tgt = lag.lagval3d(x1, x2, x3, c)
  314. res = np.dot(van, c.flat)
  315. assert_almost_equal(res, tgt)
  316. # check shape
  317. van = lag.lagvander3d([x1], [x2], [x3], [1, 2, 3])
  318. assert_(van.shape == (1, 5, 24))
  319. class TestFitting:
  320. def test_lagfit(self):
  321. def f(x):
  322. return x*(x - 1)*(x - 2)
  323. # Test exceptions
  324. assert_raises(ValueError, lag.lagfit, [1], [1], -1)
  325. assert_raises(TypeError, lag.lagfit, [[1]], [1], 0)
  326. assert_raises(TypeError, lag.lagfit, [], [1], 0)
  327. assert_raises(TypeError, lag.lagfit, [1], [[[1]]], 0)
  328. assert_raises(TypeError, lag.lagfit, [1, 2], [1], 0)
  329. assert_raises(TypeError, lag.lagfit, [1], [1, 2], 0)
  330. assert_raises(TypeError, lag.lagfit, [1], [1], 0, w=[[1]])
  331. assert_raises(TypeError, lag.lagfit, [1], [1], 0, w=[1, 1])
  332. assert_raises(ValueError, lag.lagfit, [1], [1], [-1,])
  333. assert_raises(ValueError, lag.lagfit, [1], [1], [2, -1, 6])
  334. assert_raises(TypeError, lag.lagfit, [1], [1], [])
  335. # Test fit
  336. x = np.linspace(0, 2)
  337. y = f(x)
  338. #
  339. coef3 = lag.lagfit(x, y, 3)
  340. assert_equal(len(coef3), 4)
  341. assert_almost_equal(lag.lagval(x, coef3), y)
  342. coef3 = lag.lagfit(x, y, [0, 1, 2, 3])
  343. assert_equal(len(coef3), 4)
  344. assert_almost_equal(lag.lagval(x, coef3), y)
  345. #
  346. coef4 = lag.lagfit(x, y, 4)
  347. assert_equal(len(coef4), 5)
  348. assert_almost_equal(lag.lagval(x, coef4), y)
  349. coef4 = lag.lagfit(x, y, [0, 1, 2, 3, 4])
  350. assert_equal(len(coef4), 5)
  351. assert_almost_equal(lag.lagval(x, coef4), y)
  352. #
  353. coef2d = lag.lagfit(x, np.array([y, y]).T, 3)
  354. assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
  355. coef2d = lag.lagfit(x, np.array([y, y]).T, [0, 1, 2, 3])
  356. assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
  357. # test weighting
  358. w = np.zeros_like(x)
  359. yw = y.copy()
  360. w[1::2] = 1
  361. y[0::2] = 0
  362. wcoef3 = lag.lagfit(x, yw, 3, w=w)
  363. assert_almost_equal(wcoef3, coef3)
  364. wcoef3 = lag.lagfit(x, yw, [0, 1, 2, 3], w=w)
  365. assert_almost_equal(wcoef3, coef3)
  366. #
  367. wcoef2d = lag.lagfit(x, np.array([yw, yw]).T, 3, w=w)
  368. assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
  369. wcoef2d = lag.lagfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
  370. assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
  371. # test scaling with complex values x points whose square
  372. # is zero when summed.
  373. x = [1, 1j, -1, -1j]
  374. assert_almost_equal(lag.lagfit(x, x, 1), [1, -1])
  375. assert_almost_equal(lag.lagfit(x, x, [0, 1]), [1, -1])
  376. class TestCompanion:
  377. def test_raises(self):
  378. assert_raises(ValueError, lag.lagcompanion, [])
  379. assert_raises(ValueError, lag.lagcompanion, [1])
  380. def test_dimensions(self):
  381. for i in range(1, 5):
  382. coef = [0]*i + [1]
  383. assert_(lag.lagcompanion(coef).shape == (i, i))
  384. def test_linear_root(self):
  385. assert_(lag.lagcompanion([1, 2])[0, 0] == 1.5)
  386. class TestGauss:
  387. def test_100(self):
  388. x, w = lag.laggauss(100)
  389. # test orthogonality. Note that the results need to be normalized,
  390. # otherwise the huge values that can arise from fast growing
  391. # functions like Laguerre can be very confusing.
  392. v = lag.lagvander(x, 99)
  393. vv = np.dot(v.T * w, v)
  394. vd = 1/np.sqrt(vv.diagonal())
  395. vv = vd[:, None] * vv * vd
  396. assert_almost_equal(vv, np.eye(100))
  397. # check that the integral of 1 is correct
  398. tgt = 1.0
  399. assert_almost_equal(w.sum(), tgt)
  400. class TestMisc:
  401. def test_lagfromroots(self):
  402. res = lag.lagfromroots([])
  403. assert_almost_equal(trim(res), [1])
  404. for i in range(1, 5):
  405. roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
  406. pol = lag.lagfromroots(roots)
  407. res = lag.lagval(roots, pol)
  408. tgt = 0
  409. assert_(len(pol) == i + 1)
  410. assert_almost_equal(lag.lag2poly(pol)[-1], 1)
  411. assert_almost_equal(res, tgt)
  412. def test_lagroots(self):
  413. assert_almost_equal(lag.lagroots([1]), [])
  414. assert_almost_equal(lag.lagroots([0, 1]), [1])
  415. for i in range(2, 5):
  416. tgt = np.linspace(0, 3, i)
  417. res = lag.lagroots(lag.lagfromroots(tgt))
  418. assert_almost_equal(trim(res), trim(tgt))
  419. def test_lagtrim(self):
  420. coef = [2, -1, 1, 0]
  421. # Test exceptions
  422. assert_raises(ValueError, lag.lagtrim, coef, -1)
  423. # Test results
  424. assert_equal(lag.lagtrim(coef), coef[:-1])
  425. assert_equal(lag.lagtrim(coef, 1), coef[:-3])
  426. assert_equal(lag.lagtrim(coef, 2), [0])
  427. def test_lagline(self):
  428. assert_equal(lag.lagline(3, 4), [7, -4])
  429. def test_lag2poly(self):
  430. for i in range(7):
  431. assert_almost_equal(lag.lag2poly([0]*i + [1]), Llist[i])
  432. def test_poly2lag(self):
  433. for i in range(7):
  434. assert_almost_equal(lag.poly2lag(Llist[i]), [0]*i + [1])
  435. def test_weight(self):
  436. x = np.linspace(0, 10, 11)
  437. tgt = np.exp(-x)
  438. res = lag.lagweight(x)
  439. assert_almost_equal(res, tgt)