【问题标题】:How to implement Matlab's mldivide (a.k.a. the backslash operator "\")如何实现 Matlab 的 mldivide(又名反斜杠运算符“\”)
【发布时间】:2023-03-16 16:35:01
【问题描述】:

我目前正在尝试开发一个小型的面向矩阵的数学库(我使用Eigen 3 进行矩阵数据结构和运算)并且我想实现一些方便的 Matlab 函数,例如广泛使用的反斜杠运算符 (等价于mldivide),用于计算线性系统的解(以矩阵形式表示)。

有没有关于如何实现这一点的详细解释? (我已经用经典的 SVD 分解实现了 Moore-Penrose 伪逆 pinv 函数,但我在某处读到 A\b 并不总是 pinv(A)*b ,至少 Matalb 不会简单地这样做)

谢谢

【问题讨论】:

标签: c++ matlab matrix linear-algebra equation-solving


【解决方案1】:

对于x = A\bbackslash 运算符包含多个algorithms 来处理不同类型的输入矩阵。因此矩阵A被诊断出来,并根据其特征选择执行路径。

以下page 以伪代码描述A 为全矩阵时:

if size(A,1) == size(A,2)         % A is square
    if isequal(A,tril(A))         % A is lower triangular
        x = A \ b;                % This is a simple forward substitution on b
    elseif isequal(A,triu(A))     % A is upper triangular
        x = A \ b;                % This is a simple backward substitution on b
    else
        if isequal(A,A')          % A is symmetric
            [R,p] = chol(A);
            if (p == 0)           % A is symmetric positive definite
                x = R \ (R' \ b); % a forward and a backward substitution
                return
            end
        end
        [L,U,P] = lu(A);          % general, square A
        x = U \ (L \ (P*b));      % a forward and a backward substitution
    end
else                              % A is rectangular
    [Q,R] = qr(A);
    x = R \ (Q' * b);
end

对于非方阵,使用QR decomposition。对于方三角矩阵,它执行简单的forward/backward substitution。对于平方对称正定矩阵,使用Cholesky decomposition。否则LU decomposition 用于一般方阵。

更新: MathWorks 更新了mldivide 文档页面中的algorithm section 并添加了一些漂亮的流程图。请参阅 herehere(完整和稀疏案例)。

所有这些算法在@​​987654331@ 中都有对应的方法,实际上这可能是 MATLAB 正在做的事情(请注意,最新版本的 MATLAB 附带了优化的 Intel MKL 实现)。

使用不同方法的原因是它试图使用最具体的算法来求解利用系数矩阵的所有特征的方程组(因为它会更快或更数值稳定)。所以你当然可以使用通用求解器,但它不会是最有效的。

事实上,如果您事先知道A 是什么样的,您可以通过调用linsolve 并直接指定选项来跳过额外的测试过程。

如果A 是矩形或奇异的,您还可以使用PINV 来找到最小范数最小二乘解(使用SVD decomposition 实现):

x = pinv(A)*b

以上所有内容都适用于稠密矩阵,稀疏矩阵则完全不同。通常在这种情况下使用iterative solvers。我相信 MATLAB 将 UMFPACK 和 SuiteSpase 包中的其他相关库用于直接求解器。

使用稀疏矩阵时,您可以打开诊断信息并查看使用spparms 执行的测试和选择的算法:

spparms('spumoni',2)
x = A\b;

此外,反斜杠运算符也适用于 gpuArray,在这种情况下,它依赖于 cuBLASMAGMA 在 GPU 上执行。

它也为distributed arrays 实现,它在分布式计算环境中工作(工作在一组计算机之间分配,每个工作人员只有数组的一部分,可能整个矩阵不能一次全部存储在内存中) .底层实现使用ScaLAPACK

如果你想自己实现所有这些,这是一个相当高的要求:)

【讨论】:

  • 谢谢 Amro,这是一个非常有建设性的回答。 “A”最有可能是一个非方阵,所以,如果我理解正确的话,最适合使用的方法是 QR 分解。是的,我愿意(至少尝试)实现所需的东西以制作一个有点独立的库,所以我真的不想使用其他数学包(算法的效率是,对于时刻,不是我的主要目标;))。这是一个个人项目,暂时没有什么大不了的……
  • @M4XMX:是的,您可以使用 QR 分解:Ax=b --> QRx=b --> Rx=Q'b --> x=R\(Q'b)(最后一步是一个简单的反向替换过程)。有关说明,请参阅here。这里还有一个相关的question,展示了如何使用各种库解决Ax=b:GSL、Armadillo、Eigen。无需重新发明轮子:)
  • 我认为 MATLAB 也可能使用 pivoting 来提高数值精度。那就是分解为:AP=QR 其中P 是一个置换矩阵
  • 多么美丽的答案。我一直想知道使用了什么算法`\`。 + 1.
  • @tommsch 我们使用A' 的QR 分解并解决(QR)'*x=b: en.wikipedia.org/wiki/…
猜你喜欢
  • 1970-01-01
  • 2016-02-07
  • 2017-12-31
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 2011-09-06
  • 2014-09-09
相关资源
最近更新 更多