当只有少数常数项发生变化时,如何有效地求解大型线性方程组。例如:
我目前有系统 Ax=b。我计算 A 的逆一次,将其存储在矩阵中,并且每次 b 中的任何条目更新执行矩阵向量乘法 A^-1(b) 以重新计算 x。
这是低效的,因为只有几个条目会在 b 中更新。当 A-1 保持不变但 b 中特定的已知值发生变化时,是否有更有效的方法来解决这个系统?
我使用 uBlas 和 Eigen,但不知道可以解决这个选择性重新计算问题的解决方案。感谢您的任何指导。
当只有少数常数项发生变化时,如何有效地求解大型线性方程组。例如:
我目前有系统 Ax=b。我计算 A 的逆一次,将其存储在矩阵中,并且每次 b 中的任何条目更新执行矩阵向量乘法 A^-1(b) 以重新计算 x。
这是低效的,因为只有几个条目会在 b 中更新。当 A-1 保持不变但 b 中特定的已知值发生变化时,是否有更有效的方法来解决这个系统?
我使用 uBlas 和 Eigen,但不知道可以解决这个选择性重新计算问题的解决方案。感谢您的任何指导。
计算A^-1
。如果b_i
是 的第 i 个分量b
,则检查d/db_i A^-1 b
(A^-1 相对于 的第 i 个分量的导数b
)——它等于A^-1
(特别是第 i 个列)的列。并且线性函数的导数在其域上是常数。因此,如果您有b
和b'
,并且它们仅在第 i 个分量上有所不同,则A^-1 b - A^-1 b' = [d/db_i A^-1] * (b-b')_i
. 对于多个组件,只需将它们相加(A^-1
线性)。
或者,简而言之,您可以A^-1 (b'-b)
对为零的输入组件进行一些优化(如果只有一些组件发生变化,则将是大部分组件)。 A^-1 b' = A^-1 (b'-b) + A^-1 (b)
. 如果您知道只有某些组件会发生变化,您可以复制 的相应列A^-1
,然后将其乘以 b 的该组件的变化。
您可以利用问题的线性:
x0 = A_(-1)*b0
x = A_(-1)*b = x0 + A_(-1)*db
b
其中 db 是和之间的差异矩阵b0
,它应该用零填充:您可以将其压缩为稀疏矩阵。
Eigen lib有很多很酷的稀疏矩阵函数(乘法,逆,...)。
首先,不要执行矩阵求逆,而是使用求解器库。其次,将您的姓名首字母x
作为第一个猜测传递给图书馆。
该库将执行某种分解,如 LU,并使用它来计算x
. 如果您选择一个迭代求解器,那么它已经在完成您描述的解决方案中的大部分内容;它会从一个更糟糕的猜测开始并产生一个更好的猜测,任何好的例程都需要一个初步的猜测来加速这个过程。在许多情况下,无论如何您都对结果有一个很好的了解,因此利用它是有意义的。
如果新b
的接近旧的b
,那么新的x
应该接近旧的x
,这将作为一个很好的初步猜测。
首先,不要计算矩阵逆,而是使用 LU 分解或 QR 分解(比 LU 慢但更稳定)。这种分解在矩阵大小方面比反演性能更好,并且通常更稳定(尤其是 QR)。
如果 A 发生轻微变化(例如,通过一级矩阵),有一些方法可以更新 QR 分解,但是如果 B 发生变化,则必须用新的 b 再次求解——你无法逃避这一点,这是 O(n ^2)。
但是,如果右手边 B 只改变一个固定元素,即。B' = B + dB 预先知道 dB,您可以一劳永逸地解决 A dx = dB,现在 Ax' = B' 的解决方案 x' 是 x + dX。
如果预先不知道dB,但总是几个dB_i向量的线性组合,你可以解出A dx_i = dB_i,但是如果你有很多这样的dB_i,你最终会得到一个^2过程(这实际上相当于计算逆)...