deflagrange_interpolate(points): L = 0# 插值多项式 for i, (xi, yi) inenumerate(points): li = 1 for j, (xj, yj) inenumerate(points): if j == i: continue li *= (x - xj) / (xi - xj) L += yi * li return L
这个程序不太好懂,还是看公式:
$$ L(x)=\sum {j=0}^{k}y{j}\ell _{j}(x) $$
P.S. 这个公式是直接 Wikipedia 上复制的,KaTeX 渲染不出来,就放图片了。下面是它的源码:
h = 1 t = Symbol('t') for j inrange(n+1): if j != k: h *= (t - j)
ckn *= integrate(h, (t, 0, n))
return ckn
打张表方便手算:
牛顿-科特斯求积公式:
1 2 3 4
defnewton_cotes_integral(f, a, b, n): step = (b - a) / n xs = [a + i * step for i inrange(n+1)] return (b - a) * sum([costes_coefficient(n, k) * f(xs[k]) for k inrange(0, n+1)])
常微分方程初值问题
问题: $$ \begin{cases} y’(x)=f(x,y)\ y(a)=y_0\ \end{cases} \qquad (a\le x \le b) $$
改进 Euler
1 2 3 4 5 6 7 8 9 10 11 12
defimproved_euler(f, a, b, h, y0): x = a y = y0
while x <= b: yield (x, y)
y_next_g = y + h * f(x, y) # 预估 y_next = y + h * ( f(x, y) + f(x+h, y_next_g) ) / 2# 校正 x = x + h y = y_next
RK4
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defrunge_kutta(f, a, b, h, y0): x = a y = y0
while x <= b: yield (x, y)
k1 = f(x, y) k2 = f(x + h / 2, y + h * k1 / 2) k3 = f(x + h / 2, y + h * k2 / 2) k4 = f(x + h, y + h * k3) x = x + h y = y + h * (k1 + 2 * k2 + 2 * k3 + k4) / 6
# 消元 for k inrange(n-1): # 列选主元,如果做顺序消元就不用做下面两行 i_max = k + argmax(abs(A[k:n, k])) A[[i_max, k]] = A[[k, i_max]] # if A[k][k] == 0: 求解失败 for i inrange(k+1, n): m = A[i][k] / A[k][k]; A[i][k] = 0; for j inrange(k+1, n+1): A[i][j] -= A[k][j] * m
# 回代:解三角方程 x[n-1] = A[n-1][n] / A[n-1][n-1] for k inrange(n-2, -1, -1): # from n-2 (included) to 0 (included) for j inrange(k+1, n): A[k][n] -= A[k][j] * x[j] x[k] = A[k][n] / A[k][k]
LU 分解
系数矩阵 a:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
n = a.shape[0] p = [0, 1, ..., n-1] # 记录交换
for k inrange(n-1): if 列选主元: i_max = k + argmax(abs(a[k:n, k])) if i_max != k: a[[i_max, k]] = a[[k, i_max]] # swap rows p[[i_max, k]] = p[[k, i_max]] # record
assert a[k][k] != 0, "错误: 主元素为零"
for i inrange(k+1, n): a[i][k] /= a[k][k] # L @ 严格下三角 for j inrange(k+1, n): a[i][j] -= a[i][k] * a[k][j] # U @ 上三角
把右端常数 b 做相同的行交换(p 记录):
1
b = [b[v] for v in p]
然后就可以解方程了:
1 2
解方程("L * y = b") => y 解方程("U * x = y") => x
附:解三角方程:
1 2 3 4 5 6 7
x = np.zeros(n, dtype=np.float) x[n-1] = y[n-1] / u[n-1][n-1] for i inrange(n-2, -1, -1): # from n-2 (included) to 0 (included) yi = y[i] for j inrange(i+1, n): yi -= x[j] * u[i][j] x[i] = yi / u[i][i]
线性方程组迭代解法
Jacobi 迭代
1 2 3 4 5 6 7 8 9 10 11
# A = D - L - U D = diag(diag(A)) L = - tril(A, -1) U = - triu(A, 1)
B = inv(D) @ (L + U) f = inv(D) @
whileTrue: x_prev = x x = B @ x + f
emmmm,这种去手算不太现实。我依稀记得直接写出方程来算更容易(我考完试好久了,已经忘了)。。。
Gauss-Seidel 迭代
1 2
B = inv(D - L) @ U f = inv(D - L) @ b
特征值求法
正幂法
1 2 3 4 5 6 7 8 9 10 11
A = array(shape=(n, n)) # A 是要求特征值的 n*n 矩阵
m = m0 = 1# 主特征值 u = u0 = [1, 1, ..., 1] # 对应的特征向量