]>
gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/interpolation.py
5 def lagrange_denominator(k
, xs
):
7 Return the denominator of the kth Lagrange coefficient.
11 - ``k`` -- The index of the coefficient.
13 - ``xs`` -- The list of points at which the function values are
18 The product of all xs[j] with j != k.
21 return product( xs
[k
] - xs
[j
] for j
in xrange(len(xs
)) if j
!= k
)
24 def lagrange_coefficient(k
, x
, xs
):
26 Returns the coefficient function l_{k}(variable) of y_{k} in the
27 Lagrange polynomial of f. See,
29 http://en.wikipedia.org/wiki/Lagrange_polynomial
35 - ``k`` -- The index of the coefficient.
37 - ``x`` -- The symbolic variable to use for the first argument
40 - ``xs`` -- The list of points at which the function values are
45 A symbolic expression of one variable.
49 sage: from mjo.interpolation import lagrange_coefficient
53 sage: xs = [ -pi/2, -pi/6, 0, pi/6, pi/2 ]
54 sage: lagrange_coefficient(0, x, xs)
55 1/8*(pi + 6*x)*(pi - 2*x)*(pi - 6*x)*x/pi^4
58 numerator
= lagrange_psi(x
, xs
)/(x
- xs
[k
])
59 denominator
= lagrange_denominator(k
, xs
)
61 return (numerator
/ denominator
)
65 def lagrange_polynomial(x
, xs
, ys
):
67 Return the Lagrange form of the interpolating polynomial in `x`
68 at the points (xs[k], ys[k]).
72 - ``x`` - The independent variable of the resulting polynomial.
74 - ``xs`` - The list of points at which we interpolate `f`.
76 - ``ys`` - The function values at `xs`.
80 A symbolic expression (polynomial) interpolating each (xs[k], ys[k]).
84 sage: from mjo.interpolation import lagrange_polynomial
88 sage: xs = [ -pi/2, -pi/6, 0, pi/6, pi/2 ]
89 sage: ys = map(sin, xs)
90 sage: L = lagrange_polynomial(x, xs, ys)
91 sage: expected = 27/16*(pi - 6*x)*(pi - 2*x)*(pi + 2*x)*x/pi^4
92 sage: expected -= 1/8*(pi - 6*x)*(pi - 2*x)*(pi + 6*x)*x/pi^4
93 sage: expected -= 1/8*(pi - 6*x)*(pi + 2*x)*(pi + 6*x)*x/pi^4
94 sage: expected += 27/16*(pi - 2*x)*(pi + 2*x)*(pi + 6*x)*x/pi^4
95 sage: bool(L == expected)
99 ls
= [ lagrange_coefficient(k
, x
, xs
) for k
in xrange(len(xs
)) ]
100 return sum( ys
[k
] * ls
[k
] for k
in xrange(len(xs
)) )
104 def lagrange_interpolate(f
, x
, xs
):
106 Interpolate the function ``f`` at the points ``xs`` using the
107 Lagrange form of the interpolating polynomial.
111 - ``f`` -- The function to interpolate.
113 - ``x`` -- The independent variable of the resulting polynomial.
115 - ``xs`` -- A list of points at which to interpolate ``f``.
119 A polynomial in ``x`` which interpolates ``f`` at ``xs``.
123 sage: from mjo.interpolation import lagrange_interpolate
127 We're exact on polynomials of degree `n` if we use `n+1` points::
129 sage: t = SR.symbol('t', domain='real')
130 sage: lagrange_interpolate(x^2, t, [-1,0,1]).simplify_rational()
134 # f should be a function of one variable.
136 # We're really just doing map(f, xs) here; the additional
137 # gymnastics are to avoid a warning when calling `f` with an
139 ys
= [ f({z: xk}
) for xk
in xs
]
140 return lagrange_polynomial(x
, xs
, ys
)
144 def divided_difference_coefficients(xs
):
146 Assuming some function `f`, compute the coefficients of the
147 divided difference f[xs[0], ..., xs[n]].
151 sage: from mjo.interpolation import divided_difference_coefficients
155 sage: divided_difference_coefficients([0])
157 sage: divided_difference_coefficients([0, pi])
159 sage: divided_difference_coefficients([0, pi, 2*pi])
160 [1/2/pi^2, -1/pi^2, 1/2/pi^2]
163 return [ ~
lagrange_denominator(k
, xs
) for k
in xrange(len(xs
)) ]
166 def divided_difference(xs
, ys
):
168 Return the Newton divided difference of the points (xs[k],
171 http://en.wikipedia.org/wiki/Divided_differences
175 - ``xs`` -- The list of x-values.
177 - ``ys`` -- The function values at `xs`.
181 The (possibly symbolic) divided difference function.
185 sage: from mjo.interpolation import divided_difference
190 sage: ys = map(sin, xs)
191 sage: divided_difference(xs, ys)
194 sage: ys = map(sin, xs)
195 sage: divided_difference(xs, ys)
197 sage: xs = [0, pi, 2*pi]
198 sage: ys = map(sin, xs)
199 sage: divided_difference(xs, ys)
202 We try something entirely symbolic::
204 sage: f = function('f')(x)
205 sage: divided_difference([x], [f(x=x)])
207 sage: x1,x2 = SR.var('x1,x2')
208 sage: divided_difference([x1,x2], [f(x=x1),f(x=x2)])
209 f(x1)/(x1 - x2) - f(x2)/(x1 - x2)
212 coeffs
= divided_difference_coefficients(xs
)
213 v_cs
= vector(coeffs
)
215 return v_cs
.dot_product(v_ys
)
218 def newton_polynomial(x
, xs
, ys
):
220 Return the Newton form of the interpolating polynomial of the
221 points (xs[k], ys[k]) in the variable `x`.
225 - ``x`` -- The independent variable to use for the interpolating
228 - ``xs`` -- The list of x-values.
230 - ``ys`` -- The function values at `xs`.
234 A symbolic expression.
238 sage: from mjo.interpolation import lagrange_polynomial, newton_polynomial
242 sage: xs = [ -pi/2, -pi/6, 0, pi/6, pi/2 ]
243 sage: ys = map(sin, xs)
244 sage: L = lagrange_polynomial(x, xs, ys)
245 sage: N = newton_polynomial(x, xs, ys)
250 return sum( divided_difference(xs
[:k
+1], ys
[:k
+1])*lagrange_psi(x
, xs
[:k
])
251 for k
in xrange(len(xs
)) )
254 def hermite_coefficient(k
, x
, xs
):
256 Return the Hermite coefficient h_{k}(x). See Atkinson, p. 160.
260 - ``k`` -- The index of the coefficient.
262 - ``x`` -- The symbolic variable to use as the argument of h_{k}.
264 - ``xs`` -- The list of points at which the function values are
269 A symbolic expression.
272 lk
= lagrange_coefficient(k
, x
, xs
)
273 return (1 - 2*lk
.diff(x
)(x
=xs
[k
])*(x
- xs
[k
]))*(lk
**2)
276 def hermite_deriv_coefficient(k
, x
, xs
):
278 Return the Hermite derivative coefficient, \tilde{h}_{k}(x). See
283 - ``k`` -- The index of the coefficient.
285 - ``x`` -- The symbolic variable to use as the argument of h_{k}.
287 - ``xs`` -- The list of points at which the function values are
292 A symbolic expression.
295 lk
= lagrange_coefficient(k
, x
, xs
)
296 return (x
- xs
[k
])*(lk
**2)
299 def hermite_interpolant(x
, xs
, ys
, y_primes
):
301 Return the Hermite interpolant `H(x)` such that H(xs[k]) = ys[k]
302 and H'(xs[k]) = y_primes[k] for each k.
304 Reference: Atkinson, p. 160.
308 - ``x`` -- The symbolic variable to use as the argument of H(x).
310 - ``xs`` -- The list of points at which the function values are
313 - ``ys`` -- The function values at the `xs`.
315 - ``y_primes`` -- The derivatives at the `xs`.
319 A symbolic expression.
323 sage: from mjo.interpolation import hermite_interpolant
327 sage: xs = [ 0, pi/6, pi/2 ]
328 sage: ys = map(sin, xs)
329 sage: y_primes = map(cos, xs)
330 sage: H = hermite_interpolant(x, xs, ys, y_primes)
331 sage: expected = -27/4*(pi - 6*x)*(pi - 2*x)^2*sqrt(3)*x^2/pi^4
332 sage: expected += (5*(pi - 2*x)/pi + 1)*(pi - 6*x)^2*x^2/pi^4
333 sage: expected += 81/2*((pi - 6*x)/pi + 1)*(pi - 2*x)^2*x^2/pi^4
334 sage: expected += (pi - 6*x)^2*(pi - 2*x)^2*x/pi^4
335 sage: bool(H == expected)
339 s1
= sum( ys
[k
] * hermite_coefficient(k
, x
, xs
)
340 for k
in xrange(len(xs
)) )
342 s2
= sum( y_primes
[k
] * hermite_deriv_coefficient(k
, x
, xs
)
343 for k
in xrange(len(xs
)) )
348 def lagrange_psi(x
, xs
):
352 Psi(x) = (x - xs[0])*(x - xs[1])* ... *(x - xs[-1])
354 used in Lagrange and Hermite interpolation.
358 - ``x`` -- The independent variable of the resulting expression.
360 - ``xs`` -- A list of points.
364 A symbolic expression in one variable, `x`.
368 return product( (x
- xj
) for xj
in xs
)