MRDIVIDE或者操作符/
实际上解决的是线性方程组xb = a
,而不是MLDIVIDE或者操作符\
所解决的方程组bx = a
。
要解决一个非对称、非可逆矩阵b
的方程组xb = a
,你可以使用mridivide()
通过高斯消元分解 b 来完成,或者使用pinv()
通过奇异值分解并将奇异值下降到(默认)容差水平以下来完成。
这里是它们之间的区别(对于mldivide
的情况):求解A*x=b时,PINV和MLDIVIDE有什么区别?
当系统是超定的时候,两种算法提供相同的答案。当系统是欠定的时候,PINV将返回具有最小范数(min NORM(x))的解x。而MLDIVIDE将选择具有最少非零元素的解。
在你的例子中:
a = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9];
b = ones(25, 18);
该系统是欠定的,因此存在两个不同的解决方案:
x1 = a/b;
x2 = a*pinv(b);
>> x1 = a/b
Warning: Rank deficient, rank = 1, tol = 2.3551e-014.
ans =
5.0000 0 0 ... 0
>> x2 = a*pinv(b)
ans =
0.2 0.2 0.2 ... 0.2
在两种情况下,xb-a
的近似误差是非常重要的(非精确解),且相同,即norm(x1*b-a)
和norm(x2*b-a)
将返回相同的结果。
MATLAB正在做什么?
这篇帖子在scicomp.stackexchange.com中提供了关于“\”操作符所涉及到的算法(以及属性检查)的详细分解,具体取决于矩阵b
的结构。我假设类似的选项适用于“/”操作符。
对于你的例子,MATLAB很可能执行高斯消元,在无穷多个最稀疏的解中给出最稀疏的解(这就是5的来源)。
Python正在做什么?
Python的linalg.lstsq
使用伪逆/SVD,如上所示(这就是为什么您会得到一组0.2的向量)。实际上,以下两种方法都会给出与MATLAB的pinv()
相同的结果:
from numpy import *
a = array([1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9])
b = ones((25, 18))
x2 = linalg.lstsq(b.T, a.T)[0]
x2 = dot(a, linalg.pinv(b))
XA = B
的X
。对两边进行转置计算得到A'X' = B'
。由于np.linalg.solve
解决了CY = D
的Y
,那么我们可以让C = A'
和D = B'
得到Y = X'
。最后,通过对Y
进行转置,我们得到了X
。 - mhdadk