/** * Called to initialize the structural anatomy with configured values and prepare the anatomical * entities for activation. * * @param c */ public void initMatrices(final Connections c) { SparseObjectMatrix<Column> mem = c.getMemory(); c.setMemory(mem == null ? mem = new SparseObjectMatrix<>(c.getColumnDimensions()) : mem); c.setInputMatrix(new SparseBinaryMatrix(c.getInputDimensions())); // Calculate numInputs and numColumns int numInputs = c.getInputMatrix().getMaxIndex() + 1; int numColumns = c.getMemory().getMaxIndex() + 1; if (numColumns <= 0) { throw new InvalidSPParamValueException("Invalid number of columns: " + numColumns); } if (numInputs <= 0) { throw new InvalidSPParamValueException("Invalid number of inputs: " + numInputs); } c.setNumInputs(numInputs); c.setNumColumns(numColumns); // Fill the sparse matrix with column objects for (int i = 0; i < numColumns; i++) { mem.set(i, new Column(c.getCellsPerColumn(), i)); } c.setPotentialPools(new SparseObjectMatrix<Pool>(c.getMemory().getDimensions())); c.setConnectedMatrix(new SparseBinaryMatrix(new int[] {numColumns, numInputs})); // Initialize state meta-management statistics c.setOverlapDutyCycles(new double[numColumns]); c.setActiveDutyCycles(new double[numColumns]); c.setMinOverlapDutyCycles(new double[numColumns]); c.setMinActiveDutyCycles(new double[numColumns]); c.setBoostFactors(new double[numColumns]); Arrays.fill(c.getBoostFactors(), 1); }
/** * Updates the minimum duty cycles. The minimum duty cycles are determined locally. Each column's * minimum duty cycles are set to be a percent of the maximum duty cycles in the column's * neighborhood. Unlike {@link #updateMinDutyCyclesGlobal(Connections)}, here the values can be * quite different for different columns. * * @param c */ public void updateMinDutyCyclesLocal(Connections c) { int len = c.getNumColumns(); for (int i = 0; i < len; i++) { int[] maskNeighbors = getNeighborsND(c, i, c.getMemory(), c.getInhibitionRadius(), true).toArray(); c.getMinOverlapDutyCycles()[i] = ArrayUtils.max(ArrayUtils.sub(c.getOverlapDutyCycles(), maskNeighbors)) * c.getMinPctOverlapDutyCycles(); c.getMinActiveDutyCycles()[i] = ArrayUtils.max(ArrayUtils.sub(c.getActiveDutyCycles(), maskNeighbors)) * c.getMinPctActiveDutyCycles(); } }
/** * Performs inhibition. This method calculates the necessary values needed to actually perform * inhibition and then delegates the task of picking the active columns to helper functions. * * @param c the {@link Connections} matrix * @param overlaps an array containing the overlap score for each column. The overlap score for a * column is defined as the number of synapses in a "connected state" (connected synapses) * that are connected to input bits which are turned on. * @param density The fraction of columns to survive inhibition. This value is only an intended * target. Since the surviving columns are picked in a local fashion, the exact fraction of * surviving columns is likely to vary. * @return indices of the winning columns */ public int[] inhibitColumnsLocal(Connections c, double[] overlaps, double density) { int numCols = c.getNumColumns(); int[] activeColumns = new int[numCols]; double addToWinners = ArrayUtils.max(overlaps) / 1000.0; for (int i = 0; i < numCols; i++) { TIntArrayList maskNeighbors = getNeighborsND(c, i, c.getMemory(), c.getInhibitionRadius(), false); double[] overlapSlice = ArrayUtils.sub(overlaps, maskNeighbors.toArray()); int numActive = (int) (0.5 + density * (maskNeighbors.size() + 1)); int numBigger = ArrayUtils.valueGreaterCount(overlaps[i], overlapSlice); if (numBigger < numActive) { activeColumns[i] = 1; overlaps[i] += addToWinners; } } return ArrayUtils.where(activeColumns, ArrayUtils.INT_GREATER_THAN_0); }
/** * This method increases the permanence values of synapses of columns whose activity level has * been too low. Such columns are identified by having an overlap duty cycle that drops too much * below those of their peers. The permanence values for such columns are increased. * * @param c */ public void bumpUpWeakColumns(final Connections c) { int[] weakColumns = ArrayUtils.where( c.getMemory().get1DIndexes(), new Condition.Adapter<Integer>() { @Override public boolean eval(int i) { return c.getOverlapDutyCycles()[i] < c.getMinOverlapDutyCycles()[i]; } }); for (int i = 0; i < weakColumns.length; i++) { Pool pool = c.getPotentialPools().get(weakColumns[i]); double[] perm = pool.getSparsePermanences(); ArrayUtils.raiseValuesBy(c.getSynPermBelowStimulusInc(), perm); int[] indexes = pool.getSparsePotential(); Column col = c.getColumn(weakColumns[i]); updatePermanencesForColumnSparse(c, perm, col, indexes, true); } }
/** * Maps a column to its respective input index, keeping to the topology of the region. It takes * the index of the column as an argument and determines what is the index of the flattened input * vector that is to be the center of the column's potential pool. It distributes the columns over * the inputs uniformly. The return value is an integer representing the index of the input bit. * Examples of the expected output of this method: * If the topology is one dimensional, and the * column index is 0, this method will return the input index 0. If the column index is 1, and * there are 3 columns over 7 inputs, this method will return the input index 3. * If the topology * is two dimensional, with column dimensions [3, 5] and input dimensions [7, 11], and the column * index is 3, the method returns input index 8. * * @param columnIndex The index identifying a column in the permanence, potential and connectivity * matrices. * @return A boolean value indicating that boundaries should be ignored. */ public int mapColumn(Connections c, int columnIndex) { int[] columnCoords = c.getMemory().computeCoordinates(columnIndex); double[] colCoords = ArrayUtils.toDoubleArray(columnCoords); double[] ratios = ArrayUtils.divide(colCoords, ArrayUtils.toDoubleArray(c.getColumnDimensions()), 0, 0); double[] inputCoords = ArrayUtils.multiply(ArrayUtils.toDoubleArray(c.getInputDimensions()), ratios, 0, 0); inputCoords = ArrayUtils.d_add( inputCoords, ArrayUtils.multiply( ArrayUtils.divide( ArrayUtils.toDoubleArray(c.getInputDimensions()), ArrayUtils.toDoubleArray(c.getColumnDimensions()), 0, 0), 0.5)); int[] inputCoordInts = ArrayUtils.clip(ArrayUtils.toIntArray(inputCoords), c.getInputDimensions(), -1); return c.getInputMatrix().computeIndex(inputCoordInts); }