Operations on Sparse Matrices

Given two sparse matrices (Sparse Matrix and its representations | Set 1 (Using Arrays and Linked Lists)), perform operations such as add, multiply or transpose of the matrices in their sparse form itself. The result should consist of three sparse matrices, one obtained by adding the two input matrices, one by multiplying the two matrices and one obtained by transpose of the first matrix.

Example: Note that other entries of matrices will be zero as matrices are sparse.

Input : 

Matrix 1: (4x4)
Row Column Value
1   2       10
1   4       12
3   3       5
4   1       15
4   2       12

Matrix 2: (4X4)
Row Column Value
1   3       8
2   4       23
3   3       9
4   1       20
4   2       25

Output :

Result of Addition: (4x4)
Row Column Value
1   2      10
1   3      8
1   4      12
2   4      23
3   3      14
4   1      35
4   2      37

Result of Multiplication: (4x4)
Row Column Value
1   1      240
1   2      300
1   4      230
3   3      45
4   3      120
4   4      276

Result of transpose on the first matrix: (4x4)
Row Column Value
1   4      15
2   1      10
2   4      12
3   3      5
4   1      12



The sparse matrix used anywhere in the program is sorted according to its row values. Two elements with the same row values are further sorted according to their column values.

Now to Add the matrices, we simply traverse through both matrices element by element and insert the smaller element (one with smaller row and col value) into the resultant matrix. If we come across an element with the same row and column value, we simply add their values and insert the added data into the resultant matrix.

To Transpose a matrix, we can simply change every column value to the row value and vice-versa, however, in this case, the resultant matrix won’t be sorted as we require. Hence, we initially determine the number of elements less than the current element’s column being inserted in order to get the exact index of the resultant matrix where the current element should be placed. This is done by maintaining an array index[] whose ith value indicates the number of elements in the matrix less than the column i.

To Multiply the matrices, we first calculate transpose of the second matrix to simplify our comparisons and maintain the sorted order. So, the resultant matrix is obtained by traversing through the entire length of both matrices and summing the appropriate multiplied values.
Any row value equal to x in the first matrix and row value equal to y in the second matrix (transposed one) will contribute towards result[x][y]. This is obtained by multiplying all such elements having col value in both matrices and adding only those with the row as x in first matrix and row as y in the second transposed matrix to get the result[x][y].

For example: Consider 2 matrices:

Row Col Val      Row Col Val
1   2   10       1   1   2
1   3   12       1   2   5
2   1   1        2   2   1
2   3   2        3   1   8

The resulting matrix after multiplication will be obtained as follows:

Transpose of second matrix:

Row Col Val      Row Col Val
1   2   10       1   1   2
1   3   12       1   3   8
2   1   1        2   1   5
2   3   2        2   2   1

Summation of multiplied values:

result[1][1] = A[1][3]*B[1][3] = 12*8 = 96
result[1][2] = A[1][2]*B[2][2] = 10*1 = 10
result[2][1] = A[2][1]*B[1][1] + A[2][3]*B[1][3] = 2*1 + 2*8 = 18
result[2][2] = A[2][1]*B[2][1] = 1*5 = 5

Any other element cannot be obtained 
by any combination of row in 
Matrix A and Row in Matrix B.

Hence the final resultant matrix will be:
 
Row Col Val 
1   1   96 
1   2   10 
2   1   18  
2   2   5  

Following is the implementation of above approach:

Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java code to perform add,
// multiply and transpose on sparse matrices
  
public class sparse_matrix {
  
    // Maximum number of elements in matrix
    int MAX = 100;
  
    // Array representation
    // of sparse matrix
    //[][0] represents row
    //[][1] represents col
    //[][2] represents value
    int data[][] = new int[MAX][3];
  
    // dimensions of matrix
    int row, col;
  
    // total number of elements in matrix
    int len;
  
