【问题标题】:Sparse Matrix multiplication like (maxmin) in C++ using Octave libraries使用 Octave 库的 C++ 中的稀疏矩阵乘法,如 (maxmin)
【发布时间】:2011-05-27 21:59:33
【问题描述】:

我正在实现一个 maxmin 函数,它的工作原理类似于矩阵乘法,但它不是对乘积求和,而是在两个数字之间逐点获得最小值的最大值。一个简单实现的例子是

double mx = 0;
double mn = 0;
for (i = 0; i < rowsC;i++)
{
    for(j = 0; j < colsC;j++)
    {
        mx = 0;
        for(k = 0; k < colsA; k++)
        { 
            if (a(i, k) < b(k, j))
                mn = a(i,k);
            else
                mn = b(k,j);

            if (mn > mx)
                mx = mn;
        } 
        c(i, j) = mx;
    }
}

我将它编码为 Octave 八进制文件,所以我必须使用 oct.h 数据结构。问题是我想实现一个稀疏版本,但通常你需要在一行或一列中引用下一个非零元素,如本例所示(参见 4.3 算法): http://www.eecs.harvard.edu/~ellard/Q-97/HTML/root/node20.html

row_p->next 给出了行的下一个非零元素(列相同)。有没有办法对 octave SparseMatrix 类做同样的事情?或者是否有另一种实现稀疏矩阵乘法的方法可以用于我的 maxmin 函数?

【问题讨论】:

    标签: c++ octave sparse-matrix matrix-multiplication min


    【解决方案1】:

    我不知道是否有人会感兴趣,但我设法找到了解决方案。 该解决方案的代码是 fl-core1.0 的一部分,它是 Octave 的模糊逻辑核心包,它是在 LGPL 许可下发布的。 (代码依赖一些八度函数)

    // Calculate the S-Norm/T-Norm composition of sparse matrices (single thread)
    void sparse_compose(octave_value_list args)
    {
        // Create constant versions of the input matrices to prevent them to be filled by zeros on reading.
        // a is the const reference to the transpose of a because octave sparse matrices are column compressed
        // (to cycle on the rows, we cycle on the columns of the transpose).
        SparseMatrix atmp = args(0).sparse_matrix_value();
        const SparseMatrix a = atmp.transpose();
        const SparseMatrix b = args(1).sparse_matrix_value();
    
        // Declare variables for the T-Norm and S-Norm values 
        float snorm_val;    
        float tnorm_val;    
    
        // Initialize the result sparse matrix
        sparseC = SparseMatrix((int)colsB, (int)rowsA, (int)(colsB*rowsA));
    
        // Initialize the number of nonzero elements in the sparse matrix c
        int nel = 0;
        sparseC.xcidx(0) = 0;
    
        // Calculate the composition for each element
        for (int i = 0; i < rowsC; i++)
        {
            for(int j = 0; j < colsC; j++)
            {
    
                // Get the index of the first element of the i-th column of a transpose (i-th row of a)
                // and the index of the first element of the j-th column of b
                int ka = a.cidx(i);
                int kb = b.cidx(j);
                snorm_val = 0;
    
                // Check if the values of the matrix are really not 0 (it happens if the column of a or b hasn't any value)
                // because otherwise the cidx(i) or cidx(j) returns the first nonzero element of the previous column
                if(a(a.ridx(ka),i)!=0 && b(b.ridx(kb),j)!=0)
                {
                    // Cicle on the i-th column of a transpose (i-th row of a) and j-th column of b
                    // From a.cidx(i) to a.cidx(i+1)-1 there are all the nonzero elements of the column i of a transpose (i-th row of a)
                    // From b.cidx(j) to b.cidx(j+1)-1 there are all the nonzero elements of the column j of b
                    while ((ka <= (a.cidx(i+1)-1)) && (kb <= (b.cidx(j+1)-1)))
                    {
    
                        // If a.ridx(ka) == b.ridx(kb) is true, then there's a nonzero value on the same row
                        // so there's a k for that a'(k, i) (equals to a(i, k)) and b(k, j) are both nonzero
                        if (a.ridx(ka) == b.ridx(kb))
                        {
                            tnorm_val = calc_tnorm(a.data(ka), b.data(kb)); 
                            snorm_val = calc_snorm(snorm_val, tnorm_val);
                            ka++;
                            kb++;
                        }
    
                        // If a.ridx(ka) == b.ridx(kb) ka should become the index of the next nonzero element on the i column of a 
                        // transpose (i row of a)
                        else if (a.ridx(ka) < b.ridx(kb))           
                            ka++;
                        // If a.ridx(ka) > b.ridx(kb) kb should become the index of the next nonzero element on the j column of b
                        else
                            kb++;
                    }
                }
    
                if (snorm_val != 0)
                {
                    // Equivalent to sparseC(i, j) = snorm_val;
                    sparseC.xridx(nel) = j;
                    sparseC.xdata(nel++) = snorm_val;
                }
            }
            sparseC.xcidx(i+1) = nel;
        }
    
        // Compress the result sparse matrix because it is initialized with a number of nonzero element probably greater than the real one
        sparseC.maybe_compress();
    
        // Transpose the result
        sparseC = sparseC.transpose();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 2011-11-20
      • 1970-01-01
      • 2015-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多