G-S迭代

代码最少可以这么写:

def GS(A,b,X,N):X_old = X.copy()n = X.shape[0]for k in range(N):X[0,0] = (b[0,0] - A[0:1,1:n]@X_old[1:n,0])/A[0,0]for i in range(1,n):X[i,0] = (b[i,0] - A[i:i + 1,0:i]@X[0:i] - A[i: i + 1,i + 1:n]@X_old[i + 1:n])/A[i,i]X_old = Xif max(abs(A@X_old - b)) < 1e-5:breakprint(k)return X

然而上面这个代码一般求解常系数矩阵,在我们做优化的过程中,往往需要求解牛顿方程Gkd=−gkG_{k}d=-g_{k}Gk​d=−gk​,这个时候的代码需要做修改:

def GS(HH,GG,X,eta,N):A = HH(X);b = -GG(X).Tn = X.shape[1]b_norm = (b**2).mean()x0 = bx = x0.copy()for k in range(N):x[0,0] = (b[0,0] - (A[0:1,1:n]@x0[1:n,0]).item())/A[0,0]for i in range(1,n):x[i,0] = (b[i,0] - (A[i:i + 1,0:i]@x[0:i]).item() - (A[i: i + 1,i + 1:n]@x0[i + 1:n]).item())/A[i,i]x0 = xr_norm = ((A@x - b)**2).mean()if r_norm < eta*b_norm:break#print(k)return x

上面这个函数的参数HH,GG分别表示我们需要优化的那个函数的梯度和Hessen矩阵。
重点:G-S迭代求解一般用在对称正定矩阵,其他类型的矩阵很难保证迭代收敛性
我们拿差分法来测试一下刚才写的关于G-S迭代的正确性。

