For any set of data points there is a unique order polynomial that passes through all of the points. Its construction can be bootstrapped from the linear case that is so well known. Let and be on a line . Then the equations
have solution
which we rewrite as
From this we see how to build the general solution, for example for three data points the unique quadratic polynomial that interpolates the points is (Lagrange interpolation formula)
which is the solution to the linear system
Chebyshev polynomials make a much better choice than functions for expansion on the domain because the matrix that is inverted in the algorithm is far better conditioned than in the monomial case. If we are working with data such that , we can transform it into the domain with the transformation .
By changing one routine in the program, we could expand the data into a sum of orthogonal polynomials of any type, Chebyshev, Legendre, Hermite, and so forth.
Best fits to curves
Suppose that you have lab data: and you need a best fit to a curve . Using least squares we can find the coefficients such that
where are some well-behaved polynomial functions on the domain of your , . Map this domain into and use Chebyshev polynomials , since on these polynomials are bounded and the resulting linear equations are well-conditioned.
We create the cumulative deviation function
and set up the linear equations
or
and invert the array
Select in . You need to compute all from to which can be done recursively using , , .
Let’s code it up in julia, which is very easy to translate into python, R, C, whatever…
using LinearAlgebra
"""Chebyshev fit N^th order y=sum_j^N a_jT_j(u+vx) for input
vectors X, Y. outputs [a_0,...,a_{N-1}],[u,v].
CFit(X,Y,N,digits)
Example: X=[1,2,3,4], Y=[1,4,9,16], CFit(X,Y,3,5) outpu is
[7.375, 7.5, 1.125, 0.0], [-1.6666666666666667, 0.6666666666666666]
ie y=7.375+7.5*T_1((2*x-5)/3)+1.125*T_2((2*x-5)/3)=x^2 """
CFit=function(X::Array{Float64},y::Array{Float64},N::Int,prec::Int)
n=length(X)
a=X[1]
b=X[n]
u=(a+b)/(b-a)
v=2.0/(b-a)
x=(v .* X) .-u
M=zeros(n,n)
Z=zeros(N)
B=zeros(N,N)
for j in 1:n
M[j,1]=1.0
M[j,2]=x[j]
for k in 3:N
M[j,k]=2.0*x[j]*M[j,k-1]-M[j,k-2]
end
end
for k in 1:N
Z[k]=sum(y .* M[:,k])
for l in 1:N
B[k,l]= sum(M[:,l] .* M[:,k])
end
end
round.(inv(B)*Z,digits=prec), [-u;v]
end
We output the coefficients and the rule to get from .
Try it out:
x=[1.0;2;3;4;5]
y=[1.0,4,9,16,25]
CFit(x,y,4,5)
([11.0, 12.0, 2.0, 0.0], [-1.5, 0.5])
so we got
Integration and differentiation of the best fit curve is pretty trivial once this expansion is known.
Using
we get a very simple formula for the integral of our data’s best fit curve