gpt4 book ai didi

eigen - 重用 Eigen::SimplicialLLT 的符号分解

转载 作者:行者123 更新时间:2023-12-02 15:28:28 33 4
gpt4 key购买 nike

我在 Eigen 库的 API 上遇到了一些困难,即用于稀疏矩阵 Cholesky 分解的 SimplicialLLT 类。我需要分解三个矩阵,然后用它们来求解许多方程组(仅更改右侧) - 因此我只想将这些矩阵分解一次,然后重新使用它们。此外,它们都具有相同的稀疏模式,因此我只想进行一次符号分解,然后将其用于所有三个矩阵的数值分解。根据文档,这正是 SimplicialLLT::analyzePatternSimplicialLLT::factor 方法的用途。 但是,我似乎找不到一种方法来将所有三个因素都保留在内存中。这是我的代码:

我的类中有这些成员变量,我想用这些因素填充:

Eigen::SimplicialLLT<Eigen::SparseMatrix<double>> choleskyA;
Eigen::SimplicialLLT<Eigen::SparseMatrix<double>> choleskyB;
Eigen::SimplicialLLT<Eigen::SparseMatrix<double>> choleskyC;

然后我创建三个稀疏矩阵 A、B 和 C 并希望对它们进行因式分解:

choleskyA.analyzePattern(A);
choleskyA.factorize(A);
choleskyB.analyzePattern(B); // this has already been done!
choleskyB.factorize(B);
choleskyC.analyzePattern(C); // this has already been done!
choleskyC.factorize(C);

之后我可以一遍又一遍地使用它们来解决问题,只需更改右侧的 b 向量即可:

xA = choleskyA.solve(bA);
xB = choleskyB.solve(bB);
xC = choleskyC.solve(bC);

这可行(我认为),但是对analyzePattern的第二次和第三次调用是多余的。我想做的是这样的:

choleskyA.analyzePattern(A);
choleskyA.factorize(A);
choleskyB = choleskyA.factorize(B);
choleskyC = choleskyA.factorize(C);

但这不是当前 API 的一个选项(我们使用 Eigen 3.2.3,但如果我没看错的话,3.3.2 在这方面没有任何变化)。 这里的问题是,对 SimplcialLLT 的同一实例进行因式分解的后续调用将覆盖之前计算的因式,同时,我无法找到一种方法来复制它以保留。 我查看了源代码,但我必须承认这没有多大帮助,因为我看不到任何复制底层数据结构的简单方法。在我看来,这是一个相当常见的用法,所以我觉得我遗漏了一些明显的东西,请帮忙。

我尝试过的:

我尝试简单地使用choleskyB = choleskyA,希望默认的复制构造函数能够完成任务,但我发现基类被设计为不可复制。

我可以从 choleskyA 获取 L 和 U 矩阵(它们有一个 setter/getter ),复制它们并仅存储它们,然后基本上复制粘贴 SimplicialCholeskyBase::_solve_impl 的内容()(下面复制粘贴)直接用之前存储的L和U来写自己求解的方法。

template<typename Rhs,typename Dest>
void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
{
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
eigen_assert(m_matrix.rows()==b.rows());

if(m_info!=Success)
return;

if(m_P.size()>0)
dest = m_P * b;
else
dest = b;

if(m_matrix.nonZeros()>0) // otherwise L==I
derived().matrixL().solveInPlace(dest);

if(m_diag.size()>0)
dest = m_diag.asDiagonal().inverse() * dest;

if (m_matrix.nonZeros()>0) // otherwise U==I
derived().matrixU().solveInPlace(dest);

if(m_P.size()>0)
dest = m_Pinv * dest;
}

...但这是一个相当丑陋的解决方案,而且我可能会把它搞砸,因为我对这个过程没有很好的理解(我不需要上面代码中的 m_diag,因为我正在做 LLT,对吧?只有当我使用 LDLT 时,这才有意义?)。我希望这不是我需要做的......

最后一点 - 将必要的 getter/setter 添加到 Eigen 类并编译“我自己的”Eigen 不是一种选择(好吧,不是一个好的选择),因为此代码将(希望)作为开源进一步重新分发,所以会很麻烦。

最佳答案

这是一个非常不寻常的模式。在实践中,与数值因式分解相比,符号因式分解非常便宜,因此我不确定是否值得如此费心。解决此模式的最简洁的解决方案是让 SimplialL?LT 可复制。

关于eigen - 重用 Eigen::SimplicialLLT 的符号分解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41899666/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com