All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.numenta.nupic.util.Topology Maven / Gradle / Ivy

There is a newer version: 0.6.13
Show newest version
/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2016, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */
package org.numenta.nupic.util;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

import gnu.trove.list.TIntList;
import gnu.trove.list.array.TIntArrayList;


public class Topology extends Coordinator implements Serializable {
    /** keep it simple */
    private static final long serialVersionUID = 1L;
    
    private IntGenerator[] igs;
    private int[] centerPosition;
    
    
    /**
     * Constructs a new {@link AbstractFlatMatrix} object to be configured with specified
     * dimensions and major ordering.
     * @param shape  the dimensions of this matrix 
     */
    public Topology(int... shape) {
        super(shape, false);
    }
    
    /**
     * Translate an index into coordinates, using the given coordinate system.
     * 
     * @param index     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.
     * @return          A array of coordinates of length len(dimensions).
     */
    public int[] coordinatesFromIndex(int index) {
        return computeCoordinates(index);
    }

    /**
     * Translate coordinates into an index, using the given coordinate system.
     * 
     * @param coordinates       A array of coordinates of length dimensions.size().
     * @param shape             The coordinate system.
     * @return                  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.
     */
    public int indexFromCoordinates(int... coordinates) {
        return computeIndex(coordinates);
    }
    
    /**
     * Get the points in the neighborhood of a point.
     *
     * A point's neighborhood is the n-dimensional hypercube with sides ranging
     * [center - radius, center + radius], inclusive. For example, if there are two
     * dimensions and the radius is 3, the neighborhood is 6x6. Neighborhoods are
     * truncated when they are near an edge.
     * 
     * @param 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 radius            The radius of this neighborhood about the centerIndex.
     * @return  The points in the neighborhood, including centerIndex.
     */
    public int[] neighborhood(int centerIndex, int radius) {
        centerPosition = coordinatesFromIndex(centerIndex);
        
        igs = IntStream.range(0, dimensions.length)
            .mapToObj(i -> 
                IntGenerator.of(Math.max(0, centerPosition[i] - radius), 
                    Math.min(dimensions[i] - 1, centerPosition[i] + radius) + 1))
            .toArray(IntGenerator[]::new);
       
        List result = new ArrayList<>();
        result.add(new TIntArrayList());
        List interim = new ArrayList<>();
        for(IntGenerator pool : igs) {
            int size = result.size();
            interim.clear();
            interim.addAll(result);
            result.clear();
            for(int x = 0;x < size;x++) {
                TIntList lx = interim.get(x);
                pool.reset();
                for(int y = 0;y < pool.size();y++) {
                    int py = pool.next();
                    TIntArrayList tl = new TIntArrayList();
                    tl.addAll(lx);
                    tl.add(py);
                    result.add(tl);
                }
            }
        }
        
        return result.stream().mapToInt(tl -> indexFromCoordinates(tl.toArray())).toArray();
    }
    
    /**
     * Like {@link #neighborhood(int, int)}, except that the neighborhood isn't truncated when it's
     * near an edge. It wraps around to the other side.
     * 
     * @param 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 radius            The radius of this neighborhood about the centerIndex.
     * @return  The points in the neighborhood, including centerIndex.
     */
    public int[] wrappingNeighborhood(int centerIndex, int radius) {
        int[] cp = coordinatesFromIndex(centerIndex);
        
        IntGenerator[] igs = IntStream.range(0, dimensions.length)
            .mapToObj(i -> 
                new IntGenerator(cp[i] - radius, 
                    Math.min((cp[i] - radius) + dimensions[i] - 1, cp[i] + radius) + 1))
            .toArray(IntGenerator[]::new);
        
        List result = new ArrayList<>();
        result.add(new TIntArrayList());
        List interim = new ArrayList<>();
        for(int i = 0;i < igs.length;i++) {
            IntGenerator pool = igs[i];
            int size = result.size();
            interim.clear();
            interim.addAll(result);
            result.clear();
            for(int x = 0;x < size;x++) {
                TIntList lx = interim.get(x);
                pool.reset();
                for(int y = 0;y < pool.size();y++) {
                    int py = ArrayUtils.modulo(pool.next(), dimensions[i]);
                    TIntArrayList tl = new TIntArrayList();
                    tl.addAll(lx);
                    tl.add(py);
                    result.add(tl);
                }
            }
        }
        
        return result.stream().mapToInt(tl -> indexFromCoordinates(tl.toArray())).toArray();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy