laguerre.py 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804
  1. """
  2. Objects for dealing with Laguerre series.
  3. This module provides a number of objects (mostly functions) useful for
  4. dealing with Laguerre series, including a `Laguerre` class that
  5. encapsulates the usual arithmetic operations. (General information
  6. on how this module represents and works with such polynomials is in the
  7. docstring for its "parent" sub-package, `numpy.polynomial`).
  8. Constants
  9. ---------
  10. - `lagdomain` -- Laguerre series default domain, [-1,1].
  11. - `lagzero` -- Laguerre series that evaluates identically to 0.
  12. - `lagone` -- Laguerre series that evaluates identically to 1.
  13. - `lagx` -- Laguerre series for the identity map, ``f(x) = x``.
  14. Arithmetic
  15. ----------
  16. - `lagmulx` -- multiply a Laguerre series in ``P_i(x)`` by ``x``.
  17. - `lagadd` -- add two Laguerre series.
  18. - `lagsub` -- subtract one Laguerre series from another.
  19. - `lagmul` -- multiply two Laguerre series.
  20. - `lagdiv` -- divide one Laguerre series by another.
  21. - `lagval` -- evaluate a Laguerre series at given points.
  22. - `lagval2d` -- evaluate a 2D Laguerre series at given points.
  23. - `lagval3d` -- evaluate a 3D Laguerre series at given points.
  24. - `laggrid2d` -- evaluate a 2D Laguerre series on a Cartesian product.
  25. - `laggrid3d` -- evaluate a 3D Laguerre series on a Cartesian product.
  26. Calculus
  27. --------
  28. - `lagder` -- differentiate a Laguerre series.
  29. - `lagint` -- integrate a Laguerre series.
  30. Misc Functions
  31. --------------
  32. - `lagfromroots` -- create a Laguerre series with specified roots.
  33. - `lagroots` -- find the roots of a Laguerre series.
  34. - `lagvander` -- Vandermonde-like matrix for Laguerre polynomials.
  35. - `lagvander2d` -- Vandermonde-like matrix for 2D power series.
  36. - `lagvander3d` -- Vandermonde-like matrix for 3D power series.
  37. - `laggauss` -- Gauss-Laguerre quadrature, points and weights.
  38. - `lagweight` -- Laguerre weight function.
  39. - `lagcompanion` -- symmetrized companion matrix in Laguerre form.
  40. - `lagfit` -- least-squares fit returning a Laguerre series.
  41. - `lagtrim` -- trim leading coefficients from a Laguerre series.
  42. - `lagline` -- Laguerre series of given straight line.
  43. - `lag2poly` -- convert a Laguerre series to a polynomial.
  44. - `poly2lag` -- convert a polynomial to a Laguerre series.
  45. Classes
  46. -------
  47. - `Laguerre` -- A Laguerre series class.
  48. See also
  49. --------
  50. `numpy.polynomial`
  51. """
  52. from __future__ import division, absolute_import, print_function
  53. import warnings
  54. import numpy as np
  55. import numpy.linalg as la
  56. from . import polyutils as pu
  57. from ._polybase import ABCPolyBase
  58. __all__ = [
  59. 'lagzero', 'lagone', 'lagx', 'lagdomain', 'lagline', 'lagadd',
  60. 'lagsub', 'lagmulx', 'lagmul', 'lagdiv', 'lagpow', 'lagval', 'lagder',
  61. 'lagint', 'lag2poly', 'poly2lag', 'lagfromroots', 'lagvander',
  62. 'lagfit', 'lagtrim', 'lagroots', 'Laguerre', 'lagval2d', 'lagval3d',
  63. 'laggrid2d', 'laggrid3d', 'lagvander2d', 'lagvander3d', 'lagcompanion',
  64. 'laggauss', 'lagweight']
  65. lagtrim = pu.trimcoef
  66. def poly2lag(pol):
  67. """
  68. poly2lag(pol)
  69. Convert a polynomial to a Laguerre series.
  70. Convert an array representing the coefficients of a polynomial (relative
  71. to the "standard" basis) ordered from lowest degree to highest, to an
  72. array of the coefficients of the equivalent Laguerre series, ordered
  73. from lowest to highest degree.
  74. Parameters
  75. ----------
  76. pol : array_like
  77. 1-D array containing the polynomial coefficients
  78. Returns
  79. -------
  80. c : ndarray
  81. 1-D array containing the coefficients of the equivalent Laguerre
  82. series.
  83. See Also
  84. --------
  85. lag2poly
  86. Notes
  87. -----
  88. The easy way to do conversions between polynomial basis sets
  89. is to use the convert method of a class instance.
  90. Examples
  91. --------
  92. >>> from numpy.polynomial.laguerre import poly2lag
  93. >>> poly2lag(np.arange(4))
  94. array([ 23., -63., 58., -18.])
  95. """
  96. [pol] = pu.as_series([pol])
  97. deg = len(pol) - 1
  98. res = 0
  99. for i in range(deg, -1, -1):
  100. res = lagadd(lagmulx(res), pol[i])
  101. return res
  102. def lag2poly(c):
  103. """
  104. Convert a Laguerre series to a polynomial.
  105. Convert an array representing the coefficients of a Laguerre series,
  106. ordered from lowest degree to highest, to an array of the coefficients
  107. of the equivalent polynomial (relative to the "standard" basis) ordered
  108. from lowest to highest degree.
  109. Parameters
  110. ----------
  111. c : array_like
  112. 1-D array containing the Laguerre series coefficients, ordered
  113. from lowest order term to highest.
  114. Returns
  115. -------
  116. pol : ndarray
  117. 1-D array containing the coefficients of the equivalent polynomial
  118. (relative to the "standard" basis) ordered from lowest order term
  119. to highest.
  120. See Also
  121. --------
  122. poly2lag
  123. Notes
  124. -----
  125. The easy way to do conversions between polynomial basis sets
  126. is to use the convert method of a class instance.
  127. Examples
  128. --------
  129. >>> from numpy.polynomial.laguerre import lag2poly
  130. >>> lag2poly([ 23., -63., 58., -18.])
  131. array([ 0., 1., 2., 3.])
  132. """
  133. from .polynomial import polyadd, polysub, polymulx
  134. [c] = pu.as_series([c])
  135. n = len(c)
  136. if n == 1:
  137. return c
  138. else:
  139. c0 = c[-2]
  140. c1 = c[-1]
  141. # i is the current degree of c1
  142. for i in range(n - 1, 1, -1):
  143. tmp = c0
  144. c0 = polysub(c[i - 2], (c1*(i - 1))/i)
  145. c1 = polyadd(tmp, polysub((2*i - 1)*c1, polymulx(c1))/i)
  146. return polyadd(c0, polysub(c1, polymulx(c1)))
  147. #
  148. # These are constant arrays are of integer type so as to be compatible
  149. # with the widest range of other types, such as Decimal.
  150. #
  151. # Laguerre
  152. lagdomain = np.array([0, 1])
  153. # Laguerre coefficients representing zero.
  154. lagzero = np.array([0])
  155. # Laguerre coefficients representing one.
  156. lagone = np.array([1])
  157. # Laguerre coefficients representing the identity x.
  158. lagx = np.array([1, -1])
  159. def lagline(off, scl):
  160. """
  161. Laguerre series whose graph is a straight line.
  162. Parameters
  163. ----------
  164. off, scl : scalars
  165. The specified line is given by ``off + scl*x``.
  166. Returns
  167. -------
  168. y : ndarray
  169. This module's representation of the Laguerre series for
  170. ``off + scl*x``.
  171. See Also
  172. --------
  173. polyline, chebline
  174. Examples
  175. --------
  176. >>> from numpy.polynomial.laguerre import lagline, lagval
  177. >>> lagval(0,lagline(3, 2))
  178. 3.0
  179. >>> lagval(1,lagline(3, 2))
  180. 5.0
  181. """
  182. if scl != 0:
  183. return np.array([off + scl, -scl])
  184. else:
  185. return np.array([off])
  186. def lagfromroots(roots):
  187. """
  188. Generate a Laguerre series with given roots.
  189. The function returns the coefficients of the polynomial
  190. .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
  191. in Laguerre form, where the `r_n` are the roots specified in `roots`.
  192. If a zero has multiplicity n, then it must appear in `roots` n times.
  193. For instance, if 2 is a root of multiplicity three and 3 is a root of
  194. multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
  195. roots can appear in any order.
  196. If the returned coefficients are `c`, then
  197. .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x)
  198. The coefficient of the last term is not generally 1 for monic
  199. polynomials in Laguerre form.
  200. Parameters
  201. ----------
  202. roots : array_like
  203. Sequence containing the roots.
  204. Returns
  205. -------
  206. out : ndarray
  207. 1-D array of coefficients. If all roots are real then `out` is a
  208. real array, if some of the roots are complex, then `out` is complex
  209. even if all the coefficients in the result are real (see Examples
  210. below).
  211. See Also
  212. --------
  213. polyfromroots, legfromroots, chebfromroots, hermfromroots,
  214. hermefromroots.
  215. Examples
  216. --------
  217. >>> from numpy.polynomial.laguerre import lagfromroots, lagval
  218. >>> coef = lagfromroots((-1, 0, 1))
  219. >>> lagval((-1, 0, 1), coef)
  220. array([ 0., 0., 0.])
  221. >>> coef = lagfromroots((-1j, 1j))
  222. >>> lagval((-1j, 1j), coef)
  223. array([ 0.+0.j, 0.+0.j])
  224. """
  225. if len(roots) == 0:
  226. return np.ones(1)
  227. else:
  228. [roots] = pu.as_series([roots], trim=False)
  229. roots.sort()
  230. p = [lagline(-r, 1) for r in roots]
  231. n = len(p)
  232. while n > 1:
  233. m, r = divmod(n, 2)
  234. tmp = [lagmul(p[i], p[i+m]) for i in range(m)]
  235. if r:
  236. tmp[0] = lagmul(tmp[0], p[-1])
  237. p = tmp
  238. n = m
  239. return p[0]
  240. def lagadd(c1, c2):
  241. """
  242. Add one Laguerre series to another.
  243. Returns the sum of two Laguerre series `c1` + `c2`. The arguments
  244. are sequences of coefficients ordered from lowest order term to
  245. highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
  246. Parameters
  247. ----------
  248. c1, c2 : array_like
  249. 1-D arrays of Laguerre series coefficients ordered from low to
  250. high.
  251. Returns
  252. -------
  253. out : ndarray
  254. Array representing the Laguerre series of their sum.
  255. See Also
  256. --------
  257. lagsub, lagmul, lagdiv, lagpow
  258. Notes
  259. -----
  260. Unlike multiplication, division, etc., the sum of two Laguerre series
  261. is a Laguerre series (without having to "reproject" the result onto
  262. the basis set) so addition, just like that of "standard" polynomials,
  263. is simply "component-wise."
  264. Examples
  265. --------
  266. >>> from numpy.polynomial.laguerre import lagadd
  267. >>> lagadd([1, 2, 3], [1, 2, 3, 4])
  268. array([ 2., 4., 6., 4.])
  269. """
  270. # c1, c2 are trimmed copies
  271. [c1, c2] = pu.as_series([c1, c2])
  272. if len(c1) > len(c2):
  273. c1[:c2.size] += c2
  274. ret = c1
  275. else:
  276. c2[:c1.size] += c1
  277. ret = c2
  278. return pu.trimseq(ret)
  279. def lagsub(c1, c2):
  280. """
  281. Subtract one Laguerre series from another.
  282. Returns the difference of two Laguerre series `c1` - `c2`. The
  283. sequences of coefficients are from lowest order term to highest, i.e.,
  284. [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
  285. Parameters
  286. ----------
  287. c1, c2 : array_like
  288. 1-D arrays of Laguerre series coefficients ordered from low to
  289. high.
  290. Returns
  291. -------
  292. out : ndarray
  293. Of Laguerre series coefficients representing their difference.
  294. See Also
  295. --------
  296. lagadd, lagmul, lagdiv, lagpow
  297. Notes
  298. -----
  299. Unlike multiplication, division, etc., the difference of two Laguerre
  300. series is a Laguerre series (without having to "reproject" the result
  301. onto the basis set) so subtraction, just like that of "standard"
  302. polynomials, is simply "component-wise."
  303. Examples
  304. --------
  305. >>> from numpy.polynomial.laguerre import lagsub
  306. >>> lagsub([1, 2, 3, 4], [1, 2, 3])
  307. array([ 0., 0., 0., 4.])
  308. """
  309. # c1, c2 are trimmed copies
  310. [c1, c2] = pu.as_series([c1, c2])
  311. if len(c1) > len(c2):
  312. c1[:c2.size] -= c2
  313. ret = c1
  314. else:
  315. c2 = -c2
  316. c2[:c1.size] += c1
  317. ret = c2
  318. return pu.trimseq(ret)
  319. def lagmulx(c):
  320. """Multiply a Laguerre series by x.
  321. Multiply the Laguerre series `c` by x, where x is the independent
  322. variable.
  323. Parameters
  324. ----------
  325. c : array_like
  326. 1-D array of Laguerre series coefficients ordered from low to
  327. high.
  328. Returns
  329. -------
  330. out : ndarray
  331. Array representing the result of the multiplication.
  332. Notes
  333. -----
  334. The multiplication uses the recursion relationship for Laguerre
  335. polynomials in the form
  336. .. math::
  337. xP_i(x) = (-(i + 1)*P_{i + 1}(x) + (2i + 1)P_{i}(x) - iP_{i - 1}(x))
  338. Examples
  339. --------
  340. >>> from numpy.polynomial.laguerre import lagmulx
  341. >>> lagmulx([1, 2, 3])
  342. array([ -1., -1., 11., -9.])
  343. """
  344. # c is a trimmed copy
  345. [c] = pu.as_series([c])
  346. # The zero series needs special treatment
  347. if len(c) == 1 and c[0] == 0:
  348. return c
  349. prd = np.empty(len(c) + 1, dtype=c.dtype)
  350. prd[0] = c[0]
  351. prd[1] = -c[0]
  352. for i in range(1, len(c)):
  353. prd[i + 1] = -c[i]*(i + 1)
  354. prd[i] += c[i]*(2*i + 1)
  355. prd[i - 1] -= c[i]*i
  356. return prd
  357. def lagmul(c1, c2):
  358. """
  359. Multiply one Laguerre series by another.
  360. Returns the product of two Laguerre series `c1` * `c2`. The arguments
  361. are sequences of coefficients, from lowest order "term" to highest,
  362. e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
  363. Parameters
  364. ----------
  365. c1, c2 : array_like
  366. 1-D arrays of Laguerre series coefficients ordered from low to
  367. high.
  368. Returns
  369. -------
  370. out : ndarray
  371. Of Laguerre series coefficients representing their product.
  372. See Also
  373. --------
  374. lagadd, lagsub, lagdiv, lagpow
  375. Notes
  376. -----
  377. In general, the (polynomial) product of two C-series results in terms
  378. that are not in the Laguerre polynomial basis set. Thus, to express
  379. the product as a Laguerre series, it is necessary to "reproject" the
  380. product onto said basis set, which may produce "unintuitive" (but
  381. correct) results; see Examples section below.
  382. Examples
  383. --------
  384. >>> from numpy.polynomial.laguerre import lagmul
  385. >>> lagmul([1, 2, 3], [0, 1, 2])
  386. array([ 8., -13., 38., -51., 36.])
  387. """
  388. # s1, s2 are trimmed copies
  389. [c1, c2] = pu.as_series([c1, c2])
  390. if len(c1) > len(c2):
  391. c = c2
  392. xs = c1
  393. else:
  394. c = c1
  395. xs = c2
  396. if len(c) == 1:
  397. c0 = c[0]*xs
  398. c1 = 0
  399. elif len(c) == 2:
  400. c0 = c[0]*xs
  401. c1 = c[1]*xs
  402. else:
  403. nd = len(c)
  404. c0 = c[-2]*xs
  405. c1 = c[-1]*xs
  406. for i in range(3, len(c) + 1):
  407. tmp = c0
  408. nd = nd - 1
  409. c0 = lagsub(c[-i]*xs, (c1*(nd - 1))/nd)
  410. c1 = lagadd(tmp, lagsub((2*nd - 1)*c1, lagmulx(c1))/nd)
  411. return lagadd(c0, lagsub(c1, lagmulx(c1)))
  412. def lagdiv(c1, c2):
  413. """
  414. Divide one Laguerre series by another.
  415. Returns the quotient-with-remainder of two Laguerre series
  416. `c1` / `c2`. The arguments are sequences of coefficients from lowest
  417. order "term" to highest, e.g., [1,2,3] represents the series
  418. ``P_0 + 2*P_1 + 3*P_2``.
  419. Parameters
  420. ----------
  421. c1, c2 : array_like
  422. 1-D arrays of Laguerre series coefficients ordered from low to
  423. high.
  424. Returns
  425. -------
  426. [quo, rem] : ndarrays
  427. Of Laguerre series coefficients representing the quotient and
  428. remainder.
  429. See Also
  430. --------
  431. lagadd, lagsub, lagmul, lagpow
  432. Notes
  433. -----
  434. In general, the (polynomial) division of one Laguerre series by another
  435. results in quotient and remainder terms that are not in the Laguerre
  436. polynomial basis set. Thus, to express these results as a Laguerre
  437. series, it is necessary to "reproject" the results onto the Laguerre
  438. basis set, which may produce "unintuitive" (but correct) results; see
  439. Examples section below.
  440. Examples
  441. --------
  442. >>> from numpy.polynomial.laguerre import lagdiv
  443. >>> lagdiv([ 8., -13., 38., -51., 36.], [0, 1, 2])
  444. (array([ 1., 2., 3.]), array([ 0.]))
  445. >>> lagdiv([ 9., -12., 38., -51., 36.], [0, 1, 2])
  446. (array([ 1., 2., 3.]), array([ 1., 1.]))
  447. """
  448. # c1, c2 are trimmed copies
  449. [c1, c2] = pu.as_series([c1, c2])
  450. if c2[-1] == 0:
  451. raise ZeroDivisionError()
  452. lc1 = len(c1)
  453. lc2 = len(c2)
  454. if lc1 < lc2:
  455. return c1[:1]*0, c1
  456. elif lc2 == 1:
  457. return c1/c2[-1], c1[:1]*0
  458. else:
  459. quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
  460. rem = c1
  461. for i in range(lc1 - lc2, - 1, -1):
  462. p = lagmul([0]*i + [1], c2)
  463. q = rem[-1]/p[-1]
  464. rem = rem[:-1] - q*p[:-1]
  465. quo[i] = q
  466. return quo, pu.trimseq(rem)
  467. def lagpow(c, pow, maxpower=16):
  468. """Raise a Laguerre series to a power.
  469. Returns the Laguerre series `c` raised to the power `pow`. The
  470. argument `c` is a sequence of coefficients ordered from low to high.
  471. i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
  472. Parameters
  473. ----------
  474. c : array_like
  475. 1-D array of Laguerre series coefficients ordered from low to
  476. high.
  477. pow : integer
  478. Power to which the series will be raised
  479. maxpower : integer, optional
  480. Maximum power allowed. This is mainly to limit growth of the series
  481. to unmanageable size. Default is 16
  482. Returns
  483. -------
  484. coef : ndarray
  485. Laguerre series of power.
  486. See Also
  487. --------
  488. lagadd, lagsub, lagmul, lagdiv
  489. Examples
  490. --------
  491. >>> from numpy.polynomial.laguerre import lagpow
  492. >>> lagpow([1, 2, 3], 2)
  493. array([ 14., -16., 56., -72., 54.])
  494. """
  495. # c is a trimmed copy
  496. [c] = pu.as_series([c])
  497. power = int(pow)
  498. if power != pow or power < 0:
  499. raise ValueError("Power must be a non-negative integer.")
  500. elif maxpower is not None and power > maxpower:
  501. raise ValueError("Power is too large")
  502. elif power == 0:
  503. return np.array([1], dtype=c.dtype)
  504. elif power == 1:
  505. return c
  506. else:
  507. # This can be made more efficient by using powers of two
  508. # in the usual way.
  509. prd = c
  510. for i in range(2, power + 1):
  511. prd = lagmul(prd, c)
  512. return prd
  513. def lagder(c, m=1, scl=1, axis=0):
  514. """
  515. Differentiate a Laguerre series.
  516. Returns the Laguerre series coefficients `c` differentiated `m` times
  517. along `axis`. At each iteration the result is multiplied by `scl` (the
  518. scaling factor is for use in a linear change of variable). The argument
  519. `c` is an array of coefficients from low to high degree along each
  520. axis, e.g., [1,2,3] represents the series ``1*L_0 + 2*L_1 + 3*L_2``
  521. while [[1,2],[1,2]] represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) +
  522. 2*L_0(x)*L_1(y) + 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is
  523. ``y``.
  524. Parameters
  525. ----------
  526. c : array_like
  527. Array of Laguerre series coefficients. If `c` is multidimensional
  528. the different axis correspond to different variables with the
  529. degree in each axis given by the corresponding index.
  530. m : int, optional
  531. Number of derivatives taken, must be non-negative. (Default: 1)
  532. scl : scalar, optional
  533. Each differentiation is multiplied by `scl`. The end result is
  534. multiplication by ``scl**m``. This is for use in a linear change of
  535. variable. (Default: 1)
  536. axis : int, optional
  537. Axis over which the derivative is taken. (Default: 0).
  538. .. versionadded:: 1.7.0
  539. Returns
  540. -------
  541. der : ndarray
  542. Laguerre series of the derivative.
  543. See Also
  544. --------
  545. lagint
  546. Notes
  547. -----
  548. In general, the result of differentiating a Laguerre series does not
  549. resemble the same operation on a power series. Thus the result of this
  550. function may be "unintuitive," albeit correct; see Examples section
  551. below.
  552. Examples
  553. --------
  554. >>> from numpy.polynomial.laguerre import lagder
  555. >>> lagder([ 1., 1., 1., -3.])
  556. array([ 1., 2., 3.])
  557. >>> lagder([ 1., 0., 0., -4., 3.], m=2)
  558. array([ 1., 2., 3.])
  559. """
  560. c = np.array(c, ndmin=1, copy=1)
  561. if c.dtype.char in '?bBhHiIlLqQpP':
  562. c = c.astype(np.double)
  563. cnt, iaxis = [int(t) for t in [m, axis]]
  564. if cnt != m:
  565. raise ValueError("The order of derivation must be integer")
  566. if cnt < 0:
  567. raise ValueError("The order of derivation must be non-negative")
  568. if iaxis != axis:
  569. raise ValueError("The axis must be integer")
  570. if not -c.ndim <= iaxis < c.ndim:
  571. raise ValueError("The axis is out of range")
  572. if iaxis < 0:
  573. iaxis += c.ndim
  574. if cnt == 0:
  575. return c
  576. c = np.rollaxis(c, iaxis)
  577. n = len(c)
  578. if cnt >= n:
  579. c = c[:1]*0
  580. else:
  581. for i in range(cnt):
  582. n = n - 1
  583. c *= scl
  584. der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
  585. for j in range(n, 1, -1):
  586. der[j - 1] = -c[j]
  587. c[j - 1] += c[j]
  588. der[0] = -c[1]
  589. c = der
  590. c = np.rollaxis(c, 0, iaxis + 1)
  591. return c
  592. def lagint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
  593. """
  594. Integrate a Laguerre series.
  595. Returns the Laguerre series coefficients `c` integrated `m` times from
  596. `lbnd` along `axis`. At each iteration the resulting series is
  597. **multiplied** by `scl` and an integration constant, `k`, is added.
  598. The scaling factor is for use in a linear change of variable. ("Buyer
  599. beware": note that, depending on what one is doing, one may want `scl`
  600. to be the reciprocal of what one might expect; for more information,
  601. see the Notes section below.) The argument `c` is an array of
  602. coefficients from low to high degree along each axis, e.g., [1,2,3]
  603. represents the series ``L_0 + 2*L_1 + 3*L_2`` while [[1,2],[1,2]]
  604. represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) + 2*L_0(x)*L_1(y) +
  605. 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
  606. Parameters
  607. ----------
  608. c : array_like
  609. Array of Laguerre series coefficients. If `c` is multidimensional
  610. the different axis correspond to different variables with the
  611. degree in each axis given by the corresponding index.
  612. m : int, optional
  613. Order of integration, must be positive. (Default: 1)
  614. k : {[], list, scalar}, optional
  615. Integration constant(s). The value of the first integral at
  616. ``lbnd`` is the first value in the list, the value of the second
  617. integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
  618. default), all constants are set to zero. If ``m == 1``, a single
  619. scalar can be given instead of a list.
  620. lbnd : scalar, optional
  621. The lower bound of the integral. (Default: 0)
  622. scl : scalar, optional
  623. Following each integration the result is *multiplied* by `scl`
  624. before the integration constant is added. (Default: 1)
  625. axis : int, optional
  626. Axis over which the integral is taken. (Default: 0).
  627. .. versionadded:: 1.7.0
  628. Returns
  629. -------
  630. S : ndarray
  631. Laguerre series coefficients of the integral.
  632. Raises
  633. ------
  634. ValueError
  635. If ``m < 0``, ``len(k) > m``, ``np.isscalar(lbnd) == False``, or
  636. ``np.isscalar(scl) == False``.
  637. See Also
  638. --------
  639. lagder
  640. Notes
  641. -----
  642. Note that the result of each integration is *multiplied* by `scl`.
  643. Why is this important to note? Say one is making a linear change of
  644. variable :math:`u = ax + b` in an integral relative to `x`. Then
  645. .. math::`dx = du/a`, so one will need to set `scl` equal to
  646. :math:`1/a` - perhaps not what one would have first thought.
  647. Also note that, in general, the result of integrating a C-series needs
  648. to be "reprojected" onto the C-series basis set. Thus, typically,
  649. the result of this function is "unintuitive," albeit correct; see
  650. Examples section below.
  651. Examples
  652. --------
  653. >>> from numpy.polynomial.laguerre import lagint
  654. >>> lagint([1,2,3])
  655. array([ 1., 1., 1., -3.])
  656. >>> lagint([1,2,3], m=2)
  657. array([ 1., 0., 0., -4., 3.])
  658. >>> lagint([1,2,3], k=1)
  659. array([ 2., 1., 1., -3.])
  660. >>> lagint([1,2,3], lbnd=-1)
  661. array([ 11.5, 1. , 1. , -3. ])
  662. >>> lagint([1,2], m=2, k=[1,2], lbnd=-1)
  663. array([ 11.16666667, -5. , -3. , 2. ])
  664. """
  665. c = np.array(c, ndmin=1, copy=1)
  666. if c.dtype.char in '?bBhHiIlLqQpP':
  667. c = c.astype(np.double)
  668. if not np.iterable(k):
  669. k = [k]
  670. cnt, iaxis = [int(t) for t in [m, axis]]
  671. if cnt != m:
  672. raise ValueError("The order of integration must be integer")
  673. if cnt < 0:
  674. raise ValueError("The order of integration must be non-negative")
  675. if len(k) > cnt:
  676. raise ValueError("Too many integration constants")
  677. if iaxis != axis:
  678. raise ValueError("The axis must be integer")
  679. if not -c.ndim <= iaxis < c.ndim:
  680. raise ValueError("The axis is out of range")
  681. if iaxis < 0:
  682. iaxis += c.ndim
  683. if cnt == 0:
  684. return c
  685. c = np.rollaxis(c, iaxis)
  686. k = list(k) + [0]*(cnt - len(k))
  687. for i in range(cnt):
  688. n = len(c)
  689. c *= scl
  690. if n == 1 and np.all(c[0] == 0):
  691. c[0] += k[i]
  692. else:
  693. tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
  694. tmp[0] = c[0]
  695. tmp[1] = -c[0]
  696. for j in range(1, n):
  697. tmp[j] += c[j]
  698. tmp[j + 1] = -c[j]
  699. tmp[0] += k[i] - lagval(lbnd, tmp)
  700. c = tmp
  701. c = np.rollaxis(c, 0, iaxis + 1)
  702. return c
  703. def lagval(x, c, tensor=True):
  704. """
  705. Evaluate a Laguerre series at points x.
  706. If `c` is of length `n + 1`, this function returns the value:
  707. .. math:: p(x) = c_0 * L_0(x) + c_1 * L_1(x) + ... + c_n * L_n(x)
  708. The parameter `x` is converted to an array only if it is a tuple or a
  709. list, otherwise it is treated as a scalar. In either case, either `x`
  710. or its elements must support multiplication and addition both with
  711. themselves and with the elements of `c`.
  712. If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
  713. `c` is multidimensional, then the shape of the result depends on the
  714. value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
  715. x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
  716. scalars have shape (,).
  717. Trailing zeros in the coefficients will be used in the evaluation, so
  718. they should be avoided if efficiency is a concern.
  719. Parameters
  720. ----------
  721. x : array_like, compatible object
  722. If `x` is a list or tuple, it is converted to an ndarray, otherwise
  723. it is left unchanged and treated as a scalar. In either case, `x`
  724. or its elements must support addition and multiplication with
  725. with themselves and with the elements of `c`.
  726. c : array_like
  727. Array of coefficients ordered so that the coefficients for terms of
  728. degree n are contained in c[n]. If `c` is multidimensional the
  729. remaining indices enumerate multiple polynomials. In the two
  730. dimensional case the coefficients may be thought of as stored in
  731. the columns of `c`.
  732. tensor : boolean, optional
  733. If True, the shape of the coefficient array is extended with ones
  734. on the right, one for each dimension of `x`. Scalars have dimension 0
  735. for this action. The result is that every column of coefficients in
  736. `c` is evaluated for every element of `x`. If False, `x` is broadcast
  737. over the columns of `c` for the evaluation. This keyword is useful
  738. when `c` is multidimensional. The default value is True.
  739. .. versionadded:: 1.7.0
  740. Returns
  741. -------
  742. values : ndarray, algebra_like
  743. The shape of the return value is described above.
  744. See Also
  745. --------
  746. lagval2d, laggrid2d, lagval3d, laggrid3d
  747. Notes
  748. -----
  749. The evaluation uses Clenshaw recursion, aka synthetic division.
  750. Examples
  751. --------
  752. >>> from numpy.polynomial.laguerre import lagval
  753. >>> coef = [1,2,3]
  754. >>> lagval(1, coef)
  755. -0.5
  756. >>> lagval([[1,2],[3,4]], coef)
  757. array([[-0.5, -4. ],
  758. [-4.5, -2. ]])
  759. """
  760. c = np.array(c, ndmin=1, copy=0)
  761. if c.dtype.char in '?bBhHiIlLqQpP':
  762. c = c.astype(np.double)
  763. if isinstance(x, (tuple, list)):
  764. x = np.asarray(x)
  765. if isinstance(x, np.ndarray) and tensor:
  766. c = c.reshape(c.shape + (1,)*x.ndim)
  767. if len(c) == 1:
  768. c0 = c[0]
  769. c1 = 0
  770. elif len(c) == 2:
  771. c0 = c[0]
  772. c1 = c[1]
  773. else:
  774. nd = len(c)
  775. c0 = c[-2]
  776. c1 = c[-1]
  777. for i in range(3, len(c) + 1):
  778. tmp = c0
  779. nd = nd - 1
  780. c0 = c[-i] - (c1*(nd - 1))/nd
  781. c1 = tmp + (c1*((2*nd - 1) - x))/nd
  782. return c0 + c1*(1 - x)
  783. def lagval2d(x, y, c):
  784. """
  785. Evaluate a 2-D Laguerre series at points (x, y).
  786. This function returns the values:
  787. .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * L_i(x) * L_j(y)
  788. The parameters `x` and `y` are converted to arrays only if they are
  789. tuples or a lists, otherwise they are treated as a scalars and they
  790. must have the same shape after conversion. In either case, either `x`
  791. and `y` or their elements must support multiplication and addition both
  792. with themselves and with the elements of `c`.
  793. If `c` is a 1-D array a one is implicitly appended to its shape to make
  794. it 2-D. The shape of the result will be c.shape[2:] + x.shape.
  795. Parameters
  796. ----------
  797. x, y : array_like, compatible objects
  798. The two dimensional series is evaluated at the points `(x, y)`,
  799. where `x` and `y` must have the same shape. If `x` or `y` is a list
  800. or tuple, it is first converted to an ndarray, otherwise it is left
  801. unchanged and if it isn't an ndarray it is treated as a scalar.
  802. c : array_like
  803. Array of coefficients ordered so that the coefficient of the term
  804. of multi-degree i,j is contained in ``c[i,j]``. If `c` has
  805. dimension greater than two the remaining indices enumerate multiple
  806. sets of coefficients.
  807. Returns
  808. -------
  809. values : ndarray, compatible object
  810. The values of the two dimensional polynomial at points formed with
  811. pairs of corresponding values from `x` and `y`.
  812. See Also
  813. --------
  814. lagval, laggrid2d, lagval3d, laggrid3d
  815. Notes
  816. -----
  817. .. versionadded::1.7.0
  818. """
  819. try:
  820. x, y = np.array((x, y), copy=0)
  821. except:
  822. raise ValueError('x, y are incompatible')
  823. c = lagval(x, c)
  824. c = lagval(y, c, tensor=False)
  825. return c
  826. def laggrid2d(x, y, c):
  827. """
  828. Evaluate a 2-D Laguerre series on the Cartesian product of x and y.
  829. This function returns the values:
  830. .. math:: p(a,b) = \sum_{i,j} c_{i,j} * L_i(a) * L_j(b)
  831. where the points `(a, b)` consist of all pairs formed by taking
  832. `a` from `x` and `b` from `y`. The resulting points form a grid with
  833. `x` in the first dimension and `y` in the second.
  834. The parameters `x` and `y` are converted to arrays only if they are
  835. tuples or a lists, otherwise they are treated as a scalars. In either
  836. case, either `x` and `y` or their elements must support multiplication
  837. and addition both with themselves and with the elements of `c`.
  838. If `c` has fewer than two dimensions, ones are implicitly appended to
  839. its shape to make it 2-D. The shape of the result will be c.shape[2:] +
  840. x.shape + y.shape.
  841. Parameters
  842. ----------
  843. x, y : array_like, compatible objects
  844. The two dimensional series is evaluated at the points in the
  845. Cartesian product of `x` and `y`. If `x` or `y` is a list or
  846. tuple, it is first converted to an ndarray, otherwise it is left
  847. unchanged and, if it isn't an ndarray, it is treated as a scalar.
  848. c : array_like
  849. Array of coefficients ordered so that the coefficient of the term of
  850. multi-degree i,j is contained in `c[i,j]`. If `c` has dimension
  851. greater than two the remaining indices enumerate multiple sets of
  852. coefficients.
  853. Returns
  854. -------
  855. values : ndarray, compatible object
  856. The values of the two dimensional Chebyshev series at points in the
  857. Cartesian product of `x` and `y`.
  858. See Also
  859. --------
  860. lagval, lagval2d, lagval3d, laggrid3d
  861. Notes
  862. -----
  863. .. versionadded::1.7.0
  864. """
  865. c = lagval(x, c)
  866. c = lagval(y, c)
  867. return c
  868. def lagval3d(x, y, z, c):
  869. """
  870. Evaluate a 3-D Laguerre series at points (x, y, z).
  871. This function returns the values:
  872. .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * L_i(x) * L_j(y) * L_k(z)
  873. The parameters `x`, `y`, and `z` are converted to arrays only if
  874. they are tuples or a lists, otherwise they are treated as a scalars and
  875. they must have the same shape after conversion. In either case, either
  876. `x`, `y`, and `z` or their elements must support multiplication and
  877. addition both with themselves and with the elements of `c`.
  878. If `c` has fewer than 3 dimensions, ones are implicitly appended to its
  879. shape to make it 3-D. The shape of the result will be c.shape[3:] +
  880. x.shape.
  881. Parameters
  882. ----------
  883. x, y, z : array_like, compatible object
  884. The three dimensional series is evaluated at the points
  885. `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
  886. any of `x`, `y`, or `z` is a list or tuple, it is first converted
  887. to an ndarray, otherwise it is left unchanged and if it isn't an
  888. ndarray it is treated as a scalar.
  889. c : array_like
  890. Array of coefficients ordered so that the coefficient of the term of
  891. multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
  892. greater than 3 the remaining indices enumerate multiple sets of
  893. coefficients.
  894. Returns
  895. -------
  896. values : ndarray, compatible object
  897. The values of the multidimension polynomial on points formed with
  898. triples of corresponding values from `x`, `y`, and `z`.
  899. See Also
  900. --------
  901. lagval, lagval2d, laggrid2d, laggrid3d
  902. Notes
  903. -----
  904. .. versionadded::1.7.0
  905. """
  906. try:
  907. x, y, z = np.array((x, y, z), copy=0)
  908. except:
  909. raise ValueError('x, y, z are incompatible')
  910. c = lagval(x, c)
  911. c = lagval(y, c, tensor=False)
  912. c = lagval(z, c, tensor=False)
  913. return c
  914. def laggrid3d(x, y, z, c):
  915. """
  916. Evaluate a 3-D Laguerre series on the Cartesian product of x, y, and z.
  917. This function returns the values:
  918. .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * L_i(a) * L_j(b) * L_k(c)
  919. where the points `(a, b, c)` consist of all triples formed by taking
  920. `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
  921. a grid with `x` in the first dimension, `y` in the second, and `z` in
  922. the third.
  923. The parameters `x`, `y`, and `z` are converted to arrays only if they
  924. are tuples or a lists, otherwise they are treated as a scalars. In
  925. either case, either `x`, `y`, and `z` or their elements must support
  926. multiplication and addition both with themselves and with the elements
  927. of `c`.
  928. If `c` has fewer than three dimensions, ones are implicitly appended to
  929. its shape to make it 3-D. The shape of the result will be c.shape[3:] +
  930. x.shape + y.shape + z.shape.
  931. Parameters
  932. ----------
  933. x, y, z : array_like, compatible objects
  934. The three dimensional series is evaluated at the points in the
  935. Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
  936. list or tuple, it is first converted to an ndarray, otherwise it is
  937. left unchanged and, if it isn't an ndarray, it is treated as a
  938. scalar.
  939. c : array_like
  940. Array of coefficients ordered so that the coefficients for terms of
  941. degree i,j are contained in ``c[i,j]``. If `c` has dimension
  942. greater than two the remaining indices enumerate multiple sets of
  943. coefficients.
  944. Returns
  945. -------
  946. values : ndarray, compatible object
  947. The values of the two dimensional polynomial at points in the Cartesian
  948. product of `x` and `y`.
  949. See Also
  950. --------
  951. lagval, lagval2d, laggrid2d, lagval3d
  952. Notes
  953. -----
  954. .. versionadded::1.7.0
  955. """
  956. c = lagval(x, c)
  957. c = lagval(y, c)
  958. c = lagval(z, c)
  959. return c
  960. def lagvander(x, deg):
  961. """Pseudo-Vandermonde matrix of given degree.
  962. Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
  963. `x`. The pseudo-Vandermonde matrix is defined by
  964. .. math:: V[..., i] = L_i(x)
  965. where `0 <= i <= deg`. The leading indices of `V` index the elements of
  966. `x` and the last index is the degree of the Laguerre polynomial.
  967. If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
  968. array ``V = lagvander(x, n)``, then ``np.dot(V, c)`` and
  969. ``lagval(x, c)`` are the same up to roundoff. This equivalence is
  970. useful both for least squares fitting and for the evaluation of a large
  971. number of Laguerre series of the same degree and sample points.
  972. Parameters
  973. ----------
  974. x : array_like
  975. Array of points. The dtype is converted to float64 or complex128
  976. depending on whether any of the elements are complex. If `x` is
  977. scalar it is converted to a 1-D array.
  978. deg : int
  979. Degree of the resulting matrix.
  980. Returns
  981. -------
  982. vander : ndarray
  983. The pseudo-Vandermonde matrix. The shape of the returned matrix is
  984. ``x.shape + (deg + 1,)``, where The last index is the degree of the
  985. corresponding Laguerre polynomial. The dtype will be the same as
  986. the converted `x`.
  987. Examples
  988. --------
  989. >>> from numpy.polynomial.laguerre import lagvander
  990. >>> x = np.array([0, 1, 2])
  991. >>> lagvander(x, 3)
  992. array([[ 1. , 1. , 1. , 1. ],
  993. [ 1. , 0. , -0.5 , -0.66666667],
  994. [ 1. , -1. , -1. , -0.33333333]])
  995. """
  996. ideg = int(deg)
  997. if ideg != deg:
  998. raise ValueError("deg must be integer")
  999. if ideg < 0:
  1000. raise ValueError("deg must be non-negative")
  1001. x = np.array(x, copy=0, ndmin=1) + 0.0
  1002. dims = (ideg + 1,) + x.shape
  1003. dtyp = x.dtype
  1004. v = np.empty(dims, dtype=dtyp)
  1005. v[0] = x*0 + 1
  1006. if ideg > 0:
  1007. v[1] = 1 - x
  1008. for i in range(2, ideg + 1):
  1009. v[i] = (v[i-1]*(2*i - 1 - x) - v[i-2]*(i - 1))/i
  1010. return np.rollaxis(v, 0, v.ndim)
  1011. def lagvander2d(x, y, deg):
  1012. """Pseudo-Vandermonde matrix of given degrees.
  1013. Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
  1014. points `(x, y)`. The pseudo-Vandermonde matrix is defined by
  1015. .. math:: V[..., deg[1]*i + j] = L_i(x) * L_j(y),
  1016. where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
  1017. `V` index the points `(x, y)` and the last index encodes the degrees of
  1018. the Laguerre polynomials.
  1019. If ``V = lagvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
  1020. correspond to the elements of a 2-D coefficient array `c` of shape
  1021. (xdeg + 1, ydeg + 1) in the order
  1022. .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
  1023. and ``np.dot(V, c.flat)`` and ``lagval2d(x, y, c)`` will be the same
  1024. up to roundoff. This equivalence is useful both for least squares
  1025. fitting and for the evaluation of a large number of 2-D Laguerre
  1026. series of the same degrees and sample points.
  1027. Parameters
  1028. ----------
  1029. x, y : array_like
  1030. Arrays of point coordinates, all of the same shape. The dtypes
  1031. will be converted to either float64 or complex128 depending on
  1032. whether any of the elements are complex. Scalars are converted to
  1033. 1-D arrays.
  1034. deg : list of ints
  1035. List of maximum degrees of the form [x_deg, y_deg].
  1036. Returns
  1037. -------
  1038. vander2d : ndarray
  1039. The shape of the returned matrix is ``x.shape + (order,)``, where
  1040. :math:`order = (deg[0]+1)*(deg([1]+1)`. The dtype will be the same
  1041. as the converted `x` and `y`.
  1042. See Also
  1043. --------
  1044. lagvander, lagvander3d. lagval2d, lagval3d
  1045. Notes
  1046. -----
  1047. .. versionadded::1.7.0
  1048. """
  1049. ideg = [int(d) for d in deg]
  1050. is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
  1051. if is_valid != [1, 1]:
  1052. raise ValueError("degrees must be non-negative integers")
  1053. degx, degy = ideg
  1054. x, y = np.array((x, y), copy=0) + 0.0
  1055. vx = lagvander(x, degx)
  1056. vy = lagvander(y, degy)
  1057. v = vx[..., None]*vy[..., None,:]
  1058. return v.reshape(v.shape[:-2] + (-1,))
  1059. def lagvander3d(x, y, z, deg):
  1060. """Pseudo-Vandermonde matrix of given degrees.
  1061. Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
  1062. points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
  1063. then The pseudo-Vandermonde matrix is defined by
  1064. .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = L_i(x)*L_j(y)*L_k(z),
  1065. where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
  1066. indices of `V` index the points `(x, y, z)` and the last index encodes
  1067. the degrees of the Laguerre polynomials.
  1068. If ``V = lagvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
  1069. of `V` correspond to the elements of a 3-D coefficient array `c` of
  1070. shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
  1071. .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
  1072. and ``np.dot(V, c.flat)`` and ``lagval3d(x, y, z, c)`` will be the
  1073. same up to roundoff. This equivalence is useful both for least squares
  1074. fitting and for the evaluation of a large number of 3-D Laguerre
  1075. series of the same degrees and sample points.
  1076. Parameters
  1077. ----------
  1078. x, y, z : array_like
  1079. Arrays of point coordinates, all of the same shape. The dtypes will
  1080. be converted to either float64 or complex128 depending on whether
  1081. any of the elements are complex. Scalars are converted to 1-D
  1082. arrays.
  1083. deg : list of ints
  1084. List of maximum degrees of the form [x_deg, y_deg, z_deg].
  1085. Returns
  1086. -------
  1087. vander3d : ndarray
  1088. The shape of the returned matrix is ``x.shape + (order,)``, where
  1089. :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`. The dtype will
  1090. be the same as the converted `x`, `y`, and `z`.
  1091. See Also
  1092. --------
  1093. lagvander, lagvander3d. lagval2d, lagval3d
  1094. Notes
  1095. -----
  1096. .. versionadded::1.7.0
  1097. """
  1098. ideg = [int(d) for d in deg]
  1099. is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
  1100. if is_valid != [1, 1, 1]:
  1101. raise ValueError("degrees must be non-negative integers")
  1102. degx, degy, degz = ideg
  1103. x, y, z = np.array((x, y, z), copy=0) + 0.0
  1104. vx = lagvander(x, degx)
  1105. vy = lagvander(y, degy)
  1106. vz = lagvander(z, degz)
  1107. v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
  1108. return v.reshape(v.shape[:-3] + (-1,))
  1109. def lagfit(x, y, deg, rcond=None, full=False, w=None):
  1110. """
  1111. Least squares fit of Laguerre series to data.
  1112. Return the coefficients of a Laguerre series of degree `deg` that is the
  1113. least squares fit to the data values `y` given at points `x`. If `y` is
  1114. 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
  1115. fits are done, one for each column of `y`, and the resulting
  1116. coefficients are stored in the corresponding columns of a 2-D return.
  1117. The fitted polynomial(s) are in the form
  1118. .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x),
  1119. where `n` is `deg`.
  1120. Parameters
  1121. ----------
  1122. x : array_like, shape (M,)
  1123. x-coordinates of the M sample points ``(x[i], y[i])``.
  1124. y : array_like, shape (M,) or (M, K)
  1125. y-coordinates of the sample points. Several data sets of sample
  1126. points sharing the same x-coordinates can be fitted at once by
  1127. passing in a 2D-array that contains one dataset per column.
  1128. deg : int or 1-D array_like
  1129. Degree(s) of the fitting polynomials. If `deg` is a single integer
  1130. all terms up to and including the `deg`'th term are included in the
  1131. fit. For Numpy versions >= 1.11 a list of integers specifying the
  1132. degrees of the terms to include may be used instead.
  1133. rcond : float, optional
  1134. Relative condition number of the fit. Singular values smaller than
  1135. this relative to the largest singular value will be ignored. The
  1136. default value is len(x)*eps, where eps is the relative precision of
  1137. the float type, about 2e-16 in most cases.
  1138. full : bool, optional
  1139. Switch determining nature of return value. When it is False (the
  1140. default) just the coefficients are returned, when True diagnostic
  1141. information from the singular value decomposition is also returned.
  1142. w : array_like, shape (`M`,), optional
  1143. Weights. If not None, the contribution of each point
  1144. ``(x[i],y[i])`` to the fit is weighted by `w[i]`. Ideally the
  1145. weights are chosen so that the errors of the products ``w[i]*y[i]``
  1146. all have the same variance. The default value is None.
  1147. Returns
  1148. -------
  1149. coef : ndarray, shape (M,) or (M, K)
  1150. Laguerre coefficients ordered from low to high. If `y` was 2-D,
  1151. the coefficients for the data in column k of `y` are in column
  1152. `k`.
  1153. [residuals, rank, singular_values, rcond] : list
  1154. These values are only returned if `full` = True
  1155. resid -- sum of squared residuals of the least squares fit
  1156. rank -- the numerical rank of the scaled Vandermonde matrix
  1157. sv -- singular values of the scaled Vandermonde matrix
  1158. rcond -- value of `rcond`.
  1159. For more details, see `linalg.lstsq`.
  1160. Warns
  1161. -----
  1162. RankWarning
  1163. The rank of the coefficient matrix in the least-squares fit is
  1164. deficient. The warning is only raised if `full` = False. The
  1165. warnings can be turned off by
  1166. >>> import warnings
  1167. >>> warnings.simplefilter('ignore', RankWarning)
  1168. See Also
  1169. --------
  1170. chebfit, legfit, polyfit, hermfit, hermefit
  1171. lagval : Evaluates a Laguerre series.
  1172. lagvander : pseudo Vandermonde matrix of Laguerre series.
  1173. lagweight : Laguerre weight function.
  1174. linalg.lstsq : Computes a least-squares fit from the matrix.
  1175. scipy.interpolate.UnivariateSpline : Computes spline fits.
  1176. Notes
  1177. -----
  1178. The solution is the coefficients of the Laguerre series `p` that
  1179. minimizes the sum of the weighted squared errors
  1180. .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
  1181. where the :math:`w_j` are the weights. This problem is solved by
  1182. setting up as the (typically) overdetermined matrix equation
  1183. .. math:: V(x) * c = w * y,
  1184. where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
  1185. coefficients to be solved for, `w` are the weights, and `y` are the
  1186. observed values. This equation is then solved using the singular value
  1187. decomposition of `V`.
  1188. If some of the singular values of `V` are so small that they are
  1189. neglected, then a `RankWarning` will be issued. This means that the
  1190. coefficient values may be poorly determined. Using a lower order fit
  1191. will usually get rid of the warning. The `rcond` parameter can also be
  1192. set to a value smaller than its default, but the resulting fit may be
  1193. spurious and have large contributions from roundoff error.
  1194. Fits using Laguerre series are probably most useful when the data can
  1195. be approximated by ``sqrt(w(x)) * p(x)``, where `w(x)` is the Laguerre
  1196. weight. In that case the weight ``sqrt(w(x[i])`` should be used
  1197. together with data values ``y[i]/sqrt(w(x[i])``. The weight function is
  1198. available as `lagweight`.
  1199. References
  1200. ----------
  1201. .. [1] Wikipedia, "Curve fitting",
  1202. http://en.wikipedia.org/wiki/Curve_fitting
  1203. Examples
  1204. --------
  1205. >>> from numpy.polynomial.laguerre import lagfit, lagval
  1206. >>> x = np.linspace(0, 10)
  1207. >>> err = np.random.randn(len(x))/10
  1208. >>> y = lagval(x, [1, 2, 3]) + err
  1209. >>> lagfit(x, y, 2)
  1210. array([ 0.96971004, 2.00193749, 3.00288744])
  1211. """
  1212. x = np.asarray(x) + 0.0
  1213. y = np.asarray(y) + 0.0
  1214. deg = np.asarray(deg)
  1215. # check arguments.
  1216. if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
  1217. raise TypeError("deg must be an int or non-empty 1-D array of int")
  1218. if deg.min() < 0:
  1219. raise ValueError("expected deg >= 0")
  1220. if x.ndim != 1:
  1221. raise TypeError("expected 1D vector for x")
  1222. if x.size == 0:
  1223. raise TypeError("expected non-empty vector for x")
  1224. if y.ndim < 1 or y.ndim > 2:
  1225. raise TypeError("expected 1D or 2D array for y")
  1226. if len(x) != len(y):
  1227. raise TypeError("expected x and y to have same length")
  1228. if deg.ndim == 0:
  1229. lmax = deg
  1230. order = lmax + 1
  1231. van = lagvander(x, lmax)
  1232. else:
  1233. deg = np.sort(deg)
  1234. lmax = deg[-1]
  1235. order = len(deg)
  1236. van = lagvander(x, lmax)[:, deg]
  1237. # set up the least squares matrices in transposed form
  1238. lhs = van.T
  1239. rhs = y.T
  1240. if w is not None:
  1241. w = np.asarray(w) + 0.0
  1242. if w.ndim != 1:
  1243. raise TypeError("expected 1D vector for w")
  1244. if len(x) != len(w):
  1245. raise TypeError("expected x and w to have same length")
  1246. # apply weights. Don't use inplace operations as they
  1247. # can cause problems with NA.
  1248. lhs = lhs * w
  1249. rhs = rhs * w
  1250. # set rcond
  1251. if rcond is None:
  1252. rcond = len(x)*np.finfo(x.dtype).eps
  1253. # Determine the norms of the design matrix columns.
  1254. if issubclass(lhs.dtype.type, np.complexfloating):
  1255. scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
  1256. else:
  1257. scl = np.sqrt(np.square(lhs).sum(1))
  1258. scl[scl == 0] = 1
  1259. # Solve the least squares problem.
  1260. c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond)
  1261. c = (c.T/scl).T
  1262. # Expand c to include non-fitted coefficients which are set to zero
  1263. if deg.ndim > 0:
  1264. if c.ndim == 2:
  1265. cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
  1266. else:
  1267. cc = np.zeros(lmax+1, dtype=c.dtype)
  1268. cc[deg] = c
  1269. c = cc
  1270. # warn on rank reduction
  1271. if rank != order and not full:
  1272. msg = "The fit may be poorly conditioned"
  1273. warnings.warn(msg, pu.RankWarning)
  1274. if full:
  1275. return c, [resids, rank, s, rcond]
  1276. else:
  1277. return c
  1278. def lagcompanion(c):
  1279. """
  1280. Return the companion matrix of c.
  1281. The usual companion matrix of the Laguerre polynomials is already
  1282. symmetric when `c` is a basis Laguerre polynomial, so no scaling is
  1283. applied.
  1284. Parameters
  1285. ----------
  1286. c : array_like
  1287. 1-D array of Laguerre series coefficients ordered from low to high
  1288. degree.
  1289. Returns
  1290. -------
  1291. mat : ndarray
  1292. Companion matrix of dimensions (deg, deg).
  1293. Notes
  1294. -----
  1295. .. versionadded::1.7.0
  1296. """
  1297. # c is a trimmed copy
  1298. [c] = pu.as_series([c])
  1299. if len(c) < 2:
  1300. raise ValueError('Series must have maximum degree of at least 1.')
  1301. if len(c) == 2:
  1302. return np.array([[1 + c[0]/c[1]]])
  1303. n = len(c) - 1
  1304. mat = np.zeros((n, n), dtype=c.dtype)
  1305. top = mat.reshape(-1)[1::n+1]
  1306. mid = mat.reshape(-1)[0::n+1]
  1307. bot = mat.reshape(-1)[n::n+1]
  1308. top[...] = -np.arange(1, n)
  1309. mid[...] = 2.*np.arange(n) + 1.
  1310. bot[...] = top
  1311. mat[:, -1] += (c[:-1]/c[-1])*n
  1312. return mat
  1313. def lagroots(c):
  1314. """
  1315. Compute the roots of a Laguerre series.
  1316. Return the roots (a.k.a. "zeros") of the polynomial
  1317. .. math:: p(x) = \\sum_i c[i] * L_i(x).
  1318. Parameters
  1319. ----------
  1320. c : 1-D array_like
  1321. 1-D array of coefficients.
  1322. Returns
  1323. -------
  1324. out : ndarray
  1325. Array of the roots of the series. If all the roots are real,
  1326. then `out` is also real, otherwise it is complex.
  1327. See Also
  1328. --------
  1329. polyroots, legroots, chebroots, hermroots, hermeroots
  1330. Notes
  1331. -----
  1332. The root estimates are obtained as the eigenvalues of the companion
  1333. matrix, Roots far from the origin of the complex plane may have large
  1334. errors due to the numerical instability of the series for such
  1335. values. Roots with multiplicity greater than 1 will also show larger
  1336. errors as the value of the series near such points is relatively
  1337. insensitive to errors in the roots. Isolated roots near the origin can
  1338. be improved by a few iterations of Newton's method.
  1339. The Laguerre series basis polynomials aren't powers of `x` so the
  1340. results of this function may seem unintuitive.
  1341. Examples
  1342. --------
  1343. >>> from numpy.polynomial.laguerre import lagroots, lagfromroots
  1344. >>> coef = lagfromroots([0, 1, 2])
  1345. >>> coef
  1346. array([ 2., -8., 12., -6.])
  1347. >>> lagroots(coef)
  1348. array([ -4.44089210e-16, 1.00000000e+00, 2.00000000e+00])
  1349. """
  1350. # c is a trimmed copy
  1351. [c] = pu.as_series([c])
  1352. if len(c) <= 1:
  1353. return np.array([], dtype=c.dtype)
  1354. if len(c) == 2:
  1355. return np.array([1 + c[0]/c[1]])
  1356. m = lagcompanion(c)
  1357. r = la.eigvals(m)
  1358. r.sort()
  1359. return r
  1360. def laggauss(deg):
  1361. """
  1362. Gauss-Laguerre quadrature.
  1363. Computes the sample points and weights for Gauss-Laguerre quadrature.
  1364. These sample points and weights will correctly integrate polynomials of
  1365. degree :math:`2*deg - 1` or less over the interval :math:`[0, \inf]`
  1366. with the weight function :math:`f(x) = \exp(-x)`.
  1367. Parameters
  1368. ----------
  1369. deg : int
  1370. Number of sample points and weights. It must be >= 1.
  1371. Returns
  1372. -------
  1373. x : ndarray
  1374. 1-D ndarray containing the sample points.
  1375. y : ndarray
  1376. 1-D ndarray containing the weights.
  1377. Notes
  1378. -----
  1379. .. versionadded::1.7.0
  1380. The results have only been tested up to degree 100 higher degrees may
  1381. be problematic. The weights are determined by using the fact that
  1382. .. math:: w_k = c / (L'_n(x_k) * L_{n-1}(x_k))
  1383. where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
  1384. is the k'th root of :math:`L_n`, and then scaling the results to get
  1385. the right value when integrating 1.
  1386. """
  1387. ideg = int(deg)
  1388. if ideg != deg or ideg < 1:
  1389. raise ValueError("deg must be a non-negative integer")
  1390. # first approximation of roots. We use the fact that the companion
  1391. # matrix is symmetric in this case in order to obtain better zeros.
  1392. c = np.array([0]*deg + [1])
  1393. m = lagcompanion(c)
  1394. x = la.eigvalsh(m)
  1395. # improve roots by one application of Newton
  1396. dy = lagval(x, c)
  1397. df = lagval(x, lagder(c))
  1398. x -= dy/df
  1399. # compute the weights. We scale the factor to avoid possible numerical
  1400. # overflow.
  1401. fm = lagval(x, c[1:])
  1402. fm /= np.abs(fm).max()
  1403. df /= np.abs(df).max()
  1404. w = 1/(fm * df)
  1405. # scale w to get the right value, 1 in this case
  1406. w /= w.sum()
  1407. return x, w
  1408. def lagweight(x):
  1409. """Weight function of the Laguerre polynomials.
  1410. The weight function is :math:`exp(-x)` and the interval of integration
  1411. is :math:`[0, \inf]`. The Laguerre polynomials are orthogonal, but not
  1412. normalized, with respect to this weight function.
  1413. Parameters
  1414. ----------
  1415. x : array_like
  1416. Values at which the weight function will be computed.
  1417. Returns
  1418. -------
  1419. w : ndarray
  1420. The weight function at `x`.
  1421. Notes
  1422. -----
  1423. .. versionadded::1.7.0
  1424. """
  1425. w = np.exp(-x)
  1426. return w
  1427. #
  1428. # Laguerre series class
  1429. #
  1430. class Laguerre(ABCPolyBase):
  1431. """A Laguerre series class.
  1432. The Laguerre class provides the standard Python numerical methods
  1433. '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
  1434. attributes and methods listed in the `ABCPolyBase` documentation.
  1435. Parameters
  1436. ----------
  1437. coef : array_like
  1438. Laguerre coefficients in order of increasing degree, i.e,
  1439. ``(1, 2, 3)`` gives ``1*L_0(x) + 2*L_1(X) + 3*L_2(x)``.
  1440. domain : (2,) array_like, optional
  1441. Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
  1442. to the interval ``[window[0], window[1]]`` by shifting and scaling.
  1443. The default value is [0, 1].
  1444. window : (2,) array_like, optional
  1445. Window, see `domain` for its use. The default value is [0, 1].
  1446. .. versionadded:: 1.6.0
  1447. """
  1448. # Virtual Functions
  1449. _add = staticmethod(lagadd)
  1450. _sub = staticmethod(lagsub)
  1451. _mul = staticmethod(lagmul)
  1452. _div = staticmethod(lagdiv)
  1453. _pow = staticmethod(lagpow)
  1454. _val = staticmethod(lagval)
  1455. _int = staticmethod(lagint)
  1456. _der = staticmethod(lagder)
  1457. _fit = staticmethod(lagfit)
  1458. _line = staticmethod(lagline)
  1459. _roots = staticmethod(lagroots)
  1460. _fromroots = staticmethod(lagfromroots)
  1461. # Virtual properties
  1462. nickname = 'lag'
  1463. domain = np.array(lagdomain)
  1464. window = np.array(lagdomain)