package cs437.som.network;

import cs437.som.SelfOrganizingMap;
import cs437.som.visualization.SOM2dPlotter;

import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Random;

/**
 * A simple self-organizing map, using a hexagonal grid for the neurons.
 *
 * An simple example usage:
 *
 * <code>
 * <pre>
 * private static final int iterations = 500;
 *
 * public static void main(String[] args) {
 *     SelfOrganizingMap som = new BasicHexGridSOM(7, 2, iterations);
 *     Random r = new SecureRandom();
 *
 *     for (int i = 0; i < iterations; i++) {
 *         double[] in = {r.nextDouble() * 10, r.nextDouble() * 10};
 *         som.trainWith(in);
 *     }
 *
 *     // At this point, the SOM would be queried for it's BMU.
 * }
 * </pre>
 * </code>
 */
public class BasicHexGridSOM extends NetworkBase {
    private int gridSize;

    public BasicHexGridSOM(int gridSize, int inputVectorSize, int expectedIterations) {
        super(inputVectorSize, gridSize * gridSize, expectedIterations, gridSize);
        this.gridSize = gridSize;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected double neuronDistance(int neuron0, int neuron1) {
        int row0 = neuron0 / gridSize;
        int col0 = neuron0 % gridSize;
        int row1 = neuron1 / gridSize;
        int col1 = neuron1 % gridSize;

        int dx = row1 - row0;
        int dy = col1 - col0;

        int distance;
        if (sign(dx) == sign(dy)) {
            distance = Math.abs(dx + dy);
        } else {
            distance = Math.max(Math.abs(dx), Math.abs(dy));
        }

        return distance;
    }

    private int sign(int n) {
        return (n >= 0) ? 1 : -1;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "BasicHexGridSOM{time=" + time +
                ", weightMatrix=" + (weightMatrix == null ? null : Arrays.asList(weightMatrix)) +
                ", neuronCount=" + neuronCount + ", inputSize=" + inputVectorSize + '}';
    }

    private static final int iters = 500;
    private static final int iterDelay = 20; /* ms */

    public static void main(String[] args) {
        SelfOrganizingMap som = new BasicHexGridSOM(7, 2, iters);
        Random r = new SecureRandom();

        SOM2dPlotter plot = new SOM2dPlotter(som);
        for (int i = 0; i < iters; i++) {
            double[] in = {r.nextDouble() * 10, r.nextDouble() * 10};
            som.trainWith(in);
            plot.draw();
            try { Thread.sleep(iterDelay); } catch (InterruptedException ignored) { }
        }
    }
}

@@ -32,166 +32,24 @@
 ort 
-cs437.som.SelfOrganizingMap;%0Aimport cs437.som.visualization.SOM2dPlotter;%0A%0Aimport java.security.SecureRandom;%0Aimport java.util.Arrays;%0Aimport java.util.Random
+java.util.Arrays
 ;%0A%0A/
@@ -1875,575 +1875,6 @@
  %7D%0A%0A
-    private static final int iters = 500;%0A    private static final int iterDelay = 20; /* ms */%0A%0A    public static void main(String%5B%5D args) %7B%0A        SelfOrganizingMap som = new BasicHexGridSOM(7, 2, iters);%0A        Random r = new SecureRandom();%0A%0A        SOM2dPlotter plot = new SOM2dPlotter(som);%0A        for (int i = 0; i %3C iters; i++) %7B%0A            double%5B%5D in = %7Br.nextDouble() * 10, r.nextDouble() * 10%7D;%0A            som.trainWith(in);%0A            plot.draw();%0A            try %7B Thread.sleep(iterDelay); %7D catch (InterruptedException ignored) %7B %7D%0A        %7D%0A    %7D%0A
 %7D%0A

Remove main(..) from BasicHexGridSOM. BasicMapDemo has the same functionality.