
org.numenta.nupic.model.Connections 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
The newest version!
package org.numenta.nupic.model;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import org.numenta.nupic.Parameters;
import org.numenta.nupic.algorithms.SpatialPooler;
import org.numenta.nupic.algorithms.TemporalMemory;
import org.numenta.nupic.network.Persistence;
import org.numenta.nupic.network.PersistenceAPI;
import org.numenta.nupic.serialize.SerialConfig;
import org.numenta.nupic.util.AbstractSparseBinaryMatrix;
import org.numenta.nupic.util.ArrayUtils;
import org.numenta.nupic.util.FlatMatrix;
import org.numenta.nupic.util.SparseMatrix;
import org.numenta.nupic.util.SparseObjectMatrix;
import org.numenta.nupic.util.Topology;
import org.numenta.nupic.util.UniversalRandom;
import chaschev.lang.Pair;
import gnu.trove.list.array.TIntArrayList;
/**
* Contains the definition of the interconnected structural state of the {@link SpatialPooler} and
* {@link TemporalMemory} as well as the state of all support structures
* (i.e. Cells, Columns, Segments, Synapses etc.).
*
* In the separation of data from logic, this class represents the data/state.
*/
public class Connections implements Persistable {
/** keep it simple */
private static final long serialVersionUID = 1L;
private static final double EPSILON = 0.00001;
/////////////////////////////////////// Spatial Pooler Vars ///////////////////////////////////////////
/** WARNING: potentialRadius **must** be set to
* the inputWidth if using "globalInhibition" and if not
* using the Network API (which sets this automatically)
*/
private int potentialRadius = 16;
private double potentialPct = 0.5;
private boolean globalInhibition = false;
private double localAreaDensity = -1.0;
private double numActiveColumnsPerInhArea;
private double stimulusThreshold = 0;
private double synPermInactiveDec = 0.008;
private double synPermActiveInc = 0.05;
private double synPermConnected = 0.10;
private double synPermBelowStimulusInc = synPermConnected / 10.0;
private double minPctOverlapDutyCycles = 0.001;
private double minPctActiveDutyCycles = 0.001;
private double predictedSegmentDecrement = 0.0;
private int dutyCyclePeriod = 1000;
private double maxBoost = 10.0;
private boolean wrapAround = true;
private int numInputs = 1; //product of input dimensions
private int numColumns = 1; //product of column dimensions
//Extra parameter settings
private double synPermMin = 0.0;
private double synPermMax = 1.0;
private double synPermTrimThreshold = synPermActiveInc / 2.0;
private int updatePeriod = 50;
private double initConnectedPct = 0.5;
//Internal state
private double version = 1.0;
public int spIterationNum = 0;
public int spIterationLearnNum = 0;
public long tmIteration = 0;
public double[] boostedOverlaps;
public int[] overlaps;
/** Manages input neighborhood transformations */
private Topology inputTopology;
/** Manages column neighborhood transformations */
private Topology columnTopology;
/** A matrix representing the shape of the input. */
protected SparseMatrix> inputMatrix;
/**
* Store the set of all inputs that are within each column's potential pool.
* 'potentialPools' is a matrix, whose rows represent cortical columns, and
* whose columns represent the input bits. if potentialPools[i][j] == 1,
* then input bit 'j' is in column 'i's potential pool. A column can only be
* connected to inputs in its potential pool. The indices refer to a
* flattened version of both the inputs and columns. Namely, irrespective
* of the topology of the inputs and columns, they are treated as being a
* one dimensional array. Since a column is typically connected to only a
* subset of the inputs, many of the entries in the matrix are 0. Therefore
* the potentialPool matrix is stored using the SparseObjectMatrix
* class, to reduce memory footprint and computation time of algorithms that
* require iterating over the data structure.
*/
private FlatMatrix potentialPools;
/**
* Initialize a tiny random tie breaker. This is used to determine winning
* columns where the overlaps are identical.
*/
private double[] tieBreaker;
/**
* Stores the number of connected synapses for each column. This is simply
* a sum of each row of 'connectedSynapses'. again, while this
* information is readily available from 'connectedSynapses', it is
* stored separately for efficiency purposes.
*/
private AbstractSparseBinaryMatrix connectedCounts;
/**
* The inhibition radius determines the size of a column's local
* neighborhood. of a column. A cortical column must overcome the overlap
* score of columns in its neighborhood in order to become actives. This
* radius is updated every learning round. It grows and shrinks with the
* average number of connected synapses per column.
*/
private int inhibitionRadius = 0;
private double[] overlapDutyCycles;
private double[] activeDutyCycles;
private volatile double[] minOverlapDutyCycles;
private volatile double[] minActiveDutyCycles;
private double[] boostFactors;
/////////////////////////////////////// Temporal Memory Vars ///////////////////////////////////////////
protected Set activeCells = new LinkedHashSet();
protected Set winnerCells = new LinkedHashSet();
protected Set predictiveCells = new LinkedHashSet<>();
protected List activeSegments = new ArrayList<>();
protected List matchingSegments = new ArrayList<>();
/** Total number of columns */
protected int[] columnDimensions = new int[] { 2048 };
/** Total number of cells per column */
protected int cellsPerColumn = 32;
/** What will comprise the Layer input. Input (i.e. from encoder) */
protected int[] inputDimensions = new int[] { 32, 32 };
/**
* If the number of active connected synapses on a segment
* is at least this threshold, the segment is said to be active.
*/
private int activationThreshold = 13;
/**
* Radius around cell from which it can
* sample to form distal {@link DistalDendrite} connections.
*/
private int learningRadius = 2048;
/**
* If the number of synapses active on a segment is at least this
* threshold, it is selected as the best matching
* cell in a bursting column.
*/
private int minThreshold = 10;
/** The maximum number of synapses added to a segment during learning. */
private int maxNewSynapseCount = 20;
/** The maximum number of segments (distal dendrites) allowed on a cell */
private int maxSegmentsPerCell = 255;
/** The maximum number of synapses allowed on a given segment (distal dendrite) */
private int maxSynapsesPerSegment = 255;
/** Initial permanence of a new synapse */
private double initialPermanence = 0.21;
/**
* If the permanence value for a synapse
* is greater than this value, it is said
* to be connected.
*/
private double connectedPermanence = 0.50;
/**
* Amount by which permanences of synapses
* are incremented during learning.
*/
private double permanenceIncrement = 0.10;
/**
* Amount by which permanences of synapses
* are decremented during learning.
*/
private double permanenceDecrement = 0.10;
/** The main data structure containing columns, cells, and synapses */
private SparseObjectMatrix memory;
private Cell[] cells;
/////////////////////// Structural Elements /////////////////////////
/** Reverse mapping from source cell to {@link Synapse} */
public Map> receptorSynapses;
protected Map> segments;
public Map> distalSynapses;
protected Map> proximalSynapses;
/** Helps index each new proximal Synapse */
protected int proximalSynapseCounter = -1;
/** Global tracker of the next available segment index */
protected int nextFlatIdx;
/** Global counter incremented for each DD segment creation*/
protected int nextSegmentOrdinal;
/** Global counter incremented for each DD synapse creation*/
protected int nextSynapseOrdinal;
/** Total number of synapses */
protected long numSynapses;
/** Used for recycling {@link DistalDendrite} indexes */
protected TIntArrayList freeFlatIdxs = new TIntArrayList();
/** Indexed segments by their global index (can contain nulls) */
protected List segmentForFlatIdx = new ArrayList<>();
/** Stores each cycle's most recent activity */
public Activity lastActivity;
/** The default random number seed */
protected int seed = 42;
/** The random number generator */
public Random random = new UniversalRandom(seed);
/** Sorting Lambda used for sorting active and matching segments */
public Comparator segmentPositionSortKey = (Comparator & Serializable)(s1,s2) -> {
double c1 = s1.getParentCell().getIndex() + ((double)(s1.getOrdinal() / (double)nextSegmentOrdinal));
double c2 = s2.getParentCell().getIndex() + ((double)(s2.getOrdinal() / (double)nextSegmentOrdinal));
return c1 == c2 ? 0 : c1 > c2 ? 1 : -1;
};
/** Sorting Lambda used for SpatialPooler inhibition */
public Comparator> inhibitionComparator = (Comparator> & Serializable)
(p1, p2) -> {
int p1key = p1.getFirst();
int p2key = p2.getFirst();
double p1val = p1.getSecond();
double p2val = p2.getSecond();
if(Math.abs(p2val - p1val) < 0.000000001) {
return Math.abs(p2key - p1key) < 0.000000001 ? 0 : p2key > p1key ? -1 : 1;
} else {
return p2val > p1val ? -1 : 1;
}
};
////////////////////////////////////////
// Connections Constructor //
////////////////////////////////////////
/**
* Constructs a new {@code OldConnections} object. This object
* is usually configured via the {@link Parameters#apply(Object)}
* method.
*/
public Connections() {}
/**
* Returns a deep copy of this {@code Connections} object.
* @return a deep copy of this {@code Connections}
*/
public Connections copy() {
PersistenceAPI api = Persistence.get(new SerialConfig());
byte[] myBytes = api.serializer().serialize(this);
return api.serializer().deSerialize(myBytes);
}
/**
* Sets the derived values of the {@link SpatialPooler}'s initialization.
*/
public void doSpatialPoolerPostInit() {
synPermBelowStimulusInc = synPermConnected / 10.0;
synPermTrimThreshold = synPermActiveInc / 2.0;
if(potentialRadius == -1) {
potentialRadius = ArrayUtils.product(inputDimensions);
}
}
/////////////////////////////////////////
// General Methods //
/////////////////////////////////////////
/**
* Sets the seed used for the internal random number generator.
* If the generator has been instantiated, this method will initialize
* a new random generator with the specified seed.
*
* @param seed
*/
public void setSeed(int seed) {
this.seed = seed;
}
/**
* Returns the configured random number seed
* @return
*/
public int getSeed() {
return seed;
}
/**
* Returns the thread specific {@link Random} number generator.
* @return
*/
public Random getRandom() {
return random;
}
/**
* Sets the random number generator.
* @param random
*/
public void setRandom(Random random){
this.random = random;
}
/**
* Returns the {@link Cell} specified by the index passed in.
* @param index of the specified cell to return.
* @return
*/
public Cell getCell(int index) {
return cells[index];
}
/**
* Returns an array containing all of the {@link Cell}s.
* @return
*/
public Cell[] getCells() {
return cells;
}
/**
* Sets the flat array of cells
* @param cells
*/
public void setCells(Cell[] cells) {
this.cells = cells;
}
/**
* Returns an array containing the {@link Cell}s specified
* by the passed in indexes.
*
* @param cellIndexes indexes of the Cells to return
* @return
*/
public Cell[] getCells(int... cellIndexes) {
Cell[] retVal = new Cell[cellIndexes.length];
for(int i = 0;i < cellIndexes.length;i++) {
retVal[i] = cells[cellIndexes[i]];
}
return retVal;
}
/**
* Returns a {@link LinkedHashSet} containing the {@link Cell}s specified
* by the passed in indexes.
*
* @param cellIndexes indexes of the Cells to return
* @return
*/
public LinkedHashSet getCellSet(int... cellIndexes) {
LinkedHashSet retVal = new LinkedHashSet(cellIndexes.length);
for(int i = 0;i < cellIndexes.length;i++) {
retVal.add(cells[cellIndexes[i]]);
}
return retVal;
}
/**
* Sets the matrix containing the {@link Column}s
* @param mem
*/
public void setMemory(SparseObjectMatrix mem) {
this.memory = mem;
}
/**
* Returns the matrix containing the {@link Column}s
* @return
*/
public SparseObjectMatrix getMemory() {
return memory;
}
/**
* Returns the {@link Topology} overseeing input
* neighborhoods.
* @return
*/
public Topology getInputTopology() {
return inputTopology;
}
/**
* Sets the {@link Topology} overseeing input
* neighborhoods.
*
* @param topology the input Topology
*/
public void setInputTopology(Topology topology) {
this.inputTopology = topology;
}
/**
* Returns the {@link Topology} overseeing {@link Column}
* neighborhoods.
* @return
*/
public Topology getColumnTopology() {
return columnTopology;
}
/**
* Sets the {@link Topology} overseeing {@link Column}
* neighborhoods.
*
* @param topology the column Topology
*/
public void setColumnTopology(Topology topology) {
this.columnTopology = topology;
}
/**
* Returns the input column mapping
*/
public SparseMatrix> getInputMatrix() {
return inputMatrix;
}
/**
* Sets the input column mapping matrix
* @param matrix
*/
public void setInputMatrix(SparseMatrix> matrix) {
this.inputMatrix = matrix;
}
////////////////////////////////////////
// SpatialPooler Methods //
////////////////////////////////////////
/**
* Returns the configured initial connected percent.
* @return
*/
public double getInitConnectedPct() {
return this.initConnectedPct;
}
/**
* Returns the cycle count.
* @return
*/
public int getIterationNum() {
return spIterationNum;
}
/**
* Sets the iteration count.
* @param num
*/
public void setIterationNum(int num) {
this.spIterationNum = num;
}
/**
* Returns the period count which is the number of cycles
* between meta information updates.
* @return
*/
public int getUpdatePeriod() {
return updatePeriod;
}
/**
* Sets the update period
* @param period
*/
public void setUpdatePeriod(int period) {
this.updatePeriod = period;
}
/**
* Returns the inhibition radius
* @return
*/
public int getInhibitionRadius() {
return inhibitionRadius;
}
/**
* Sets the inhibition radius
* @param radius
*/
public void setInhibitionRadius(int radius) {
this.inhibitionRadius = radius;
}
/**
* Returns the product of the input dimensions
* @return the product of the input dimensions
*/
public int getNumInputs() {
return numInputs;
}
/**
* Sets the product of the input dimensions to
* establish a flat count of bits in the input field.
* @param n
*/
public void setNumInputs(int n) {
this.numInputs = n;
}
/**
* Returns the product of the column dimensions
* @return the product of the column dimensions
*/
public int getNumColumns() {
return numColumns;
}
/**
* Sets the product of the column dimensions to be
* the column count.
* @param n
*/
public void setNumColumns(int n) {
this.numColumns = n;
}
/**
* This parameter determines the extent of the input
* that each column can potentially be connected to.
* This can be thought of as the input bits that
* are visible to each column, or a 'receptiveField' of
* the field of vision. A large enough value will result
* in 'global coverage', meaning that each column
* can potentially be connected to every input bit. This
* parameter defines a square (or hyper square) area: a
* column will have a max square potential pool with
* sides of length 2 * potentialRadius + 1.
*
* WARNING: potentialRadius **must** be set to
* the inputWidth if using "globalInhibition" and if not
* using the Network API (which sets this automatically)
*
*
* @param potentialRadius
*/
public void setPotentialRadius(int potentialRadius) {
this.potentialRadius = potentialRadius;
}
/**
* Returns the configured potential radius
*
* @return the configured potential radius
* @see setPotentialRadius
*/
public int getPotentialRadius() {
return potentialRadius;
}
/**
* The percent of the inputs, within a column's
* potential radius, that a column can be connected to.
* If set to 1, the column will be connected to every
* input within its potential radius. This parameter is
* used to give each column a unique potential pool when
* a large potentialRadius causes overlap between the
* columns. At initialization time we choose
* ((2*potentialRadius + 1)^(# inputDimensions) *
* potentialPct) input bits to comprise the column's
* potential pool.
*
* @param potentialPct
*/
public void setPotentialPct(double potentialPct) {
this.potentialPct = potentialPct;
}
/**
* Returns the configured potential pct
*
* @return the configured potential pct
* @see setPotentialPct
*/
public double getPotentialPct() {
return potentialPct;
}
/**
* Sets the {@link SparseObjectMatrix} which represents the
* proximal dendrite permanence values.
*
* @param s the {@link SparseObjectMatrix}
*/
public void setProximalPermanences(SparseObjectMatrix s) {
for(int idx : s.getSparseIndices()) {
memory.getObject(idx).setProximalPermanences(this, s.getObject(idx));
}
}
/**
* Returns the count of {@link Synapse}s on
* {@link ProximalDendrite}s
* @return
*/
public int getProximalSynapseCount() {
return proximalSynapseCounter + 1;
}
/**
* Sets the count of {@link Synapse}s on
* {@link ProximalDendrite}s
* @param i
*/
public void setProximalSynapseCount(int i) {
this.proximalSynapseCounter = i;
}
/**
* Increments and returns the incremented
* proximal {@link Synapse} count.
*
* @return
*/
public int incrementProximalSynapses() {
return ++proximalSynapseCounter;
}
/**
* Decrements and returns the decremented
* proximal {link Synapse} count
* @return
*/
public int decrementProximalSynapses() {
return --proximalSynapseCounter;
}
/**
* Returns the indexed count of connected synapses per column.
* @return
*/
public AbstractSparseBinaryMatrix getConnectedCounts() {
return connectedCounts;
}
/**
* Returns the connected count for the specified column.
* @param columnIndex
* @return
*/
public int getConnectedCount(int columnIndex) {
return connectedCounts.getTrueCount(columnIndex);
}
/**
* Sets the indexed count of synapses connected at the columns in each index.
* @param counts
*/
public void setConnectedCounts(int[] counts) {
for(int i = 0;i < counts.length;i++) {
connectedCounts.setTrueCount(i, counts[i]);
}
}
/**
* Sets the connected count {@link AbstractSparseBinaryMatrix}
* @param columnIndex
* @param count
*/
public void setConnectedMatrix(AbstractSparseBinaryMatrix matrix) {
this.connectedCounts = matrix;
}
/**
* Sets the array holding the random noise added to proximal dendrite overlaps.
*
* @param tieBreaker random values to help break ties
*/
public void setTieBreaker(double[] tieBreaker) {
this.tieBreaker = tieBreaker;
}
/**
* Returns the array holding random values used to add to overlap scores
* to break ties.
*
* @return
*/
public double[] getTieBreaker() {
return tieBreaker;
}
/**
* If true, then during inhibition phase the winning
* columns are selected as the most active columns from
* the region as a whole. Otherwise, the winning columns
* are selected with respect to their local
* neighborhoods. Using global inhibition boosts
* performance x60.
*
* @param globalInhibition
*/
public void setGlobalInhibition(boolean globalInhibition) {
this.globalInhibition = globalInhibition;
}
/**
* Returns the configured global inhibition flag
* @return the configured global inhibition flag
*
* @see setGlobalInhibition
*/
public boolean getGlobalInhibition() {
return globalInhibition;
}
/**
* The desired density of active columns within a local
* inhibition area (the size of which is set by the
* internally calculated inhibitionRadius, which is in
* turn determined from the average size of the
* connected potential pools of all columns). The
* inhibition logic will insure that at most N columns
* remain ON within a local inhibition area, where N =
* localAreaDensity * (total number of columns in
* inhibition area).
*
* @param localAreaDensity
*/
public void setLocalAreaDensity(double localAreaDensity) {
this.localAreaDensity = localAreaDensity;
}
/**
* Returns the configured local area density
* @return the configured local area density
* @see setLocalAreaDensity
*/
public double getLocalAreaDensity() {
return localAreaDensity;
}
/**
* An alternate way to control the density of the active
* columns. If numActivePerInhArea is specified then
* localAreaDensity must be less than 0, and vice versa.
* When using numActivePerInhArea, the inhibition logic
* will insure that at most 'numActivePerInhArea'
* columns remain ON within a local inhibition area (the
* size of which is set by the internally calculated
* inhibitionRadius, which is in turn determined from
* the average size of the connected receptive fields of
* all columns). When using this method, as columns
* learn and grow their effective receptive fields, the
* inhibitionRadius will grow, and hence the net density
* of the active columns will *decrease*. This is in
* contrast to the localAreaDensity method, which keeps
* the density of active columns the same regardless of
* the size of their receptive fields.
*
* @param numActiveColumnsPerInhArea
*/
public void setNumActiveColumnsPerInhArea(double numActiveColumnsPerInhArea) {
this.numActiveColumnsPerInhArea = numActiveColumnsPerInhArea;
}
/**
* Returns the configured number of active columns per
* inhibition area.
* @return the configured number of active columns per
* inhibition area.
* @see setNumActiveColumnsPerInhArea
*/
public double getNumActiveColumnsPerInhArea() {
return numActiveColumnsPerInhArea;
}
/**
* This is a number specifying the minimum number of
* synapses that must be on in order for a columns to
* turn ON. The purpose of this is to prevent noise
* input from activating columns. Specified as a percent
* of a fully grown synapse.
*
* @param stimulusThreshold
*/
public void setStimulusThreshold(double stimulusThreshold) {
this.stimulusThreshold = stimulusThreshold;
}
/**
* Returns the stimulus threshold
* @return the stimulus threshold
* @see setStimulusThreshold
*/
public double getStimulusThreshold() {
return stimulusThreshold;
}
/**
* The amount by which an inactive synapse is
* decremented in each round. Specified as a percent of
* a fully grown synapse.
*
* @param synPermInactiveDec
*/
public void setSynPermInactiveDec(double synPermInactiveDec) {
this.synPermInactiveDec = synPermInactiveDec;
}
/**
* Returns the synaptic permanence inactive decrement.
* @return the synaptic permanence inactive decrement.
* @see setSynPermInactiveDec
*/
public double getSynPermInactiveDec() {
return synPermInactiveDec;
}
/**
* The amount by which an active synapse is incremented
* in each round. Specified as a percent of a
* fully grown synapse.
*
* @param synPermActiveInc
*/
public void setSynPermActiveInc(double synPermActiveInc) {
this.synPermActiveInc = synPermActiveInc;
}
/**
* Returns the configured active permanence increment
* @return the configured active permanence increment
* @see setSynPermActiveInc
*/
public double getSynPermActiveInc() {
return synPermActiveInc;
}
/**
* The default connected threshold. Any synapse whose
* permanence value is above the connected threshold is
* a "connected synapse", meaning it can contribute to
* the cell's firing.
*
* @param synPermConnected
*/
public void setSynPermConnected(double synPermConnected) {
this.synPermConnected = synPermConnected;
}
/**
* Returns the synapse permanence connected threshold
* @return the synapse permanence connected threshold
* @see setSynPermConnected
*/
public double getSynPermConnected() {
return synPermConnected;
}
/**
* Sets the stimulus increment for synapse permanences below
* the measured threshold.
* @param stim
*/
public void setSynPermBelowStimulusInc(double stim) {
this.synPermBelowStimulusInc = stim;
}
/**
* Returns the stimulus increment for synapse permanences below
* the measured threshold.
*
* @return
*/
public double getSynPermBelowStimulusInc() {
return synPermBelowStimulusInc;
}
/**
* A number between 0 and 1.0, used to set a floor on
* how often a column should have at least
* stimulusThreshold active inputs. Periodically, each
* column looks at the overlap duty cycle of
* all other columns within its inhibition radius and
* sets its own internal minimal acceptable duty cycle
* to: minPctDutyCycleBeforeInh * max(other columns'
* duty cycles).
* On each iteration, any column whose overlap duty
* cycle falls below this computed value will get
* all of its permanence values boosted up by
* synPermActiveInc. Raising all permanences in response
* to a sub-par duty cycle before inhibition allows a
* cell to search for new inputs when either its
* previously learned inputs are no longer ever active,
* or when the vast majority of them have been
* "hijacked" by other columns.
*
* @param minPctOverlapDutyCycle
*/
public void setMinPctOverlapDutyCycles(double minPctOverlapDutyCycle) {
this.minPctOverlapDutyCycles = minPctOverlapDutyCycle;
}
/**
* see {@link #setMinPctOverlapDutyCycles(double)}
* @return
*/
public double getMinPctOverlapDutyCycles() {
return minPctOverlapDutyCycles;
}
/**
* A number between 0 and 1.0, used to set a floor on
* how often a column should be activate.
* Periodically, each column looks at the activity duty
* cycle of all other columns within its inhibition
* radius and sets its own internal minimal acceptable
* duty cycle to:
* minPctDutyCycleAfterInh *
* max(other columns' duty cycles).
* On each iteration, any column whose duty cycle after
* inhibition falls below this computed value will get
* its internal boost factor increased.
*
* @param minPctActiveDutyCycle
*/
public void setMinPctActiveDutyCycles(double minPctActiveDutyCycle) {
this.minPctActiveDutyCycles = minPctActiveDutyCycle;
}
/**
* Returns the minPctActiveDutyCycle
* see {@link #setMinPctActiveDutyCycles(double)}
* @return the minPctActiveDutyCycle
*/
public double getMinPctActiveDutyCycles() {
return minPctActiveDutyCycles;
}
/**
* The period used to calculate duty cycles. Higher
* values make it take longer to respond to changes in
* boost or synPerConnectedCell. Shorter values make it
* more unstable and likely to oscillate.
*
* @param dutyCyclePeriod
*/
public void setDutyCyclePeriod(int dutyCyclePeriod) {
this.dutyCyclePeriod = dutyCyclePeriod;
}
/**
* Returns the configured duty cycle period
* see {@link #setDutyCyclePeriod(double)}
* @return the configured duty cycle period
*/
public int getDutyCyclePeriod() {
return dutyCyclePeriod;
}
/**
* The maximum overlap boost factor. Each column's
* overlap gets multiplied by a boost factor
* before it gets considered for inhibition.
* The actual boost factor for a column is number
* between 1.0 and maxBoost. A boost factor of 1.0 is
* used if the duty cycle is >= minOverlapDutyCycle,
* maxBoost is used if the duty cycle is 0, and any duty
* cycle in between is linearly extrapolated from these
* 2 end points.
*
* @param maxBoost
*/
public void setMaxBoost(double maxBoost) {
this.maxBoost = maxBoost;
}
/**
* Returns the max boost
* see {@link #setMaxBoost(double)}
* @return the max boost
*/
public double getMaxBoost() {
return maxBoost;
}
/**
* Specifies whether neighborhoods wider than the
* borders wrap around to the other side.
* @param b
*/
public void setWrapAround(boolean b) {
this.wrapAround = b;
}
/**
* Returns a flag indicating whether neighborhoods
* wider than the borders, wrap around to the other
* side.
* @return
*/
public boolean isWrapAround() {
return wrapAround;
}
/**
* Sets and Returns the boosted overlap score for each column
* @param boostedOverlaps
* @return
*/
public double[] setBoostedOverlaps(double[] boostedOverlaps) {
return this.boostedOverlaps = boostedOverlaps;
}
/**
* Returns the boosted overlap score for each column
* @return the boosted overlaps
*/
public double[] getBoostedOverlaps() {
return boostedOverlaps;
}
/**
* Sets and Returns the overlap score for each column
* @param overlaps
* @return
*/
public int[] setOverlaps(int[] overlaps) {
return this.overlaps = overlaps;
}
/**
* Returns the overlap score for each column
* @return the overlaps
*/
public int[] getOverlaps() {
return overlaps;
}
/**
* Sets the synPermTrimThreshold
* @param threshold
*/
public void setSynPermTrimThreshold(double threshold) {
this.synPermTrimThreshold = threshold;
}
/**
* Returns the synPermTrimThreshold
* @return
*/
public double getSynPermTrimThreshold() {
return synPermTrimThreshold;
}
/**
* Sets the {@link FlatMatrix} which holds the mapping
* of column indexes to their lists of potential inputs.
*
* @param pools {@link FlatMatrix} which holds the pools.
*/
public void setPotentialPools(FlatMatrix pools) {
this.potentialPools = pools;
}
/**
* Returns the {@link FlatMatrix} which holds the mapping
* of column indexes to their lists of potential inputs.
* @return the potential pools
*/
public FlatMatrix getPotentialPools() {
return this.potentialPools;
}
/**
* Returns the minimum {@link Synapse} permanence.
* @return
*/
public double getSynPermMin() {
return synPermMin;
}
/**
* Returns the maximum {@link Synapse} permanence.
* @return
*/
public double getSynPermMax() {
return synPermMax;
}
/**
* Returns the version number
* @return
*/
public double getVersion() {
return version;
}
/**
* Returns the overlap duty cycles.
* @return
*/
public double[] getOverlapDutyCycles() {
return overlapDutyCycles;
}
/**
* Sets the overlap duty cycles
* @param overlapDutyCycles
*/
public void setOverlapDutyCycles(double[] overlapDutyCycles) {
this.overlapDutyCycles = overlapDutyCycles;
}
/**
* Returns the dense (size=numColumns) array of duty cycle stats.
* @return the dense array of active duty cycle values.
*/
public double[] getActiveDutyCycles() {
return activeDutyCycles;
}
/**
* Sets the dense (size=numColumns) array of duty cycle stats.
* @param activeDutyCycles
*/
public void setActiveDutyCycles(double[] activeDutyCycles) {
this.activeDutyCycles = activeDutyCycles;
}
/**
* Applies the dense array values which aren't -1 to the array containing
* the active duty cycles of the column corresponding to the index specified.
* The length of the specified array must be as long as the configured number
* of columns of this {@code OldConnections}' column configuration.
*
* @param denseActiveDutyCycles a dense array containing values to set.
*/
public void updateActiveDutyCycles(double[] denseActiveDutyCycles) {
for(int i = 0;i < denseActiveDutyCycles.length;i++) {
if(denseActiveDutyCycles[i] != -1) {
activeDutyCycles[i] = denseActiveDutyCycles[i];
}
}
}
/**
* Returns the minOverlapDutyCycles.
* @return the minOverlapDutyCycles.
*/
public double[] getMinOverlapDutyCycles() {
return minOverlapDutyCycles;
}
/**
* Sets the minOverlapDutyCycles
* @param minOverlapDutyCycles the minOverlapDutyCycles
*/
public void setMinOverlapDutyCycles(double[] minOverlapDutyCycles) {
this.minOverlapDutyCycles = minOverlapDutyCycles;
}
/**
* Returns the minActiveDutyCycles
* @return the minActiveDutyCycles
*/
public double[] getMinActiveDutyCycles() {
return minActiveDutyCycles;
}
/**
* Sets the minActiveDutyCycles
* @param minActiveDutyCycles the minActiveDutyCycles
*/
public void setMinActiveDutyCycles(double[] minActiveDutyCycles) {
this.minActiveDutyCycles = minActiveDutyCycles;
}
/**
* Returns the array of boost factors
* @return the array of boost factors
*/
public double[] getBoostFactors() {
return boostFactors;
}
/**
* Sets the array of boost factors
* @param boostFactors the array of boost factors
*/
public void setBoostFactors(double[] boostFactors) {
this.boostFactors = boostFactors;
}
////////////////////////////////////////
// TemporalMemory Methods //
////////////////////////////////////////
/**
* Return type from {@link Connections#computeActivity(Set, double, int, double, int, boolean)}
*/
public static class Activity implements Serializable {
/** default serial */
private static final long serialVersionUID = 1L;
public int[] numActiveConnected;
public int[] numActivePotential;
public Activity(int[] numConnected, int[] numPotential) {
this.numActiveConnected = numConnected;
this.numActivePotential = numPotential;
}
}
/**
* Compute each segment's number of active synapses for a given input.
* In the returned lists, a segment's active synapse count is stored at index
* `segment.flatIdx`.
*
* @param activePresynapticCells
* @param connectedPermanence
* @return
*/
public Activity computeActivity(Collection activePresynapticCells, double connectedPermanence) {
int[] numActiveConnectedSynapsesForSegment = new int[nextFlatIdx];
int[] numActivePotentialSynapsesForSegment = new int[nextFlatIdx];
double threshold = connectedPermanence - EPSILON;
for(Cell cell : activePresynapticCells) {
for(Synapse synapse : getReceptorSynapses(cell)) {
int flatIdx = synapse.getSegment().getIndex();
++numActivePotentialSynapsesForSegment[flatIdx];
if(synapse.getPermanence() > threshold) {
++numActiveConnectedSynapsesForSegment[flatIdx];
}
}
}
return lastActivity = new Activity(
numActiveConnectedSynapsesForSegment,
numActivePotentialSynapsesForSegment);
}
/**
* Returns the last {@link Activity} computed during the most
* recently executed cycle.
*
* @return the last activity to be computed.
*/
public Activity getLastActivity() {
return lastActivity;
}
/**
* Record the fact that a segment had some activity. This information is
* used during segment cleanup.
*
* @param segment the segment for which to record activity
*/
public void recordSegmentActivity(DistalDendrite segment) {
segment.setLastUsedIteration(tmIteration);
}
/**
* Mark the passage of time. This information is used during segment
* cleanup.
*/
public void startNewIteration() {
++tmIteration;
}
/////////////////////////////////////////////////////////////////
// Segment (Specifically, Distal Dendrite) Operations //
/////////////////////////////////////////////////////////////////
/**
* Adds a new {@link DistalDendrite} segment on the specified {@link Cell},
* or reuses an existing one.
*
* @param cell the Cell to which a segment is added.
* @return the newly created segment or a reused segment
*/
public DistalDendrite createSegment(Cell cell) {
while(numSegments(cell) >= maxSegmentsPerCell) {
destroySegment(leastRecentlyUsedSegment(cell));
}
int flatIdx;
int len;
if((len = freeFlatIdxs.size()) > 0) {
flatIdx = freeFlatIdxs.get(len - 1);
freeFlatIdxs.remove(len - 1, 1);
}else{
flatIdx = nextFlatIdx;
segmentForFlatIdx.add(null);
++nextFlatIdx;
}
int ordinal = nextSegmentOrdinal;
++nextSegmentOrdinal;
DistalDendrite segment = new DistalDendrite(cell, flatIdx, tmIteration, ordinal);
getSegments(cell, true).add(segment);
segmentForFlatIdx.set(flatIdx, segment);
return segment;
}
/**
* Destroys a segment ({@link DistalDendrite})
* @param segment the segment to destroy
*/
public void destroySegment(DistalDendrite segment) {
// Remove the synapses from all data structures outside this Segment.
List synapses = getSynapses(segment);
int len = synapses.size();
getSynapses(segment).stream().forEach(s -> removeSynapseFromPresynapticMap(s));
numSynapses -= len;
// Remove the segment from the cell's list.
getSegments(segment.getParentCell()).remove(segment);
// Remove the segment from the map
distalSynapses.remove(segment);
// Free the flatIdx and remove the final reference so the Segment can be
// garbage-collected.
freeFlatIdxs.add(segment.getIndex());
segmentForFlatIdx.set(segment.getIndex(), null);
}
/**
* Used internally to return the least recently activated segment on
* the specified cell
*
* @param cell cell to search for segments on
* @return the least recently activated segment on
* the specified cell
*/
private DistalDendrite leastRecentlyUsedSegment(Cell cell) {
List segments = getSegments(cell, false);
DistalDendrite minSegment = null;
long minIteration = Long.MAX_VALUE;
for(DistalDendrite dd : segments) {
if(dd.lastUsedIteration() < minIteration) {
minSegment = dd;
minIteration = dd.lastUsedIteration();
}
}
return minSegment;
}
/**
* Returns the total number of {@link DistalDendrite}s
*
* @return the total number of segments
*/
public int numSegments() {
return numSegments(null);
}
/**
* Returns the number of {@link DistalDendrite}s on a given {@link Cell}
* if specified, or the total number if the "optionalCellArg" is null.
*
* @param optionalCellArg an optional Cell to specify the context of the segment count.
* @return either the total number of segments or the number on a specified cell.
*/
public int numSegments(Cell optionalCellArg) {
if(optionalCellArg != null) {
return getSegments(optionalCellArg).size();
}
return nextFlatIdx - freeFlatIdxs.size();
}
/**
* Returns the mapping of {@link Cell}s to their {@link DistalDendrite}s.
*
* @param cell the {@link Cell} used as a key.
* @return the mapping of {@link Cell}s to their {@link DistalDendrite}s.
*/
public List getSegments(Cell cell) {
return getSegments(cell, false);
}
/**
* Returns the mapping of {@link Cell}s to their {@link DistalDendrite}s.
*
* @param cell the {@link Cell} used as a key.
* @param doLazyCreate create a container for future use if true, if false
* return an orphaned empty set.
* @return the mapping of {@link Cell}s to their {@link DistalDendrite}s.
*/
public List getSegments(Cell cell, boolean doLazyCreate) {
if(cell == null) {
throw new IllegalArgumentException("Cell was null");
}
if(segments == null) {
segments = new LinkedHashMap>();
}
List retVal = null;
if((retVal = segments.get(cell)) == null) {
if(!doLazyCreate) return Collections.emptyList();
segments.put(cell, retVal = new ArrayList());
}
return retVal;
}
/**
* Get the segment with the specified flatIdx.
* @param index The segment's flattened list index.
* @return the {@link DistalDendrite} who's index matches.
*/
public DistalDendrite segmentForFlatIdx(int index) {
return segmentForFlatIdx.get(index);
}
/**
* Returns the index of the {@link Column} owning the cell which owns
* the specified segment.
* @param segment the {@link DistalDendrite} of the cell whose column index is desired.
* @return the owning column's index
*/
public int columnIndexForSegment(DistalDendrite segment) {
return segment.getParentCell().getIndex() / cellsPerColumn;
}
/**
* FOR TEST USE ONLY
* @return
*/
public Map> getSegmentMapping() {
return new LinkedHashMap<>(segments);
}
/**
* Set by the {@link TemporalMemory} following a compute cycle.
* @param l
*/
public void setActiveSegments(List l) {
this.activeSegments = l;
}
/**
* Retrieved by the {@link TemporalMemorty} prior to a compute cycle.
* @return
*/
public List getActiveSegments() {
return activeSegments;
}
/**
* Set by the {@link TemporalMemory} following a compute cycle.
* @param l
*/
public void setMatchingSegments(List l) {
this.matchingSegments = l;
}
/**
* Retrieved by the {@link TemporalMemorty} prior to a compute cycle.
* @return
*/
public List getMatchingSegments() {
return matchingSegments;
}
/////////////////////////////////////////////////////////////////
// Synapse Operations //
/////////////////////////////////////////////////////////////////
/**
* Creates a new synapse on a segment.
*
* @param segment the {@link DistalDendrite} segment to which a {@link Synapse} is
* being created
* @param presynapticCell the source {@link Cell}
* @param permanence the initial permanence
* @return the created {@link Synapse}
*/
public Synapse createSynapse(DistalDendrite segment, Cell presynapticCell, double permanence) {
while(numSynapses(segment) >= maxSynapsesPerSegment) {
destroySynapse(minPermanenceSynapse(segment));
}
Synapse synapse = null;
getSynapses(segment).add(
synapse = new Synapse(
presynapticCell, segment, nextSynapseOrdinal, permanence));
getReceptorSynapses(presynapticCell, true).add(synapse);
++nextSynapseOrdinal;
++numSynapses;
return synapse;
}
/**
* Destroys the specified {@link Synapse}
* @param synapse the Synapse to destroy
*/
public void destroySynapse(Synapse synapse) {
--numSynapses;
removeSynapseFromPresynapticMap(synapse);
getSynapses((DistalDendrite)synapse.getSegment()).remove(synapse);
}
/**
* Removes the specified {@link Synapse} from its
* pre-synaptic {@link Cell}'s map of synapses it
* activates.
*
* @param synapse the synapse to remove
*/
public void removeSynapseFromPresynapticMap(Synapse synapse) {
Set presynapticSynapses;
Cell cell = synapse.getPresynapticCell();
(presynapticSynapses = getReceptorSynapses(cell, false)).remove(synapse);
if(presynapticSynapses.isEmpty()) {
receptorSynapses.remove(cell);
}
}
/**
* Used internally to find the synapse with the smallest permanence
* on the given segment.
*
* @param dd Segment object to search for synapses on
* @return Synapse object on the segment with the minimal permanence
*/
private Synapse minPermanenceSynapse(DistalDendrite dd) {
List synapses = getSynapses(dd).stream().sorted().collect(Collectors.toList());
Synapse min = null;
double minPermanence = Double.MAX_VALUE;
for(Synapse synapse : synapses) {
if(!synapse.destroyed() && synapse.getPermanence() < minPermanence - EPSILON) {
min = synapse;
minPermanence = synapse.getPermanence();
}
}
return min;
}
/**
* Returns the total number of {@link Synapse}s
*
* @return either the total number of synapses
*/
public long numSynapses() {
return numSynapses(null);
}
/**
* Returns the number of {@link Synapse}s on a given {@link DistalDendrite}
* if specified, or the total number if the "optionalSegmentArg" is null.
*
* @param optionalSegmentArg an optional Segment to specify the context of the synapse count.
* @return either the total number of synapses or the number on a specified segment.
*/
public long numSynapses(DistalDendrite optionalSegmentArg) {
if(optionalSegmentArg != null) {
return getSynapses(optionalSegmentArg).size();
}
return numSynapses;
}
/**
* Returns the mapping of {@link Cell}s to their reverse mapped
* {@link Synapse}s.
*
* @param cell the {@link Cell} used as a key.
* @return the mapping of {@link Cell}s to their reverse mapped
* {@link Synapse}s.
*/
public Set getReceptorSynapses(Cell cell) {
return getReceptorSynapses(cell, false);
}
/**
* Returns the mapping of {@link Cell}s to their reverse mapped
* {@link Synapse}s.
*
* @param cell the {@link Cell} used as a key.
* @param doLazyCreate create a container for future use if true, if false
* return an orphaned empty set.
* @return the mapping of {@link Cell}s to their reverse mapped
* {@link Synapse}s.
*/
public Set getReceptorSynapses(Cell cell, boolean doLazyCreate) {
if(cell == null) {
throw new IllegalArgumentException("Cell was null");
}
if(receptorSynapses == null) {
receptorSynapses = new LinkedHashMap<>();
}
LinkedHashSet retVal = null;
if((retVal = receptorSynapses.get(cell)) == null) {
if(!doLazyCreate) return Collections.emptySet();
receptorSynapses.put(cell, retVal = new LinkedHashSet<>());
}
return retVal;
}
/**
* Returns the mapping of {@link DistalDendrite}s to their {@link Synapse}s.
*
* @param segment the {@link DistalDendrite} used as a key.
* @return the mapping of {@link DistalDendrite}s to their {@link Synapse}s.
*/
public List getSynapses(DistalDendrite segment) {
if(segment == null) {
throw new IllegalArgumentException("Segment was null");
}
if(distalSynapses == null) {
distalSynapses = new LinkedHashMap>();
}
List retVal = null;
if((retVal = distalSynapses.get(segment)) == null) {
distalSynapses.put(segment, retVal = new ArrayList());
}
return retVal;
}
/**
* Returns the mapping of {@link ProximalDendrite}s to their {@link Synapse}s.
*
* @param segment the {@link ProximalDendrite} used as a key.
* @return the mapping of {@link ProximalDendrite}s to their {@link Synapse}s.
*/
public List getSynapses(ProximalDendrite segment) {
if(segment == null) {
throw new IllegalArgumentException("Segment was null");
}
if(proximalSynapses == null) {
proximalSynapses = new LinkedHashMap>();
}
List retVal = null;
if((retVal = proximalSynapses.get(segment)) == null) {
proximalSynapses.put(segment, retVal = new ArrayList());
}
return retVal;
}
/**
* FOR TEST USE ONLY
* @return
*/
public Map> getReceptorSynapseMapping() {
return new LinkedHashMap<>(receptorSynapses);
}
/**
* Clears all {@link TemporalMemory} state.
*/
public void clear() {
activeCells.clear();
winnerCells.clear();
predictiveCells.clear();
}
/**
* Returns the current {@link Set} of active {@link Cell}s
*
* @return the current {@link Set} of active {@link Cell}s
*/
public Set getActiveCells() {
return activeCells;
}
/**
* Sets the current {@link Set} of active {@link Cell}s
* @param cells
*/
public void setActiveCells(Set cells) {
this.activeCells = cells;
}
/**
* Returns the current {@link Set} of winner cells
*
* @return the current {@link Set} of winner cells
*/
public Set getWinnerCells() {
return winnerCells;
}
/**
* Sets the current {@link Set} of winner {@link Cell}s
* @param cells
*/
public void setWinnerCells(Set cells) {
this.winnerCells = cells;
}
/**
* Returns the {@link Set} of predictive cells.
* @return
*/
public Set getPredictiveCells() {
if(predictiveCells.isEmpty()) {
Cell previousCell = null;
Cell currCell = null;
List temp = new ArrayList<>(activeSegments);
for(DistalDendrite activeSegment : temp) {
if((currCell = activeSegment.getParentCell()) != previousCell) {
predictiveCells.add(previousCell = currCell);
}
}
}
return predictiveCells;
}
/**
* Clears the previous predictive cells from the list.
*/
public void clearPredictiveCells() {
this.predictiveCells.clear();
}
/**
* Returns the column at the specified index.
* @param index
* @return
*/
public Column getColumn(int index) {
return memory.getObject(index);
}
/**
* Sets the number of {@link Column}.
*
* @param columnDimensions
*/
public void setColumnDimensions(int[] columnDimensions) {
this.columnDimensions = columnDimensions;
}
/**
* Gets the number of {@link Column}.
*
* @return columnDimensions
*/
public int[] getColumnDimensions() {
return this.columnDimensions;
}
/**
* A list representing the dimensions of the input
* vector. Format is [height, width, depth, ...], where
* each value represents the size of the dimension. For a
* topology of one dimension with 100 inputs use 100, or
* [100]. For a two dimensional topology of 10x5 use
* [10,5].
*
* @param inputDimensions
*/
public void setInputDimensions(int[] inputDimensions) {
this.inputDimensions = inputDimensions;
}
/**
* Returns the configured input dimensions
* see {@link #setInputDimensions(int[])}
* @return the configured input dimensions
*/
public int[] getInputDimensions() {
return inputDimensions;
}
/**
* Sets the number of {@link Cell}s per {@link Column}
* @param cellsPerColumn
*/
public void setCellsPerColumn(int cellsPerColumn) {
this.cellsPerColumn = cellsPerColumn;
}
/**
* Gets the number of {@link Cell}s per {@link Column}.
*
* @return cellsPerColumn
*/
public int getCellsPerColumn() {
return this.cellsPerColumn;
}
/**
* Sets the activation threshold.
*
* If the number of active connected synapses on a segment
* is at least this threshold, the segment is said to be active.
*
* @param activationThreshold
*/
public void setActivationThreshold(int activationThreshold) {
this.activationThreshold = activationThreshold;
}
/**
* Returns the activation threshold.
* @return
*/
public int getActivationThreshold() {
return activationThreshold;
}
/**
* Radius around cell from which it can
* sample to form distal dendrite connections.
*
* @param learningRadius
*/
public void setLearningRadius(int learningRadius) {
this.learningRadius = learningRadius;
}
/**
* Returns the learning radius.
* @return
*/
public int getLearningRadius() {
return learningRadius;
}
/**
* If the number of synapses active on a segment is at least this
* threshold, it is selected as the best matching
* cell in a bursting column.
*
* @param minThreshold
*/
public void setMinThreshold(int minThreshold) {
this.minThreshold = minThreshold;
}
/**
* Returns the minimum threshold of active synapses to be picked as best.
* @return
*/
public int getMinThreshold() {
return minThreshold;
}
/**
* The maximum number of synapses added to a segment during learning.
*
* @param maxNewSynapseCount
*/
public void setMaxNewSynapseCount(int maxNewSynapseCount) {
this.maxNewSynapseCount = maxNewSynapseCount;
}
/**
* Returns the maximum number of synapses added to a segment during
* learning.
*
* @return
*/
public int getMaxNewSynapseCount() {
return maxNewSynapseCount;
}
/**
* The maximum number of segments allowed on a given cell
* @param maxSegmentsPerCell
*/
public void setMaxSegmentsPerCell(int maxSegmentsPerCell) {
this.maxSegmentsPerCell = maxSegmentsPerCell;
}
/**
* Returns the maximum number of segments allowed on a given cell
* @return
*/
public int getMaxSegmentsPerCell() {
return maxSegmentsPerCell;
}
/**
* The maximum number of synapses allowed on a given segment
* @param maxSynapsesPerSegment
*/
public void setMaxSynapsesPerSegment(int maxSynapsesPerSegment) {
this.maxSynapsesPerSegment = maxSynapsesPerSegment;
}
/**
* Returns the maximum number of synapses allowed per segment
* @return
*/
public int getMaxSynapsesPerSegment() {
return maxSynapsesPerSegment;
}
/**
* Initial permanence of a new synapse
*
* @param initialPermanence
*/
public void setInitialPermanence(double initialPermanence) {
this.initialPermanence = initialPermanence;
}
/**
* Returns the initial permanence setting.
* @return
*/
public double getInitialPermanence() {
return initialPermanence;
}
/**
* If the permanence value for a synapse
* is greater than this value, it is said
* to be connected.
*
* @param connectedPermanence
*/
public void setConnectedPermanence(double connectedPermanence) {
this.connectedPermanence = connectedPermanence;
}
/**
* If the permanence value for a synapse
* is greater than this value, it is said
* to be connected.
*
* @return
*/
public double getConnectedPermanence() {
return connectedPermanence;
}
/**
* Amount by which permanences of synapses
* are incremented during learning.
*
* @param permanenceIncrement
*/
public void setPermanenceIncrement(double permanenceIncrement) {
this.permanenceIncrement = permanenceIncrement;
}
/**
* Amount by which permanences of synapses
* are incremented during learning.
*/
public double getPermanenceIncrement() {
return this.permanenceIncrement;
}
/**
* Amount by which permanences of synapses
* are decremented during learning.
*
* @param permanenceDecrement
*/
public void setPermanenceDecrement(double permanenceDecrement) {
this.permanenceDecrement = permanenceDecrement;
}
/**
* Amount by which permanences of synapses
* are decremented during learning.
*/
public double getPermanenceDecrement() {
return this.permanenceDecrement;
}
/**
* Amount by which active permanences of synapses of previously predicted but inactive segments are decremented.
* @param predictedSegmentDecrement
*/
public void setPredictedSegmentDecrement(double predictedSegmentDecrement) {
this.predictedSegmentDecrement = predictedSegmentDecrement;
}
/**
* Returns the predictedSegmentDecrement amount.
* @return
*/
public double getPredictedSegmentDecrement() {
return this.predictedSegmentDecrement;
}
/**
* Converts a {@link Collection} of {@link Cell}s to a list
* of cell indexes.
*
* @param cells
* @return
*/
public static List asCellIndexes(Collection cells) {
List ints = new ArrayList();
for(Cell cell : cells) {
ints.add(cell.getIndex());
}
return ints;
}
/**
* Converts a {@link Collection} of {@link Column}s to a list
* of column indexes.
*
* @param columns
* @return
*/
public static List asColumnIndexes(Collection columns) {
List ints = new ArrayList();
for(Column col : columns) {
ints.add(col.getIndex());
}
return ints;
}
/**
* Returns a list of the {@link Cell}s specified.
* @param cells the indexes of the {@link Cell}s to return
* @return the specified list of cells
*/
public List asCellObjects(Collection cells) {
List objs = new ArrayList();
for(int i : cells) {
objs.add(this.cells[i]);
}
return objs;
}
/**
* Returns a list of the {@link Column}s specified.
* @param cols the indexes of the {@link Column}s to return
* @return the specified list of columns
*/
public List asColumnObjects(Collection cols) {
List objs = new ArrayList();
for(int i : cols) {
objs.add(this.memory.getObject(i));
}
return objs;
}
/**
* Returns a {@link Set} view of the {@link Column}s specified by
* the indexes passed in.
*
* @param indexes the indexes of the Columns to return
* @return a set view of the specified columns
*/
public LinkedHashSet getColumnSet(int[] indexes) {
LinkedHashSet retVal = new LinkedHashSet();
for(int i = 0;i < indexes.length;i++) {
retVal.add(memory.getObject(indexes[i]));
}
return retVal;
}
/**
* Returns a {@link List} view of the {@link Column}s specified by
* the indexes passed in.
*
* @param indexes the indexes of the Columns to return
* @return a List view of the specified columns
*/
public List getColumnList(int[] indexes) {
List retVal = new ArrayList();
for(int i = 0;i < indexes.length;i++) {
retVal.add(memory.getObject(indexes[i]));
}
return retVal;
}
/**
* High verbose output useful for debugging
*/
public void printParameters() {
System.out.println("------------ SpatialPooler Parameters ------------------");
System.out.println("numInputs = " + getNumInputs());
System.out.println("numColumns = " + getNumColumns());
System.out.println("cellsPerColumn = " + getCellsPerColumn());
System.out.println("columnDimensions = " + Arrays.toString(getColumnDimensions()));
System.out.println("numActiveColumnsPerInhArea = " + getNumActiveColumnsPerInhArea());
System.out.println("potentialPct = " + getPotentialPct());
System.out.println("potentialRadius = " + getPotentialRadius());
System.out.println("globalInhibition = " + getGlobalInhibition());
System.out.println("localAreaDensity = " + getLocalAreaDensity());
System.out.println("inhibitionRadius = " + getInhibitionRadius());
System.out.println("stimulusThreshold = " + getStimulusThreshold());
System.out.println("synPermActiveInc = " + getSynPermActiveInc());
System.out.println("synPermInactiveDec = " + getSynPermInactiveDec());
System.out.println("synPermConnected = " + getSynPermConnected());
System.out.println("minPctOverlapDutyCycle = " + getMinPctOverlapDutyCycles());
System.out.println("minPctActiveDutyCycle = " + getMinPctActiveDutyCycles());
System.out.println("dutyCyclePeriod = " + getDutyCyclePeriod());
System.out.println("maxBoost = " + getMaxBoost());
System.out.println("version = " + getVersion());
System.out.println("\n------------ TemporalMemory Parameters ------------------");
System.out.println("activationThreshold = " + getActivationThreshold());
System.out.println("learningRadius = " + getLearningRadius());
System.out.println("minThreshold = " + getMinThreshold());
System.out.println("maxNewSynapseCount = " + getMaxNewSynapseCount());
System.out.println("maxSynapsesPerSegment = " + getMaxSynapsesPerSegment());
System.out.println("maxSegmentsPerCell = " + getMaxSegmentsPerCell());
System.out.println("initialPermanence = " + getInitialPermanence());
System.out.println("connectedPermanence = " + getConnectedPermanence());
System.out.println("permanenceIncrement = " + getPermanenceIncrement());
System.out.println("permanenceDecrement = " + getPermanenceDecrement());
System.out.println("predictedSegmentDecrement = " + getPredictedSegmentDecrement());
}
/**
* High verbose output useful for debugging
*/
public String getPrintString() {
StringWriter sw;
PrintWriter pw = new PrintWriter(sw = new StringWriter());
pw.println("---------------------- General -------------------------");
pw.println("columnDimensions = " + Arrays.toString(getColumnDimensions()));
pw.println("inputDimensions = " + Arrays.toString(getInputDimensions()));
pw.println("cellsPerColumn = " + getCellsPerColumn());
pw.println("random = " + getRandom());
pw.println("seed = " + getSeed());
pw.println("\n------------ SpatialPooler Parameters ------------------");
pw.println("numInputs = " + getNumInputs());
pw.println("numColumns = " + getNumColumns());
pw.println("numActiveColumnsPerInhArea = " + getNumActiveColumnsPerInhArea());
pw.println("potentialPct = " + getPotentialPct());
pw.println("potentialRadius = " + getPotentialRadius());
pw.println("globalInhibition = " + getGlobalInhibition());
pw.println("localAreaDensity = " + getLocalAreaDensity());
pw.println("inhibitionRadius = " + getInhibitionRadius());
pw.println("stimulusThreshold = " + getStimulusThreshold());
pw.println("synPermActiveInc = " + getSynPermActiveInc());
pw.println("synPermInactiveDec = " + getSynPermInactiveDec());
pw.println("synPermConnected = " + getSynPermConnected());
pw.println("synPermBelowStimulusInc = " + getSynPermBelowStimulusInc());
pw.println("synPermTrimThreshold = " + getSynPermTrimThreshold());
pw.println("minPctOverlapDutyCycles = " + getMinPctOverlapDutyCycles());
pw.println("minPctActiveDutyCycles = " + getMinPctActiveDutyCycles());
pw.println("dutyCyclePeriod = " + getDutyCyclePeriod());
pw.println("wrapAround = " + isWrapAround());
pw.println("maxBoost = " + getMaxBoost());
pw.println("version = " + getVersion());
pw.println("\n------------ TemporalMemory Parameters ------------------");
pw.println("activationThreshold = " + getActivationThreshold());
pw.println("learningRadius = " + getLearningRadius());
pw.println("minThreshold = " + getMinThreshold());
pw.println("maxNewSynapseCount = " + getMaxNewSynapseCount());
pw.println("maxSynapsesPerSegment = " + getMaxSynapsesPerSegment());
pw.println("maxSegmentsPerCell = " + getMaxSegmentsPerCell());
pw.println("initialPermanence = " + getInitialPermanence());
pw.println("connectedPermanence = " + getConnectedPermanence());
pw.println("permanenceIncrement = " + getPermanenceIncrement());
pw.println("permanenceDecrement = " + getPermanenceDecrement());
pw.println("predictedSegmentDecrement = " + getPredictedSegmentDecrement());
return sw.toString();
}
/**
* Returns a 2 Dimensional array of 1's and 0's indicating
* which of the column's pool members are above the connected
* threshold, and therefore considered "connected"
* @return
*/
public int[][] getConnecteds() {
int[][] retVal = new int[getNumColumns()][];
for(int i = 0;i < getNumColumns();i++) {
Pool pool = getPotentialPools().get(i);
int[] indexes = pool.getDenseConnected(this);
retVal[i] = indexes;
}
return retVal;
}
/**
* Returns a 2 Dimensional array of 1's and 0's indicating
* which input bits belong to which column's pool.
* @return
*/
public int[][] getPotentials() {
int[][] retVal = new int[getNumColumns()][];
for(int i = 0;i < getNumColumns();i++) {
Pool pool = getPotentialPools().get(i);
int[] indexes = pool.getDensePotential(this);
retVal[i] = indexes;
}
return retVal;
}
/**
* Returns a 2 Dimensional array of the permanences for SP
* proximal dendrite column pooled connections.
* @return
*/
public double[][] getPermanences() {
double[][] retVal = new double[getNumColumns()][];
for(int i = 0;i < getNumColumns();i++) {
Pool pool = getPotentialPools().get(i);
double[] perm = pool.getDensePermanences(this);
retVal[i] = perm;
}
return retVal;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + activationThreshold;
result = prime * result + ((activeCells == null) ? 0 : activeCells.hashCode());
result = prime * result + Arrays.hashCode(activeDutyCycles);
result = prime * result + Arrays.hashCode(boostFactors);
result = prime * result + Arrays.hashCode(cells);
result = prime * result + cellsPerColumn;
result = prime * result + Arrays.hashCode(columnDimensions);
result = prime * result + ((connectedCounts == null) ? 0 : connectedCounts.hashCode());
long temp;
temp = Double.doubleToLongBits(connectedPermanence);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + dutyCyclePeriod;
result = prime * result + (globalInhibition ? 1231 : 1237);
result = prime * result + inhibitionRadius;
temp = Double.doubleToLongBits(initConnectedPct);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(initialPermanence);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + Arrays.hashCode(inputDimensions);
result = prime * result + ((inputMatrix == null) ? 0 : inputMatrix.hashCode());
result = prime * result + spIterationLearnNum;
result = prime * result + spIterationNum;
result = prime * result + (new Long(tmIteration)).intValue();
result = prime * result + learningRadius;
temp = Double.doubleToLongBits(localAreaDensity);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(maxBoost);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + maxNewSynapseCount;
result = prime * result + ((memory == null) ? 0 : memory.hashCode());
result = prime * result + Arrays.hashCode(minActiveDutyCycles);
result = prime * result + Arrays.hashCode(minOverlapDutyCycles);
temp = Double.doubleToLongBits(minPctActiveDutyCycles);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(minPctOverlapDutyCycles);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + minThreshold;
temp = Double.doubleToLongBits(numActiveColumnsPerInhArea);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + numColumns;
result = prime * result + numInputs;
temp = numSynapses;
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + Arrays.hashCode(overlapDutyCycles);
temp = Double.doubleToLongBits(permanenceDecrement);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(permanenceIncrement);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(potentialPct);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + ((potentialPools == null) ? 0 : potentialPools.hashCode());
result = prime * result + potentialRadius;
temp = Double.doubleToLongBits(predictedSegmentDecrement);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + ((predictiveCells == null) ? 0 : predictiveCells.hashCode());
result = prime * result + ((random == null) ? 0 : random.hashCode());
result = prime * result + ((receptorSynapses == null) ? 0 : receptorSynapses.hashCode());
result = prime * result + seed;
result = prime * result + ((segments == null) ? 0 : segments.hashCode());
temp = Double.doubleToLongBits(stimulusThreshold);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(synPermActiveInc);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(synPermBelowStimulusInc);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(synPermConnected);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(synPermInactiveDec);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(synPermMax);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(synPermMin);
result = prime * result + (int)(temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(synPermTrimThreshold);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + proximalSynapseCounter;
result = prime * result + ((proximalSynapses == null) ? 0 : proximalSynapses.hashCode());
result = prime * result + ((distalSynapses == null) ? 0 : distalSynapses.hashCode());
result = prime * result + Arrays.hashCode(tieBreaker);
result = prime * result + updatePeriod;
temp = Double.doubleToLongBits(version);
result = prime * result + (int)(temp ^ (temp >>> 32));
result = prime * result + ((winnerCells == null) ? 0 : winnerCells.hashCode());
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Connections other = (Connections)obj;
if(activationThreshold != other.activationThreshold)
return false;
if(activeCells == null) {
if(other.activeCells != null)
return false;
} else if(!activeCells.equals(other.activeCells))
return false;
if(!Arrays.equals(activeDutyCycles, other.activeDutyCycles))
return false;
if(!Arrays.equals(boostFactors, other.boostFactors))
return false;
if(!Arrays.equals(cells, other.cells))
return false;
if(cellsPerColumn != other.cellsPerColumn)
return false;
if(!Arrays.equals(columnDimensions, other.columnDimensions))
return false;
if(connectedCounts == null) {
if(other.connectedCounts != null)
return false;
} else if(!connectedCounts.equals(other.connectedCounts))
return false;
if(Double.doubleToLongBits(connectedPermanence) != Double.doubleToLongBits(other.connectedPermanence))
return false;
if(dutyCyclePeriod != other.dutyCyclePeriod)
return false;
if(globalInhibition != other.globalInhibition)
return false;
if(inhibitionRadius != other.inhibitionRadius)
return false;
if(Double.doubleToLongBits(initConnectedPct) != Double.doubleToLongBits(other.initConnectedPct))
return false;
if(Double.doubleToLongBits(initialPermanence) != Double.doubleToLongBits(other.initialPermanence))
return false;
if(!Arrays.equals(inputDimensions, other.inputDimensions))
return false;
if(inputMatrix == null) {
if(other.inputMatrix != null)
return false;
} else if(!inputMatrix.equals(other.inputMatrix))
return false;
if(spIterationLearnNum != other.spIterationLearnNum)
return false;
if(spIterationNum != other.spIterationNum)
return false;
if(tmIteration != other.tmIteration)
return false;
if(learningRadius != other.learningRadius)
return false;
if(Double.doubleToLongBits(localAreaDensity) != Double.doubleToLongBits(other.localAreaDensity))
return false;
if(Double.doubleToLongBits(maxBoost) != Double.doubleToLongBits(other.maxBoost))
return false;
if(maxNewSynapseCount != other.maxNewSynapseCount)
return false;
if(memory == null) {
if(other.memory != null)
return false;
} else if(!memory.equals(other.memory))
return false;
if(!Arrays.equals(minActiveDutyCycles, other.minActiveDutyCycles))
return false;
if(!Arrays.equals(minOverlapDutyCycles, other.minOverlapDutyCycles))
return false;
if(Double.doubleToLongBits(minPctActiveDutyCycles) != Double.doubleToLongBits(other.minPctActiveDutyCycles))
return false;
if(Double.doubleToLongBits(minPctOverlapDutyCycles) != Double.doubleToLongBits(other.minPctOverlapDutyCycles))
return false;
if(minThreshold != other.minThreshold)
return false;
if(Double.doubleToLongBits(numActiveColumnsPerInhArea) != Double.doubleToLongBits(other.numActiveColumnsPerInhArea))
return false;
if(numColumns != other.numColumns)
return false;
if(numInputs != other.numInputs)
return false;
if(numSynapses != other.numSynapses)
return false;
if(!Arrays.equals(overlapDutyCycles, other.overlapDutyCycles))
return false;
if(Double.doubleToLongBits(permanenceDecrement) != Double.doubleToLongBits(other.permanenceDecrement))
return false;
if(Double.doubleToLongBits(permanenceIncrement) != Double.doubleToLongBits(other.permanenceIncrement))
return false;
if(Double.doubleToLongBits(potentialPct) != Double.doubleToLongBits(other.potentialPct))
return false;
if(potentialPools == null) {
if(other.potentialPools != null)
return false;
} else if(!potentialPools.equals(other.potentialPools))
return false;
if(potentialRadius != other.potentialRadius)
return false;
if(Double.doubleToLongBits(predictedSegmentDecrement) != Double.doubleToLongBits(other.predictedSegmentDecrement))
return false;
if(predictiveCells == null) {
if(other.predictiveCells != null)
return false;
} else if(!getPredictiveCells().equals(other.getPredictiveCells()))
return false;
if(receptorSynapses == null) {
if(other.receptorSynapses != null)
return false;
} else if(!receptorSynapses.toString().equals(other.receptorSynapses.toString()))
return false;
if(seed != other.seed)
return false;
if(segments == null) {
if(other.segments != null)
return false;
} else if(!segments.equals(other.segments))
return false;
if(Double.doubleToLongBits(stimulusThreshold) != Double.doubleToLongBits(other.stimulusThreshold))
return false;
if(Double.doubleToLongBits(synPermActiveInc) != Double.doubleToLongBits(other.synPermActiveInc))
return false;
if(Double.doubleToLongBits(synPermBelowStimulusInc) != Double.doubleToLongBits(other.synPermBelowStimulusInc))
return false;
if(Double.doubleToLongBits(synPermConnected) != Double.doubleToLongBits(other.synPermConnected))
return false;
if(Double.doubleToLongBits(synPermInactiveDec) != Double.doubleToLongBits(other.synPermInactiveDec))
return false;
if(Double.doubleToLongBits(synPermMax) != Double.doubleToLongBits(other.synPermMax))
return false;
if(Double.doubleToLongBits(synPermMin) != Double.doubleToLongBits(other.synPermMin))
return false;
if(Double.doubleToLongBits(synPermTrimThreshold) != Double.doubleToLongBits(other.synPermTrimThreshold))
return false;
if(proximalSynapseCounter != other.proximalSynapseCounter)
return false;
if(proximalSynapses == null) {
if(other.proximalSynapses != null)
return false;
} else if(!proximalSynapses.equals(other.proximalSynapses))
return false;
if(distalSynapses == null) {
if(other.distalSynapses != null)
return false;
} else if(!distalSynapses.equals(other.distalSynapses))
return false;
if(!Arrays.equals(tieBreaker, other.tieBreaker))
return false;
if(updatePeriod != other.updatePeriod)
return false;
if(Double.doubleToLongBits(version) != Double.doubleToLongBits(other.version))
return false;
if(winnerCells == null) {
if(other.winnerCells != null)
return false;
} else if(!winnerCells.equals(other.winnerCells))
return false;
return true;
}
}
| | | | | | | | | | | | | | | | | | | | | | |
© 2015 - 2025 Weber Informatics LLC | Privacy Policy