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