Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

Interpolation basis

Project: Interpolation
Views: 887
1
from numpy import array,ones,pi,cos,concatenate,linspace,sin,NaN,shape
2
from sympy import symbols,lambdify,latex,diff,Function,expand,sin
3
from sympy.utilities.lambdify import implemented_function
4
from sympy.parsing.sympy_parser import parse_expr
5
from src.dbg import dbg
6
import matplotlib.pyplot as plt
7
from pandas import DataFrame
8
9
class Lagrange():
10
def __init__(self,points=[-1,-1,1,1]):
11
self.points=points
12
self.x= symbols('x')
13
self.f=0
14
self.iF=0
15
self.A=0
16
self.d=[]
17
self.dd=[]
18
self.dataFrameD=0
19
self.dataFrameDD=0
20
self.x0=0
21
22
def showInNotebook(self):
23
if len(self.dd)!=0:
24
self.dataFrameDD=DataFrame(self.dd)
25
26
if len(self.d)!=0:
27
columns=[]
28
index=[]
29
m,n=shape(self.d)
30
for i in range(n):
31
#if i==0:
32
# columns.append(r'$'+latex("x_{i}")+'$')
33
if i==0:
34
columns.append(r'$'+latex("f(x_{i})")+'$')
35
elif i==1:
36
columns.append(r'$'+latex("f(x_{i};x_{j})")+'$')
37
elif i==n-1:
38
columns.append(r'$'+latex("f(x_{i};...;x_{j})")+'$')
39
else:
40
columns.append("...")
41
index=self.points
42
self.dataFrameD=DataFrame(self.d,index=index,columns=columns)
43
44
def plot(self):
45
x=self.x
46
iF=lambdify(x,self.iF,"numpy")
47
f=self.f
48
a=linspace(self.points[0],self.points[-1],30)#array(self.points)
49
plt.plot(a,f(a),'o',a,iF(a))
50
plt.legend(('f(x)','interp f(x)'),loc='upper left')
51
#print(array(self.points))
52
plt.stem(array(self.points),iF(array(self.points)))
53
plt.show()
54
55
def lagrangeInterp(self,points=[],func="sin(pi*x)",y=0):
56
'''
57
INTUITION PHASE in solving Lagrange interpolation problem:
58
STEP 0:
59
a[1:]-a[:-1]
60
61
a[::2][1:]-a[::2][:-1]
62
a[1::2][1:]-a[1::2][:-1]
63
64
c[::3][:-1]=a[::3][1:]-a[::3][:-1]
65
c[1::3][:-1]=a[1::3][1:]-a[1::3][:-1]
66
c[2::3][:-1]=a[2::3][1:]-a[2::3][:-1]
67
c[3::3][:-1]=a[3::3][1:]-a[3::3][:-1]
68
c[4::3][:-1]=a[4::3][1:]-a[4::3][:-1]
69
c[5::3][:-1]=a[5::3][1:]-a[5::3][:-1]
70
c[6::3][:-1]=a[6::3][1:]-a[6::3][:-1]
71
6=9-3
72
73
for i in range(len(a)-1-3):
74
c[i::3]=a[i::3][1:]-a[i::3][:-1]
75
76
STEP 1:
77
c[::9]
78
c=d=ones((n+1,n))
79
c[0]=a
80
c[1]=f
81
82
QUESTIONs:
83
+c=ones((n+1),n)#i.e lines below
84
+c=ones((n+1),n)
85
+j from 1 or 2 ?
86
+if from 1 what menans i
87
88
STEP 5:
89
c[0]=a[1:]-a[:-1]
90
for j in range(len(a)-1+1)[2:]:
91
for i in range(len(a)-1-j+1):
92
c[j-1][i::j][:-1]=a[i::j][1:]-a[i::j][:-1]
93
d[j+2]=(d[j+1][1:]-d[j+1][:-1])/float(c[j+2])
94
95
SOME USEFUL REMARKs:
96
f = implemented_function(Function('f'), lambda x: x+1)
97
func = lambdify(x, f(x))
98
func(4)
99
expr=sp.parsing.sympy_parser.parse_expr("sin(x)+x**2")
100
sp.diff(expr)
101
ff=sp.lambdify(x,sp.diff(expr),"numpy")
102
103
TESTS:
104
import src.lagrange as lg
105
lg.lagrangeInterp(listX=[pi,2*pi,3*pi,2*pi])
106
lg.lagrangeInterp(listX=[0,-2,0.5,2/3.],func='x*sin(pi*x)')
107
lg.lagrangeInterp(listX=[-1,-1,1,1],func="sin(pi*x)")
108
'''
109
if len(points)==0:
110
points=self.points
111
else:
112
self.points=list(points)
113
a=array(points)
114
n=len(points)
115
c=ones((n,n))*NaN#(-100)
116
d=ones((n,n))*NaN#(-100)
117
#dd=ones((n,n))*NaN#(-100)
118
119
c[0][:-1]=a[1:]-a[:-1]
120
121
x=self.x
122
expr=parse_expr(func)
123
f=lambdify(x,expr,"numpy")
124
self.f=f
125
df=lambdify(x,diff(expr),"numpy")
126
dbg(**{"lagrangeInterp|part1":expr})
127
128
d[0][:-1]=(f(a[1:])-f(a[:-1]))
129
firstElementF=f(a[0])
130
131
if y:
132
y=array(y)
133
d[0][:-1]=y[1:]-y[:-1]
134
firstElementF=y[0]
135
136
dbg(**{"lagrangeInterp|part2":(len(c[0][:-1]),a,d[0])})
137
138
c,d=self.ifEqPoints(a,c,d,j=1,df=df)
139
#print('**********')
140
for j in range(len(a)-1+1)[2:]:
141
for i in range(j):#len(a)-1-j+1
142
#find delta(x) for all levels
143
if(len(a[i::j])>1):
144
c[j-1][i::j][:-1]=a[i::j][1:]-a[i::j][:-1]
145
dbg(**{"lagrangeInterp|part3":(i,j,c[0][i::j][:-1],a[i::j],a[i::j][1:]-a[i::j][:-1])})
146
d[j-1][:-(j)]=(d[j-2][1:-(j-1)]-d[j-2][:-j])
147
dbg(**{"lagrangeInterp|part4":(j,d[j-1][:],d[j-2][1:-(j-1)],d[j-2][:-j])})
148
#print('-----')
149
c,d=self.ifEqPoints(a,c,d,j=j,df=df)
150
151
dbg(**{"lagrangeInterp|part5":(a,c,d)})
152
153
#f(a)
154
#concatenate((b[::-1],self.d),axis=0)
155
156
#print(array([f(a)]))
157
#print(d)
158
#print(a)
159
#print(concatenate((array([a]),d.T),axis=0).T)
160
#tmpD=concatenate((array([a]),d.T),axis=0).T
161
#print(array([f(a)]))
162
163
#self.d=concatenate((tmpD[::-1],array([f(a)])),axis=0)[::-1][:-1].T
164
self.d=concatenate((d[::-1],array([f(a)])),axis=0)[::-1][:-1].T#d.T[:-1]
165
166
A=d.T[0][:]
167
X=a[:]
168
dbg(**{"lagrangeInterp|part6":(A,X)})
169
170
exprSum=firstElementF
171
exprMult=1
172
for ai in d.T[0][:-1]:
173
exprMult=exprMult*(x-X[0])
174
X=X[1:]
175
exprSum=exprSum+ai*exprMult
176
dbg(**{"lagrangeInterp|part7":(f(a[0]),exprSum)})
177
#exprSum=expand(exprSum)
178
g=lambdify(x,exprSum,"numpy")
179
self.iF=exprSum
180
self.A=concatenate([array([firstElementF]),A[:-1]])
181
return(exprSum)
182
#return(concatenate([array([firstElementF]),A[:-1]]))
183
184
def ifEqPoints(self,a,c,d,j=1,df=0):
185
if(0 not in c[j-1][:-j]):
186
d[j-1][:-j]=d[j-1][:-j]/c[j-1][:-j]
187
dbg(**{"ifEqPoints|part1":(j,c[j-1][:],d[j-1][:])})
188
else:
189
for i in range(len(c[j-1][:-j])):
190
if(c[j-1][:-j][i]!=0):
191
d[j-1][:-j][i]=d[j-1][:-j][i]/c[j-1][:-j][i]
192
dbg(**{"ifEqPoints|part21":(j,i,d[j-1][:-j][i])})
193
else:
194
if(df==0):print("FATAL ERROR!!!")
195
d[j-1][:-j][i]=df(a[:-1][i])
196
dbg(**{"ifEqPoints|part22":(j,i,d[j-1][:-j][i])})
197
198
return(c,d)
199
200
def diffSocket(self,func="sin(x)",x0=0,points=[]):
201
'''
202
DECRCIPTION:
203
find len(points)-1 derivation of function func
204
205
step1 (find b):
206
207
b[n]=a[n]
208
for k=n-1,...,1 do
209
b[k]=a[k]+(x0-x[k])b[k+1]
210
b[1] is f'(x0)
211
212
step2:
213
a=b
214
and try agen step1
215
after k+1 steps
216
b[1]=f'(x0),...,b[k]=f^{k}(x0)
217
218
INPUT:
219
func-whom derivations we want to find
220
x0 is point to find derivations in
221
points will be generated in small area near x0 as Chebyshev points
222
223
questions:
224
+x0 from left in points?
225
+check array.copy's
226
227
'''
228
self.x0=x0
229
points=array(points)
230
if not len(points):
231
points=choosingPoints(x0=x0,n=5)
232
233
self.lagrangeInterp(points=points,func=func)
234
a=self.A
235
b=ones((len(a),len(a)))
236
dbg(**{"diffSocket|part1":(a,points)})
237
238
for i in range(len(a)):
239
b[i][-1]=a[-1]
240
for k in range(len(a))[1:]:
241
b[i][:-1][-k]=a[:-1][-k]+(x0-points[:-1][-k])*b[i][-(k)]
242
dbg(**{"diffSocket|part21":((len(b)-k-1,len(b)-1-k,len(b)-1-k,len(b)-k,b[i][:-1][-k]))})
243
a=b[i].copy()
244
points=concatenate([array([x0]),points[:-1]])
245
dbg(**{"diffSocket|part22":points})
246
deriv=[self.fact(i)*b[-1][i] for i in range(len(b[-1]))[1:]]
247
dbg(**{"diffSocket|part3":(b,deriv)})
248
249
self.dd=concatenate((b[::-1],self.d),axis=0)
250
return(deriv)
251
252
def fact(self,n):
253
if n==1:
254
return(1)
255
else:
256
return(n*self.fact(n-1))
257
258
def choosingPoints(x0=0,n=10):
259
'''Choose different points near x0
260
'''
261
262
#x=concatenate([linspace(x0-1,x0-0.1,n),linspace(x0+0.1,x0+1,n)])
263
x=linspace(x0+0.1,x0+2,n)
264
x=array(range(n))
265
a=x0+0.1
266
b=x0+2
267
x=array([(a+b-(a-b)*cos((2*j-1)*pi/float(2*n))/float(cos(pi/float(2*n))))/2. for j in range(n+1)[1:]])
268
if x[0]>x[-1]:
269
x=x[x.argsort()]
270
return(x)
271
272
273
274
275
def dividedDifferences(l,f=lambda x:x):
276
if len(l)==2:
277
return((f(l[1])-f(l[0]))/float(l[1]-l[0]))
278
else:
279
dD=dividedDifferences
280
return((dD(l[1:],f)-dD(l[:-1],f))/float(l[-1]-l[0]))
281
282
283