/* ---------------------------------------------------------------------
* Numenta Platform for Intelligent Computing (NuPIC)
* Copyright (C) 2014, Numenta, Inc. Unless you have an agreement
* with Numenta, Inc., for a separate license for this software code, the
* following terms and conditions apply:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* http://numenta.org/licenses/
* ---------------------------------------------------------------------
*/
package org.numenta.nupic.encoders;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import gnu.trove.list.TDoubleList;
import gnu.trove.list.array.TDoubleArrayList;
import java.util.HashMap;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.numenta.nupic.util.ArrayUtils;
import org.numenta.nupic.util.Tuple;
public class SparsePassThroughEncoderTest {
@SuppressWarnings("unchecked")
@Test
public void testEncodeArray_24outputBits() {
SparsePassThroughEncoder encoder = new SparsePassThroughEncoder(24, 5);
encoder.setName("foo");
//Send bitmap as array of indices
int bitmap[] = {2, 7, 15, 18, 23};
int output[] = new int[24];
encoder.encodeIntoArray(bitmap, output);
assertEquals(bitmap.length, ArrayUtils.sum(output));
Tuple decode = encoder.decode(output, null);
assertTrue(((HashMap<String, RangeList>) decode.get(0)).containsKey(encoder.getName()));
}
@SuppressWarnings("unchecked")
@Test
public void testEncodeArray_12outputBits() {
SparsePassThroughEncoder encoder = new SparsePassThroughEncoder(12, 2);
encoder.setName("foo2");
//Send bitmap as array of indices
int bitmap[] = {0, 11};
int output[] = new int[12];
encoder.encodeIntoArray(bitmap, output);
assertEquals(bitmap.length, ArrayUtils.sum(output));
Tuple decode = encoder.decode(output, null);
assertTrue(((HashMap<String, RangeList>) decode.get(0)).containsKey(encoder.getName()));
}
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void testArrayInvalidWTooBig() {
SparsePassThroughEncoder encoder = new SparsePassThroughEncoder(9, 3);
exception.expect(IllegalArgumentException.class);
encoder.encode(new int[]{2});
encoder = SparsePassThroughEncoder.sparseBuilder()
.n(9)
.w(3)
.name("foo")
.build();
exception.expect(IllegalArgumentException.class);
encoder.encode(new int[]{2});
}
@Test
public void testArrayInvalidWTooSmall() {
SparsePassThroughEncoder encoder = new SparsePassThroughEncoder(9, 3);
exception.expect(IllegalArgumentException.class);
encoder.encode(new int[]{2, 7, 15, 18, 23});
encoder = SparsePassThroughEncoder.sparseBuilder()
.n(9)
.w(3)
.name("foo")
.build();
exception.expect(IllegalArgumentException.class);
encoder.encode(new int[]{2, 7, 15, 18, 23});
}
@Ignore
private void testCloseInner(int[] bitmap1, int outputWidth1, int[] bitmap2, int outputWidth2, double expectedScore) {
SparsePassThroughEncoder encoder1 = new SparsePassThroughEncoder(outputWidth1, ArrayUtils.where(bitmap1, ArrayUtils.GREATER_OR_EQUAL_0).length);
SparsePassThroughEncoder encoder2 = new SparsePassThroughEncoder(outputWidth2, ArrayUtils.where(bitmap2, ArrayUtils.GREATER_OR_EQUAL_0).length);
int[] out1 = encoder1.encode(bitmap1);
int[] out2 = encoder2.encode(bitmap2);
TDoubleList result = encoder1.closenessScores(new TDoubleArrayList(ArrayUtils.toDoubleArray(out1)), new TDoubleArrayList(ArrayUtils.toDoubleArray(out2)), true);
assertTrue(result.size() == 1);
assertEquals(expectedScore, result.get(0), 0.0);
encoder1 = SparsePassThroughEncoder.sparseBuilder()
.n(outputWidth1)
.w(ArrayUtils.where(bitmap1, ArrayUtils.GREATER_OR_EQUAL_0).length)
.build();
encoder2 = SparsePassThroughEncoder.sparseBuilder()
.n(outputWidth2)
.w(ArrayUtils.where(bitmap2, ArrayUtils.GREATER_OR_EQUAL_0).length)
.build();
out1 = encoder1.encode(bitmap1);
out2 = encoder2.encode(bitmap2);
result = encoder1.closenessScores(new TDoubleArrayList(ArrayUtils.toDoubleArray(out1)), new TDoubleArrayList(ArrayUtils.toDoubleArray(out2)), true);
assertTrue(result.size() == 1);
assertEquals(expectedScore, result.get(0), 0.0);
}
@Test
public void testClosenessScores() {
//Identical => 1
testCloseInner(new int[]{2, 7, 15, 18, 23}, 24, new int[]{2, 7, 15, 18, 23}, 24, 1.0);
//No overlap => 0
testCloseInner(new int[]{2, 7, 15, 18, 23}, 24, new int[]{3, 9, 14, 19, 24}, 25, .0);
//Similar => 4 of 5 match
testCloseInner(new int[]{2, 7, 15, 18, 23}, 24, new int[]{2, 7, 17, 18, 23}, 24, .8);
//Little => 1 of 5 match
testCloseInner(new int[]{2, 7, 15, 18, 23}, 24, new int[]{3, 7, 17, 19, 24}, 25, .2);
//Extra active bit => off by 1 of 5
testCloseInner(new int[]{2, 7, 15, 18, 23}, 24, new int[]{2, 7, 11, 15, 18, 23}, 24, .8);
//Missing active bit => off by 1 of 5
testCloseInner(new int[]{2, 7, 15, 18, 23}, 24, new int[]{2, 7, 18, 23}, 24, .8);
}
}