/// <summary> /// Uniform Column Mapping <br></br> /// 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: /// <list type="bullet"> /// <item> /// 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. /// </item> /// <item>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. /// </item> /// </list> /// </summary> /// <param name="columnIndex">The index identifying a column in the permanence, potential and connectivity matrices.</param> /// <param name="colTop"></param> /// <param name="inpTop"></param> /// <returns>Flat index of mapped column.</returns> public static int MapColumn(int columnIndex, HtmModuleTopology colTop, HtmModuleTopology inpTop) { int[] columnCoords = AbstractFlatMatrix.ComputeCoordinates(colTop.NumDimensions, colTop.DimensionMultiplies, colTop.IsMajorOrdering, columnIndex); double[] colCoords = ArrayUtils.ToDoubleArray(columnCoords); double[] columnRatios = ArrayUtils.Divide( colCoords, ArrayUtils.ToDoubleArray(colTop.Dimensions), 0, 0); double[] inputCoords = ArrayUtils.Multiply( ArrayUtils.ToDoubleArray(inpTop.Dimensions), columnRatios, 0, 0); var colSpanOverInputs = ArrayUtils.Divide( ArrayUtils.ToDoubleArray(inpTop.Dimensions), ArrayUtils.ToDoubleArray(colTop.Dimensions), 0, 0); inputCoords = ArrayUtils.AddOffset(inputCoords, ArrayUtils.Multiply(colSpanOverInputs, 0.5)); // Makes sure that inputCoords are in range [0, inpDims] int[] inputCoordInts = ArrayUtils.Clip(ArrayUtils.ToIntArray(inputCoords), inpTop.Dimensions, -1); return(AbstractFlatMatrix.ComputeIndex(inputCoordInts, inpTop.Dimensions, inpTop.NumDimensions, inpTop.DimensionMultiplies, inpTop.IsMajorOrdering, true)); }
/// <summary> /// Returns a flat index computed from the specified coordinates. /// </summary> /// <param name="coordinates"> The index of the point</param> /// <param name="topology"></param> /// <returns>using the dimensions as a mixed radix definition.For example, in dimensions /// 42x10, the point [1, 4] is index 1*420 + 4*10 = 460.</returns> public static int GetFlatIndexFromCoordinates(int[] coordinates, HtmModuleTopology topology) { int[] localMults = topology.IsMajorOrdering ? HtmCompute.Reverse(topology.DimensionMultiplies) : topology.DimensionMultiplies; int baseNum = 0; for (int i = 0; i < coordinates.Length; i++) { baseNum += (localMults[i] * coordinates[i]); } return(baseNum); }
/// <summary> /// Calculates multidimensional coordinates from flat array index. /// </summary> /// <param name="index">Flat index.</param> /// <returns>Coordinates in multidimensional space.</returns> public static int[] GetCoordinatesFromIndex(int index, HtmModuleTopology topology) { int[] returnVal = new int[topology.NumDimensions]; int baseNum = index; for (int i = 0; i < topology.DimensionMultiplies.Length; i++) { int quotient = baseNum / topology.DimensionMultiplies[i]; baseNum %= topology.DimensionMultiplies[i]; returnVal[i] = quotient; } return(topology.IsMajorOrdering ? Reverse(returnVal) : returnVal); }
public void SerializeHtmModuleTopologyTest(int[] dimensions, bool isMajorOrdering) { HtmModuleTopology htm = new HtmModuleTopology(dimensions, isMajorOrdering); using (StreamWriter sw = new StreamWriter($"ser_{nameof(SerializeHtmModuleTopologyTest)}.txt")) { htm.Serialize(sw); } using (StreamReader sr = new StreamReader($"ser_{nameof(SerializeHtmModuleTopologyTest)}.txt")) { HtmModuleTopology htm1 = HtmModuleTopology.Deserialize(sr); Assert.IsTrue(htm1.Equals(htm)); } }
/// <summary> /// Gets indexes of neighborhood cells within centered radius /// </summary> /// <param name="centerIndex">The index of the point. The coordinates are expressed as a single index by /// using the dimensions as a mixed radix definition. For example, in dimensions 42x10, the point [1, 4] is index 1*420 + 4*10 = 460. /// </param> /// <param name="radius"></param> /// <param name="topology"></param> /// <returns>The points in the neighborhood, including centerIndex.</returns> public static int[] GetWrappingNeighborhood(int centerIndex, int radius, HtmModuleTopology topology) { int[] cp = HtmCompute.GetCoordinatesFromIndex(centerIndex, topology); // Dims of columns IntGenerator[] intGens = new IntGenerator[topology.Dimensions.Length]; for (int i = 0; i < topology.Dimensions.Length; i++) { intGens[i] = new IntGenerator(cp[i] - radius, Math.Min((cp[i] - radius) + topology.Dimensions[i] - 1, cp[i] + radius) + 1); } List <List <int> > result = new List <List <int> >(); result.Add(new List <int>()); List <List <int> > interim = new List <List <int> >(); int k = 0; foreach (IntGenerator gen in intGens) { interim.Clear(); interim.AddRange(result); result.Clear(); foreach (var lx in interim) { gen.Reset(); for (int y = 0; y < gen.Size(); y++) { int py = ArrayUtils.Modulo(gen.Next(), topology.Dimensions[k]); //int py = gen.next() % dimensions[k]; List <int> tl = new List <int>(); tl.AddRange(lx); tl.Add(py); result.Add(tl); } } k++; } return(result.Select((tl) => GetFlatIndexFromCoordinates(tl.ToArray(), topology)).ToArray()); }
/// <summary> /// Gets the list of neighborhood columns around the centar with the given radius in the specified topology. /// </summary> /// <param name="centerIndex"></param> /// <param name="radius"></param> /// <param name="topology"></param> /// <returns></returns> public static int[] GetNeighborhood(int centerIndex, int radius, HtmModuleTopology topology) { var centerPosition = HtmCompute.GetCoordinatesFromIndex(centerIndex, topology); IntGenerator[] intGens = new IntGenerator[topology.Dimensions.Length]; for (int i = 0; i < topology.Dimensions.Length; i++) { intGens[i] = new IntGenerator(Math.Max(0, centerPosition[i] - radius), Math.Min(topology.Dimensions[i] - 1, centerPosition[i] + radius) + 1); } List <List <int> > result = new List <List <int> >(); result.Add(new List <int>()); List <List <int> > interim = new List <List <int> >(); foreach (IntGenerator gen in intGens) { interim.Clear(); interim.AddRange(result); result.Clear(); foreach (var lx in interim) { gen.Reset(); for (int y = 0; y < gen.Size(); y++) { int py = gen.Next(); List <int> tl = new List <int>(); tl.AddRange(lx); tl.Add(py); result.Add(tl); } } } return(result.Select((tl) => GetFlatIndexFromCoordinates(tl.ToArray(), topology)).ToArray()); }
/// <summary> /// Gets a neighborhood of inputs. Simply calls topology.wrappingNeighborhood or topology.neighborhood. A subclass can insert different topology behavior by overriding this method. /// </summary> /// <param name="isWrapAround"></param> /// <param name="inputTopology"></param> /// <param name="centerInput">The center of the neighborhood.</param> /// <param name="potentialRadius">Span of the input field included in each neighborhood</param> /// <returns>The input's in the neighborhood. (1D)</returns> public static int[] GetInputNeighborhood(bool isWrapAround, HtmModuleTopology inputTopology, int centerInput, int potentialRadius) { return(isWrapAround ? GetWrappingNeighborhood(centerInput, potentialRadius, inputTopology) : GetNeighborhood(centerInput, potentialRadius, inputTopology)); }