    public sparse_matrix(int r, int c)
    {
  
        // initialize row
        row = r;
  
        // initialize col
        col = c;
  
        // intialize length to 0
        len = 0;
    }
  
    // insert elements into sparse matrix
    public void insert(int r, int c, int val)
    {
  
        // invalid entry
        if (r > row || c > col) {
            System.out.println("Wrong entry");
        }
  
        else {
  
            // insert row value
            data[len][0] = r;
  
            // insert col value
            data[len][1] = c;
  
            // insert element's value
            data[len][2] = val;
  
            // increment number of data in matrix
            len++;
        }
    }
  
    public void add(sparse_matrix b)
    {
  
        // if matrices don't have same dimensions
        if (row != b.row || col != b.col) {
            System.out.println("Matrices can't be added");
        }
  
        else {
  
            int apos = 0, bpos = 0;
            sparse_matrix result = new sparse_matrix(row, col);
  
            while (apos < len && bpos < b.len) {
  
                // if b's row and col is smaller
                if (data[apos][0] > b.data[bpos][0] || 
                  (data[apos][0] == b.data[bpos][0] && 
                   data[apos][1] > b.data[bpos][1]))
  
                {
  
                    // insert smaller value into result
                    result.insert(b.data[bpos][0],
                                  b.data[bpos][1],
                                  b.data[bpos][2]);
  
                    bpos++;
                }
  
                // if a's row and col is smaller
                else if (data[apos][0] < b.data[bpos][0] || 
                (data[apos][0] == b.data[bpos][0] && 
                  data[apos][1] < b.data[bpos][1]))
  
                {
  
                    // insert smaller value into result
                    result.insert(data[apos][0],
                                  data[apos][1],
                                  data[apos][2]);
  
                    apos++;
                }
  
                else {
  
                    // add the values as row and col is same
                    int addedval = data[apos][2] + b.data[bpos][2];
  
                    if (addedval != 0)
                        result.insert(data[apos][0],
                                      data[apos][1],
                                      addedval);
                    // then insert
                    apos++;
                    bpos++;
                }
            }
  
            // insert remaining elements
            while (apos < len)
                result.insert(data[apos][0],
                              data[apos][1],
                              data[apos++][2]);
  
            while (bpos < b.len)
                result.insert(b.data[bpos][0],
                              b.data[bpos][1],
                              b.data[bpos++][2]);
  
            // print result
            result.print();
        }
    }
  
    public sparse_matrix transpose()
    {
  
        // new matrix with inversed row X col
        sparse_matrix result = new sparse_matrix(col, row);
  
        // same number of elements
        result.len = len;
  
        // to count number of elements in each column
        int count[] = new int[col + 1];
  
        // initialize all to 0
        for (int i = 1; i <= col; i++)
            count[i] = 0;
  
        for (int i = 0; i < len; i++)
            count[data[i][1]]++;
  
        int[] index = new int[col + 1];
  
        // to count number of elements having col smaller
        // than particular i
  
        // as there is no col with value < 1
        index[1] = 0;
  
        // initialize rest of the indices
        for (int i = 2; i <= col; i++)
  
            index[i] = index[i - 1] + count[i - 1];
  
        for (int i = 0; i < len; i++) {
  
            // insert a data at rpos and increment its value
            int rpos = index[data[i][1]]++;
  
            // transpose row=col
            result.data[rpos][0] = data[i][1];
  
            // transpose col=row
            result.data[rpos][1] = data[i][0];
  
            // same value
            result.data[rpos][2] = data[i][2];
        }
  
        // the above method ensures
        // sorting of transpose matrix
        // according to row-col value
        return result;
    }
  
    public void multiply(sparse_matrix b)
    {
  
        if (col != b.row) {
  
            // Invalid multiplication
            System.out.println("Can't multiply, "
                               + "Invalid dimensions");
  
            return;
        }
  
        // transpose b to compare row
        // and col values and to add them at the end
        b = b.transpose();
        int apos, bpos;
  
        // result matrix of dimension row X b.col
        // however b has been transposed, hence row X b.row
        sparse_matrix result = new sparse_matrix(row, b.row);
  
        // iterate over all elements of A
        for (apos = 0; apos < len;) {
  
            // current row of result matrix
            int r = data[apos][0];
  
            // iterate over all elements of B
            for (bpos = 0; bpos < b.len;) {
  
                // current column of result matrix
                // data[][0] used as b is transposed
                int c = b.data[bpos][0];
  
                // temporary pointers created to add all
                // multiplied values to obtain current
                // element of result matrix
                int tempa = apos;
                int tempb = bpos;
  
                int sum = 0;
  
                // iterate over all elements with
                // same row and col value
                // to calculate result[r]
                while (tempa < len && data[tempa][0] == r
                       && tempb < b.len && b.data[tempb][0] == c) {
  
                    if (data[tempa][1] < b.data[tempb][1])
  
                        // skip a
                        tempa++;
  
                    else if (data[tempa][1] > b.data[tempb][1])
  
                        // skip b
                        tempb++;
                    else
  
                        // same col, so multiply and increment
                        sum += data[tempa++][2] * b.data[tempb++][2];
                }
  
                // insert sum obtained in result[r]
                // if its not equal to 0
                if (sum != 0)
                    result.insert(r, c, sum);
  
                while (bpos < b.len && b.data[bpos][0] == c)
  
                    // jump to next column
                    bpos++;
            }
  
            while (apos < len && data[apos][0] == r)
  
                // jump to next row
                apos++;
        }
  
        result.print();
    }
  
    // printing matrix
    public void print()
    {
        System.out.println("Dimension: " + row + "x" + col);
        System.out.println("Sparse Matrix: \nRow Column Value");
  
        for (int i = 0; i < len; i++) {
  
            System.out.println(data[i][0] + " " 
                             + data[i][1] + " " + data[i][2]);
        }
    }
  
    public static void main(String args[])
    {
  
        // create two sparse matrices and insert values
        sparse_matrix a = new sparse_matrix(4, 4);
        sparse_matrix b = new sparse_matrix(4, 4);
  
        a.insert(1, 2, 10);
        a.insert(1, 4, 12);
        a.insert(3, 3, 5);
        a.insert(4, 1, 15);
        a.insert(4, 2, 12);
        b.insert(1, 3, 8);
        b.insert(2, 4, 23);
        b.insert(3, 3, 9);
        b.insert(4, 1, 20);
        b.insert(4, 2, 25);
  
        // Output result
        System.out.println("Addition: ");
        a.add(b);
        System.out.println("\nMultiplication: ");
        a.multiply(b);
        System.out.println("\nTranspose: ");
        sparse_matrix atranspose = a.transpose();
        atranspose.print();
    }
}
  
// This code is contributed by Sudarshan Khasnis

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# code to perform add, 
// multiply and transpose on sparse matrices 
  
public class sparse_matrix { 
  
    // Maximum number of elements in matrix 
    static int MAX = 100; 
  
    // Array representation 
    // of sparse matrix 
    //[,0] represents row 
    //[,1] represents col 
    //[,2] represents value 
    int[,] data = new int[MAX,3]; 
  
    // dimensions of matrix 
    int row, col; 
  
    // total number of elements in matrix 
    int len; 
  
    public sparse_matrix(int r, int c) 
    
  
        // initialize row 
        row = r; 
  
        // initialize col 
        col = c; 
  
