Definition

Tn(x)=cos(narccos(x))T_n(x) = cos(n*arccos(x))
Tn(x)=2xTn1(x)Tn2(x)T_n(x) = 2x * T_{n-1}(x) - T_{n-2}(x)
T0(x)=1T_0(x) = 1
T1(x)=xT_1(x) = x

Orthogonality

0π cosmt cosntdt=0    (m!=n)\int_{0}^{\pi} ~ cosm t ~ cosn t dt = 0 ~~~~ (m!=n)
0π cosmt cosntdt=π2    (m=n!=0)\int_{0}^{\pi} ~ cosm t ~ cosn t dt = \frac{\pi}{2} ~~~~ (m=n!=0)
0π cosmt cosntdt=π(m=n=0)\int_{0}^{\pi} ~ cosm t ~ cosn t dt = \pi (m=n=0)

Which means cosmtcosmt forms a set of orthogonal functions on the interval [1,1][-1,1].

Let t=arccos(x)t=arccos(x),t[0,π]t∈[0,\pi], then x=costx=cost, x[1,1]x∈[-1,1]

0π cosmt cosntdt\int_{0}^{\pi} ~ cosm t ~ cosn t dt
=11cos(marccos(x))cos(narccos(x)) d arccos(x)= \int_{-1}^{1} cos(m*arccos(x)) * cos(n*arccos(x))~ d~arccos(x)
=11Tm(x)Tn(x)1x2dx= \int_{-1}^{1} \frac { T_m(x) * T_n(x) } { \sqrt {1-x^2} } dx

Since the Chebyshev Polynomial gives a set of orthogonal functions on the interval [1,1][-1,1], any continuous, real-valued funcionf(x)f(x) can be expanded as a series of Chebyshev Polynomials.

f(x)=k=1infAkTk(x)f(x) = \sum_{k=1}^{\inf} A_kT_k(x)
=A0T0(x)+A1T1(x)+AkTk(x)+...+AnTn(x)+...= A_0T_0(x) + A_1T_1(x) + A_kT_k(x) + ... + A_nT_n(x) + ...

Like Fourier Series, to compute AkA_k, we "mask out" other terms in the series.

11f(x)Tk(x)1x2dx=\int_{-1}^{1} \frac { f(x) * T_k(x) } {\sqrt{1-x^2}} dx =
A011T0(x)Tk(x)1x2dx+...+A_0 \int_{-1}^{1} \frac { T_0(x) * T_k(x) } {\sqrt{1-x^2}} dx + ... +
Ak11Tk(x)Tk(x)1x2dx+...A_k \int_{-1}^{1} \frac { T_k(x) * T_k(x) } {\sqrt{1-x^2}} dx + ...
=π2Ak= \frac{\pi}{2} A_k
Ak=2π11f(x)Tk(x)1x2dx   n=1,2,3,...A_k = \frac{2}{\pi} \int_{-1}^{1} \frac { f(x) * T_k(x) } {\sqrt{1-x^2}} dx~~~n=1,2,3,...
A0=1π11f(x)1x2dxA_0 = \frac{1}{\pi} \int_{-1}^{1} \frac { f(x) } {\sqrt{1-x^2}} dx

And to convert it back to Fourier-like projection, let t=arccos(x)t=arccos(x),x[1,1]x∈[-1,1], then x=cos(t)x=cos(t),t[0,π]t∈[0,\pi].

Ak=2π11f(x)Tk(x)1x2dxA_k = \frac{2}{\pi} \int_{-1}^{1} \frac { f(x) * T_k(x) } {\sqrt{1-x^2}} dx
=2π11f(x)cos(karccos(x))darccosx= \frac{2}{\pi} \int_{-1}^{1} f(x)*cos(karccos(x)) darccosx
=2π0πf(cos(t))cos(kt)dt= \frac{2}{\pi} \int_{0}^{\pi} f(cos(t)) * cos(kt) dt

Zeros of Tn(x)T_n(x)

