简体   繁体   中英

How do I create 2d arrays based on sparse column matrix parameters in Java?

I am a new to Java. I want to create a 2d java arrays based on compressed sparse column matrix parameters. For example, I can create an 2d arrays by using the following code in python:

from scipy.sparse import csc_matrix

indices = [0, 2, 2, 0, 1, 2]
indptr = [0,2,3,6]
data = [1, 2, 3, 4, 5, 6]
shape = [3,3]
sp_mat = csc_matrix((data, indices, indptr), shape=shape).todense()
print(sp_mat)
[[1 0 4]
 [0 0 5]
 [2 3 6]]

But I don't know how to achieve it in Java.

import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        int[] indices = new int[]{0, 2, 2, 0, 1, 2};
        int[] indptr = new int[]{0, 2, 3, 6};
        int[] data = new int[]{1, 2, 3, 4, 5, 6};
        int[] shape = new int[]{3, 3};
        // some code to create 2D arrays
    }
}

I will have indices , indptr , data and shape 1d array as above code. I expect to be able to create the following 2d arrays:

int[][] sp_mat = new int[][]{{1, 0, 4}, {0, 0, 5}, {2, 3, 6}};

I doubt there is any standard method to do so. If you would like to use dedicated classes then probably some Math libraries with sparse matrices will provide such constructors. If you just want 2D array then you can easily implement such code yourself. If you need such signature then here is the simple method:

private static int[][] to2dArray(int[] row, int[] col, int[] data, int[] shape) {
    //check here row.length == col.length == data.length and shape.length == 2
    int[][] mat = new int[shape[0]][shape[1]];
    var length = row.length;
    for (int i = 0; i < length; i++) {
        mat[row[i]][col[i]] = data[i];
    }
    return mat;
}

After post edit, here is CSC (compressed sparse column) version:

private static int[][] to2dArray(
        int[] indices, int[] indicesPtr, int[] data, int[] shape) {
    int[][] mat = new int[shape[0]][shape[1]];
    for (int column = 0; column < shape[1]; column++) {
        var from = indicesPtr[column];
        var to = indicesPtr[column + 1];
        for (int index = from; index < to; index++) {
            mat[indices[index]][column] = data[index];
        }
    }
    return mat;
}

I finally found what I needed Java la4j library. First add dependencies:

<dependency>
    <groupId>org.la4j</groupId>
    <artifactId>la4j</artifactId>
    <version>0.6.0</version>
</dependency>

Then I can create CCSMatrix martix and convert matrix to 2d arrays.

import java.io.IOException;
import org.la4j.matrix.sparse.CCSMatrix;

public class Main {
    public static void main(String[] args) throws IOException {
        int[] indices = new int[]{0, 2, 2, 0, 1, 2};
        int[] indptr = new int[]{0, 2, 3, 6};
        double[] data = new int[]{1, 2, 3, 4, 5, 6};
        int[] shape = new int[]{3, 3};
        // some code to create 2D arrays
        CCSMatrix a = new CCSMatrix(
                shape[0], shape[1], data.length, data, indices, indptr);
        double[][] mat = a.toDenseMatrix().toArray();
    }
}

You can create the toDenseMatrix method yourself using a stream in a stream :

public static int[][] toDenseMatrix(
        int[] indices, int[] indptr, int[] data, int[] shape) {
    int[][] m = new int[shape[0]][shape[1]];
    IntStream.range(0, shape[1])
            .forEach(column -> IntStream.range(indptr[column], indptr[column + 1])
                    .forEach(index -> m[indices[index]][column] = data[index]));
    return m;
}
public static void main(String[] args) {
    int[] indices = {0, 2, 2, 0, 1, 2};
    int[] indptr = {0, 2, 3, 6};
    int[] data = {1, 2, 3, 4, 5, 6};
    int[] shape = {3, 3};

    int[][] m = toDenseMatrix(indices, indptr, data, shape);

    // output
    Arrays.stream(m).map(Arrays::toString).forEach(System.out::println);
}

Output:

[1, 0, 4]
[0, 0, 5]
[2, 3, 6]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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