        // intialize length to 0 
        len = 0; 
    
  
    // insert elements into sparse matrix 
    public void insert(int r, int c, int val) 
    
  
        // invalid entry 
        if (r > row || c > col) { 
            System.Console.WriteLine("Wrong entry"); 
        
  
        else
  
            // insert row value 
            data[len,0] = r; 
  
            // insert col value 
            data[len,1] = c; 
  
            // insert element's value 
            data[len,2] = val; 
  
            // increment number of data in matrix 
            len++; 
        
    
  
    public void add(sparse_matrix b) 
    
  
        // if matrices don't have same dimensions 
        if (row != b.row || col != b.col) { 
            System.Console.WriteLine("Matrices can't be added"); 
        
  
        else
  
            int apos = 0, bpos = 0; 
            sparse_matrix result = new sparse_matrix(row, col); 
  
            while (apos < len && bpos < b.len) { 
  
                // if b's row and col is smaller 
                if (data[apos,0] > b.data[bpos,0] || 
                (data[apos,0] == b.data[bpos,0] && 
                data[apos,1] > b.data[bpos,1])) 
  
                
  
                    // insert smaller value into result 
                    result.insert(b.data[bpos,0], 
                                b.data[bpos,1], 
                                b.data[bpos,2]); 
  
                    bpos++; 
                
  
                // if a's row and col is smaller 
                else if (data[apos,0] < b.data[bpos,0] || 
                (data[apos,0] == b.data[bpos,0] && 
                data[apos,1] < b.data[bpos,1])) 
  
                
  
                    // insert smaller value into result 
                    result.insert(data[apos,0], 
                                data[apos,1], 
                                data[apos,2]); 
  
                    apos++; 
                
  
                else
  
                    // add the values as row and col is same 
                    int addedval = data[apos,2] + b.data[bpos,2]; 
  
                    if (addedval != 0) 
                        result.insert(data[apos,0], 
                                    data[apos,1], 
                                    addedval); 
                    // then insert 
                    apos++; 
                    bpos++; 
                
            
  
            // insert remaining elements 
            while (apos < len) 
                result.insert(data[apos,0], 
                            data[apos,1], 
                            data[apos++,2]); 
  
            while (bpos < b.len) 
                result.insert(b.data[bpos,0], 
                            b.data[bpos,1], 
                            b.data[bpos++,2]); 
  
            // print result 
            result.print(); 
        
    
  
    public sparse_matrix transpose() 
    
  
        // new matrix with inversed row X col 
        sparse_matrix result = new sparse_matrix(col, row); 
  
        // same number of elements 
        result.len = len; 
  
        // to count number of elements in each column 
        int[] count = new int[col + 1]; 
  
        // initialize all to 0 
        for (int i = 1; i <= col; i++) 
            count[i] = 0; 
  
        for (int i = 0; i < len; i++) 
            count[data[i,1]]++; 
  
        int[] index = new int[col + 1]; 
  
        // to count number of elements having col smaller 
        // than particular i 
  
        // as there is no col with value < 1 
        index[1] = 0; 
  
        // initialize rest of the indices 
        for (int i = 2; i <= col; i++) 
  
            index[i] = index[i - 1] + count[i - 1]; 
  
        for (int i = 0; i < len; i++) { 
  
            // insert a data at rpos and increment its value 
            int rpos = index[data[i,1]]++; 
  
            // transpose row=col 
            result.data[rpos,0] = data[i,1]; 
  
            // transpose col=row 
            result.data[rpos,1] = data[i,0]; 
  
            // same value 
            result.data[rpos,2] = data[i,2]; 
        
  
        // the above method ensures 
        // sorting of transpose matrix 
        // according to row-col value 
        return result; 
    
  
    public void multiply(sparse_matrix b) 
    
  
        if (col != b.row) { 
  
            // Invalid multiplication 
            System.Console.WriteLine("Can't multiply, "
                            + "Invalid dimensions"); 
  
            return
        
  
        // transpose b to compare row 
        // and col values and to add them at the end 
        b = b.transpose(); 
        int apos, bpos; 
  
        // result matrix of dimension row X b.col 
        // however b has been transposed, hence row X b.row 
        sparse_matrix result = new sparse_matrix(row, b.row); 
  
        // iterate over all elements of A 
        for (apos = 0; apos < len;) { 
  
            // current row of result matrix 
            int r = data[apos,0]; 
  
            // iterate over all elements of B 
            for (bpos = 0; bpos < b.len;) { 
  
                // current column of result matrix 
                // data[,0] used as b is transposed 
                int c = b.data[bpos,0]; 
  
                // temporary pointers created to add all 
                // multiplied values to obtain current 
                // element of result matrix 
                int tempa = apos; 
                int tempb = bpos; 
  
                int sum = 0; 
  
                // iterate over all elements with 
                // same row and col value 
                // to calculate result[r] 
                while (tempa < len && data[tempa,0] == r 
                    && tempb < b.len && b.data[tempb,0] == c) { 
  
                    if (data[tempa,1] < b.data[tempb,1]) 
  
                        // skip a 
                        tempa++; 
  
                    else if (data[tempa,1] > b.data[tempb,1]) 
  
                        // skip b 
                        tempb++; 
                    else
  
                        // same col, so multiply and increment 
                        sum += data[tempa++,2] * b.data[tempb++,2]; 
                
  
                // insert sum obtained in result[r] 
                // if its not equal to 0 
                if (sum != 0) 
                    result.insert(r, c, sum); 
  
                while (bpos < b.len && b.data[bpos,0] == c) 
  
                    // jump to next column 
                    bpos++; 
            
  
            while (apos < len && data[apos,0] == r) 
  
                // jump to next row 
                apos++; 
        
  
        result.print(); 
    
  
    // printing matrix 
    public void print() 
    
        System.Console.WriteLine("Dimension: " + row + "x" + col); 
        System.Console.WriteLine("Sparse Matrix: \nRow Column Value"); 
  
        for (int i = 0; i < len; i++) { 
  
            System.Console.WriteLine(data[i,0] + " "
                            + data[i,1] + " " + data[i,2]); 
        
    
  
    public static void Main() 
    
  
        // create two sparse matrices and insert values 
        sparse_matrix a = new sparse_matrix(4, 4); 
        sparse_matrix b = new sparse_matrix(4, 4); 
  
        a.insert(1, 2, 10); 
        a.insert(1, 4, 12); 
        a.insert(3, 3, 5); 
        a.insert(4, 1, 15); 
        a.insert(4, 2, 12); 
        b.insert(1, 3, 8); 
        b.insert(2, 4, 23); 
        b.insert(3, 3, 9); 
        b.insert(4, 1, 20); 
        b.insert(4, 2, 25); 
  
        // Output result 
        System.Console.WriteLine("Addition: "); 
        a.add(b); 
        System.Console.WriteLine("\nMultiplication: "); 
        a.multiply(b); 
        System.Console.WriteLine("\nTranspose: "); 
        sparse_matrix atranspose = a.transpose(); 
        atranspose.print(); 
    
  
// This code is contributed by mits

chevron_right



Output:

Addition: 
Dimension: 4x4
Sparse Matrix: 
Row Column Value
1 2 10
1 3 8
1 4 12
2 4 23
3 3 14
4 1 35
4 2 37

Multiplication: 
Dimension: 4x4
Sparse Matrix: 
Row Column Value
1 1 240
1 2 300
1 4 230
3 3 45
4 3 120
4 4 276

Transpose: 
Dimension: 4x4
Sparse Matrix: 
Row Column Value
1 4 15
2 1 10
2 4 12
3 3 5
4 1 12

Worst case time complexity: Addition operation traverses the matrices linearly, hence, has a time complexity of O(n), where n is the number of non-zero elements in the larger matrix amongst the two. Transpose has a time complexity of O(n+m), where n is the number of columns and m is the number of non-zero elements in the matrix. Multiplication, however, has a time complexity of O(x*n + y*m), where (x, m) is number of columns and terms in the second matrix; and (y, n) is number of rows and terms in the first matrix.



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.