
org.numenta.nupic.encoders.CoordinateEncoder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of htm.java Show documentation
Show all versions of htm.java Show documentation
The Java version of Numenta's HTM technology
/* ---------------------------------------------------------------------
* 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 org.numenta.nupic.util.ArrayUtils;
import org.numenta.nupic.util.MersenneTwister;
import org.numenta.nupic.util.SortablePair;
import org.numenta.nupic.util.Tuple;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CoordinateEncoder extends Encoder implements CoordinateOrder {
private static final long serialVersionUID = 1L;
private static MersenneTwister random = new MersenneTwister();
/**
* Package private to encourage construction using the Builder Pattern
* but still allow inheritance.
*/
CoordinateEncoder() {
/*
*description has a {@link List} of {@link Tuple}s containing
*/
Tuple desc = new Tuple("coordinate", 0);
Tuple desc2 = new Tuple("radius", 1);
description.add(desc);
description.add(desc2);
}
/**
* @see Encoder for more information
*/
@Override
public int getWidth() {
return n;
}
/**
* @see Encoder for more information
*/
@Override
public boolean isDelta() {
return false;
}
/**
* Returns a builder for building ScalarEncoders.
* This builder may be reused to produce multiple builders
*
* @return a {@code CoordinateEncoder.Builder}
*/
public static Encoder.Builder builder() {
return new CoordinateEncoder.Builder();
}
/**
* Returns coordinates around given coordinate, within given radius.
* Includes given coordinate.
*
* @param coordinate Coordinate whose neighbors to find
* @param radius Radius around `coordinate`
* @return
*/
public List neighbors(int[] coordinate, double radius) {
int[][] ranges = new int[coordinate.length][];
for(int i = 0;i < coordinate.length;i++) {
ranges[i] = ArrayUtils.range(coordinate[i] - (int)radius, coordinate[i] + (int)radius + 1);
}
List retVal = new ArrayList();
int len = ranges.length == 1 ? 1 : ranges[0].length;
for(int k = 0;k < ranges[0].length;k++) {
for(int j = 0;j < len;j++) {
int[] entry = new int[ranges.length];
entry[0] = ranges[0][k];
for(int i = 1;i < ranges.length;i++) {
entry[i] = ranges[i][j];
}
retVal.add(entry);
}
}
return retVal;
}
/**
* Returns the top W coordinates by order.
*
* @param co Implementation of {@link CoordinateOrder}
* @param coordinates A 2D array, where each element
is a coordinate
* @param w (int) Number of top coordinates to return
* @return
*/
@SuppressWarnings("unchecked")
public int[][] topWCoordinates(CoordinateOrder co, int[][] coordinates, int w) {
SortablePair[] pairs = new SortablePair[coordinates.length];
for(int i = 0; i < coordinates.length;i++) {
pairs[i] = new SortablePair(co.orderForCoordinate(coordinates[i]), i);
}
Arrays.sort(pairs);
int[][] topCoordinates = new int[w][];
for(int i = 0, wIdx = pairs.length - w; i < w; i++, wIdx++) {
int index = pairs[wIdx].second();
topCoordinates[i] = coordinates[index];
}
return topCoordinates;
}
/**
* Returns the order for a coordinate.
*
* @param coordinate coordinate array
*
* @return A value in the interval [0, 1), representing the
* order of the coordinate
*/
@Override
public double orderForCoordinate(int[] coordinate) {
random.setSeed(coordinate);
return random.nextDouble();
}
/**
* Returns the order for a coordinate.
*
* @param coordinate coordinate array
* @param n the number of available bits in the SDR
*
* @return The index to a bit in the SDR
*/
public static int bitForCoordinate(int[] coordinate, int n) {
random.setSeed(coordinate);
return random.nextInt(n);
}
/**
* {@inheritDoc}
*/
@Override
public void encodeIntoArray(Tuple inputData, int[] output) {
List neighs = neighbors((int[])inputData.get(0), (double)inputData.get(1));
int[][] neighbors = new int[neighs.size()][];
for(int i = 0;i < neighs.size();i++) neighbors[i] = neighs.get(i);
int[][] winners = topWCoordinates(this, neighbors, w);
for(int i = 0;i < winners.length;i++) {
int bit = bitForCoordinate(winners[i], n);
output[bit] = 1;
}
}
@Override
public List getBucketValues(Class returnType) {
return null;
}
/**
* Returns a {@code Builder} for constructing {@link CoordinateEncoder}s
*
* The base class architecture is put together in such a way where boilerplate
* initialization can be kept to a minimum for implementing subclasses, while avoiding
* the mistake-proneness of extremely long argument lists.
*
* @see ScalarEncoder.Builder#setStuff(int)
*/
public static class Builder extends Encoder.Builder {
private Builder() {}
@Override
public CoordinateEncoder build() {
//Must be instantiated so that super class can initialize
//boilerplate variables.
encoder = new CoordinateEncoder();
//Call super class here
super.build();
////////////////////////////////////////////////////////
// Implementing classes would do setting of specific //
// vars here together with any sanity checking //
////////////////////////////////////////////////////////
if(w <= 0 || w % 2 == 0) {
throw new IllegalArgumentException("w must be odd, and must be a positive integer");
}
if(n <= 6 * w) {
throw new IllegalArgumentException(
"n must be an int strictly greater than 6*w. For " +
"good results we recommend n be strictly greater than 11*w");
}
if(name == null || name.equals("None")) {
name = new StringBuilder("[").append(n).append(":").append(w).append("]").toString();
}
return (CoordinateEncoder)encoder;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy