Sherman-Morrison公式及其应用
Sherman-Morrison公式
Sherman-Morrison公式以 Jack Sherman 和 Winifred J. Morrison命名,在线性代数中,是求解逆矩阵的一种方法。本篇博客将介绍该公式及其应用,首先我们来看一下该公式的内容及其证明。
(Sherman-Morrison公式)假设\(A\in\mathbb{R}^{n\times n}\)为可逆矩阵,\(u,v\in\mathbb{R}^{n}\)为列向量,则\(A+uv^{T}\)可逆当且仅当\(1+v^{T}A^{-1}u\neq 0\), 且当\(A+uv^{T}\)可逆时,该逆矩阵由以下公式给出:
\]
证明:
\((\Leftarrow)\)当\(1+v^{T}A^{-1}u\neq 0\)时,令\(X=A+uv^{T}, Y=A^{-1}-{A^{-1}uv^{T}A^{-1} \over 1+v^{T}A^{-1}u}\),则只需证明\(XY=YX=I\)即可,其中\(I\)为n阶单位矩阵。
{\begin{aligned}
XY&=(A+uv^{T})\left(A^{-1}-{A^{-1}uv^{T}A^{-1} \over 1+v^{T}A^{-1}u}\right)\\
&=AA^{-1}+uv^{T}A^{-1}-{AA^{-1}uv^{T}A^{-1}+uv^{T}A^{-1}uv^{T}A^{-1} \over 1+v^{T}A^{-1}u}\\
&=I+uv^{T}A^{-1}-{uv^{T}A^{-1}+uv^{T}A^{-1}uv^{T}A^{-1} \over 1+v^{T}A^{-1}u}\\
&=I+uv^{T}A^{-1}-{u(1+v^{T}A^{-1}u)v^{T}A^{-1} \over 1+v^{T}A^{-1}u}\\
&=I+uv^{T}A^{-1}-uv^{T}A^{-1}\\
&=I\end{aligned}}}
\]
同理,有\(YX=I\).因此,当\(1+v^{T}A^{-1}u\neq 0\)时,\((A+uv^{T})^{-1}=A^{-1}-{A^{-1}uv^{T}A^{-1} \over 1+v^{T}A^{-1}u}.\)
\((\Rightarrow)\)当\(u=0\)时,显然有\(1+v^{T}A^{-1}u=1\neq 0.\)当\(u\neq0\)时,用反正法证明该命题成立。假设\(A+uv^{T}\)可逆,但\(1+v^{T}A^{-1}u = 0\),则有
\]
因为\(A+uv^{T}\)可逆,故\(A^{-1}\)u=0,又因为\(A^{-1}\)可逆,故\(u=0\),此与假设\(u\neq 0\)矛盾。因此,当\(A+uv^{T}\)可逆时,有\(1+v^{T}A^{-1}u \neq 0.\)
Sherman-Morrison公式的应用
应用1:\(A=I\)时的Sherman-Morrison公式
在Sherman-Morrison公式中,令\(A=I\),则有:\(I+uv^{T}\)可逆当且仅当\(1+v^{T}u\neq 0\), 且当\(I+uv^{T}\)可逆时,该逆矩阵由以下公式给出:
\]
再令\(v=u\),则\(1+u^{T}u > 0\), 因此,\(I+uu^{T}\)可逆,且
\]
应用2:BFGS算法
Sherman-Morrison公式在BFGS算法中的应用,可用来求解BFGS算法中近似Hessian矩阵的逆。本篇博客并不打算给出Sherman-Morrison公式在BFGS算法中的应用,将会再写篇博客介绍BFGS算法,到时再给出该公式的应用,并会在之后补上该博客的链接(因为笔者还没写)。
应用3:循环三对角线性方程组的求解
本篇博客将详细讲述Sherman-Morrison公式在循环三对角线性方程组的求解中的应用。
首先给给出理论知识介绍部分。
对于\(A\in\mathbb{R}^{n\times n}\)为可逆矩阵,\(u,v\in\mathbb{R}^{n}\)为列向量,\(1+v^{T}A^{-1}u\neq 0\),需要求解方程\((A+uv^{T})x=b.\)对此,我们可以先求解以下两个方程:
然后令$x=y-\frac{v^{T}y}{1+v^{T}z}z$,该解即为原方程的解,验证如下:
\]
{\displaystyle
{\begin{aligned}
(A+uv{T})x&=(A+uv{T})(y-\frac{v{T}y}{1+v{T}z}z)\
&=Ay+uv{T}y-\frac{v{T}y}{1+v{T}z}Az-\frac{v{T}y}{1+v{T}z}uv{T}z\
&=b+uv{T}y-\frac{v{T}yu+v{T}yuv{T}z}{1+v^{T}z}\
&=b+uv{T}y-\frac{(1+v{T}z)v{T}yu}{1+v{T}z}\
&=b+uv{T}y-uv{T}y\
&=b\end{aligned}}}
  所谓循环三对角线性方程组,指的是系数矩阵为如下形式:
\]
A=\begin{bmatrix}
b_1&c_1&0&\cdots&0&a_1\
a_2&b_2&c_2&0&\vdots&0\
0&\ddots&\ddots&\ddots&0&\vdots\
\vdots&\vdots&a_{n-2}&b_{n-2}&c_{n-2}&0\
0&\cdots&\cdots&a_{n-1}&b_{n-1}&c_{n-1}\
c_n&0&\cdots&0&a_n&b_n\end{bmatrix}
  对于此方程的求解,我们令$u=(\gamma, 0,0,...,c_{n})^{T}, v=(1,0,0,...,\frac{a_1}{\gamma})^{T}$, 且$A=A^{'}+uv^{T}$,其中$A^{'}$如下:
\]
A^{'}=\begin{bmatrix}
b_1-\gamma&c_1&0&\cdots&0&0\
a_2&b_2&c_2&0&\vdots&0\
0&\ddots&\ddots&\ddots&0&\vdots\
\vdots&\vdots&a_{n-2}&b_{n-2}&c_{n-2}&0\
0&\cdots&\cdots&a_{n-1}&b_{n-1}&c_{n-1}\
0&0&\cdots&0&a_n&b_n-\frac{a_1c_n}{\gamma}\end{bmatrix}
$$A^{'}y=d,\qquad A^{'}z=u,\]
然后,就能根据\(y,z\)求出\(x\).而以上两个方程为三对角线性方程组,可以用追赶法(或Thomas法)求解,具体算法可以参考博客:三对角线性方程组(tridiagonal systems of equations)的求解 。
综上,我们利用Sherman-Morrison公式的思想,可以将循环三对角线性方程组转化为三对角线性方程组求解。我们将会在下面给出该算法的Python语言实现。
Python实现
我们要解的循环三对角线性方程组如下:
4&1&{0}&{0}&{2}\\
{1}&{4}&{1}&{0}&{0}\\
{0}&{1}&{4}&{1}&{0}\\
{0}&{0}&{1}&{4}&{1}\\
{3}&{0}&{0}&{1}&{4}\\
\end{bmatrix}}
{\begin{bmatrix}{x_{1}}\\{x_{2}}\\{x_{3}}\\{x_{4}} \\{x_{5}}\\\end{bmatrix}}={\begin{bmatrix}{7\\6\\ 6\\6\\8}\\\end{bmatrix}}
\]
用Python实现解该方程的Python完整代码如下:
# use Sherman-Morrison Formula and Thomas Method to solve cyclic tridiagonal linear equation
import numpy as np
# Thomas Method for soling tridiagonal linear equation Ax=d
# parameter: a,b,c,d are list-like of same length
# b: main diagonal of matrix A
# a: main diagonal below of matrix A
# c: main diagonal upper of matrix A
# d: Ax=d
# return: x(type=list), the solution of Ax=d
def TDMA(a,b,c,d):
try:
n = len(d) # order of tridiagonal square matrix
# use a,b,c to create matrix A, which is not necessary in the algorithm
A = np.array([[0]*n]*n, dtype='float64')
for i in range(n):
A[i,i] = b[i]
if i > 0:
A[i, i-1] = a[i]
if i < n-1:
A[i, i+1] = c[i]
# new list of modified coefficients
c_1 = [0]*n
d_1 = [0]*n
for i in range(n):
if not i:
c_1[i] = c[i]/b[i]
d_1[i] = d[i] / b[i]
else:
c_1[i] = c[i]/(b[i]-c_1[i-1]*a[i])
d_1[i] = (d[i]-d_1[i-1]*a[i])/(b[i]-c_1[i-1] * a[i])
# x: solution of Ax=d
x = [0]*n
for i in range(n-1, -1, -1):
if i == n-1:
x[i] = d_1[i]
else:
x[i] = d_1[i]-c_1[i]*x[i+1]
x = [round(_, 4) for _ in x]
return x
except Exception as e:
return e
# Sherman-Morrison Fomula for soling cyclic tridiagonal linear equation Ax=d
# parameter: a,b,c,d are list-like of same length
# b: main diagonal of matrix A
# a: main diagonal below of matrix A
# c: main diagonal upper of matrix A
# d: Ax=d
# return: x(type=list), the solution of Ax=d
def Cyclic_Tridiagnoal_Linear_Equation(a,b,c,d):
try:
# use a,b,c to create cyclic tridiagonal matrix A
n = len(d)
A = np.array([[0] * n] * n, dtype='float64')
for i in range(n):
A[i, i] = b[i]
if i > 0:
A[i, i - 1] = a[i]
if i < n - 1:
A[i, i + 1] = c[i]
A[0, n - 1] = a[0]
A[n - 1, 0] = c[n - 1]
gamma = 1 # gamma can be set freely
u = [gamma] + [0] * (n - 2) + [c[n - 1]]
v = [1] + [0] * (n - 2) + [a[0] / gamma]
# modify the coefficient to form A'
b[0] -= gamma
b[n - 1] -= a[0] * c[n - 1] / gamma
a[0] = 0
c[n - 1] = 0
# solve A'y=d, A'z=u by using Thomas Method
y = np.array(TDMA(a, b, c, d))
z = np.array(TDMA(a, b, c, u))
# use y and z to calculate x
# x = y-(v·y)/(1+v·z) *z
# x is the solution of Ax=d
x = y - (np.dot(np.array(v), y)) / (1 + np.dot(np.array(v), z)) * z
x = [round(_, 3) for _ in x]
return x
except Exception as e:
return e
def main():
'''
equation:
A = [[4,1,0,0,2],
[1,4,1,0,0],
[0,1,4,1,0],
[0,0,1,4,1],
[3,0,0,1,4]]
d = [7,6,6,6,8]
solution x should be [1,1,1,1,1]
'''
a = [2, 1, 1, 1, 1]
b = [4, 4, 4, 4, 4]
c = [1, 1, 1, 1, 3]
d = [7, 6, 6, 6, 8]
x = Cyclic_Tridiagnoal_Linear_Equation(a,b,c,d)
print('The solution is %s'%x)
main()
输出结果如下:
The solution is [1.0, 1.0, 1.0, 1.0, 1.0]
参考文献
- https://en.wikipedia.org/wiki/Sherman–Morrison_formula
- http://wwwmayr.in.tum.de/konferenzen/Jass09/courses/2/Soldatenko_paper.pdf
- https://scicomp.stackexchange.com/questions/10137/solving-system-of-linear-equations-with-cyclic-tridiagonal-matrix
- https://blog.csdn.net/jclian91/article/details/80251244
注意:本人现已开通两个微信公众号: 用Python做数学(微信号为:python_math)以及轻松学会Python爬虫(微信号为:easy_web_scrape), 欢迎大家关注哦~~
Sherman-Morrison公式及其应用的更多相关文章
- ZROI 暑期高端峰会 A班 Day2 线性代数
高斯消元 很普及组,不讲了 当主元没有逆的时候可以辗转相除. 如果也没有带余数除法--没救了 逆矩阵 我们定义矩阵 \(A\) 的逆矩阵为 \(A^{-1}\),满足 \(AA^{-1}=A^{-1} ...
- RLS自适应滤波器中用矩阵求逆引理来避免求逆运算
在RLS自适应滤波器的实现过程中,难免不涉及矩阵的求逆运算.而求逆操作双是非常耗时的,一个很自然的想法就是尽可能的避免直接对矩阵进行求逆运算.那么,在RLS自适应滤波器的实现中,有没有一种方法能避免直 ...
- 2019暑期金华集训 Day2 线性代数
自闭集训 Day2 线性代数 高斯消元 做实数时,需要找绝对值最大的作为主元,以获取更高精度. 在欧几里得环(简单例子是模合数)意义下也是对的.比如模合数意义下可以使用辗转相除法消元. 欧几里得环:对 ...
- 伍德伯里矩阵恒等式(Woodbury matrix identity)
宜言饮酒,与子偕老.琴瑟在御,莫不静好. 更多精彩内容请关注微信公众号 "优化与算法" 在数学(特别是线性代数)中,Woodbury矩阵恒等式是以Max A.Woodbury命名的 ...
- 为WLW开发Latex公式插件
WLW是写博客的利器,支持离线.格式排版等,而且拥有众多的插件.博客园推荐了代码插入插件,但是没有提供WLW的公式编译插件.目前我的一般做法是:先在Word下使用MathType编辑好公式,然后将公式 ...
- 百度编辑器UEditor与UEditor 公式插件完整Demo
1.下载UEditor(我的是.net项目) 2.下载UEditor公式插件 3.新建解决方案和项目 4.在浏览器中预览index.html页面 结果: 5.index.html源码 <!DOC ...
- poi读取excel模板,填充内容并导出,支持导出2007支持公式自动计算
/** * 版权所有(C) 2016 * @author www.xiongge.club * @date 2016-12-7 上午10:03:29 */ package xlsx; /** * @C ...
- Oracle Sales Cloud:管理沙盒(定制化)小细节1——利用公式创建字段并显示在前端页面
Oracle Sales Cloud(Oracle 销售云)是一套基于Oracle云端的CRM管理系统.由于 Oracle 销售云是基于 Oracle 云环境的,它与传统的管理系统相比,显著特点之一便 ...
- Excel公式 提取文件路径后缀
我们在代码中获取一个文件路径的后缀,是一个很简单的事. 如C#中,可以通过new FileInfo(filePath).Extension,或者Path.GetExtension(filePath)获 ...
随机推荐
- Git的SSH-key生成、导入及使用
Git主要使用4种协议传输数据:本地协议,SSH协议,Git协议和HTTP/S协议. SSH协议是最为常用的一种,正式介绍SSH之前,简要说明一下其它协议. 本地协议(file://) 本地协议的优点 ...
- C语言基础课第二次作业
一. 题目7-1 统计学生成绩 1.实验代码 #include<stdio.h> int main(void) { int i,grade,n; ,b=,c=,d=,e=; scanf( ...
- PHP字符串截取函数
substr函数 描述:实现截取字符串 语法:string substr(string $string,int $start [, int $length ]) 说明:如果省略length,则返回从s ...
- c++两个类相互调用
有可能会碰到两个类之间的相互调用的问题,例如:定义了类A和类B,A中使用了B定义的类型,B中也使用了A定义的类型 class A { B b; }; class B { A a; }; 编译器在声明A ...
- 1018 Public Bike Management (30) Dijkstra算法 + DFS
题目及题解 https://blog.csdn.net/CV_Jason/article/details/81385228 迪杰斯特拉重新认识 两个核心的存储结构: int dis[n]: //记录每 ...
- MySQL 查看修改字符集
查看MYSQL数据库服务器和数据库字符集 方法一:show variables like '%character%'; 方法二:show variables like 'collation%'; sh ...
- uniGUI中Cookies使用中文汉字的方法(使用EncodeString函数编码)
uniGUI中Cookies使用中文汉字的方法(使用EncodeString函数编码) 在目前的UniGUI(ver:0.88)中使用UniApplication.Cookies.SetCooki ...
- VS工具栏没有出现可用工具的情况
(1)没有切换到资源视图,打开具体的对话框. (2)如果你在调试状态,即使打开了具体的对话框,VS工具箱还是不会出现可用的控件的.所以不要在调试状态下添加控件.
- 用Python进行有进度条的π计算
1.tqdm是一个强大的终端进度条工具,我利用pip获取tqdm函数库. 2编写代码 2.1进行π的计算 from random import random from math import sqrt ...
- Java学习笔记50(DBCP连接池)
实际开发中,连接数据库是十分消耗资源的操作,但是,我们又需要频繁地连接数据库 这时候,为了提高效率,这里就会采用连接池技术: 连接池地通俗理解: 一个池里面放入很多的连接,需要哪一个取出来用即可,用完 ...