Which means cosmt forms a set of orthogonal functions on the interval [−1,1].
Let t=arccos(x),t∈[0,π],
then x=cost, x∈[−1,1]
∫0πcosmtcosntdt
=∫−11cos(m∗arccos(x))∗cos(n∗arccos(x))darccos(x)
=∫−111−x2Tm(x)∗Tn(x)dx
Since the Chebyshev Polynomial gives a set of orthogonal
functions on the interval [−1,1], any continuous, real-valued funcionf(x) can be expanded as a series of Chebyshev Polynomials.
f(x)=k=1∑infAkTk(x)
=A0T0(x)+A1T1(x)+AkTk(x)+...+AnTn(x)+...
Like Fourier Series, to compute Ak, we "mask out" other terms in the series.
∫−111−x2f(x)∗Tk(x)dx=
A0∫−111−x2T0(x)∗Tk(x)dx+...+
Ak∫−111−x2Tk(x)∗Tk(x)dx+...
=2πAk
Ak=π2∫−111−x2f(x)∗Tk(x)dxn=1,2,3,...
A0=π1∫−111−x2f(x)dx
And to convert it back to Fourier-like projection, let t=arccos(x),x∈[−1,1], then
x=cos(t),t∈[0,π].
Ak=π2∫−111−x2f(x)∗Tk(x)dx
=π2∫−11f(x)∗cos(karccos(x))darccosx
=π2∫0πf(cos(t))∗cos(kt)dt
Zeros of Tn(x)
n∗arccos(x)=22j+1π
arccos(x)=2n2j+1π
x=cos(2n2j+1π)j=0,1,...n−1
Discrete Chebyshev Expansion
Chebyshev Polynomials has the discrete orthogonality property
k=1∑NTm(xk)Tn(xk)=
0(m!=n)
N/2(m=n!=0)
N(M=N=0)
where N>m,n and xk is the zeros of
TN(x)
xk=cos(2N2k−1π)
TODO: since fN(xk) in terpolates f
at N+1 chebyshev nodes
To get A0, set m=0,
all Tn(xk)Tm(xk) is 0 except
Tn(xk)Tm(xk)=N when m=n=0
k=1∑Nf(xk)T0(xk)=NA0
A0=N1k=1∑Nf(xk)
To get Aj(j!=0), set m=j,
all Tm(xk)Tn(xk) is 0 except
Tm(xk)Tn(xk)=2N when m=n!=0
k=0∑Nf(xk)Tj(xk)=2NAj
Aj=N2k=1∑Nf(xk)Tj(xk)
where xk=cos(2N2k−1π)
since the approximation is null only at these points. TODO: why
Approximate A function with Chebyshev
In the previous sections, we reached the conclusion that any function can by written as expansion of chebyshev polynomial.
Furthermore, the chebyshev basis can be calculated recursively and the
chebyshev coefficients can by calculated with summation instead of integral.
If we approximate a function with K-order
chebyshev polynomial, the
chebyshev coefficients are given by
A0=N1k=1∑Nf(xk)
Aj=N2k=1∑Nf(xk)Tj(xk)
where j goes from 0 up to K, and
xk=cos(2N2k−1π)
where N>j
Typically we just choose N=K+1,and the approximated function is
f(x)=∑i=0KAi(x)Ti(x)
So, first we need a function to compute the
chebyshev basis which is done recursively
according to the recursive relation of
chebyshev polynomial
import numpy as np
K = 6defchebyshev_basis(K, xs):""" Compute the chebyshev basis from T_0(xs) up to T_{K-1}(xs) """
T = np.zeros(shape=(K, xs.size))
T[:,0] = np.ones_like(xs)
T[:,1] = xs
for k in range(2,K):
T[:,k] = 2 * xs * T[:,k-1] - T[:,k-2]
return T
xs = np.linspace(-1,1,200) # remember that the domain of T_m(x) is [-1,1]
T = chebyshev_basis(K, xs)
for i in range(K):
plt.plot(xs, T[:,i], label="T_{}(x)".format(i))
plt.legend(loc='best')
plt.show()
The chebyshev basis looks like
Then we need a function to compute the chebyshev nodes
defchebyshev_nodes(K):""" Compute the zeros of T_k(x) """return np.cos(
np.pi * (np.arange(K) - 0.5) / K
)
xs = np.linspace(-1,1,200) # remember that the domain of T_m(x) is [-1,1]
T = chebyshev_basis(K, xs)
nodes = chebyshev_nodes(K-1)
plt.plot(xs, T[:,K-1], label="T_{}(x)".format(K-1))
plt.plot(nodes, np.zeros_like(nodes), 'ro')
plt.legend(loc='best')
plt.show()
Tk(x)=0 at chebyshev nodes, that what we expected.
Finally we need a function to compute
chebyshev coefficients
defchebyshev_coefficient(K, f):"""
Compute the chebyshev coefficients from A_0 up to A_{K-1}
using chebyshev nodes of T_K(x)
"""
nodes = chebyshev_nodes(K)
basis = chebyshev_basis(K, nodes)
c = np.zeros(K)
for k in range(K):
c[k] = 2 / K * np.sum(f(nodes) * basis[:,k])
c[0] /= 2return c
To test the chebyshev approximation, first we construct a fairly complicated function
xs = np.linspace(-1,1,200) # remember that the domain of T_m(x) is [-1,1]
f = lambda x : np.sin(2*x) - 0.92 * np.tan(1.1 * x) + 0.18 * np.tanh(0.98 * x)
plt.plot(xs, f(xs))
plt.show()
Then we compute the chebyshev coefficients
and chebyshev basis and reconstruct the function.
xs = np.linspace(-1,1,200) # remember that the domain of T_m(x) is [-1,1]
f = lambda x : np.sin(2*x) - 0.92 * np.tan(1.1 * x) + 0.18 * np.tanh(0.98 * x)
c = chebyshev_coefficient(K, f)
# remeber when we pass the parameter K, actually we get basis up to order K-1
basis = chebyshev_basis(K, xs)
ys = np.zeros_like(xs)
for k in range(K):
ys += c[k] * basis[:,k]
plt.plot(xs, f(xs), label='True function')
plt.plot(xs, ys, label='Approximation')
plt.show()