# # interpolation de Lagrange : naif ou efficace ? # tic, toc : implémentation Python des fonctions tic, toc de Matlab # # Vincent Legat - 2018 # Ecole Polytechnique de Louvain # from numpy import * import time import matplotlib from matplotlib import pyplot as plt # ========================================================================= def tic(): global startTime startTime = time.time() # ========================================================================= def toc(message = ''): global startTime stopTime = time.time() if message: message = ' (' + message + ')' ; print("Elapsed time is %.6f seconds %s" % ((stopTime - startTime),message) ) startTime = 0 # ========================================================================= def lagrange_naive(x,X,U): n = min(len(X),len(U)) m = len(x) uh = zeros(m) phi = zeros(n) for j in range(m): uh[j] = 0 for i in range(n): phi[i] = 1.0 for k in range(n): if i != k: phi[i] = phi[i]*(x[j]-X[k])/(X[i]-X[k]) uh[j] = uh[j] + U[i] * phi[i] return uh # ========================================================================= def lagrange(x,X,U): n = min(len(X),len(U)) # Evite un message d'erreur :-) phi = ones((n,len(x))) # Preallocation (important !) for i in range(n): for k in list(range(0,i)) + list(range(i+1,n)): phi[i,:] = phi[i,:]*(x-X[k])/(X[i]-X[k]) return U @ phi # Produit matriciel (plus rapide !) # ============================= mainProgram =============================== matplotlib.rcParams['toolbar'] = 'None' plt.rcParams['figure.facecolor'] = 'silver' plt.figure('Polynomial interpolation') # # -1- x : c'est quoi ? # X = [0,1,2] U = [0,0,1] x = linspace(0,2,9) uh = lagrange_naive(x,X,U); plt.plot(x,zeros(size(x)),'.r',markersize=15) plt.plot(x,uh,'.-b',markersize=15) plt.plot(X,U,'.k',markersize=25) plt.show() # # -2- Interpoler une fonction # # n = 15 # h = 1/n # x = linspace(-1,1,2000) # Xunif = arange(-1+h/2,1+h/2,h) # Xcheb = cos( pi*(2*arange(0,2*n)+1) / (4*n) ) # # u = lambda x : 1/(x**2 + 0.09) # Uunif = u(Xunif) # Ucheb = u(Xcheb) # plt.figure('Polynomial interpolation') # plt.plot(x,lagrange(x,Xunif,Uunif),'-b',label='Abscisses équidistantes') # plt.plot(x,lagrange(x,Xcheb,Ucheb),'-r',label='Abscisses de Tchebychev') # plt.plot(Xunif,Uunif,'ob',Xcheb,Ucheb,'or') # plt.xlim((-1,1)) # plt.ylim((0,max(Uunif)*2)) # plt.title('Abscisses : n = %d (uniforme) %d (Tchebychev)' # % (len(Xunif),len(Xcheb))) # plt.legend(loc='upper right') # plt.show() # # -3- Interpoler plusieurs fonctions # n = 15 h = 1/n x = linspace(-1,1,2000) Xunif = arange(-1+h/2,1+h/2,h) Xcheb = cos( pi*(2*arange(0,2*n)+1) / (4*n) ) functions = [lambda x : 1/(x**2 + 0.09), lambda x : abs(x - 0.1)] for u in functions: Uunif = u(Xunif) Ucheb = u(Xcheb) plt.figure('Polynomial interpolation') plt.plot(x,lagrange(x,Xunif,Uunif),'-b',label='Abscisses équidistantes') plt.plot(x,lagrange(x,Xcheb,Ucheb),'-r',label='Abscisses de Tchebychev') plt.plot(Xunif,Uunif,'ob',Xcheb,Ucheb,'or') plt.xlim((-1,1)) plt.ylim((0,max(Uunif)*2)) plt.title('Abscisses : n = %d (uniforme) %d (Tchebychev)' % (len(Xunif),len(Xcheb))) plt.legend(loc='upper right') plt.show() # # -4- Estimation du temps CPU # # Elapsed time is 0.000219 seconds (Lagrange n = 2000) # Elapsed time is 0.017949 seconds (LagrangeNaive n = 2000) # Elapsed time is 0.088590 seconds (Lagrange n = 2000000) # Elapsed time is 16.298496 seconds (LagrangeNaive n = 2000000) # Elapsed time is 1.415670 seconds (Lagrange n = 20000000) # Elapsed time is 159.760674 seconds (LagrangeNaive n = 20000000) # for n in [2000,20000]: x = linspace(-1,1,n) tic() lagrange(x,[0,1,2],[0,1,2]) toc("Lagrange n = %d" % n) tic() lagrange_naive(x,[0,1,2],[0,1,2]) toc("LagrangeNaive n = %d" % n) # =========================================================================