【问题标题】:"no operator found" when asigning Sparse matrices results to sparse matrices将稀疏矩阵结果分配给稀疏矩阵时出现“未找到运算符”
【发布时间】:2017-04-19 23:56:35
【问题描述】:

我确实有一个实现最小化算法的函数。我没有包括所有变量,只是说明类型的矩阵:

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;
}

该过程执行以下操作:

  • 声明稀疏矩阵矩阵 (SpMat)
  • 保留矩阵内存
  • 调用外部函数填充HdzW
  • 进行矩阵乘法并将结果存储到中间矩阵中

也很稀疏。

这个函数是.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; 

据我了解,我无法将稀疏矩阵乘法的结果存储在新的稀疏矩阵中。我不知道这个问题的解决方案。

(我使用的是 Eigen 3.3.3)

【问题讨论】:

    标签: eigen3


    【解决方案1】:

    我看不出究竟是哪些行导致了您的错误,但它看起来更像是由计算 ab 引起的。你不能将一个 col-vector 乘以另一个 col-vector 而不转置它,例如

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

    但是,这实际上是一个点积,所以你应该写

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

    【讨论】:

    • 你是对的,但是编译器在此之前抛出了另一个错误。
    • @SantiPeñate-Vera 请提供 MCVE。即,提供应该编译的东西(除了你看到的错误),但删除所有不必要的东西。在您的 sn-p 中没有声明 Idnsolver
    • 我正在尝试在“干净”项目中重现问题
    【解决方案2】:

    问题是我在 .h 中编写了所有函数。 通过将函数体放在 .cpp 上一切正常。

    .h 和 .cpp 的这种二分法是 c++ 最让我讨厌的地方。

    无论如何,以供将来参考。

    【讨论】:

      猜你喜欢
      • 2018-01-19
      • 1970-01-01
      • 2023-04-10
      • 2021-11-25
      • 2017-07-02
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      • 2017-03-26
      相关资源
      最近更新 更多