Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3e295eb
modified build and pom files, Added new Parameter
cogmission Jan 9, 2016
219a023
Added new KNNClassifier class and test
cogmission Jan 9, 2016
c00eff7
Added new Enums and Constants
cogmission Jan 9, 2016
add191e
Modified BeanUtil to work with private fields, added test to ensure p…
cogmission Jan 9, 2016
ec5da11
Added assertions which validate enum compatibility
cogmission Jan 9, 2016
27e3ff1
Added test class (BeanUtilTest), and added test methods
cogmission Jan 9, 2016
7238233
Added test for builder
cogmission Jan 9, 2016
e2d4f21
Added new utility methods: rotateLeft(), rotateRight(), ravel(), unra…
cogmission Jan 10, 2016
9e8d2d1
Added new NN Matrix implementation
cogmission Jan 11, 2016
00ee815
Merge remote-tracking branch 'upstream/master' into knn_dev
cogmission Jan 11, 2016
12a1f99
more work on knn
cogmission Jan 12, 2016
8db7a17
more work on classifier
cogmission Jan 13, 2016
9223fcd
added more code and merged in ArrayUtil additions
cogmission Jan 13, 2016
2002c4c
changed input datatype to double added new ArrayUtils method for change
cogmission Jan 14, 2016
6c295da
added test files to resources dir
cogmission Jan 15, 2016
3ada066
Add test for new PCA data generation
cogmission Jan 16, 2016
6e533e1
Remove reference to test resources from source
cogmission Jan 16, 2016
aeb60ed
add tests for new ArrayUtils functions
cogmission Jan 17, 2016
c7d8f65
Add new TupleCollector and change test to use Streams
cogmission Jan 17, 2016
d9d1d79
Added matrix transpose method
cogmission Jan 17, 2016
7d62579
added original test code back in
cogmission Jan 17, 2016
a3ecca1
remove working code
cogmission Jan 17, 2016
edf9065
added test for another branch to dot product
cogmission Jan 17, 2016
0b58b3d
Renamed an ArrayUtil method, added a subtract method to support knn dev
cogmission Jan 18, 2016
4782e40
Added matrix dot with 2d to 1d, added new transpose, removed unused libs
cogmission Jan 18, 2016
2f502d5
Add completed sparsifyVector test
cogmission Jan 18, 2016
de02de1
Added more ArrayUtils tests (setRangeTo()), and finished logic branch…
cogmission Jan 19, 2016
5ac8ec8
Added la4j library
cogmission Jan 19, 2016
7db47f6
Added new linear matrix lib
cogmission Jan 29, 2016
37accba
add changes to .classpath
cogmission Jan 29, 2016
eb080e8
Merge branch 'master' into knn_dev
cogmission Jan 29, 2016
13d82ff
interim merge from ongoing work on master
May 29, 2016
0f74c76
Bring into interim working fashion following update as merge from master
May 30, 2016
8dde067
Update test following merge from master
May 30, 2016
26751a3
Merge remote-tracking branch 'upstream/master' into knn_dev
Jul 13, 2016
b7e858f
Merge remote-tracking branch 'origin/master' into knn_dev
Jul 13, 2016
abd1543
Fixing merge with latest master
Sep 30, 2016
7e374e8
Fix up tests for recent merge
Sep 30, 2016
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
Prev Previous commit
Next Next commit
Added new utility methods: rotateLeft(), rotateRight(), ravel(), unra…
…vel(), reshape() to ArrayUtils
  • Loading branch information
cogmission committed Jan 10, 2016
commit e2d4f2159f24368382dc79aeb652aba33f4d1a19
38 changes: 38 additions & 0 deletions src/main/java/org/numenta/nupic/algorithms/KNNClassifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ public class KNNClassifier {
private int cellsPerCol;




/**
* Privately constructs a {@code KNNClassifier}.
* This method is called by the
Expand All @@ -127,6 +129,42 @@ public static Builder builder() {
return new KNNClassifier.Builder();
}

///////////////////////////////////////////////////////
// Core Methods //
///////////////////////////////////////////////////////
/**
* Train the classifier to associate specified input pattern with a
* particular category.
*
* @param inputPattern The pattern to be assigned a category. If
* isSparse is 0, this should be a dense array (both ON and OFF bits
* present). Otherwise, if isSparse > 0, this should be a list of the
* indices of the non-zero bits in sorted order
*
* @param inputCategory The category to be associated with the training pattern
*
* @param partitionId allows you to associate an id with each
* input vector. It can be used to associate input patterns stored in the
* classifier with an external id. This can be useful for debugging or
* visualizing. Another use case is to ignore vectors with a specific id
* during inference (see description of infer() for details). There can be
* at most one partitionId per stored pattern (i.e. if two patterns are
* within distThreshold, only the first partitionId will be stored). This
* is an optional parameter.
*
* @param sparseSpec If 0, the input pattern is a dense representation. If
* isSparse > 0, the input pattern is a list of non-zero indices and
* isSparse is the length of the dense representation
*
* @return The number of patterns currently stored in the classifier
*/
public int learn(int[] inputPattern, int inputCategory, int partitionId, int sparseSpec) {
return -1;
}

///////////////////////////////////////////////////////
// Accessor Methods //
///////////////////////////////////////////////////////
/**
* Returns the number of nearest neighbors used in the classification of patterns. <b>Must be odd</b>
* @return the k
Expand Down
168 changes: 168 additions & 0 deletions src/main/java/org/numenta/nupic/util/ArrayUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,174 @@ public static int[] initDimensionMultiples(int[] dimensions) {
}
return dimensionMultiples;
}

/**
* Takes a two-dimensional input array and returns a new array which is "rotated"
* a quarter-turn clockwise.
*
* @param array The array to rotate.
* @return The rotated array.
*/
public static int[][] rotateRight(int[][] array) {
int r = array.length;
if (r == 0) {
return new int[0][0]; // Special case: zero-length array
}
int c = array[0].length;
int[][] result = new int[c][r];
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
result[j][r - 1 - i] = array[i][j];
}
}
return result;
}


/**
* Takes a two-dimensional input array and returns a new array which is "rotated"
* a quarter-turn counterclockwise.
*
* @param array The array to rotate.
* @return The rotated array.
*/
public static int[][] rotateLeft(int[][] array) {
int r = array.length;
if (r == 0) {
return new int[0][0]; // Special case: zero-length array
}
int c = array[0].length;
int[][] result = new int[c][r];
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
result[c - 1 - j][i] = array[i][j];
}
}
return result;
}

/**
* Takes a one-dimensional input array of m n numbers and returns a two-dimensional
* array of m rows and n columns. The first n numbers of the given array are copied
* into the first row of the new array, the second n numbers into the second row,
* and so on. This method throws an IllegalArgumentException if the length of the input
* array is not evenly divisible by n.
*
* @param array The values to put into the new array.
* @param n The number of desired columns in the new array.
* @return The new m n array.
* @throws IllegalArgumentException If the length of the given array is not
* a multiple of n.
*/
public static int[][] ravel(int[] array, int n) throws IllegalArgumentException {
if (array.length % n != 0) {
throw new IllegalArgumentException(array.length + " is not evenly divisible by " + n);
}
int length = array.length;
int[][] result = new int[length / n][n];
for (int i = 0; i < length; i++) {
result[i / n][i % n] = array[i];
}
return result;
}

/**
* Takes a m by n two dimensional array and returns a one-dimensional array of size m n
* containing the same numbers. The first n numbers of the new array are copied from the
* first row of the given array, the second n numbers from the second row, and so on.
*
* @param array The array to be unraveled.
* @return The values in the given array.
*/
public static int[] unravel(int[][] array) {
int r = array.length;
if (r == 0) {
return new int[0]; // Special case: zero-length array
}
int c = array[0].length;
int[] result = new int[r * c];
int index = 0;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
result[index] = array[i][j];
index++;
}
}
return result;
}

/**
* Takes a two-dimensional array of r rows and c columns and reshapes it to
* have (r*c)/n by n columns. The value in location [i][j] of the input array
* is copied into location [j][i] of the new array.
*
* @param array The array of values to be reshaped.
* @param n The number of columns in the created array.
* @return The new (r*c)/n by n array.
* @throws IllegalArgumentException If r*c is not evenly divisible by n.
*/
public static int[][] reshape(int[][] array, int n) throws IllegalArgumentException {
int r = array.length;
if (r == 0) {
return new int[0][0]; // Special case: zero-length array
}
if ((array.length * array[0].length) % n != 0) {
int size = array.length * array[0].length;
throw new IllegalArgumentException(size + " is not evenly divisible by " + n);
}
int c = array[0].length;
int[][] result = new int[(r * c) / n][n];
int ii = 0;
int jj = 0;

for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
result[ii][jj] = array[i][j];
jj++;
if (jj == n) {
jj = 0;
ii++;
}
}
}
return result;
}

/**
* Transforms 2D matrix of doubles to 1D by concatenation
* @param A
* @return
*/
public static double[] to1D(double[][] A){

double[] B = new double[A.length * A[0].length];
int index = 0;

for(int i = 0;i<A.length;i++){
for(int j = 0;j<A[0].length;j++){
B[index++] = A[i][j];
}
}
return B;
}

/**
* Transforms 2D matrix of integers to 1D by concatenation
* @param A
* @return
*/
public static int[] to1D(int[][] A){

int[] B = new int[A.length * A[0].length];
int index = 0;

for(int i = 0;i < A.length;i++){
for(int j = 0;j < A[0].length;j++){
B[index++] = A[i][j];
}
}
return B;
}

/**
* Returns a string representing an array of 0's and 1's
Expand Down
132 changes: 126 additions & 6 deletions src/test/java/org/numenta/nupic/util/ArrayUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,138 @@

package org.numenta.nupic.util;

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;

public class ArrayUtilsTest {

@Test
public void testReshape() {
int[][] test = {
{ 0, 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10, 11 }
};

int[][] expected = {
{ 0, 1, 2 },
{ 3, 4, 5 },
{ 6, 7, 8 },
{ 9, 10, 11 }
};

int[][] result = ArrayUtils.reshape(test, 3);
for(int i = 0;i < result.length;i++) {
for(int j = 0;j < result[i].length;j++) {
assertEquals(expected[i][j], result[i][j]);
}
}

// Unhappy case
try {
ArrayUtils.reshape(test, 5);
}catch(Exception e) {
assertTrue(e instanceof IllegalArgumentException);
assertEquals("12 is not evenly divisible by 5", e.getMessage());
}

// Test zero-length case
int[] result4 = ArrayUtils.unravel(new int[0][]);
assertNotNull(result4);
assertTrue(result4.length == 0);
}

@Test
public void testRavelAndUnRavel() {
int[] test = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
int[][] expected = {
{ 0, 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10, 11 }
};

int[][] result = ArrayUtils.ravel(test, 6);
for(int i = 0;i < result.length;i++) {
for(int j = 0;j < result[i].length;j++) {
assertEquals(expected[i][j], result[i][j]);
}
}

int[] result2 = ArrayUtils.unravel(result);
for(int i = 0;i < result2.length;i++) {
assertEquals(test[i], result2[i]);
}

// Unhappy case
try {
ArrayUtils.ravel(test, 5);
}catch(Exception e) {
assertTrue(e instanceof IllegalArgumentException);
assertEquals("12 is not evenly divisible by 5", e.getMessage());
}

// Test zero-length case
int[] result4 = ArrayUtils.unravel(new int[0][]);
assertNotNull(result4);
assertTrue(result4.length == 0);
}

@Test
public void testRotateRight() {
int[][] test = new int[][] {
{ 1, 0, 1, 0 },
{ 1, 0, 1, 0 },
{ 1, 0, 1, 0 },
{ 1, 0, 1, 0 }
};

int[][] expected = new int[][] {
{ 1, 1, 1, 1 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 },
{ 0, 0, 0, 0 }
};

int[][] result = ArrayUtils.rotateRight(test);
for(int i = 0;i < result.length;i++) {
for(int j = 0;j < result[i].length;j++) {
assertEquals(result[i][j], expected[i][j]);
}
}
}

@Test
public void testRotateLeft() {
int[][] test = new int[][] {
{ 1, 0, 1, 0 },
{ 1, 0, 1, 0 },
{ 1, 0, 1, 0 },
{ 1, 0, 1, 0 }
};

int[][] expected = new int[][] {
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 }
};

int[][] result = ArrayUtils.rotateLeft(test);
for(int i = 0;i < result.length;i++) {
for(int j = 0;j < result[i].length;j++) {
assertEquals(result[i][j], expected[i][j]);
}
}
}

@Test
public void testConcat() {
// Test happy path
Expand Down Expand Up @@ -192,16 +310,18 @@ public void testRecursiveCoordinatesAssemble() throws InterruptedException {
int dimSize = 14, dimNumber = 5;
int[] dimCoordinates = new int[dimSize];
List<int[]> dimensions = new ArrayList<int[]>();

for (int i = 0; i < dimNumber; i++) {
for (int j = 0; j < dimSize; j++) {
dimCoordinates[j] = j;
}
dimensions.add(dimCoordinates);
}
long startTime = System.currentTimeMillis();

long startTime = System.currentTimeMillis();
List<int[]> neighborList = ArrayUtils.dimensionsToCoordinateList(dimensions);
long take = System.currentTimeMillis() - startTime;

System.out.print("Execute in:" + take + " milliseconds");

assertEquals(neighborList.size(), 537824);
Expand Down