def UU(X, order,prob):#X表示(x,t)if prob==1:temp = 10*(X[:,0]+X[:,1])**2 + (X[:,0]-X[:,1])**2 + 0.5if order[0]==0 and order[1]==0:return torch.log(temp)if order[0]==1 and order[1]==0:#对x求偏导return temp**(-1) * (20*(X[:,0]+X[:,1]) + 2*(X[:,0]-X[:,1]))if order[0]==0 and order[1]==1:#对t求偏导return temp**(-1) * (20*(X[:,0]+X[:,1]) - 2*(X[:,0]-X[:,1]))if order[0]==2 and order[1]==0:return - temp**(-2) * (20*(X[:,0]+X[:,1])+2*(X[:,0]-X[:,1])) ** 2 \+ temp**(-1) * (22)if order[0]==1 and order[1]==1:return - temp**(-2) * (20*(X[:,0]+X[:,1])+2*(X[:,0]-X[:,1])) \* (20*(X[:,0]+X[:,1])-2*(X[:,0]-X[:,1])) \+ temp**(-1) * (18)if order[0]==0 and order[1]==2:return - temp**(-2) * (20*(X[:,0]+X[:,1])-2*(X[:,0]-X[:,1])) ** 2 \+ temp**(-1) * (22)if prob==2:if order[0]==0 and order[1]==0:return (X[:,0]*X[:,0]*X[:,0]-X[:,0]) * \0.5*(torch.exp(2*X[:,1])+torch.exp(-2*X[:,1]))if order[0]==1 and order[1]==0:return (3*X[:,0]*X[:,0]-1) * \0.5*(torch.exp(2*X[:,1])+torch.exp(-2*X[:,1]))if order[0]==0 and order[1]==1:return (X[:,0]*X[:,0]*X[:,0]-X[:,0]) * \(torch.exp(2*X[:,1])-torch.exp(-2*X[:,1]))if order[0]==2 and order[1]==0:return (6*X[:,0]) * \0.5*(torch.exp(2*X[:,1])+torch.exp(-2*X[:,1]))if order[0]==1 and order[1]==1:return (3*X[:,0]*X[:,0]-1) * \(torch.exp(2*X[:,1])-torch.exp(-2*X[:,1]))if order[0]==0 and order[1]==2:return (X[:,0]*X[:,0]*X[:,0]-X[:,0]) * \2*(torch.exp(2*X[:,1])+torch.exp(-2*X[:,1]))if prob==3:temp1 = X[:,0]*X[:,0] - X[:,1]*X[:,1]temp2 = X[:,0]*X[:,0] + X[:,1]*X[:,1] + 0.1if order[0]==0 and order[1]==0:return temp1 * temp2**(-1)if order[0]==1 and order[1]==0:return (2*X[:,0]) * temp2**(-1) + \temp1 * (-1)*temp2**(-2) * (2*X[:,0])if order[0]==0 and order[1]==1:return (-2*X[:,1]) * temp2**(-1) + \temp1 * (-1)*temp2**(-2) * (2*X[:,1])if order[0]==2 and order[1]==0:return (2) * temp2**(-1) + \2 * (2*X[:,0]) * (-1)*temp2**(-2) * (2*X[:,0]) + \temp1 * (2)*temp2**(-3) * (2*X[:,0])**2 + \temp1 * (-1)*temp2**(-2) * (2)if order[0]==1 and order[1]==1:return (2*X[:,0]) * (-1)*temp2**(-2) * (2*X[:,1]) + \(-2*X[:,1]) * (-1)*temp2**(-2) * (2*X[:,0]) + \temp1 * (2)*temp2**(-3) * (2*X[:,0]) * (2*X[:,1])if order[0]==0 and order[1]==2:return (-2) * temp2**(-1) + \2 * (-2*X[:,1]) * (-1)*temp2**(-2) * (2*X[:,1]) + \temp1 * (2)*temp2**(-3) * (2*X[:,1])**2 + \temp1 * (-1)*temp2**(-2) * (2)
def FF(prob,X):return -UU(X,[0,2],prob) - UU(X,[2,0],prob)
class FD():def __init__(self,bound,hx,prob):self.prob = probself.dim = 2self.hx = hxself.nx = [int((bound[0,1] - bound[0,0])/self.hx[0]) + 1,int((bound[1,1] - bound[1,0])/self.hx[1]) + 1]self.size = self.nx[0]*self.nx[1]self.X = torch.zeros(self.size,self.dim)m = 0for i in range(self.nx[0]):for j in range(self.nx[1]):self.X[m,0] = bound[0,0] + i*self.hx[0]self.X[m,1] = bound[1,0] + j*self.hx[1]m = m + 1self.u_acc = UU(self.X,[0,0],self.prob).view(-1,1)def matrix(self):self.A = torch.zeros(self.nx[0]*self.nx[1],self.nx[0]*self.nx[1])dx = self.hx[0];dy = self.hx[1]for i in range(self.nx[0]):for j in range(self.nx[1]):dx = self.hx[0];dy = self.hx[1]if i== 0 or i == self.nx[0] - 1 or j == 0 or j == self.nx[1] - 1:self.A[i*self.nx[1]+j,i*self.nx[1]+j] = 1else:self.A[i*self.nx[1]+j,i*self.nx[1]+j] = 2*(dx/dy + dy/dx)self.A[i*self.nx[1]+j,i*self.nx[1]+j-1] = -dx/dyself.A[i*self.nx[1]+j,i*self.nx[1]+j+1] = -dx/dyself.A[i*self.nx[1]+j,(i-1)*self.nx[1]+j] = -dy/dxself.A[i*self.nx[1]+j,(i+1)*self.nx[1]+j] = -dy/dxreturn self.Adef right(self):self.b = torch.zeros(self.nx[0]*self.nx[1],1)for i in range(self.nx[0]):for j in range(self.nx[1]):dx = self.hx[0];dy = self.hx[1]x = i*dx;y = j*dyX = torch.tensor([[x,y]]).float()if i== 0 or i == self.nx[0] - 1 or j == 0 or j == self.nx[1] - 1:self.b[i*self.nx[1]+j] = UU(self.X[i*self.nx[1]+j:i*self.nx[1]+j+1,:],[0,0],self.prob)else:self.b[i*self.nx[1]+j] =  FF(self.prob,self.X[i*self.nx[1]+j:i*self.nx[1]+j+1,:])*dx*dyreturn self.bdef solve(self):A = self.matrix().numpy()b = self.right().numpy()x = np.zeros([b.shape[0],1])u = GS(A,b,x,200)return u
def error(u_pred,u_acc):temp = ((u_pred - u_acc.numpy())**2).sum()/(u_acc.numpy()**2).sum()return temp**(0.5)
bound = torch.tensor([[0,2],[0,1]]).float()
hx = [0.1,0.1]
prob = 3
fd = FD(bound,hx,prob)
u_pred = fd.solve()
u_acc = fd.u_acc
print(error(u_pred,u_acc))

