Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sparse CSR matrix implementations. #101

Merged
merged 4 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,16 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.flag4j</groupId>
<groupId>org.flag4j</groupId>
<artifactId>flag4j</artifactId>
<version>v0.0.1-beta</version>

<version>v0.1.0-beta</version>
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub jacobdwatters Apache Maven Packages</name>
<url>https://maven.pkg.github.com/jacobdwatters/Flag4j</url>
</repository>
</distributionManagement>

<dependencies>
<dependency>
<groupId>junit</groupId>
Expand All @@ -30,18 +27,15 @@
<scope>test</scope>
</dependency>
</dependencies>

<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<sonar.organization>jacobdwatters</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
<testSourceDirectory>src/test/java</testSourceDirectory>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand All @@ -52,7 +46,6 @@
<target>11</target>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
Expand All @@ -61,7 +54,6 @@
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>

<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
Expand All @@ -88,5 +80,4 @@
</plugin>
</plugins>
</build>

</project>
3 changes: 1 addition & 2 deletions src/main/java/org/flag4j/arrays/dense/CTensor.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ protected CTensor makeTensor(Shape shape, CNumber[] entries) {
*/
@Override
public CooCTensor toCoo() {
// TODO: Implementation.
return null;
return CooCTensor.fromDense(this);
}


Expand Down
32 changes: 31 additions & 1 deletion src/main/java/org/flag4j/arrays/dense/CVector.java
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ public CVector flatten() {
*/
@Override
public CVector flatten(int axis) {
return null;
return this.copy();
}


Expand All @@ -1159,6 +1159,36 @@ public int size() {
}


/**
* Repeats a vector {@code n} times along a certain axis to create a matrix.
*
* @param n Number of times to repeat vector.
* @param axis Axis along which to repeat vector. If {@code axis=0} then each row of the resulting matrix will be equivalent to
* this vector. If {@code axis=1} then each column of the resulting matrix will be equivalent to this vector.
*
* @return A matrix whose rows/columns are this vector repeated.
*/
@Override
public CMatrix repeat(int n, int axis) {
ParameterChecks.assertInRange(axis, 0, 1, "axis");
ParameterChecks.assertGreaterEq(0, n, "n");
Shape tiledShape;
CNumber[] tiledEntries = new CNumber[size*n];

if(axis==0) {
tiledShape = new Shape(n, size);
for(int i=0; i<n; i++) // Set each row of the tiled matrix to be the vector values.
ArrayUtils.arraycopy(entries, 0, tiledEntries, i*size, size);
} else {
tiledShape = new Shape(size, n);
for(int i=0; i<size; i++) // Fill each row of the tiled matrix with a single value from the vector.
ArrayUtils.fill(tiledEntries, i*n, (i+1)*n, entries[i]);
}

return new CMatrix(tiledShape, tiledEntries);
}


/**
* Factory to create a tensor with the specified shape and size.
*
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/org/flag4j/arrays/dense/Vector.java
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,37 @@ public int size() {
}


/**
* Repeats a vector {@code n} times along a certain axis to create a matrix.
*
* @param n Number of times to repeat vector.
* @param axis Axis along which to repeat vector. If {@code axis=0} then each row of the resulting matrix will be equivalent to
* this vector. If {@code axis=1} then each column of the resulting matrix will be equivalent to this vector.
*
* @return A matrix whose rows/columns are this vector repeated.
*/
@Override
public Matrix repeat(int n, int axis) {
ParameterChecks.assertInRange(axis, 0, 1, "axis");
ParameterChecks.assertGreaterEq(0, n, "n");
Matrix tiled;

if(axis==0) {
tiled = new Matrix(new Shape(n, size));

for(int i=0; i<tiled.numRows; i++) // Set each row of the tiled matrix to be the vector values.
System.arraycopy(entries, 0, tiled.entries, i*tiled.numCols, size);
} else {
tiled = new Matrix(new Shape(size, n));

for(int i=0; i<tiled.numRows; i++) // Fill each row of the tiled matrix with a single value from the vector.
Arrays.fill(tiled.entries, i*tiled.numCols, (i+1)*tiled.numCols, entries[i]);
}

return tiled;
}


/**
* Flattens a tensor along the specified axis. For a vector, this simply copies the vector.
*
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/flag4j/arrays/sparse/CooCMatrix.java
Original file line number Diff line number Diff line change
Expand Up @@ -893,17 +893,17 @@ public CMatrix mult(Matrix B) {
/**
* Computes the matrix-vector multiplication.
*
* @param B Vector to multiply this matrix to.
* @param b Vector to multiply this matrix to.
* @return The vector result from multiplying this matrix by the vector {@code B}.
* @throws IllegalArgumentException If the number of columns in this matrix do not equal the number of
* entries {@code B}.
*/
@Override
public CVector mult(CooCVector B) {
ParameterChecks.assertEquals(numCols, B.size);
public CVector mult(CooCVector b) {
ParameterChecks.assertEquals(numCols, b.size);
CNumber[] dest = ComplexSparseMatrixMultiplication.standardVector(
entries, rowIndices, colIndices, shape,
B.entries, B.indices
b.entries, b.indices
);
return new CVector(dest);
}
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/org/flag4j/arrays/sparse/CooCTensor.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@
package org.flag4j.arrays.sparse;

import org.flag4j.arrays.dense.CTensor;
import org.flag4j.arrays.dense.Tensor;
import org.flag4j.complex_numbers.CNumber;
import org.flag4j.core.Shape;
import org.flag4j.core.sparse_base.ComplexSparseTensorBase;
import org.flag4j.operations.sparse.coo.complex.ComplexSparseEquals;

import java.util.ArrayList;
import java.util.List;


/**
* Complex sparse tensor. Stored in coordinate (COO) format.
Expand Down Expand Up @@ -671,7 +675,32 @@ protected CooTensor makeRealTensor(Shape shape, double[] entries, int[][] indice
*/
@Override
public void sortIndices() {
// TODO: Implementation
}


/**
* Converts a sparse {@link CooCTensor} from a dense {@link Tensor}. This is likely only worthwhile for very sparse tensors.
* @param src Dense tensor to convert to sparse COO tensor.
* @return A COO tensor which is equivalent to the {@code src} dense tensor.
*/
public static CooCTensor fromDense(CTensor src) {
List<CNumber> entries = new ArrayList<>();
List<int[]> indices = new ArrayList<>();

int size = src.entries.length;
CNumber value;

for(int i=0; i<size; i++) {
value = src.entries[i].copy();

if(value.equals(CNumber.zero())) {
entries.add(value);
indices.add(src.shape.getIndices(i));
}
}

return new CooCTensor(src.shape.copy(), entries.toArray(new CNumber[0]), indices.toArray(new int[0][]));
}


Expand Down
43 changes: 43 additions & 0 deletions src/main/java/org/flag4j/arrays/sparse/CooCVector.java
Original file line number Diff line number Diff line change
Expand Up @@ -1471,6 +1471,49 @@ public int size() {
}


/**
* Repeats a vector {@code n} times along a certain axis to create a matrix.
*
* @param n Number of times to repeat vector.
* @param axis Axis along which to repeat vector. If {@code axis=0} then each row of the resulting matrix will be equivalent to
* this vector. If {@code axis=1} then each column of the resulting matrix will be equivalent to this vector.
*
* @return A matrix whose rows/columns are this vector repeated.
*/
@Override
public CooCMatrix repeat(int n, int axis) {
ParameterChecks.assertInRange(axis, 0, 1, "axis");
ParameterChecks.assertGreaterEq(0, n, "n");

Shape tiledShape;
CNumber[] tiledEntries = new CNumber[n*entries.length];
int[] tiledRows = new int[tiledEntries.length];
int[] tiledCols = new int[tiledEntries.length];
int nnz = entries.length;

if(axis==0) {
tiledShape = new Shape(n, size);

for(int i=0; i<n; i++) { // Copy values into row and set col indices as vector indices.
ArrayUtils.arraycopy(entries, 0, tiledEntries, i*nnz, nnz);
System.arraycopy(indices, 0, tiledCols, i*nnz, indices.length);
Arrays.fill(tiledRows, i*nnz, (i+1)*nnz, i);
}
} else {
int[] colIndices = ArrayUtils.intRange(0, n);
tiledShape = new Shape(size, n);

for(int i=0; i<entries.length; i++) {
ArrayUtils.fill(tiledEntries, i*n, (i+1)*n, entries[i]);
Arrays.fill(tiledRows, i*n, (i+1)*n, indices[i]);
System.arraycopy(colIndices, 0, tiledCols, i*n, n);
}
}

return new CooCMatrix(tiledShape, tiledEntries, tiledRows, tiledCols);
}


/**
* Converts this sparse tensor to an equivalent dense tensor.
*
Expand Down
16 changes: 13 additions & 3 deletions src/main/java/org/flag4j/arrays/sparse/CooMatrix.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,17 @@
import java.util.List;

/**
* Real sparse matrix. Matrix is stored in coordinate list (COO) format.
* <p>Real sparse matrix. Matrix is stored in coordinate list (COO) format.</p>
*
* <p>COO matrices are best suited for efficient modification and construction of sparse matrices. Coo matrices are <b>not</b> well
* suited for matrix-matrix or matrix-vector multiplication (see {@link CsrMatrix}).</p>
*
* <p>If a sparse matrix needs to be incrementally constructed, then a COO matrix should be used to construct the matrix as it
* allows for efficient modification. If the matrix then needs to be used in a matrix-matrix or matrix-vector multiplication
* problem, it should first be converted to a {@link CsrMatrix} in most cases.</p>
*
* @see CsrMatrix
* @see CooCMatrix
*/
public class CooMatrix
extends RealSparseTensorBase<CooMatrix, Matrix, CooCMatrix, CMatrix>
Expand Down Expand Up @@ -1074,10 +1084,10 @@ public Matrix mult(Matrix B) {


@Override
public Vector mult(CooVector B) {
public Vector mult(CooVector b) {
double[] dest = RealSparseMatrixMultiplication.standardVector(
entries, rowIndices, colIndices, shape,
B.entries, B.indices
b.entries, b.indices
);
return new Vector(dest);
}
Expand Down
43 changes: 43 additions & 0 deletions src/main/java/org/flag4j/arrays/sparse/CooVector.java
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,49 @@ public int size() {
}


/**
* Repeats a vector {@code n} times along a certain axis to create a matrix.
*
* @param n Number of times to repeat vector.
* @param axis Axis along which to repeat vector. If {@code axis=0} then each row of the resulting matrix will be equivalent to
* this vector. If {@code axis=1} then each column of the resulting matrix will be equivalent to this vector.
*
* @return A matrix whose rows/columns are this vector repeated.
*/
@Override
public CooMatrix repeat(int n, int axis) {
ParameterChecks.assertInRange(axis, 0, 1, "axis");
ParameterChecks.assertGreaterEq(0, n, "n");

Shape tiledShape;
double[] tiledEntries = new double[n*entries.length];
int[] tiledRows = new int[tiledEntries.length];
int[] tiledCols = new int[tiledEntries.length];
int nnz = entries.length;

if(axis==0) {
tiledShape = new Shape(n, size);

for(int i=0; i<n; i++) { // Copy values into row and set col indices as vector indices.
System.arraycopy(entries, 0, tiledEntries, i*nnz, nnz);
System.arraycopy(indices, 0, tiledCols, i*nnz, indices.length);
Arrays.fill(tiledRows, i*nnz, (i+1)*nnz, i);
}
} else {
int[] colIndices = ArrayUtils.intRange(0, n);
tiledShape = new Shape(size, n);

for(int i=0; i<entries.length; i++) {
Arrays.fill(tiledEntries, i*n, (i+1)*n, entries[i]);
Arrays.fill(tiledRows, i*n, (i+1)*n, indices[i]);
System.arraycopy(colIndices, 0, tiledCols, i*n, n);
}
}

return new CooMatrix(tiledShape, tiledEntries, tiledRows, tiledCols);
}


/**
* Simply returns a reference of this tensor.
*
Expand Down
Loading
Loading