簡體   English   中英

特征稀疏 LU 求解器

[英]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&lt;_Tp&gt;::construct(_Up*, _Args&amp;&amp; ...) [with _Up = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;; _Args = {const Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double, 0, int&gt;, Eigen::COLAMDOrdering&lt;int&gt; &gt;&amp;}; _Tp = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;]</b>’:
<b>/usr/include/c++/7/bits/alloc_traits.h:475:4:</b>   required from ‘<b>static void std::allocator_traits&lt;std::allocator&lt;_CharT&gt; &gt;::construct(std::allocator_traits&lt;std::allocator&lt;_CharT&gt; &gt;::allocator_type&amp;, _Up*, _Args&amp;&amp; ...) [with _Up = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;; _Args = {const Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double, 0, int&gt;, Eigen::COLAMDOrdering&lt;int&gt; &gt;&amp;}; _Tp = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;; std::allocator_traits&lt;std::allocator&lt;_CharT&gt; &gt;::allocator_type = std::allocator&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt; &gt;]</b>’
<b>/usr/include/c++/7/bits/stl_vector.h:943:30:</b>   required from ‘<b>void std::vector&lt;_Tp, _Alloc&gt;::push_back(const value_type&amp;) [with _Tp = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;; _Alloc = std::allocator&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt; &gt;; std::vector&lt;_Tp, _Alloc&gt;::value_type = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;]</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&lt;_MatrixType, _OrderingType&gt;::SparseLU(const Eigen::SparseLU&lt;_MatrixType, _OrderingType&gt;&amp;) [with _MatrixType = Eigen::SparseMatrix&lt;double&gt;; _O<b>rderingType = Eigen::COLAMDOrdering&lt;int&gt;]</b>’ is private within this context
  { <font color="#EF2929"><b>::new((void *)__p) _Up(std::forward&lt;_Args&gt;(__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&amp; );
     <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&amp;&amp; ...) [with _T1 = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;; _Args = {Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double, 0, int&gt;, Eigen::COLAMDOrdering&lt;int&gt; &gt;}]</b>’:
<b>/usr/include/c++/7/bits/stl_uninitialized.h:83:18:</b>   required from ‘<b>static _ForwardIterator std::__uninitialized_copy&lt;_TrivialValueTypes&gt;::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*&gt;; _ForwardIterator = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*; 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&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*&gt;; _ForwardIterator = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*]</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&lt;_Tp&gt;&amp;) [with _InputIterator = std::move_iterator&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*&gt;; _ForwardIterator = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*; _Tp = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;]</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&amp;) [with _InputIterator = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*; _ForwardIterator = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*; _Allocator = std::allocator&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt; &gt;]</b>’
<b>/usr/include/c++/7/bits/vector.tcc:426:6:</b>   required from ‘<b>void std::vector&lt;_Tp, _Alloc&gt;::_M_realloc_insert(std::vector&lt;_Tp, _Alloc&gt;::iterator, _Args&amp;&amp; ...) [with _Args = {const Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double, 0, int&gt;, Eigen::COLAMDOrdering&lt;int&gt; &gt;&amp;}; _Tp = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;; _Alloc = std::allocator&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt; &gt;; std::vector&lt;_Tp, _Alloc&gt;::iterator = __gnu_cxx::__normal_iterator&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*, std::vector&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt; &gt; &gt;; typename std::_Vector_base&lt;_Tp, _Alloc&gt;::pointer = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;*]</b>’
<b>/usr/include/c++/7/bits/stl_vector.h:948:21:</b>   required from ‘<b>void std::vector&lt;_Tp, _Alloc&gt;::push_back(const value_type&amp;) [with _Tp = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;; _Alloc = std::allocator&lt;Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt; &gt;; std::vector&lt;_Tp, _Alloc&gt;::value_type = Eigen::SparseLU&lt;Eigen::SparseMatrix&lt;double&gt; &gt;]</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&lt;_MatrixType, _OrderingType&gt;::SparseLU(const Eigen::SparseLU&lt;_MatrixType, _OrderingType&gt;&amp;) [with _MatrixType = Eigen::SparseMatrix&lt;double&gt;; _O<b>rderingType = Eigen::COLAMDOrdering&lt;int&gt;]</b>’ is private within this context
     { <font color="#EF2929"><b>::new(static_cast&lt;void*&gt;(__p)) _T1(std::forward&lt;_Args&gt;(__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&amp; );
     <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::dequeemplace_back方法一起使用。 請注意, std::vector不可能做到這一點,因為這里的vector::emplace_back可能會移動現有元素。 deque::emplace_back不需要這樣做。

我不知道,您正在實施什么算法,但我遇到了類似的問題,並認為我需要存儲求解器。 在我的情況下,可以一個接一個地使用求解器(並且永遠不會再次用於同一個矩陣),所以我可以使用一個求解器而不是向量。 如果可能的話,這可能是一種更好的方法,因為它占用的內存較少,因為每個求解器僅在堆棧上就需要 500 個字節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM