
org.numenta.nupic.model.Connections Maven / Gradle / Ivy
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