Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
41425a8
Add monoids and semirings
Jul 12, 2020
df4b396
Init sparse matrix ops using semirings
Jul 12, 2020
61f5d57
Test and fix predefined monoids
Jul 13, 2020
bcbc2b6
Add predefined semi-rings
Jul 13, 2020
b553f67
Add dependency for parameterized tests
Jul 14, 2020
2ef0cc3
Test and Fix Matrix x Vector with semi-rings
Jul 14, 2020
d20b382
Test elementWiseMult and add
Jul 14, 2020
dc710e5
Initialise result of matrix-matrix mult-ops with id of plus operator …
Jul 14, 2020
f182fb7
Clarify problem with "MIN-PLUS" semi-ring and dense vectors
FlorentinD Jul 15, 2020
94ad9cf
Fix warning about lossy conversion from double to float
Jul 16, 2020
f98197f
Add semi-rings with first and second for mul operation
Jul 20, 2020
6f5571b
Use D and F instead of Double and Float for Semi-rings and Monoids
Jul 28, 2020
8a36c74
Applying previous commit to semi-ring version
Jul 28, 2020
ceea2be
Remove redundant semi-ring unspecific methods
Jul 28, 2020
4355779
Test sparse matrix-matrix mul
Jul 28, 2020
53d88cb
Remove leftover TODO and duplicated transpose method
Aug 4, 2020
599df5c
Make `add` and `elementMult` also return the matrix
Aug 4, 2020
624e0b9
Add more test for MatrixMatrix ops with semi-ring
Aug 4, 2020
762a8c0
Add masks based on matrices or primitive arrays
Aug 3, 2020
4461a0c
Add a zeroElement to Masks
Aug 3, 2020
7ad758c
Init masked operations
Aug 4, 2020
68d5fbf
Check if mask is null in MatrixVectorMult
Aug 4, 2020
f6d8e5c
Extract @Setup method in base test class
Aug 4, 2020
2a6fffc
Start testing masked operations
Aug 4, 2020
ea25bbf
Fix after rebase
Aug 4, 2020
49e07e8
Fix off by one error for corresponding result cell
Aug 4, 2020
bb68c40
More testing
Aug 4, 2020
40f9564
And another off by one error in calling mask.isSet
Aug 4, 2020
d1d9fbe
Dont overwrite existing result fields if mask is not set on this fiel…
Aug 6, 2020
15cc9be
Refactor mask related operators into extra file
Aug 6, 2020
1ddd1a5
Add tests for `elementWiseMult` and `apply`
Aug 6, 2020
82c1325
Add masks for apply and reduce
Aug 6, 2020
4e489bd
Parameterize masked tests
Aug 10, 2020
fa52eb4
Check if mask is compatible with result
Aug 10, 2020
ecd8adc
Fix reduce tests by using meaningful input
Aug 10, 2020
11be867
Fix incorrect result structure based on mask only applied to values
Aug 11, 2020
9f5bb99
Fix result for apply with mask
Aug 11, 2020
3cbce8d
Fix a bug in `multAddColA` based on the incorrect target column
Aug 11, 2020
608b720
Parameterize accumulator for combining old matrix and new result
Aug 11, 2020
c4c496e
Code format and add java doc for accumulator
Aug 11, 2020
c55312b
Add a replace flag and use a builder for masks
Aug 13, 2020
8537ef6
Support accumulator for matrixXprimitive ops
Aug 13, 2020
3f4a154
Simplify combining dense outputs
Aug 13, 2020
1e4f625
Return Mask instead of Object in MaskBuilder
Aug 13, 2020
4721dbe
Implement sparse variations of BFS
Aug 13, 2020
bad3904
Fix dense bfs variations
Aug 18, 2020
63341e3
Return bfs-result object containing also the needed iterations
FlorentinD Aug 25, 2020
97384ba
Add `get` method to Bfs-result
FlorentinD Aug 25, 2020
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
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ subprojects {
compile 'com.google.code.findbugs:jsr305:3.0.2' // @Nullable

testImplementation( 'org.junit.jupiter:junit-jupiter-api:5.4.0' )
testImplementation( 'org.junit.jupiter:junit-jupiter-params:5.4.0' )
testRuntimeOnly( 'org.junit.jupiter:junit-jupiter-engine:5.4.0' )

['core','generator-annprocess'].each { String a->
Expand Down
21 changes: 21 additions & 0 deletions main/autocode/src/org/ejml/GenerateJavaCode32.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ public GenerateJavaCode32() {
prefix32.add("FUnary");
prefix64.add("DBinary");
prefix32.add("FBinary");
prefix64.add("DMonoid");
prefix32.add("FMonoid");
prefix64.add("DSemiRing");
prefix32.add("FSemiRing");
prefix64.add("DMonoids");
prefix32.add("FMonoids");
prefix64.add("DSemiRings");
prefix32.add("FSemiRings");
prefix64.add("PrimitiveDMask");
prefix32.add("PrimitiveFMask");
prefix64.add("SparseDMask");
prefix32.add("SparseFMask");
prefix64.add("DMasks");
prefix32.add("FMasks");
prefix64.add("DScalar");
prefix32.add("FScalar");
prefix64.add("DMatrix");
Expand Down Expand Up @@ -93,6 +107,11 @@ public GenerateJavaCode32() {
converter.replacePattern("DScalar", "FScalar");
converter.replacePattern("DUnary", "FUnary");
converter.replacePattern("DBinary", "FBinary");
converter.replacePattern("DMonoid", "FMonoid");
converter.replacePattern("DSemiRing", "FSemiRing");
converter.replacePattern("SparseDMask", "SparseFMask");
converter.replacePattern("PrimitiveDMask", "PrimitiveFMask");
converter.replacePattern("DMasks", "FMasks");
converter.replacePattern("ConvertD", "ConvertF");
converter.replacePattern("DGrowArray", "FGrowArray");
converter.replacePattern("DMatrix", "FMatrix");
Expand Down Expand Up @@ -133,6 +152,8 @@ public static void main(String[] args ) {
"main/ejml-core/test/org/ejml/data",
"main/ejml-core/src/org/ejml/ops",
"main/ejml-core/test/org/ejml/ops",
"main/ejml-core/src/org/ejml/masks",
"main/ejml-core/test/org/ejml/masks",
"main/ejml-experimental/src/org/ejml/dense/row/decomposition/bidiagonal/"
};

Expand Down
7 changes: 7 additions & 0 deletions main/ejml-core/src/org/ejml/data/DMatrixRMaj.java
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,13 @@ public void zero() {
Arrays.fill(data, 0, getNumElements(), 0.0);
}

/**
* Sets all elements equal to the specified value.
*/
public void fill(double value) {
Arrays.fill(data, 0, getNumElements(), value);
}

/**
* Creates and returns a matrix which is idential to this one.
*
Expand Down
43 changes: 43 additions & 0 deletions main/ejml-core/src/org/ejml/masks/DMasks.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2009-2020, Peter Abeles. All Rights Reserved.
*
* This file is part of Efficient Java Matrix Library (EJML).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ejml.masks;

import org.ejml.data.*;

/**
* Helper class to get the corresponding mask builder based on a matrix or primitive array
*/
public class DMasks {
public static PrimitiveDMask.Builder builder(double[] values) {
return new PrimitiveDMask.Builder(values);
}

public static PrimitiveDMask.Builder builder(DMatrixD1 matrix) {
return new PrimitiveDMask.Builder(matrix.data).withNumCols(matrix.numCols);
}

public static MaskBuilder builder(DMatrixSparseCSC matrix, boolean structural){
if (structural) {
return new SparseStructuralMask.Builder(matrix);
}
else {
return new SparseDMask.Builder(matrix);
}
}
}
75 changes: 75 additions & 0 deletions main/ejml-core/src/org/ejml/masks/Mask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2009-2020, Peter Abeles. All Rights Reserved.
*
* This file is part of Efficient Java Matrix Library (EJML).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ejml.masks;


import org.ejml.MatrixDimensionException;
import org.ejml.data.Matrix;

/**
* Mask used for specifying which matrix entries should be computed
*/
public abstract class Mask {
// useful for sparse matrices, as actual negation would be costly and result in dense masks
public final boolean negated;

// whether the result should replace the initial result (otherwise merge them)
// same as the "GrB_REPLACE" descriptor
public final boolean replace;

public Mask(boolean negated, boolean replace) {
this.negated = negated;
this.replace = replace;
}

public abstract boolean isSet(int row, int col);

public abstract int getNumCols();

public abstract int getNumRows();

public void print() {
String result = "";
for (int row = 0; row < getNumRows(); row++) {
for (int col = 0; col < getNumCols(); col++) {
result += isSet(row, col) ? "+ " : "- ";
}
result += System.lineSeparator();
}

System.out.println(result);
};

/**
* Checks whether the dimensions of the mask and matrix match
* @param matrix the mask is applied to
*/
public void compatible(Matrix matrix) {
if (matrix.getNumCols() != getNumCols() || matrix.getNumRows() != getNumRows()) {
throw new MatrixDimensionException(String.format(
"Mask of (%d, %d) cannot be applied for matrix (%d, %d)",
getNumRows(), getNumCols(), matrix.getNumCols(), matrix.getNumCols()
));
}
}

// TODO: use an Iterator as it should be faster as stepping can be used -> no need to call for each entry?
// Problem .. dense matrices are row-based, whereas existing sparse matrix format is column based
//public abstract Iterator<BMatrixSparseCSC.CoordinateBoolValue>
}
36 changes: 36 additions & 0 deletions main/ejml-core/src/org/ejml/masks/MaskBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2009-2020, Peter Abeles. All Rights Reserved.
*
* This file is part of Efficient Java Matrix Library (EJML).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ejml.masks;

public abstract class MaskBuilder<MASK extends Mask> {
protected boolean negated = false;
protected boolean replace = true;

public MaskBuilder<MASK> withNegated(boolean negated) {
this.negated = negated;
return this;
}

public MaskBuilder<MASK> withReplace(boolean replace) {
this.replace = replace;
return this;
}

public abstract MASK build();
}
93 changes: 93 additions & 0 deletions main/ejml-core/src/org/ejml/masks/PrimitiveDMask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2009-2020, Peter Abeles. All Rights Reserved.
*
* This file is part of Efficient Java Matrix Library (EJML).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ejml.masks;

import org.ejml.MatrixDimensionException;

public class PrimitiveDMask extends Mask {
// TODO: Check if creating dense boolean mask is worth it (currently converting to boolean on the fly)
private final double[] values;
// alternatively declare extra separate masks for primitive and dense DMatrix
private final int numCols;
//
private final double zeroElement;

public PrimitiveDMask(double[] values, int numCols, boolean negated, boolean replace, double zeroElement) {
// for dense structures they cannot be used for structural masks
super(negated, replace);
this.values = values;
this.numCols = numCols;
this.zeroElement = zeroElement;
}

@Override
public boolean isSet(int row, int col) {
// XOR as negated flips the mask flag
return negated ^ (values[row * numCols + col] != zeroElement);
}

@Override
public int getNumCols() {
return numCols;
}

@Override
public int getNumRows() {
return values.length / numCols;
}

public boolean isSet(int index) {
return negated ^ (values[index] != zeroElement);
}

public void compatible(double[] vector) {
if (vector.length != values.length) {
throw new MatrixDimensionException(String.format(
"Mask of length %d cannot be applied to vector of lenght %d",
values.length, vector.length
));
}
}

public static class Builder extends MaskBuilder<PrimitiveDMask> {
private double[] values;
private int numCols = 1;
private double zeroElement = 0;

public Builder(double[] values) {
this.values = values;
}

public Builder withNumCols(int numCols) {
this.numCols = numCols;
return this;
}

public Builder withZeroElement(double zeroElement) {
this.zeroElement = zeroElement;
return this;
}

@Override
public PrimitiveDMask build() {
return new PrimitiveDMask(values, numCols, negated, replace, zeroElement);
}
}
}

66 changes: 66 additions & 0 deletions main/ejml-core/src/org/ejml/masks/SparseDMask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2009-2020, Peter Abeles. All Rights Reserved.
*
* This file is part of Efficient Java Matrix Library (EJML).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ejml.masks;

import org.ejml.data.DMatrixSparseCSC;

public class SparseDMask extends Mask {
protected final DMatrixSparseCSC matrix;
protected final double zeroElement;

public SparseDMask(DMatrixSparseCSC matrix, boolean negated, boolean replace, double zeroElement) {
super(negated, replace);
this.matrix = matrix;
this.zeroElement = zeroElement;
}

@Override
public boolean isSet(int row, int col) {
return negated ^ (matrix.unsafe_get(row, col) != zeroElement);
}

@Override
public int getNumCols() {
return matrix.numCols;
}

@Override
public int getNumRows() {
return matrix.numRows;
}

public static class Builder extends MaskBuilder<SparseDMask> {
private DMatrixSparseCSC matrix;
private double zeroElement = 0;

public Builder(DMatrixSparseCSC matrix) {
this.matrix = matrix;
}

public Builder withZeroElement(double zeroElement) {
this.zeroElement = zeroElement;
return this;
}

@Override
public SparseDMask build() {
return new SparseDMask(matrix, negated, replace, zeroElement);
}
}
}
Loading