简体   繁体   English

使用Octave库的C ++中的(maxmin)稀疏矩阵乘法

[英]Sparse Matrix multiplication like (maxmin) in C++ using Octave libraries

I'm implementing a maxmin function, it works like matrix multiplication but instead of summing products it gets max of min between two numbers pointwise. 我正在实现一个maxmin函数,它的作用类似于矩阵乘法,但是不是求和乘积,而是逐点获取两个数字之间的min的最大值。 An example of naive implementation is 天真的实现的一个例子是

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

I'm coding it as an Octave oct-file so i have to use oct.h data structure. 我将其编码为八度八进制文件,因此我必须使用oct.h数据结构。 The problem is that i want to implement a sparse version, but usually you need a reference to the next non zero element in a row or in a column like in this example (see 4.3 algorithm): http://www.eecs.harvard.edu/~ellard/Q-97/HTML/root/node20.html 问题是我想实现一个稀疏版本,但是通常您需要像在此示例中一样,对行或列中的下一个非零元素进行引用(请参见4.3算法): http://www.eecs.harvard .edu /〜ellard / Q-97 / HTML / root / node20.html

There doing row_p->next gave the next nonzero element of the row (the same for the column). 执行row_p-> next给出了行的下一个非零元素(与列相同)。 Is there a way to do the same with the octave SparseMatrix class? 有没有办法对八度SparseMatrix类做同样的事情? Or is there another way of implementing the sparse matrix multiplication i can adopt for my maxmin function? 还是有其他方法可以实现我的maxmin函数可以采用的稀疏矩阵乘法?

I don't know if anyoe would ever be interested, but i managed to find a solution. 我不知道是否有兴趣,但是我设法找到了解决方案。 The code of the solution is part of fl-core1.0 a fuzzy logic core package for Octave and it is released under LGPL license. 该解决方案的代码是fl-core1.0的一部分,后者是Octave的模糊逻辑核心软件包,已根据LGPL许可发布。 (The code relies on some octave functions) (代码依赖于某些八度音阶函数)

// 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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM