首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何乘稀疏矩阵和稠密向量?

如何乘稀疏矩阵和稠密向量?
EN

Stack Overflow用户
提问于 2021-11-03 21:17:37
回答 2查看 201关注 0票数 2

我正在尝试以下几点:

代码语言:javascript
复制
Eigen::SparseMatrix<double> bijection(2 * face_count, 2 * vert_count);
/* initialization */
Eigen::VectorXd toggles(2 * vert_count);
toggles.setOnes();
Eigen::SparseMatrix<double> deformed;
deformed = bijection * toggles;

艾根正在返回一个错误,声称:

代码语言:javascript
复制
 error: static assertion failed: THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS
  586 |       EIGEN_STATIC_ASSERT((internal::is_same<Dest,void>::value),THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS);

根据艾根文献

允许稀疏矩阵和向量积。我做错了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-03 22:21:31

问题是产品的输出类型错误。

特征文档指出,定义了以下类型的乘法:

dv2 = sm1 * dv1;

稀疏矩阵乘以稠密向量等于密集向量。

如果您确实需要稀疏表示,我认为没有比执行上面的乘法,然后将乘积转换为具有sparseView成员函数的稀疏矩阵更好的方法了。例如:

代码语言:javascript
复制
Eigen::SparseMatrix<double> bijection(2 * face_count, 2 * vert_count);
/* initialization */
Eigen::VectorXd toggles(2 * vert_count);
toggles.setOnes();
Eigen::VectorXd deformedDense = bijection * toggles;
Eigen::SparseMatrix<double> deformedSparse = deformedDense.sparseView();
票数 5
EN

Stack Overflow用户

发布于 2021-11-24 01:59:05

如果向量非常稀疏,这可能比输出到密集向量更快。否则,99/100倍的传统产品是更快。

代码语言:javascript
复制
void sparsem_densev_sparsev(const SparseMatrix<double>& A, const VectorX<double>& x, SparseVector<double>& Ax)
{
    Ax.resize(x.size());

    for (int j = 0; j < A.outerSize(); ++j)
    {
        if (A.outerIndexPtr()[j + 1] - A.outerIndexPtr()[j] > 0)
        {
            Ax.insertBack(j) = 0;
        }
    }

    for (int j_idx = 0; j_idx < Ax.nonZeros(); j_idx++)
    {
        int j = Ax.innerIndexPtr()[j_idx];

        for (int k = A.outerIndexPtr()[j]; k < A.outerIndexPtr()[j + 1]; ++k)
        {
            int i = A.innerIndexPtr()[k];
            Ax.valuePtr()[j_idx] += A.valuePtr()[k] * x.coeff(i);
        }
    }
}

对于(可能不是最优的)自伴版本(下三角),将j_idx循环更改为:

代码语言:javascript
复制
for (int j_idx = 0; j_idx < Ax.nonZeros(); j_idx++)
    {
        int j = Ax.innerIndexPtr()[j_idx];
        int i_idx = j_idx;//i>= j, trick to improve binary search

        for (int k = A.outerIndexPtr()[j]; k < A.outerIndexPtr()[j + 1]; ++k)
        {
            int i = A.innerIndexPtr()[k];
            Ax.valuePtr()[j_idx] += A.valuePtr()[k] * x.coeff(i);
            if (i != j)
            {
                i_idx = std::distance(Ax.innerIndexPtr(), std::lower_bound(Ax.innerIndexPtr() + i_idx, Ax.innerIndexPtr() + Ax.nonZeros(), i));
                Ax.valuePtr()[i_idx] += A.valuePtr()[k] * x.coeff(j);
            }
        }
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69831837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档