线高斯迭代

针对五点差分法,我们可以利用矩阵的特殊性构造线高斯方法,具体的原理参考下面这个表达式:
−dydx∗ui−1,j+2(dxdy+dydx)ui,j−dydx∗ui+1,j=dx∗dy∗fi,j+dxdy∗(ui,j−1+ui,j+1)- \frac{dy}{dx}*u_{i - 1,j}+2(\frac{dx}{dy} + \frac{dy}{dx})u_{i,j}- \frac{dy}{dx}*u_{i + 1,j}=dx*dy*f_{i,j}+\frac{dx}{dy}*(u_{i ,j-1}+u_{i ,j+1})−dxdy​∗ui−1,j​+2(dydx​+dxdy​)ui,j​−dxdy​∗ui+1,j​=dx∗dy∗fi,j​+dydx​∗(ui,j−1​+ui,j+1​)
那么根据这个表达式,不断更新每一层的近似解,参考下面这个公式:
−dydx∗ui−1,jnew+2(dxdy+dydx)ui,jnew−dydx∗ui+1,jnew=dx∗dy∗fi,j+dxdy∗(ui,j−1new+ui,j+1old)- \frac{dy}{dx}*u_{i - 1,j}^{new}+2(\frac{dx}{dy} + \frac{dy}{dx})u_{i,j}^{new}- \frac{dy}{dx}*u_{i + 1,j}^{new}=dx*dy*f_{i,j}+\frac{dx}{dy}*(u_{i ,j-1}^{new}+u_{i ,j+1}^{old})−dxdy​∗ui−1,jnew​+2(dydx​+dxdy​)ui,jnew​−dxdy​∗ui+1,jnew​=dx∗dy∗fi,j​+dydx​∗(ui,j−1new​+ui,j+1old​)
其中在更新每一层的近似解过程中,都会涉及到一个三对角矩阵的求解,为此我们还需要写一个三对角矩阵的求解过程。

def TH(d,l,u,b):n = b.shape[0]y = np.zeros([n,1]);x = np.zeros([n,1])alpha = np.zeros_like(d)beta = np.zeros_like(u)gama = l.copy()alpha[0,0] = d[0,0];beta[0,0] = u[0,0]/d[0,0]for i in range(1,n - 1):alpha[i,0] = d[i,0] - l[i - 1,0]*beta[i - 1,0]beta[i,0] = u[i,0]/alpha[i,0]alpha[n - 1,0] = d[n - 1,0] - l[n - 2,0]*beta[n - 2,0]y[0,0] = b[0,0]/alpha[0,0]for i in range(1,n):y[i,0] = (b[i,0] - gama[i - 1,0]*y[i - 1,0])/alpha[i,0]x[n - 1,0] = y[n - 1,0]for j in range(n - 2,-1,-1):x[j,0] = y[j,0] - beta[j,0]*x[j + 1,0]return x

这里的d,l,u,bd,l,u,bd,l,u,b都是向量,存储的是三对角矩阵的对角线元素,和上下对角线元素,b表示方程的右端项。这样做可以节省存储量。整个求解代码过程参考以下:

import numpy as np
import time
def TH(d,l,u,b):n = b.shape[0]y = np.zeros([n,1]);x = np.zeros([n,1])alpha = np.zeros_like(d)beta = np.zeros_like(u)gama = l.copy()alpha[0,0] = d[0,0];beta[0,0] = u[0,0]/d[0,0]for i in range(1,n - 1):alpha[i,0] = d[i,0] - l[i - 1,0]*beta[i - 1,0]beta[i,0] = u[i,0]/alpha[i,0]alpha[n - 1,0] = d[n - 1,0] - l[n - 2,0]*beta[n - 2,0]y[0,0] = b[0,0]/alpha[0,0]for i in range(1,n):y[i,0] = (b[i,0] - gama[i - 1,0]*y[i - 1,0])/alpha[i,0]x[n - 1,0] = y[n - 1,0]for j in range(n - 2,-1,-1):x[j,0] = y[j,0] - beta[j,0]*x[j + 1,0]return xdef UU(X, order,prob):#X表示(x,t)if prob==1:temp = 10*(X[:,0]+X[:,1])**2 + (X[:,0]-X[:,1])**2 + 0.5if order[0]==0 and order[1]==0:return np.log(temp)if order[0]==1 and order[1]==0:#对x求偏导return temp**(-1) * (20*(X[:,0]+X[:,1]) + 2*(X[:,0]-X[:,1]))if order[0]==0 and order[1]==1:#对t求偏导return temp**(-1) * (20*(X[:,0]+X[:,1]) - 2*(X[:,0]-X[:,1]))if order[0]==2 and order[1]==0:return - temp**(-2) * (20*(X[:,0]+X[:,1])+2*(X[:,0]-X[:,1])) ** 2 \+ temp**(-1) * (22)if order[0]==1 and order[1]==1:return - temp**(-2) * (20*(X[:,0]+X[:,1])+2*(X[:,0]-X[:,1])) \* (20*(X[:,0]+X[:,1])-2*(X[:,0]-X[:,1])) \+ temp**(-1) * (18)if order[0]==0 and order[1]==2:return - temp**(-2) * (20*(X[:,0]+X[:,1])-2*(X[:,0]-X[:,1])) ** 2 \+ temp**(-1) * (22)if prob==2:if order[0]==0 and order[1]==0:return (X[:,0]*X[:,0]*X[:,0]-X[:,0]) * \0.5*(np.exp(2*X[:,1])+np.exp(-2*X[:,1]))if order[0]==1 and order[1]==0:return (3*X[:,0]*X[:,0]-1) * \0.5*(np.exp(2*X[:,1])+np.exp(-2*X[:,1]))if order[0]==0 and order[1]==1:return (X[:,0]*X[:,0]*X[:,0]-X[:,0]) * \(np.exp(2*X[:,1])-np.exp(-2*X[:,1]))if order[0]==2 and order[1]==0:return (6*X[:,0]) * \0.5*(np.exp(2*X[:,1])+np.exp(-2*X[:,1]))if order[0]==1 and order[1]==1:return (3*X[:,0]*X[:,0]-1) * \(np.exp(2*X[:,1])-np.exp(-2*X[:,1]))if order[0]==0 and order[1]==2:return (X[:,0]*X[:,0]*X[:,0]-X[:,0]) * \2*(np.exp(2*X[:,1])+np.exp(-2*X[:,1]))if prob==3:temp1 = X[:,0]*X[:,0] - X[:,1]*X[:,1]temp2 = X[:,0]*X[:,0] + X[:,1]*X[:,1] + 0.1if order[0]==0 and order[1]==0:return temp1 * temp2**(-1)if order[0]==1 and order[1]==0:return (2*X[:,0]) * temp2**(-1) + \temp1 * (-1)*temp2**(-2) * (2*X[:,0])if order[0]==0 and order[1]==1:return (-2*X[:,1]) * temp2**(-1) + \temp1 * (-1)*temp2**(-2) * (2*X[:,1])if order[0]==2 and order[1]==0:return (2) * temp2**(-1) + \2 * (2*X[:,0]) * (-1)*temp2**(-2) * (2*X[:,0]) + \temp1 * (2)*temp2**(-3) * (2*X[:,0])**2 + \temp1 * (-1)*temp2**(-2) * (2)if order[0]==1 and order[1]==1:return (2*X[:,0]) * (-1)*temp2**(-2) * (2*X[:,1]) + \(-2*X[:,1]) * (-1)*temp2**(-2) * (2*X[:,0]) + \temp1 * (2)*temp2**(-3) * (2*X[:,0]) * (2*X[:,1])if order[0]==0 and order[1]==2:return (-2) * temp2**(-1) + \2 * (-2*X[:,1]) * (-1)*temp2**(-2) * (2*X[:,1]) + \temp1 * (2)*temp2**(-3) * (2*X[:,1])**2 + \temp1 * (-1)*temp2**(-2) * (2)
def FF(prob,X):return -UU(X,[0,2],prob) - UU(X,[2,0],prob)
np.random.seed(1234)class FD():def __init__(self,bound,hx,prob):self.prob = probself.dim = 2self.hx = hxself.nx = [int((bound[0,1] - bound[0,0])/self.hx[0]) + 1,int((bound[1,1] - bound[1,0])/self.hx[1]) + 1]self.size = self.nx[0]*self.nx[1]self.X = np.zeros([self.size,self.dim])m = 0for i in range(self.nx[0]):for j in range(self.nx[1]):self.X[m,0] = bound[0,0] + i*self.hx[0]self.X[m,1] = bound[1,0] + j*self.hx[1]m = m + 1def u_init(self):u = np.zeros([self.nx[0],self.nx[1]])x = self.X.reshape([self.nx[0],self.nx[1],self.dim])u[0,:] = UU(x[0,:,:],[0,0],self.prob)u[-1,:] = UU(x[-1,:,:],[0,0],self.prob)u[1:self.nx[0] - 1,0] = UU(x[1:self.nx[0] - 1,0,:],[0,0],self.prob)u[1:self.nx[0] - 1,-1] = UU(x[1:self.nx[0] - 1,-1,:],[0,0],self.prob)return udef solve(self,rig):tic = time.time()u_old = self.u_init()u_new = u_old.copy()M = self.nx[0];N = self.nx[1]dx = self.hx[0];dy = self.hx[1]right = (dx*dy*rig).reshape([M - 2,N - 2])#print(right[0,:].shape,u_new[0,1:N - 2].shape)right[0,:] += u_new[0,1:N - 1]*dy/dxright[-1,:] += u_new[- 1,1:N - 1]*dy/dxr1 = dy/dx;r2 = dx/dyl = - np.ones([M - 3,1])*r1u = - np.ones([M - 3,1])*r1d = np.ones([M - 2,1])*2*(r1 + r2)#print(d.shape)for k in range(1000):for j in range(1,N - 1):#print(u_old[1:M - 1,j - 1].shape,right[:,j].shape)b = r2*(u_new[1:M - 1,j - 1] + u_old[1:M - 1,j + 1]) + right[:,j - 1]u_new[1:M - 1,j:j + 1] = TH(d,l,u,b.reshape(-1,1))#print(np.linalg.norm(u_new - u_old))if (np.linalg.norm(u_new - u_old) < 1e-7):breakelse:u_old = u_new.copy()if k%100 == 0:print('the iteration = %d'%(k + 1))ela = time.time() - ticprint('the end iteration is %d,the time:%.2f'%(k + 1,ela))return u_new.reshape(-1,1)
bound = np.array([[0,2.0],[0,1.0]])
hx = [0.05,0.05]
prob = 1
fd = FD(bound,hx,prob)
M = fd.nx[0];N = fd.nx[1]
X = fd.X
u_acc = UU(X,[0,0],prob).reshape(-1,1)
rig_in = (FF(prob,X).reshape(M,N))[1:M - 1,1:N - 1]
u_pred = fd.solve(rig_in)print(max(abs(u_acc - u_pred)))

G-S迭代求解线性方程,以及三对角矩阵求解相关推荐

  1. ORBSLAM中单应矩阵求解

    ORBSLAM中单应矩阵求解 1. 单应矩阵求解 2.用DLT方法求解单应矩阵H 3. 三角化求深度 4. 使用RT三角化 1. 单应矩阵求解 /*** @brief 计算单应矩阵,假设场景为平面情况 ...

  2. Matlab实现——严格对角占优三对角方程组求解(高斯赛尔德Gauss-Seidel迭代、超松弛)

    欢迎前往个人博客 驽马点滴 和视频空间 哔哩哔哩-<挨踢日志> 严格对角占优三对角方程组求解 对中等规模的n阶的(n<100)线性方程组,直接法的准确性和可靠性,所以常采用直接法 对 ...

  3. matlab trisys,Matlab实现——严格对角占优三对角方程组求解(高斯赛尔德Gauss-Seidel迭代、超松弛) | 学步园...

    严格对角占优三对角方程组求解 对中等规模的n阶的(n<100)线性方程组,直接法的准确性和可靠性,所以常采用直接法 对于较高阶的方程组,特别是地于某些偏微分方程离散化后得到的大型稀疏方程组(系统 ...

  4. 对称矩阵到三对角矩阵的Lanczos推导(python,数值积分)

    第三十二篇 Lanczos转化到三对角形式 在之前的篇章里,有许多求解线性方程的迭代方法,如最陡下降法,可以通过向量乘法和各种简单的向量运算,简化为一个单个矩阵的循环.将矩阵化为三对角形式的Lancz ...

  5. OpenCV基础矩阵求解解析笔记

    文章目录 1. 基础矩阵求解原理 1.1 基础矩阵推导 1.1.1 相机模型 1.1.2 对极几何 1.1.3 基础矩阵性质 1.2 7 7 7点法求解基础矩阵 1.3 8 8 8点法求解基础矩阵 1 ...

  6. c语言程序编程线性方程,C语言编程求解线性方程.doc

    C语言编程求解线性方程 本 科 专 业 学 年 论 文 题目:线性方程组求解方法比较 姓 名 郭 凤 专 业 计算机科学与技术专业 班 级 08级本科(2)班 指导教师 刘 晓 娜 完成日期:2010 ...

  7. Levenberg-Marquardt算法求解单应性矩阵

    A. Levenberg-Marquardt算法 待估计的模型参数 x=[x1,x2,⋯,xn]T\mathbf{x}=[x_1, x_2, \cdots,x_n]^Tx=[x1​,x2​,⋯,xn​ ...

  8. Matlab随笔之求解线性方程

    原文:Matlab随笔之求解线性方程 理论知识补充: %矩阵除分为矩阵右除和矩阵左除. %矩阵右除的运算符号为"/",设A,B为两个矩阵,则"A/B"是指方程X ...

  9. 利用稀疏格式矩阵求解方程组以及机器学习训练速度对比

    本文要点: 1.几个稀疏矩阵的应用场景 2.scipy得到稀疏格式矩阵后专用的方程组求解器 3.用稀疏格式求解方程组的速度对比 4.稀疏矩阵与原矩阵内存大小对比 5.python稀疏格式与array格 ...

最新文章

  1. linux回到桌面的命令符_Linux命令行环境与桌面环境护切换
  2. 阿里云文件存储的高性能架构演进之路
  3. 【报告分享】2021年营销数智化趋势洞察报告:深链经营孕育品牌发展新商机.pdf(附下载链接)...
  4. ReactNative从零到完整项目-Flexbox使用
  5. react for循环_5个很棒的 React.js 库,值得你亲手试试!
  6. Open XML应用安全(3)隐藏数据
  7. Why Blink and Why not Blink
  8. OSChina 周一乱弹 —— 老夫聊发少年狂
  9. 可编辑div的一些方法总结(二)自定义空格和回车事件
  10. 用AW国际版激活国行moto二代
  11. Windows程序意外挂掉,但显存依然被占用
  12. Excel 表单元格数字显示为#NAME!
  13. 使用 MyBatis-Plus 分页查询
  14. 使用GloVe训练自己的语料
  15. 【中秋福利文末Kotlin书籍免费送】程序员30 岁之后:如何实现质的突破?
  16. 如何移除电路板上的元器件?
  17. SpringBoot之小彩蛋:动态Banner
  18. 《kafka中文手册》- 构架设计
  19. Ubuntu18.04环境下安装ERPNext 12
  20. 犯罪追诉时效是如何规定的?

热门文章

  1. python3APP爬虫--爬取王者荣耀英雄图片(附源码)
  2. Vue实战狗尾草博客后台管理系统第三章
  3. 一、Shell 脚本
  4. 用WebClinet实现SharePoint上文档库中文件的上传与下载
  5. Python迁移不同服务器的SqlServer数据表
  6. 修改Windows版Qt Creator界面字体
  7. 机械类外文文献 重要的CAD/CAPP/CAM设计工作
  8. 计算机在人力资源中的应用,计算机技术在人力资源管理中的应用
  9. 开发小技巧(日常记录)
  10. 楼盘小程序具备哪些功能板块?