/* Maps a column to its input bits. This method encapsultes the topology of the region. It takes the index of the column as an argument and determines what are the indices of the input vector that are located within the column's potential pool. The return value is a list containing the indices of the input bits. The current implementation of the base class only supports a 1 dimensional topology of columsn with a 1 dimensional topology of inputs. To extend this class to support 2-D topology you will need to override this method. Examples of the expected output of this method: * If the potentialRadius is greater than or equal to the entire input space, (global visibility), then this method returns an array filled with all the indices * If the topology is one dimensional, and the potentialRadius is 5, this method will return an array containing 5 consecutive values centered on the index of the column (wrapping around if necessary). * If the topology is two dimensional (not implemented), and the potentialRadius is 5, the method should return an array containing 25 '1's, where the exact indices are to be determined by the mapping from 1-D index to 2-D position. Parameters: ---------------------------- index: The index identifying a column in the permanence, potential and connectivity matrices. wrapAround: A boolean value indicating that boundaries should be region boundaries ignored. */ func (sp *SpatialPooler) mapPotential(index int, wrapAround bool) []bool { // Distribute column over inputs uniformly ratio := float64(index) / float64(mathutil.Max((sp.numColumns-1), 1)) index = int(float64(sp.numInputs-1) * ratio) var indices []int indLen := 2*sp.PotentialRadius + 1 for i := 0; i < indLen; i++ { temp := (i + index - sp.PotentialRadius) if wrapAround { temp = temp % sp.numInputs if temp < 0 { temp = sp.numInputs + temp } } else { if !(temp >= 0 && temp < sp.numInputs) { continue } } //no dupes if !utils.ContainsInt(temp, indices) { indices = append(indices, temp) } } // Select a subset of the receptive field to serve as the // the potential pool //shuffle indices for i := range indices { j := rand.Intn(i + 1) indices[i], indices[j] = indices[j], indices[i] } sampleLen := int(utils.RoundPrec(float64(len(indices))*sp.PotentialPct, 0)) sample := indices[:sampleLen] //project indices onto input mask mask := make([]bool, sp.numInputs) for i, _ := range mask { mask[i] = utils.ContainsInt(i, sample) } return mask }
/* Update the inhibition radius. The inhibition radius is a meausre of the square (or hypersquare) of columns that each a column is "conencted to" on average. Since columns are are not connected to each other directly, we determine this quantity by first figuring out how many *inputs* a column is connected to, and then multiplying it by the total number of columns that exist for each input. For multiple dimension the aforementioned calculations are averaged over all dimensions of inputs and columns. This value is meaningless if global inhibition is enabled. */ func (sp *SpatialPooler) updateInhibitionRadius(avgConnectedSpanForColumnND avgConnectedSpanForColumnNDFunc, avgColumnsPerInput avgColumnsPerInputFunc) { if sp.GlobalInhibition { cmax := utils.MaxSliceInt(sp.ColumnDimensions) sp.inhibitionRadius = cmax return } avgConnectedSpan := 0.0 for i := 0; i < sp.numColumns; i++ { avgConnectedSpan += avgConnectedSpanForColumnND(i) } avgConnectedSpan = avgConnectedSpan / float64(sp.numColumns) columnsPerInput := avgColumnsPerInput() diameter := avgConnectedSpan * columnsPerInput radius := (diameter - 1) / 2.0 radius = math.Max(1.0, radius) sp.inhibitionRadius = int(utils.RoundPrec(radius, 0)) }
func AlmostEqualFloat(a, b float64) bool { ar := utils.RoundPrec(a, 2) br := utils.RoundPrec(b, 2) return ar == br }