置的 Spectra 特征值求解器:從 ARPACK 重設(shè)計(jì)到大規(guī)模稀疏特征值計(jì)算實(shí)戰(zhàn))
計(jì)算機(jī)視覺科研【免費(fèi)下載鏈接】openMVGopen Multiple View Geometry library. Basis for 3D computer vision and Structure from Motion.項(xiàng)目地址https://gitcode.com/gh_mirrors/op/openMVG點(diǎn)擊查看免費(fèi)下載Spectra是 openMVG 倉庫內(nèi)src/third_party/spectra/目錄下捆綁的 C 大規(guī)模特征值求解庫全稱SparseEigenvalueComputationToolkit as aRedesignedARPACK。它以頭文件header-only形式隨 openMVG 分發(fā)并在 LiGT 全局優(yōu)化 等模塊中被實(shí)際用于求解特征值問題。閱讀本文后你將掌握 Spectra 的設(shè)計(jì)原理、8 類求解器的選用方法、三種典型調(diào)用范式稠密對稱 / 稀疏一般 / 自定義矩陣運(yùn)算、特征值選擇規(guī)則與 shift-and-invert 模式并理解它是如何被集成進(jìn) openMVG 的。Spectra 是什么構(gòu)建在 Eigen 之上的 C 特征值工具包根據(jù)倉庫內(nèi) Spectra 官方總覽 與 README 的說明定位面向大規(guī)模特征值問題的 C 庫構(gòu)建于開源線性代數(shù)庫 Eigen 之上形態(tài)純 header-only 實(shí)現(xiàn)唯一依賴 Eigen 同樣是 header-only 庫因此可以極其輕量地嵌入任何需要計(jì)算大型矩陣特征值的 C 項(xiàng)目適用范圍當(dāng)需要從大型方陣中求出少量特征值時(shí)Spectra 通常比計(jì)算完整的譜分解spectral decomposition高效得多。與 ARPACK 的關(guān)系重設(shè)計(jì)而非克隆ARPACK 是 FORTRAN 編寫的大規(guī)模特征值求解軟件。Spectra 的開發(fā)深受其啟發(fā)——從全稱即可看出它是 ARPACK 的 C 重設(shè)計(jì)redesignSpectra 基于 ARPACK Users Guide 描述的隱式重啟 Arnoldi/Lanczos 方法implicitly restarted Arnoldi/Lanczos method但 Spectra不使用 ARPACK 的代碼也不是 ARPACK 的 C 克隆它實(shí)現(xiàn)了 ARPACK 的主要算法卻提供了完全不同的接口并且不依賴 ARPACK文檔原文強(qiáng)調(diào) NOT a clone of ARPACK for C。這一設(shè)計(jì)帶來的直接好處是用戶不需要鏈接任何 FORTRAN 運(yùn)行時(shí)或 ARPACK 庫僅憑 Eigen 即可完成大規(guī)模特征值計(jì)算。核心設(shè)計(jì)思想只算 k 個(gè)特征值只暴露矩陣運(yùn)算Spectra 被設(shè)計(jì)為計(jì)算大型方陣 $A$ 中指定數(shù)量$k$個(gè)特征值。通常 $k$ 遠(yuǎn)小于矩陣規(guī)模$n$因此只計(jì)算少數(shù)特征值和特征向量一般比計(jì)算整個(gè)譜分解更高效。其最關(guān)鍵的抽象是用戶不需要直接提供整個(gè)矩陣算法只要求定義在 $A$ 上的某些運(yùn)算。在基本設(shè)定下這個(gè)運(yùn)算就是矩陣-向量乘法$$y Ax$$因此只要矩陣-向量積 $Ax$ 能被高效計(jì)算——例如 $A$ 是稀疏矩陣——Spectra 就能在大規(guī)模特征值問題上發(fā)揮威力。這也是它被命名為 Sparse Eigenvalue Computation Toolkit 的原因矩陣運(yùn)算被當(dāng)作黑盒稀疏性帶來的加速由用戶端的運(yùn)算實(shí)現(xiàn)自然繼承。使用 Spectra 的兩大步矩陣運(yùn)算類 求解器對象官方文檔給出了明確的兩步使用流程定義一個(gè)實(shí)現(xiàn)特定矩陣運(yùn)算的類例如矩陣-向量乘法 $yAx$或 shift-solve 運(yùn)算 $y(A-\sigma I)^{-1}x$。Spectra 提供了大量 helper 類來快速從矩陣對象構(gòu)造這類運(yùn)算例如Spectra::DenseGenMatProd、Spectra::DenseSymShiftSolve等創(chuàng)建某個(gè)特征值求解器類的對象例如面向?qū)ΨQ矩陣的Spectra::SymEigsSolver、面向一般矩陣的Spectra::GenEigsSolver然后調(diào)用其成員函數(shù)完成計(jì)算并取回特征值與特征向量。8 類求解器全景倉庫src/third_party/spectra/include/Spectra/下實(shí)際存在的求解器頭文件與官方文檔列出的求解器一一對應(yīng)求解器類適用問題說明SymEigsSolver實(shí)對稱矩陣 $Ax\lambda x$基礎(chǔ)模式見 SymEigsSolver.hGenEigsSolver一般實(shí)矩陣 $Ax\lambda x$特征值/特征向量可為復(fù)數(shù)見 GenEigsSolver.hSymEigsShiftSolver實(shí)對稱矩陣shift-and-invert 模式找最接近 $\sigma$ 的特征值見 SymEigsShiftSolver.hGenEigsRealShiftSolver一般實(shí)矩陣shift-and-invert 模式實(shí)數(shù)位移見 GenEigsRealShiftSolver.hGenEigsComplexShiftSolver一般實(shí)矩陣shift-and-invert 模式復(fù)數(shù)位移見 GenEigsComplexShiftSolver.hSymGEigsSolver廣義特征值問題 $Ax\lambda Bx$實(shí)對稱支持 Cholesky / RegularInverse 兩種模式見 SymGEigsSolver.hSymGEigsShiftSolver廣義特征值問題實(shí)對稱shift-and-invert 模式見 SymGEigsShiftSolver.hDavidsonSymEigsSolver實(shí)對稱矩陣Jacobi-Davidson 算法DPR 校正見 DavidsonSymEigsSolver.h其中SymEigsSolver與GenEigsSolver的默認(rèn)模板參數(shù)分別是DenseSymMatProddouble與DenseGenMatProddouble見 SymEigsSolver.h這也印證了文檔“兩步走”中的默認(rèn)用法。示例一稠密對稱矩陣——SymEigsSolver 入門以下示例取自官方文檔Overview.md演示對稱矩陣特征值求解#include Eigen/Core #include Spectra/SymEigsSolver.h // Spectra/MatOp/DenseSymMatProd.h is implicitly included #include iostream using namespace Spectra; int main() { // We are going to calculate the eigenvalues of M Eigen::MatrixXd A Eigen::MatrixXd::Random(10, 10); Eigen::MatrixXd M A A.transpose(); // Construct matrix operation object using the wrapper class DenseSymMatProd DenseSymMatProddouble op(M); // Construct eigen solver object, requesting the largest three eigenvalues SymEigsSolverDenseSymMatProddouble eigs(op, 3, 6); // Initialize and compute eigs.init(); int nconv eigs.compute(SortRule::LargestAlge); // Retrieve results Eigen::VectorXd evalues; if(eigs.info() CompInfo::Successful) evalues eigs.eigenvalues(); std::cout Eigenvalues found:\n evalues std::endl; return 0; }參數(shù)含義與取值約束源碼級說明從 SymEigsSolver.h 的構(gòu)造函數(shù)文檔可以確認(rèn)三個(gè)構(gòu)造參數(shù)op矩陣運(yùn)算對象實(shí)現(xiàn) $Av$ 運(yùn)算??捎肈enseSymMatProd/SparseSymMatProd等包裝類也可自定義需定義Scalar類型并實(shí)現(xiàn)與DenseSymMatProd相同的公有成員nev請求的特征值個(gè)數(shù)必須滿足 $1 \le nev \le n-1$ncv控制算法收斂速度的參數(shù)Krylov 子空間維數(shù)。通常ncv越大收斂越快但內(nèi)存占用與每輪迭代的矩陣運(yùn)算量也更大。必須滿足 $nev ncv \le n$建議取 $ncv \ge 2 \cdot nev$。以上約束在 SymEigsBase.h 的構(gòu)造函數(shù)中通過std::invalid_argument強(qiáng)制校驗(yàn)不滿足會直接拋異常。DenseSymMatProd的底層實(shí)現(xiàn)DenseSymMatProd.h利用 Eigen 的selfadjointViewUplo()只讀取對稱矩陣的下三角默認(rèn)Eigen::Lower完成 $y A x$因此即使矩陣只填了一半也能正確處理對稱結(jié)構(gòu)。示例二稀疏一般矩陣——SparseGenMatProd 與復(fù)數(shù)特征值一般實(shí)矩陣非對稱的特征值可能為復(fù)數(shù)因此eigenvalues()返回Eigen::VectorXcd。稀疏矩陣通過SparseGenMatProd、SparseSymMatProd等類支持#include Eigen/Core #include Eigen/SparseCore #include Spectra/GenEigsSolver.h #include Spectra/MatOp/SparseGenMatProd.h #include iostream using namespace Spectra; int main() { // A band matrix with 1 on the main diagonal, 2 on the below-main subdiagonal, // and 3 on the above-main subdiagonal const int n 10; Eigen::SparseMatrixdouble M(n, n); M.reserve(Eigen::VectorXi::Constant(n, 3)); for(int i 0; i n; i) { M.insert(i, i) 1.0; if(i 0) M.insert(i - 1, i) 3.0; if(i n - 1) M.insert(i 1, i) 2.0; } // Construct matrix operation object using the wrapper class SparseGenMatProd SparseGenMatProddouble op(M); // Construct eigen solver object, requesting the largest three eigenvalues GenEigsSolverSparseGenMatProddouble eigs(op, 3, 6); // Initialize and compute eigs.init(); int nconv eigs.compute(SortRule::LargestMagn); // Retrieve results Eigen::VectorXcd evalues; if(eigs.info() CompInfo::Successful) evalues eigs.eigenvalues(); std::cout Eigenvalues found:\n evalues std::endl; return 0; }GenEigsSolver 與 SymEigsSolver 的參數(shù)約束差異一般矩陣的nev/ncv約束與對稱情形不同GenEigsSolver.hnev需滿足 $1 \le nev \le n-2$ncv需滿足 $nev2 \le ncv \le n$建議取 $ncv \ge 2 \cdot nev 1$。這一差異源于一般矩陣特征值為復(fù)數(shù)時(shí)算法內(nèi)部需要保留共軛對Krylov 子空間需要更大的余量。示例三自定義矩陣運(yùn)算類——不持有矩陣也能求解Spectra 最靈活的特性是只要實(shí)現(xiàn)矩陣運(yùn)算接口甚至不需要真正構(gòu)造矩陣。下面的例子中矩陣以“對角線元素為 1..10”的隱式形式存在Overview.md#include Eigen/Core #include Spectra/SymEigsSolver.h #include iostream using namespace Spectra; // M diag(1, 2, ..., 10) class MyDiagonalTen { public: using Scalar double; // A typedef named Scalar is required int rows() const { return 10; } int cols() const { return 10; } // y_out M * x_in void perform_op(const double *x_in, double *y_out) const { for(int i 0; i rows(); i) { y_out[i] x_in[i] * (i 1); } } }; int main() { MyDiagonalTen op; SymEigsSolverMyDiagonalTen eigs(op, 3, 6); eigs.init(); eigs.compute(SortRule::LargestAlge); if(eigs.info() CompInfo::Successful) { Eigen::VectorXd evalues eigs.eigenvalues(); std::cout Eigenvalues found:\n evalues std::endl; } return 0; }該程序?qū)⒌玫?10, 9, 8)三個(gè)最大特征值注釋同樣出現(xiàn)在 SymEigsSolver.h 的類文檔中。自定義類只需滿足三個(gè)要求提供using Scalar ...;類型定義元素類型提供rows()、cols()返回矩陣維度提供perform_op(const Scalar* x_in, Scalar* y_out)實(shí)現(xiàn)核心矩陣運(yùn)算。正是這種“運(yùn)算即矩陣”的抽象使得 Spectra 可以輕松接入任何能夠高效計(jì)算 $Ax$ 的領(lǐng)域代碼——例如 openMVG 中由 LiGT_algorithm.cpp 構(gòu)造的矩陣運(yùn)算類。特征值選擇規(guī)則 SortRule9 種規(guī)則與適用邊界compute()的第一個(gè)參數(shù)selection決定要提取哪部分特征值。倉庫 SelectionRule.h 完整定義了 9 種規(guī)則SortRule 枚舉值含義適用求解器LargestMagn模絕對值/復(fù)數(shù)范數(shù)最大的特征值對稱與一般求解器LargestReal實(shí)部最大的特征值僅一般求解器LargestImag虛部按模最大的特征值僅一般求解器LargestAlge代數(shù)值最大的特征值考慮負(fù)號僅對稱求解器SmallestMagn模最小的特征值對稱與一般求解器SmallestReal實(shí)部最小的特征值僅一般求解器SmallestImag虛部按模最小的特征值僅一般求解器SmallestAlge代數(shù)值最小的特征值僅對稱求解器BothEnds譜的兩端各取一半nev為奇數(shù)時(shí)高端多取一個(gè)僅對稱求解器底層實(shí)現(xiàn)機(jī)制從源碼看排序通過 SortingTarget 的特化模板將每個(gè)特征值映射為一個(gè)“目標(biāo)值”后升序排序std::sort例如LargestMagn目標(biāo)為-abs(val)負(fù)號是因?yàn)樯蚺判蜃钚〉哪繕?biāo)值對應(yīng)最大的模LargestAlge目標(biāo)為-valBothEnds先按LargestAlge排序再通過 argsort 交錯(cuò)重排為“最大、最小、次大、次小……”的順序保證無論nev取何值前k個(gè)元素都是期望的集合。若使用不兼容的規(guī)則例如對一般矩陣使用LargestAlgeSelectionRule.h 會拋出std::invalid_argument(incompatible selection rule)異常。求解器核心 API 與計(jì)算流程對稱系求解器的全部公有接口在基類 SymEigsBase.h 中定義SymEigsSolver、SymEigsShiftSolver、SymGEigsSolver均繼承自它一般矩陣系對應(yīng) GenEigsBase.h。核心成員函數(shù)如下成員函數(shù)作用init(const Scalar* init_resid)用用戶提供的初始?xì)埐钕蛄砍跏蓟痠nit()用隨機(jī)初始?xì)埐钕蛄砍跏蓟胤莫?dú)立的 Uniform(-0.5, 0.5) 分布固定隨機(jī)種子見 SymEigsBase.hcompute(selection, maxit, tol, sorting)執(zhí)行主要計(jì)算返回收斂的特征值個(gè)數(shù)默認(rèn)參數(shù)為maxit1000、tol1e-10、sortingSortRule::LargestAlgeinfo()返回計(jì)算狀態(tài)CompInfonum_iterations()返回迭代次數(shù)num_operations()返回調(diào)用的矩陣運(yùn)算次數(shù)eigenvalues()返回已收斂的特征值向量eigenvectors(nvec)/eigenvectors()返回已收斂的特征向量矩陣按列排列compute() 的四個(gè)參數(shù)compute(SortRule selection, Index maxit, Scalar tol, SortRule sorting)SymEigsBase.h中selection選擇規(guī)則決定在全譜中選取哪些特征值如最大的 k 個(gè)maxit允許的最大迭代次數(shù)默認(rèn) 1000tol特征值的精度參數(shù)默認(rèn) 1e-10收斂判定閾值為tol * max(eps^(2/3), |θ|)其中 θ 為 Ritz 值見 SymEigsBase.hsorting對最終結(jié)果的排序規(guī)則僅支持LargestAlge/LargestMagn/SmallestAlge/SmallestMagn四種SymEigsBase.h。計(jì)算狀態(tài) CompInfoCompInfo.h 定義了四種狀態(tài)枚舉值含義Successful計(jì)算成功NotComputed尚未調(diào)用compute()NotConverging部分特征值未收斂compute()會返回已收斂個(gè)數(shù)NumericalIssue數(shù)值問題如 Cholesky 分解遇到非正定矩陣典型判讀模式compute()返回值等于請求的nev時(shí)全部收斂info()為Successful時(shí)方可安全讀取結(jié)果。注意eigenvalues()只返回已收斂的特征值未收斂部分不會混入結(jié)果。底層算法骨架隱式重啟 Lanczos對稱系求解器內(nèi)部執(zhí)行“m 步 Lanczos 分解 → 計(jì)算 Ritz 對 → 重啟”的循環(huán)SymEigsBase.hfactorize_from(1, ncv, nmatop)建立 Lanczos 分解retrieve_ritzpair(selection)計(jì)算并按選擇規(guī)則排序 Ritz 值/向量檢查收斂數(shù)nconv若未達(dá)到nev則restart(nev_adj, selection)重啟隱式重啟核心見 SymEigsBase.h對H - μI做 QR 分解、壓縮 H 與 V、再擴(kuò)展分解達(dá)到收斂或maxit上限后按sorting規(guī)則排序并返回。配套的線性代數(shù)基礎(chǔ)設(shè)施位于 LinAlg/Lanczos、TridiagEigen、UpperHessenbergQR 等矩陣運(yùn)算抽象位于 MatOp/。Shift-and-invert 模式尋找靠近 σ 的特征值當(dāng)需要找最接近某個(gè)數(shù) $\sigma$ 的特征值時(shí)——例如求正定矩陣的最小特征值此時(shí) $\sigma0$——官方文檔明確建議使用 shift-and-invert 模式。數(shù)學(xué)原理如果 $(\lambda, x)$ 是 $A$ 的特征對即 $Ax \lambda x$則對任意 $\sigma$ 有$$(A-\sigma I)^{-1}x \nu x, \quad \nu \frac{1}{\lambda - \sigma}$$也就是說 $(\nu, x)$ 是 $(A-\sigma I)^{-1}$ 的特征對。把矩陣運(yùn)算 $Ay$ 替換為 $(A-\sigma I)^{-1}y$ 傳給求解器就能得到 $\nu$再通過 $\lambda \sigma \nu^{-1}$ 還原原問題特征值。為什么需要它Spectra以及 ARPACK的算法擅長找大模特征值但在尋找接近零的特征值時(shí)可能失效。設(shè) $\sigma0$此時(shí)找 $A^{-1}$ 的最大特征值 $\nu$對應(yīng) $A$ 的最小特征值 $\lambda$因?yàn)?$\nu$ 最大意味著 $\lambda$ 最小。模式要點(diǎn)源碼確認(rèn)在 shift-and-invert 模式下選擇規(guī)則作用于 $\nu 1/(\lambda-\sigma)$ 而非 $\lambda$。因此LargestMagn 位移 $\sigma$ 找到的是 $A$ 中最接近 $\sigma$的特征值但eigenvalues()始終返回原問題的特征值 $\lambda$而非 $\nu$特征向量在兩種問題下相同還原邏輯在 SymEigsShiftSolver.h 的sort_ritzpair()重寫中實(shí)現(xiàn)m_ritz_val 1 / m_ritz_val m_sigma。實(shí)際使用SymEigsShiftSolver#include Eigen/Core #include Spectra/SymEigsShiftSolver.h // Spectra/MatOp/DenseSymShiftSolve.h is implicitly included #include iostream using namespace Spectra; int main() { // A size-10 diagonal matrix with elements 1, 2, ..., 10 Eigen::MatrixXd M Eigen::MatrixXd::Zero(10, 10); for (int i 0; i M.rows(); i) M(i, i) i 1; // Construct matrix operation object using the wrapper class DenseSymShiftSolvedouble op(M); // Construct eigen solver object with shift 0 // This will find eigenvalues that are closest to 0 SymEigsShiftSolverDenseSymShiftSolvedouble eigs(op, 3, 6, 0.0); eigs.init(); eigs.compute(SortRule::LargestMagn); if (eigs.info() CompInfo::Successful) { Eigen::VectorXd evalues eigs.eigenvalues(); // Will get (3.0, 2.0, 1.0) std::cout Eigenvalues found:\n evalues std::endl; } return 0; }SymEigsShiftSolver的構(gòu)造參數(shù)在 SymEigsShiftSolver.h 中為(op, nev, ncv, sigma)構(gòu)造函數(shù)內(nèi)部會調(diào)用op.set_shift(m_sigma)把位移寫入運(yùn)算對象。Shift-solve 運(yùn)算類的底層實(shí)現(xiàn)DenseSymShiftSolveDenseSymShiftSolve.h通過set_shift(sigma)對 $A - \sigma I$ 做BKLDLT 分解帶改進(jìn)的 LDLT見 LinAlg/BKLDLT.hperform_op則調(diào)用m_solver.solve(x)完成 $(A-\sigma I)^{-1}x$。若分解失敗例如位移使矩陣奇異set_shift會拋出std::invalid_argument異常DenseSymShiftSolve.h。自定義 shift-solve 運(yùn)算類與自定義perform_op類似shift-solve 運(yùn)算類還需額外實(shí)現(xiàn)set_shift(Scalar sigma)方法。官方文檔給出了MyDiagonalTenShiftSolve示例Overview.md// M diag(1, 2, ..., 10) class MyDiagonalTenShiftSolve { private: double sigma_; public: using Scalar double; // A typedef named Scalar is required int rows() const { return 10; } int cols() const { return 10; } void set_shift(double sigma) { sigma_ sigma; } // y_out inv(A - sigma * I) * x_in // inv(A - sigma * I) diag(1/(1-sigma), 1/(2-sigma), ...) void perform_op(double *x_in, double *y_out) const { for (int i 0; i rows(); i) { y_out[i] x_in[i] / (i 1 - sigma_); } } }; // 使用找最接近 3.14 的三個(gè)特征值得到 4.0, 3.0, 2.0 SymEigsShiftSolverMyDiagonalTenShiftSolve eigs(op, 3, 6, 3.14);廣義特征值問題SymGEigsSolver 的兩種模式SymGEigsSolver解決 $Ax \lambda Bx$$A$ 對稱、$B$ 正定對稱的廣義特征值問題。由 SymGEigsSolver.h 的文檔可知它由模板參數(shù)Mode決定兩種工作模式枚舉定義見 GEigsMode.hCholesky 模式GEigsMode::Cholesky假設(shè) $B$ 可用 Cholesky 分解是優(yōu)先推薦模式第二個(gè)運(yùn)算對象用DenseCholesky/SparseCholesky創(chuàng)建RegularInverse 模式GEigsMode::RegularInverse要求 $Bv$ 與 $B^{-1}v$ 兩種運(yùn)算僅在 Cholesky 分解難以實(shí)現(xiàn)、或 $B^{-1}v$ 計(jì)算遠(yuǎn)快于 Cholesky 分解時(shí)使用第二個(gè)運(yùn)算對象用SparseRegularInverse創(chuàng)建。GEigsMode枚舉還包含ShiftInvert、Buckling、Cayley三種模式GEigsMode.h供對應(yīng)的廣義 shift-and-invert 系列求解器如SymGEigsShiftSolver使用。openMVG 中的實(shí)際集成LiGT 的全局優(yōu)化Spectra 并非孤立捆綁的第三方庫——它已被 openMVG 的核心算法實(shí)際調(diào)用。在 LiGT 全局優(yōu)化實(shí)現(xiàn) 中第 23 行包含third_party/spectra/include/Spectra/SymEigsShiftSolver.h第 27 行using namespace Spectra;第 262 行注釋// Solve Problem by Spectras Eigs 標(biāo)記了特征值求解入口。這證明了 openMVG 在 LiGT一種用于相機(jī)全局位姿優(yōu)化的方法中正是利用 Spectra 的SymEigsShiftSolver完成大規(guī)模特征值求解是以矩陣運(yùn)算抽象替代整矩陣存儲設(shè)計(jì)思想的典型生產(chǎn)級應(yīng)用。若你需要在 openMVG 其他模塊中做特征值分解可直接復(fù)用這一集成路徑包含src/third_party/spectra/include/Spectra/下對應(yīng)頭文件即可無需額外安裝外部依賴。在 openMVG 中的構(gòu)建與安裝方式Spectra 位于src/third_party/spectra/其自身的 CMakeLists.txt 記錄了版本與集成細(xì)節(jié)項(xiàng)目版本1.0.1project (Spectra VERSION 1.0.1 LANGUAGES CXX)作為INTERFACE 庫導(dǎo)出純頭文件無編譯產(chǎn)物target_link_libraries(Spectra INTERFACE Eigen3::Eigen)可選構(gòu)建開關(guān)BUILD_TESTS測試見 test/ 下的 SymEigs.cpp、GenEigs.cpp、SymEigsShift.cpp、SparseSymMatProd.cpp 等與BUILD_EXAMPLES示例見 examples/ 的 DavidsonSymEigs_example.cpp安裝后通過find_package生成Spectra::SpectraCMake target 供其他項(xiàng)目鏈接需要 Eigen 3.x 且 C11 及以上set(CMAKE_CXX_STANDARD 11)。由于是 header-only在 openMVG 內(nèi)最直接的用法就是直接包含頭文件路徑#include Spectra/SymEigsSolver.h并保證 Eigen 頭文件在 include 路徑中openMVG 已內(nèi)置 Eigen開箱即用。許可證Spectra采用MPL2Mozilla Public License 2.0開源協(xié)議與 Eigen 相同。許可證文件見 LICENSE版本變更歷史見 CHANGELOG.md1.0.0 起存在 API 破壞性變更遷移說明見 MIGRATION.md??偨Y(jié)Spectra 以隱式重啟 Arnoldi/Lanczos 方法為核心算法用 header-only 的輕量形態(tài)和矩陣運(yùn)算對象 求解器對象的兩段式接口把大規(guī)模特征值計(jì)算的門檻降到了僅依賴 Eigen 的程度。在 openMVG 中它不僅是捆綁依賴更是 LiGT 全局優(yōu)化等模塊的運(yùn)行時(shí)引擎。掌握本文的 8 類求解器選型、9 種SortRule選擇規(guī)則、nev/ncv參數(shù)約束與 shift-and-invert 變換即可在 openMVG 及你自己的 C 項(xiàng)目中高效復(fù)用這套能力。贊分享計(jì)算機(jī)視覺科研【免費(fèi)下載鏈接】openMVGopen Multiple View Geometry library. Basis for 3D computer vision and Structure from Motion.項(xiàng)目地址https://gitcode.com/gh_mirrors/op/openMVG點(diǎn)擊查看免費(fèi)下載相關(guān)推薦OneUptime Host Monitor 完全指南用 OpenTelemetry 主機(jī)指標(biāo)構(gòu)建服務(wù)器監(jiān)控與告警OneUptime Host Monitor 完全指南用 OpenTelemetry 主機(jī)指標(biāo)構(gòu)建服務(wù)器監(jiān)控與告警 本篇技術(shù)指南圍繞 OneUptime 的計(jì)算機(jī)視覺科研SciPy 稀疏特征值問題教程用 ARPACK 的 eigs/eigsh 高效求解大規(guī)模特征值SciPy 稀疏特征值問題教程用 ARPACK 的 eigs/eigsh 高效求解大規(guī)模特征值 導(dǎo)讀 本文深入講解 SciPy 中基于 ARPACK 的大規(guī)??茖W(xué)計(jì)算數(shù)據(jù)科學(xué)高性能計(jì)算【親測免費(fèi)】 探索Spectra大規(guī)模稀疏矩陣的高效特征值計(jì)算庫探索Spectra大規(guī)模稀疏矩陣的高效特征值計(jì)算庫 如果你在尋找一個(gè)可以處理大型稀疏矩陣并計(jì)算其特征值的C庫那么Spectra絕對值得你關(guān)注。這個(gè)基于E上一篇5大核心功能3種使用場景開源IPTV播放器IPTVnator完整指南下一篇如何給 KernelSU 裝上 meta-overlayfs 元模塊讓模塊真的改得動(dòng) /system創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考