
org.numenta.nupic.encoders.PassThroughEncoder Maven / Gradle / Ivy
/* ---------------------------------------------------------------------
* 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 gnu.trove.list.array.TDoubleArrayList;
import java.util.*;
import org.numenta.nupic.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.lang.String.*;
/**
* Pass an encoded SDR straight to the model.
* Each encoding is an SDR in which w out of n bits are turned on.
*
* @author wilsondy (from Python original)
*/
public class PassThroughEncoder extends Encoder {
private static final long serialVersionUID = 1L;
protected final Logger LOGGER = LoggerFactory.getLogger(PassThroughEncoder.class);
protected PassThroughEncoder() { }
public PassThroughEncoder(int outputWidth, int outputBitsOnCount) {
super.setW(outputBitsOnCount);
super.setN(outputWidth);
super.setForced(false);
LOGGER.info("Building new PassThroughEncoder instance, outputWidth: {} outputBitsOnCount: {}", outputWidth, outputBitsOnCount);
}
/**
* Returns a builder for building PassThroughEncoders.
* This builder may be reused to produce multiple builders
*
* @return a {@code PassThroughEncoder.Builder}
*/
public static Encoder.Builder> builder() {
return new PassThroughEncoder.Builder();
}
public void init() {
setForced(false);
}
@Override
/**
* Does a bitwise compare of the two bitmaps and returns a fractional
* value between 0 and 1 of how similar they are.
* 1 => identical
* 0 => no overlapping bits
* IGNORES difference in length (only compares bits of shorter list) e..g 11 and 1100101010 are "identical"
* @see org.numenta.nupic.encoders.Encoder#closenessScores(gnu.trove.list.TDoubleList, gnu.trove.list.TDoubleList, boolean)
*/
public gnu.trove.list.TDoubleList closenessScores(gnu.trove.list.TDoubleList expValues, gnu.trove.list.TDoubleList actValues, boolean fractional) {
TDoubleArrayList result = new TDoubleArrayList();
double ratio = 1.0d;
double expectedSum = expValues.sum();
double actualSum = actValues.sum();
if (actualSum > expectedSum) {
double diff = actualSum - expectedSum;
if (diff < expectedSum)
ratio = 1 - diff / expectedSum;
else
ratio = 1 / diff;
}
int[] expectedInts = ArrayUtils.toIntArray(expValues.toArray());
int[] actualInts = ArrayUtils.toIntArray(actValues.toArray());
int[] overlap = ArrayUtils.and(expectedInts, actualInts);
int overlapSum = ArrayUtils.sum(overlap);
double r = 0.0;
if (expectedSum != 0)
r = overlapSum / expectedSum;
r = r * ratio;
if(LOGGER.isTraceEnabled()) {
LOGGER.trace("closenessScores for expValues: {} and actValues: {} is: {}", Arrays.toString(expectedInts), actualInts, r);
}
result.add(r);
return result;
}
@Override
public int getWidth() {
return n;
}
@Override
public boolean isDelta() {
return false;
}
/**
* Check for length the same and copy input into output
* If outputBitsOnCount (w) set, throw error if not true
*
* @param input
* @param output
*/
@Override
public void encodeIntoArray(T t, int[] output) {
int[] input = (int[])t;
if (input.length != output.length)
throw new IllegalArgumentException(format("Different input (%d) and output (%d) sizes", input.length, output.length));
if (ArrayUtils.sum(input) != w)
throw new IllegalArgumentException(format("Input has %d bits but w was set to %d.", ArrayUtils.sum(input), w));
System.arraycopy(input, 0, output, 0, input.length);
if(LOGGER.isTraceEnabled()) {
LOGGER.trace("encodeIntoArray: Input: {} \nOutput: {} ", Arrays.toString(input), Arrays.toString(output));
}
}
/**
* Not much real work to do here as this concept doesn't really apply.
*/
@Override
public Tuple decode(int[] encoded, String parentFieldName) {
//TODO: these methods should be properly implemented (this comment in Python)
String fieldName = this.name;
if (parentFieldName != null && parentFieldName.length() > 0 && LOGGER.isTraceEnabled())
LOGGER.trace("Decoding Field: {}.{}", parentFieldName, this.name);
List ranges = new ArrayList();
ranges.add(new MinMax(0, 0));
RangeList inner = new RangeList(ranges, "input");
Map fieldsDict = new HashMap();
fieldsDict.put(fieldName, inner);
return new DecodeResult(fieldsDict, Arrays.asList(fieldName));
}
@Override
public void setLearning(boolean learningEnabled) {
//NOOP
}
@SuppressWarnings("hiding")
@Override
public List getBucketValues(Class returnType) {
return null;
}
/**
* Returns a {@link Encoder.Builder} for constructing {@link PassThroughEncoder}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.
*/
public static class Builder extends Encoder.Builder> {
private Builder() { }
@SuppressWarnings("unchecked")
@Override
public PassThroughEncoder build() {
//Must be instantiated so that super class can initialize
//boilerplate variables.
encoder = new PassThroughEncoder();
//Call super class here
super.build();
////////////////////////////////////////////////////////
// Implementing classes would do setting of specific //
// vars here together with any sanity checking //
////////////////////////////////////////////////////////
((PassThroughEncoder) encoder).init();
return (PassThroughEncoder) encoder;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy