Skip to content

Commit

Permalink
Merge pull request #101 from jacobdwatters/develop
Browse files Browse the repository at this point in the history
Add sparse CSR matrix implementations.
  • Loading branch information
jacobdwatters authored Jul 21, 2024
2 parents 2c9a89e + 53825e0 commit fb2ab58
Show file tree
Hide file tree
Showing 35 changed files with 2,385 additions and 285 deletions.
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

0 comments on commit fb2ab58

Please sign in to comment.