问题
我希望求解线性方程组 A*x=b 的一般系统。m×m 矩阵是稀疏的、实数的、方形的、条件较差的、非对称的,但它是奇异的(rank(A)==m-1),因为x
只知道一个加性常数。
i
我可以通过在三个向量( 、j
和)中指定其非零条目来创建矩阵 A,v
使得A(i(k),j(k)) = v(k)
:
A = sparse( i, j, v, m, m );
原始方程
我可以解决这个原始方程如下:
x = A \ b;
如果我想要一个唯一的解决方案,我可以在计算非唯一解决方案后施加一个约束(例如,x(4) == 3.14159):
x = x - x(4) + 3.14159;
修正方程
我可以通过添加一个额外的唯一性约束来创建一个新的全秩矩阵C
,如下所示:
% Add the constraint x(4) == 3.14159
extraRow = zeros(1,m);
extraRow(4) = 1.0;
C = [A; extraRow]; % Add to the matrix A
d = [b; 3.14159]; % Add to the RHS vector, b
% Solve C*y = d for y
y = C \ d;
数字
我知道,当我通过x = A \ b
或求解这些方程时y = C \ b
,MATLAB 将 解释\
为mldivide()
命令(链接),该命令对矩阵运行一些测试并找出求解例程的最佳算法(有关详细信息,请参阅链接)。
通过设置 MATLAB 的稀疏矩阵求解参数,这些细节在运行时变得冗长spparms('spumoni',2)
当我计算x
和/或y
时,我注意到以下内容:
- MATLAB 通过 UMFPACK V5.4.0 将 LU 分解用于平方 m×m 原始方程。
- MATLAB 通过 SuiteSparseQR 1.1.0 对 m×(m+1) 修改方程使用 QR 分解。
UMFPACK 和 SuiteSparseQR 都是 SuiteSparse 软件包(链接)的一部分。
(有点出乎意料的是,求解修改后的方程会产生比原始方程更多的错误。虽然很重要,但这个错误仍然处于可接受的低阈值。)
我的问题
现在我可以在 MATLAB 中解决这个问题,我希望在 Fortran 中这样做。不幸的是,MATLAB 的mldivide()
命令是一个黑匣子,我看不到它是如何设置或调用SuiteSparse例程的。
鉴于我在 Fortran (90+) 中有三个稀疏向量,如下所示,如何使用SuiteSparse解决问题?
或者,是否有人知道与 UMFPACK 接口的任何 F90 包装例程以使这更容易?
如果有人可以帮助解决这个问题,我会非常高兴——无论是原始方程还是修正方程。(如果你帮助一个,我可能会得到另一个。)
subroutine solveSparseMatrixEqnViaSuiteSparse( m, n, nnz, i, j, v, x )
implicit none
integer, intent(in) :: m ! sparse matrix rows
integer, intent(in) :: n ! sparse matrix columns
integer, intent(in) :: nnz ! number of nonzero entries
integer, dimension(1:nnz), intent(in) :: i ! row indices of nonzero entries
integer, dimension(1:nnz), intent(in) :: j ! column indices of nonzero entries
real*8, dimension(1:nnz), intent(in) :: v ! values of nonzero entries
real*8, dimension(1:n), intent(out) :: x ! solution vector
! I have no idea what to do next!
end function solveSparseMatrixEqnViaSuiteSparse
让我感到困惑的是以下几点:
- MATLAB 在幕后做了什么来设置对 SuiteSparse 的调用?(它似乎没有记录在案......)
- 从 Fortran 中调用 SuiteSparse 需要做什么?(如果有足够的时间,我可能可以从这个演示中弄清楚大部分,但奇怪的是它多次调用例程......)
注意:尽管我在提出这个问题时考虑到了一个特定的问题(谁不是!?),但我相信这足够普遍,对其他人也有用。