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

Changed code to be more bug resistant and future proof #284

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
16 changes: 9 additions & 7 deletions src/main/java/org/la4j/Matrix.java
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public static Matrix fromMatrixMarket(String mm) {
}

String symmetry = header.nextToken();
if (!symmetry.equals("general")) {
if (!"general".equals(symmetry)) {
throw new IllegalArgumentException("Unknown symmetry type: " + symmetry + ".");
}

Expand Down Expand Up @@ -565,13 +565,14 @@ public Matrix power(int n) {
for (int i = 0; i < rows; i++) {
result.set(i, i, 1.0);
}

while (n > 0) {
if (n % 2 == 1) {

int m = n;
while (m > 0) {
if (m % 2 == 1) {
result = result.multiply(that);
}

n /= 2;
m /= 2;
that = that.multiply(that);
}

Expand Down Expand Up @@ -2187,9 +2188,10 @@ protected void fail(String message) {
}

private void indent(StringBuilder sb, int howMany) {
while (howMany > 0) {
int n = howMany;
while (n > 0) {
sb.append(" ");
howMany--;
n--;
}
}
}
11 changes: 0 additions & 11 deletions src/main/java/org/la4j/Vector.java
Original file line number Diff line number Diff line change
Expand Up @@ -487,17 +487,6 @@ public Matrix outerProduct(Vector that) {
return apply(LinearAlgebra.OO_PLACE_OUTER_PRODUCT, that);
}

/**
* Calculates the cosine similarity between this vector and given {@code that}.
*
* @param that the vector to calculated cosine similarity with
*
* @return the cosine similarity of the two vectors
*/
public double cosineSimilarity(Vector that) {
return this.innerProduct(that) / (this.euclideanNorm() * that.euclideanNorm());
}

/**
* Calculates an Euclidean norm of this vector.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ public Matrix[] decompose() {
iter = 0;
p--;
}
default:
break;
}
}
Expand Down
84 changes: 54 additions & 30 deletions src/main/java/org/la4j/matrix/sparse/CCSMatrix.java
Original file line number Diff line number Diff line change
Expand Up @@ -554,18 +554,19 @@ private int searchForRowIndex(int i, int left, int right) {
return right;
}

while (left < right) {
int p = (left + right) / 2;
int l = left, r = right;
while (l < r) {
int p = (l + r) / 2;
if (rowIndices[p] > i) {
right = p;
r = p;
} else if (rowIndices[p] < i) {
left = p + 1;
l = p + 1;
} else {
return p;
}
}

return left;
return l;
}

private void insert(int k, int i, int j, double value) {
Expand Down Expand Up @@ -697,6 +698,47 @@ public double minInColumn(int j) {
return (min < 0.0) ? min : 0.0;
}

/**
* Calculates the cardinality
*/
public int getCardinality(int[] sizes, int[] rowIndices, int[] columnIndices, int newCardinality){
int newRows = sizes[0];
int newCols = sizes[1];

for (int i = 0; i < newRows; i++) {
for (int j = 0; j < newCols; j++) {
if (get(rowIndices[i], columnIndices[j]) != 0.0) {
newCardinality++;
}
}
}

return newCardinality;
}

/*
* Constructs the raw structure of a Sparse Matrix
*/
public void constructSparseMatrix(int[] sizes, int[] newColumnPointers,int[] rowIndices, int[] columnIndices, double[] newValues, int[] newRowIndices){
int newRows = sizes[0];
int newCols = sizes[1];

newColumnPointers[0] = 0;
int endPtr = 0;
for (int j = 0; j < newCols; j++) {
newColumnPointers[j + 1] = newColumnPointers[j];
for (int i = 0; i < newRows; i++) {
double val = get(rowIndices[i], columnIndices[j]);
if (val != 0.0) {
newValues[endPtr] = val;
newRowIndices[endPtr] = i;
endPtr++;
newColumnPointers[j + 1]++;
}
}
}
}

/**
* Returns a CCSMatrix with the selected rows and columns.
*/
Expand All @@ -713,36 +755,18 @@ public Matrix select(int[] rowIndices, int[] columnIndices) {
// before allocating space, this is perhaps more efficient
// than single pass and calling grow() when required.
int newCardinality = 0;
for (int i = 0; i < newRows; i++) {
for (int j = 0; j < newCols; j++) {
if (get(rowIndices[i], columnIndices[j]) != 0.0) {
newCardinality++;
}
}
}
int[] sizes = {newRows, newCols};

newCardinality = getCardinality(sizes, rowIndices, columnIndices, newCardinality);

// Construct the raw structure for the sparse matrix
double[] newValues = new double[newCardinality];
int[] newRowIndices = new int[newCardinality];
int[] newColumnPointers = new int[newCols + 1];

newColumnPointers[0] = 0;
int endPtr = 0;
for (int j = 0; j < newCols; j++) {
newColumnPointers[j + 1] = newColumnPointers[j];
for (int i = 0; i < newRows; i++) {
double val = get(rowIndices[i], columnIndices[j]);
if (val != 0.0) {
newValues[endPtr] = val;
newRowIndices[endPtr] = i;
endPtr++;
newColumnPointers[j + 1]++;
}
}
}

return new CCSMatrix(newRows, newCols, newCardinality, newValues,
newRowIndices, newColumnPointers);

constructSparseMatrix(sizes, newColumnPointers,rowIndices, columnIndices, newValues, newRowIndices);

return new CCSMatrix(newRows, newCols, newCardinality, newValues, newRowIndices, newColumnPointers);
}

@Override
Expand Down
81 changes: 53 additions & 28 deletions src/main/java/org/la4j/matrix/sparse/CRSMatrix.java
Original file line number Diff line number Diff line change
Expand Up @@ -552,19 +552,20 @@ private int searchForColumnIndex(int j, int left, int right) {
if (right - left == 0 || j > columnIndices[right - 1]) {
return right;
}

while (left < right) {
int p = (left + right) / 2;

int l = left, r = right;
while (l < r) {
int p = (l + r) / 2;
if (columnIndices[p] > j) {
right = p;
r = p;
} else if (columnIndices[p] < j) {
left = p + 1;
l = p + 1;
} else {
return p;
}
}

return left;
return l;
}

private void insert(int k, int i, int j, double value) {
Expand Down Expand Up @@ -696,35 +697,31 @@ public double minInRow(int i) {
}

/**
* Returns a CRSMatrix with the selected rows and columns.
* Calculates the cardinality
*/
@Override
public Matrix select(int[] rowIndices, int[] columnIndices) {
int newRows = rowIndices.length;
int newCols = columnIndices.length;

if (newRows == 0 || newCols == 0) {
fail("No rows or columns selected.");
}

// determine number of non-zero values (cardinality)
// before allocating space, this is perhaps more efficient
// than single pass and calling grow() when required.
int newCardinality = 0;
for (int i = 0; i < newRows; i++) {
public int getCardinality(int[] sizes, int[] rowIndices, int[] columnIndices, int newCardinality){
int newRows = sizes[0];
int newCols = sizes[1];

for (int i = 0; i < newRows; i++) {
for (int j = 0; j < newCols; j++) {
if (get(rowIndices[i], columnIndices[j]) != 0.0) {
newCardinality++;
}
}
}

// Construct the raw structure for the sparse matrix
double[] newValues = new double[newCardinality];
int[] newColumnIndices = new int[newCardinality];
int[] newRowPointers = new int[newRows + 1];

newRowPointers[0] = 0;

return newCardinality;
}

/**
* Constructs the raw structure of a Sparse Matrix
*/
public void constructSparseMatrix(int[] sizes, int[] newRowPointers,int[] rowIndices, int[] columnIndices, double[] newValues, int[] newColumnIndices){
int newRows = sizes[0];
int newCols = sizes[1];

newRowPointers[0] = 0;
int endPtr = 0;
for (int i = 0; i < newRows; i++) {
newRowPointers[i + 1] = newRowPointers[i];
Expand All @@ -739,6 +736,34 @@ public Matrix select(int[] rowIndices, int[] columnIndices) {
}
}
}
}


/**
* Returns a CRSMatrix with the selected rows and columns.
*/
@Override
public Matrix select(int[] rowIndices, int[] columnIndices) {
int newRows = rowIndices.length;
int newCols = columnIndices.length;

if (newRows == 0 || newCols == 0) {
fail("No rows or columns selected.");
}

// determine number of non-zero values (cardinality)
// before allocating space, this is perhaps more efficient
// than single pass and calling grow() when required.
int newCardinality = 0;
int[] sizes = {newRows, newCols};
newCardinality = getCardinality(sizes, rowIndices, columnIndices, newCardinality);

// Construct the raw structure for the sparse matrix
double[] newValues = new double[newCardinality];
int[] newColumnIndices = new int[newCardinality];
int[] newRowPointers = new int[newRows + 1];

constructSparseMatrix(sizes, newRowPointers,rowIndices, columnIndices, newValues, newColumnIndices);

return new CRSMatrix(newRows, newCols, newCardinality, newValues,
newColumnIndices, newRowPointers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ public R apply(final DenseVector a) {
return applyCommon(a);
}

abstract R applyCommon(final Vector a);
protected abstract R applyCommon(final Vector a);
}
15 changes: 0 additions & 15 deletions src/test/java/org/la4j/vector/VectorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -743,19 +743,4 @@ public void testFromMap_invalidMap() {
public void testFromMap_NPE() {
Vector v = Vector.fromMap(null, 4);
}

@Test
public void testCosineSimilarity() {
Vector a = v(5, 1, 0, 0, 0, 1, 10, 15);
Vector b = v(1, 8, 0, 9, 6, 4, 2, 5);
Vector c = v(9, 0, 2, 1, 1, 0, 8, 12);
Vector d = v(900, 0, 200, 100, 100, 0, 800, 1200);

// a & c are more similar to each other than b
Assert.assertTrue(a.cosineSimilarity(b) < a.cosineSimilarity(c));
Assert.assertTrue(c.cosineSimilarity(b) < c.cosineSimilarity(a));

Assert.assertEquals(1.0, c.cosineSimilarity(d), 0.00005);
Assert.assertEquals(1.0, d.cosineSimilarity(c), 0.00005);
}
}