[英]Eigen Sparse LU solver
我使用 C++ 中的 Eigen 庫來求解稀疏線性方程:Ax=b 其中,A 是方形稀疏矩陣,b 是矩形稀疏矩陣。 我有多個 A 矩陣的實例,每個實例都有多個右側 b。 因此,我想將所有 A 矩陣分解一次並存儲它們,然后是每個 A 和每個 b 的解決方案。
我嘗試使用 C++ 向量來存儲所有求解器。 這是我編寫的示例代碼:
vector<Eigen::SparseMatrix<double>> A;
//fill in all A matrices
vector<Eigen::SparseLU<Eigen::SparseMatrix<double>>> solver_A;
Eigen::SparseLU<Eigen::SparseMatrix<double>> solver;
for (int i=0;i<A.size();i++){
solver.analyzePattern(A[i]);
solver.factorize(A[i]);
solver_A.push_back(solver);
}
//Later, solver_A entries are to be used to solve for various right hand sides
我正在使用 3.3.7 版本的 Eigen 並在 linux 中使用 gcc 編譯器和 c++17 標准進行編譯。 由於solver_A.push_back(solver)
行,我收到以下編譯錯誤:
<pre>/usr/include/c++/7/ext/new_allocator.h: In instantiation of ‘<b>void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Eigen::SparseLU<Eigen::SparseMatrix<double> >; _Args = {const Eigen::SparseLU<Eigen::SparseMatrix<double, 0, int>, Eigen::COLAMDOrdering<int> >&}; _Tp = Eigen::SparseLU<Eigen::SparseMatrix<double> >]</b>’:
<b>/usr/include/c++/7/bits/alloc_traits.h:475:4:</b> required from ‘<b>static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = Eigen::SparseLU<Eigen::SparseMatrix<double> >; _Args = {const Eigen::SparseLU<Eigen::SparseMatrix<double, 0, int>, Eigen::COLAMDOrdering<int> >&}; _Tp = Eigen::SparseLU<Eigen::SparseMatrix<double> >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<Eigen::SparseLU<Eigen::SparseMatrix<double> > >]</b>’
<b>/usr/include/c++/7/bits/stl_vector.h:943:30:</b> required from ‘<b>void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Eigen::SparseLU<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::SparseLU<Eigen::SparseMatrix<double> > >; std::vector<_Tp, _Alloc>::value_type = Eigen::SparseLU<Eigen::SparseMatrix<double> >]</b>’
<b>header_files/coefficient_computations.cpp:476:51:</b> required from here
<b>/usr/include/c++/7/ext/new_allocator.h:136:4:</b> <font color="#EF2929"><b>error: </b></font>‘Eigen::SparseLU<_MatrixType, _OrderingType>::SparseLU(const Eigen::SparseLU<_MatrixType, _OrderingType>&) [with _MatrixType = Eigen::SparseMatrix<double>; _O<b>rderingType = Eigen::COLAMDOrdering<int>]</b>’ is private within this context
{ <font color="#EF2929"><b>::new((void *)__p) _Up(std::forward<_Args>(__args)...)</b></font>; }
<font color="#EF2929"><b>^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</b></font>
In file included from <b>../Eigen_3_3_7/unsupported/Eigen/../../Eigen/SparseLU:44:0</b>,
from <b>../Eigen_3_3_7/unsupported/Eigen/../../Eigen/Sparse:31</b>,
from <b>../Eigen_3_3_7/unsupported/Eigen/SparseExtra:13</b>,
from <b>header_files/general_functions.hpp:17</b>,
from <b>header_files/coefficient_computations.hpp:17</b>,
from <b>header_files/coefficient_computations.cpp:2</b>:
<b>../Eigen_3_3_7/unsupported/Eigen/../../Eigen/src/SparseLU/SparseLU.h:393:5:</b> <font color="#34E2E2"><b>note: </b></font>declared private here
<font color="#34E2E2"><b>SparseLU</b></font> (const SparseLU& );
<font color="#34E2E2"><b>^~~~~~~~</b></font>
In file included from <b>/usr/include/c++/7/vector:62:0</b>,
from <b>header_files/coefficient_computations.hpp:13</b>,
from <b>header_files/coefficient_computations.cpp:2</b>:
/usr/include/c++/7/bits/stl_construct.h: In instantiation of ‘<b>void std::_Construct(_T1*, _Args&& ...) [with _T1 = Eigen::SparseLU<Eigen::SparseMatrix<double> >; _Args = {Eigen::SparseLU<Eigen::SparseMatrix<double, 0, int>, Eigen::COLAMDOrdering<int> >}]</b>’:
<b>/usr/include/c++/7/bits/stl_uninitialized.h:83:18:</b> required from ‘<b>static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Eigen::SparseLU<Eigen::SparseMatrix<double> >*>; _ForwardIterator = Eigen::SparseLU<Eigen::SparseMatrix<double> >*; bool _TrivialValueTypes = false]</b>’
<b>/usr/include/c++/7/bits/stl_uninitialized.h:134:15:</b> required from ‘<b>_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Eigen::SparseLU<Eigen::SparseMatrix<double> >*>; _ForwardIterator = Eigen::SparseLU<Eigen::SparseMatrix<double> >*]</b>’
<b>/usr/include/c++/7/bits/stl_uninitialized.h:289:37:</b> required from ‘<b>_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<Eigen::SparseLU<Eigen::SparseMatrix<double> >*>; _ForwardIterator = Eigen::SparseLU<Eigen::SparseMatrix<double> >*; _Tp = Eigen::SparseLU<Eigen::SparseMatrix<double> >]</b>’
<b>/usr/include/c++/7/bits/stl_uninitialized.h:311:2:</b> required from ‘<b>_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Eigen::SparseLU<Eigen::SparseMatrix<double> >*; _ForwardIterator = Eigen::SparseLU<Eigen::SparseMatrix<double> >*; _Allocator = std::allocator<Eigen::SparseLU<Eigen::SparseMatrix<double> > >]</b>’
<b>/usr/include/c++/7/bits/vector.tcc:426:6:</b> required from ‘<b>void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const Eigen::SparseLU<Eigen::SparseMatrix<double, 0, int>, Eigen::COLAMDOrdering<int> >&}; _Tp = Eigen::SparseLU<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::SparseLU<Eigen::SparseMatrix<double> > >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<Eigen::SparseLU<Eigen::SparseMatrix<double> >*, std::vector<Eigen::SparseLU<Eigen::SparseMatrix<double> > > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = Eigen::SparseLU<Eigen::SparseMatrix<double> >*]</b>’
<b>/usr/include/c++/7/bits/stl_vector.h:948:21:</b> required from ‘<b>void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Eigen::SparseLU<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::SparseLU<Eigen::SparseMatrix<double> > >; std::vector<_Tp, _Alloc>::value_type = Eigen::SparseLU<Eigen::SparseMatrix<double> >]</b>’
<b>header_files/coefficient_computations.cpp:476:51:</b> required from here
<b>/usr/include/c++/7/bits/stl_construct.h:75:7:</b> <font color="#EF2929"><b>error: </b></font>‘Eigen::SparseLU<_MatrixType, _OrderingType>::SparseLU(const Eigen::SparseLU<_MatrixType, _OrderingType>&) [with _MatrixType = Eigen::SparseMatrix<double>; _O<b>rderingType = Eigen::COLAMDOrdering<int>]</b>’ is private within this context
{ <font color="#EF2929"><b>::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...)</b></font>; }
<font color="#EF2929"><b>^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</b></font>
In file included from <b>../Eigen_3_3_7/unsupported/Eigen/../../Eigen/SparseLU:44:0</b>,
from <b>../Eigen_3_3_7/unsupported/Eigen/../../Eigen/Sparse:31</b>,
from <b>../Eigen_3_3_7/unsupported/Eigen/SparseExtra:13</b>,
from <b>header_files/general_functions.hpp:17</b>,
from <b>header_files/coefficient_computations.hpp:17</b>,
from <b>header_files/coefficient_computations.cpp:2</b>:
<b>../Eigen_3_3_7/unsupported/Eigen/../../Eigen/src/SparseLU/SparseLU.h:393:5:</b> <font color="#34E2E2"><b>note: </b></font>declared private here
<font color="#34E2E2"><b>SparseLU</b></font> (const SparseLU& );
<font color="#34E2E2"><b>^~~~~~~~</b></font>
</pre>
如果注釋了“solver_A.push_back(solver)”行,則編譯成功。 感謝任何幫助解決此問題或使用替代解決方案。
vector::push_back
要求向量元素是可復制或可移動的。 SparseLU
兩者都不是,因為它有一個私有復制構造函數( https://eigen.tuxfamily.org/dox/SparseLU_8h_source.html ):
private: // Disable copy constructor SparseLU (const SparseLU& );
您可以通過多種方式解決這個問題。 例如,通過構建具有適當大小的求解器向量,使其不需要動態增長( https://godbolt.org/z/vS85P8 ):
vector<Eigen::SparseMatrix<double>> A;
vector<Eigen::SparseLU<Eigen::SparseMatrix<double>>> solver_A(A.size());
for (int i=0;i<A.size();i++) {
solver_A[i].analyzePattern(A[i]);
solver_A[i].factorize(A[i]);
}
如果這是不可能的,另一種選擇是將您的求解器包裝成可移動類型,例如std::unique_ptr<Eigen::SparseMatrix<double>>
。
作為旁注,您可以使用compute
而不是analyzePattern
,然后使用factorize
。
另一種可能性是將std::deque
與emplace_back
方法一起使用。 請注意, std::vector
不可能做到這一點,因為這里的vector::emplace_back
可能會移動現有元素。 deque::emplace_back
不需要這樣做。
我不知道,您正在實施什么算法,但我遇到了類似的問題,並認為我需要存儲求解器。 在我的情況下,可以一個接一個地使用求解器(並且永遠不會再次用於同一個矩陣),所以我可以使用一個求解器而不是向量。 如果可能的話,這可能是一種更好的方法,因為它占用的內存較少,因為每個求解器僅在堆棧上就需要 500 個字節。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.