2017-04-11 90 views
0

我確實有一個實現最小化算法的函數。我並沒有包括所有的瓦爾,只是矩陣來說明類型:當分配稀疏矩陣導致稀疏矩陣時出現「no operator found」

typedef Eigen::SparseMatrix<double> SpMat; 
typedef Eigen::VectorXd Vec; 

int lm_solver(void (*f_dz)(Vec* x_, int m, Vec* dz_, SpMat* W_), 
       void (*f_H)(Vec* x_, SpMat* jac_,int n_, int m_), 
       Vec* x, int nx, int mm, int nnz, 
       double tol=1e-9, int max_iter = 100){ 

    SpMat A(mm, nx); 
    SpMat H1(mm, nx); 
    SpMat H2(mm, nx); 
    SpMat H(mm, nx); 
    SpMat W(mm, mm); 
    Vec rhs(nx); 
    Vec dz(nx); 
    Vec dx(nx); 
    Vec a(1); 
    Vec b(1); 

    double f, f_prev, lbmda, rho, nu, tau; 
    bool updateH, converged; 
    int iter_; 

    // reserve matrices memory 
    H.reserve(nnz); 
    W.reserve(mm); 


    while (!converged && iter_ < max_iter){ 

     // get the system matrices 
     if (updateH){ // if the Jacobian computation is not locked... 
      f_dz(x, mm, &dz, &W); // Residual increment (z-h(x)) vector creation or update: fill dz and W 
      f_H(x, &H, nx, mm);  // Jacobian matrix creation or update: fill H 

      // Start forming the auxiliary matrices of A 
      H1 = H.transpose() * W; 
      H2 = H1 * H; 
     } 

     // set the first value of lmbda 
     if (iter_ == 1) 
      lbmda = tau * H2.diagonal().maxCoeff(); 

     // form the system matrix A = H^t·W·H + lambda·I 
     A = H2 + lbmda * Idn; 

     // form the right hand side: H^t·W·dz 
     rhs = H1 * dz; 

     // Solve the increment: dx = solve(A, rhs); 
     solver.compute(A); 
     dx = solver.solve(rhs); 

     // calculate the objective function: Least squares function 
     a = 0.5 * dz * W * dz; //vector x matrix x vector -> vector of 1 element 
     f = a.coeffRef(0); 

     // calculate the gain ratio 
     b = 0.5 * dx * (lbmda * dx - rhs); //vector x matrix x vector -> vector of 1 element 
     rho = (f_prev - f)/b.coeffRef(0); 


    } 

    return 0; 
} 

的過程執行以下操作:

  • 聲明稀疏矩陣的矩陣(​​3210)
  • 儲備矩陣存儲
  • 調用外部函數來填充H,dzW
  • 做矩陣乘法和將結果存儲到中間矩陣中

也是稀疏的。

此功能在.h文件的唯一功能。當我獨自一人編譯靜態庫被編譯成靜態庫.lib

,它完美地編譯。

然而,當我使用的庫項目從另一個項目中,我得到以下錯誤:

error: C2679: binary '=' : no operator found which takes a right-hand operand of type 'const Eigen::CwiseBinaryOp' (or there is no acceptable conversion) 
\eigen\src/Core/Matrix.h(206): could be 'Eigen::Matrix<_Scalar,_Rows,_Cols> &Eigen::Matrix<_Scalar,_Rows,_Cols>::operator =(const Eigen::Matrix<_Scalar,_Rows,_Cols> &)' 
with 
[ 
    _Scalar=double, 
    _Rows=-1, 
    _Cols=1 
] 
d:\proyectos\proyectos_i+d\ingrid\eigen\eigen_3_3_3\eigen\src/Core/Matrix.h(281): or  'Eigen::Matrix<_Scalar,_Rows,_Cols> &Eigen::Matrix<_Scalar,_Rows,_Cols>::operator =(Eigen::Matrix<_Scalar,_Rows,_Cols> &&)' 
with 
[ 
    _Scalar=double, 
    _Rows=-1, 
    _Cols=1 
] 
while trying to match the argument list '(Vec, const Eigen::CwiseBinaryOp)' 

此錯誤標誌線:

H1 = H.transpose() * W; 

H2 = H1 * H; 

rhs = H1 * dz; 

b = 0.5 * dx * (lbmda * dx - rhs); 

a = 0.5 * dz * W * dz; 

我從這個理解,我不能存儲在一個新的稀疏矩陣中稀疏矩陣乘法的結果。我不知道這個解決方案。

(我使用3.3.3本徵)

回答

0

我看不出有什麼線究竟會導致你的錯誤,但它看起來很像是通過計算ab造成的。不能將col-向量與另一個col向量相乘而不轉置,例如

b = 0.5 * dx.transpose() * (lbmda * dx - rhs); 

然而,這其實是一個點的產品,所以你應該只寫

double b = 0.5 * dx.dot(lbmda * dx - rhs); 
+0

你是對的,但編譯器在此之前拋出了另一個錯誤。 –

+0

@SantiPeñate-Vera請提供一個MCVE。即,提供應該編譯的內容(除了你看到的錯誤外),但刪除所有不必要的東西。在你的代碼片段中沒有'Idn',也沒有聲明'solver'。 – chtz

+0

我試圖在「清潔」項目上重現問題 –

0

的問題是,我寫的所有功能,在.H。 通過將該函數的主體放在.cpp中,一切正常。

這個.h和.cpp的雙字節是讓我對C++最感興趣的東西。

無論如何,供將來參考。