narccos(x)=2j+12πn*arccos(x) = \frac{2j+1}{2} \pi
arccos(x)=2j+12nπarccos(x) = \frac{2j+1}{2n} \pi
x=cos(2j+12nπ)     j=0,1,...n1x = cos(\frac{2j+1}{2n} \pi)~~~~~j = 0,1,...n-1

Discrete Chebyshev Expansion

Chebyshev Polynomials has the discrete orthogonality property

k=1NTm(xk)Tn(xk)=\sum_{k=1}^N T_m(x_k) T_n(x_k) =
0   (m!=n)0~~~(m!=n)
N/2   (m=n!=0)N/2~~~(m=n!=0)
N   (M=N=0)N~~~(M=N=0)

where N>m,nN > m,n and xkx_k is the zeros of TN(x)T_N(x)

xk=cos(2k12Nπ)x_k = cos( \frac {2k-1} {2N} \pi )

TODO: since fN(xk)f_N(x_k) in terpolates ff at N+1N+1 chebyshev nodes

write f(xk)f(x_k) as chebyshev expansion

k=1Nf(xk)Tm(xk)\sum_{k=1}^{N} f(x_k) T_m(x_k)
=k=1N(n=0NAnTn(xk))Tm(xk)= \sum_{k=1}^{N} ( \sum_{n=0}^N A_n * T_n(x_k) ) T_m(x_k)
=n=0NAnk=0NTn(xk)Tm(xk)= \sum_{n=0}^N A_n \sum_{k=0}^N T_n(x_k) T_m(x_k)

so we have

k=1Nf(xk)Tm(xk)=n=0NAnk=1NTn(xk)Tm(xk)\sum_{k=1}^{N} f(x_k) T_m(x_k) = \sum_{n=0}^N A_n \sum_{k=1}^N T_n(x_k) T_m(x_k)

To get A0A_0, set m=0m=0, all Tn(xk)Tm(xk)T_n(x_k) T_m(x_k) is 00 except Tn(xk)Tm(xk)=NT_n(x_k) T_m(x_k)=N when m=n=0m=n=0

k=1Nf(xk)T0(xk)=NA0\sum_{k=1}^N f(x_k) T_0(x_k) = N A_0
A0=1Nk=1Nf(xk)A_0 = \frac{1}{N} \sum_{k=1}^N f(x_k)

To get Aj (j!=0)A_j~(j!=0), set m=jm=j, all Tm(xk)Tn(xk)T_m(x_k) T_n(x_k) is 00 except Tm(xk)Tn(xk)=N2T_m(x_k) T_n(x_k) = \frac{N}{2} when m=n!=0m=n!=0

k=0Nf(xk)Tj(xk)=N2Aj\sum_{k=0}^N f(x_k) T_j(x_k) = \frac{N}{2} A_j
Aj=2Nk=1Nf(xk)Tj(xk)A_j = \frac{2}{N} \sum_{k=1}^N f(x_k) T_j(x_k)

where xk=cos(2k12Nπ)x_k = cos( \frac {2k-1} {2N}\pi ) 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 KK-order chebyshev polynomial, the chebyshev coefficients are given by

A0=1Nk=1Nf(xk)A_0 = \frac{1}{N} \sum_{k=1}^N f(x_k)
Aj=2Nk=1Nf(xk)Tj(xk)A_j = \frac{2}{N} \sum_{k=1}^N f(x_k) T_j(x_k)

where jj goes from 00 up to KK, and xk=cos(2k12Nπ) x_k = cos( \frac {2k-1} {2N} \pi ) where N>jN>j

Typically we just choose N=K+1N = K+1,and the approximated function is f(x)=i=0KAi(x)Ti(x)f(x) = \sum_{i=0}^K A_i(x)T_i(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 = 6
def chebyshev_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 likeimg_basis

Then we need a function to compute the chebyshev nodes

def chebyshev_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)=0T_k(x)=0 at chebyshev nodes, that what we expected. img_nodes

Finally we need a function to compute chebyshev coefficients

def chebyshev_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] /= 2
    return 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()

functrue

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()

order5

And try different KK