C++ solve()在针对奇异矩阵时崩溃

C++ solve()在针对奇异矩阵时崩溃,c++,armadillo,singular,matrix-inverse,numerical-stability,C++,Armadillo,Singular,Matrix Inverse,Numerical Stability,我试图用最小二乘法来解线性方程组。 使用犰狳及其解函数,我想计算抛物线拟合的三个系数 vec coeffs = solve(CtC, Ctb) 与反恐委员会= 1.0e+009 * +--------------------------------+ | 2.0878 0.0221 0.0002 | | 0.0221 0.0002 0.0000 | | 0.0002 0.0000 0.0000 | +----------

我试图用最小二乘法来解线性方程组。 使用犰狳及其解函数,我想计算抛物线拟合的三个系数

vec coeffs = solve(CtC, Ctb)
与反恐委员会=

1.0e+009 *       
+--------------------------------+
|     2.0878    0.0221    0.0002 |
|     0.0221    0.0002    0.0000 |
|     0.0002    0.0000    0.0000 |
+--------------------------------+
和Ctb=

+------------+
|    -0.6163 |
|    -0.0065 |
|    -0.0001 |
+------------+
显然solve()无法解决此问题,甚至Matlab警告:

Warning: Matrix is close to singular or badly scaled. Results may be inaccurate.
RCOND = 1.303968e-022. 
<> Pr>在ARMADILO或C++中有没有任何解决方法或更强大的方法?
谢谢

行列式等于零的矩阵不能求逆。在你的例子中,行列式等于-8e-12,它实际上并不等于零,而是作为逆矩阵给出(使用R)

注意,这个逆矩阵既有非常大的数字,也有非常小的数字。这解释了您关于“接近单数”和“严重缩放”的警告。根据基础浮点库的不同,可能会出现非常严重的舍入错误


您可以返回应用程序,查看是否有任何变量表示彼此相差很多数量级的列或行。如果是这样的话,你可以重新调整尺寸。例如,如果它们之间的系数为100万,并且它们代表长度,则一个以公里表示,另一个以毫米表示。

您面临的问题是矩阵的精度非常高,这可能会由于舍入错误而使结果变得毫无意义

正如rhalbersma所建议的,您可以尝试更好地缩放不同的条目以减少此问题。如果您没有这样的解决方案,那么您必须使用。它们有很多(有些非常复杂),所以你应该找到一个适合你的问题

然而,对于你手头的这个特殊系统,我将简单地反转方程(1)和(3),这将产生一个下三角系统,这个系统很容易用Matlab求解(不需要对条件数非常敏感的迭代方法。在您的情况下,由于矩阵是对称的,Matlab可能会尝试使用cg(一种迭代方法)求解它)

顺便问一下,您的问题是否会产生近似奇异的矩阵?如果不是,我会在组装矩阵之前检查问题(或bug)(由于舍入错误,矩阵可能是非奇异的)


编辑:在我的Matlab2009上,我在尝试解决此系统时(使用
\
命令)没有收到任何警告。但是,如果我尝试使用命令
pcg
,我就明白了!

是的,我知道,这是根据预期的。我正在考虑一个实现,使用诸如Moore Penrose之类的伪逆来计算系数。这样的实现存在吗?@bogus根据您的符号,我推测您最初的问题是s
cx=b
并且
C
不是一个平方矩阵。这意味着你试图求解
ctcx=ctb
,也就是说,你用原始方程的两边乘以
Ct
(C transpose)。这已经是一个广义逆,所以你不会得到任何东西。确切地说,C不是平方的,这就是为什么我称之为C“最小二乘法风格"。我为我的实际应用找到了一个很好的解决方案,这在我的上下文中是有意义的。无论如何,谢谢!@bogus那么你做了什么?这可能会帮助其他有相同问题的人…行列式和逆式不是正确的,你忘记了矩阵前面的1e9因子。但是,这不会改变问题和y我们的答案仍然有效。+1用于提及前置条件。我已经完全忘记了这些(自从我的数值分析课程开始已经10多年了)
1.0e-009 *
              [,1]          [,2]    [,3]
[1,] -3.815763e-16  6.806617e-14    5000
[2,]  5.111864e-14  5.000000e+03 -552500
[3,]  5.000000e+03 -5.525000e+05 8856250