You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2015/08/30 18:58:04 UTC

[math] MATH-1263

Repository: commons-math
Updated Branches:
  refs/heads/MATH_3_X b54dbfb6e -> 2762c6600


MATH-1263

Accessor to get neighbouring neurons (in a square grid).


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/2762c660
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/2762c660
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/2762c660

Branch: refs/heads/MATH_3_X
Commit: 2762c66008fe76c9ae697351140a5f5b3516d80a
Parents: b54dbfb
Author: Gilles <er...@apache.org>
Authored: Sun Aug 30 18:56:50 2015 +0200
Committer: Gilles <er...@apache.org>
Committed: Sun Aug 30 18:56:50 2015 +0200

----------------------------------------------------------------------
 src/changes/changes.xml                         |   3 +
 .../ml/neuralnet/twod/NeuronSquareMesh2D.java   | 131 +++++++++++++++
 .../neuralnet/twod/NeuronSquareMesh2DTest.java  | 163 +++++++++++++++++++
 3 files changed, 297 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/2762c660/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index be42bb3..29ce88f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -51,6 +51,9 @@ If the output is not quite correct, check for invisible trailing spaces!
   </properties>
   <body>
     <release version="3.6" date="XXXX-XX-XX" description="">
+      <action dev="erans" type="add" issue="MATH-1263">
+        Accessor (class "o.a.c.m.ml.neuralnet.twod.NeuronSquareMesh2D").
+      </action>
       <action dev="erans" type="add" issue="MATH-1259">
         New "IntegerSequence" class (in package "o.a.c.m.util") with "Incrementor" inner class.
       </action>

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2762c660/src/main/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2D.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2D.java b/src/main/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2D.java
index deb2a8c..24b70af 100644
--- a/src/main/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2D.java
+++ b/src/main/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2D.java
@@ -63,6 +63,29 @@ public class NeuronSquareMesh2D implements Serializable {
     private final long[][] identifiers;
 
     /**
+     * Horizontal (along row) direction.
+     */
+    public enum HorizontalDirection {
+        /** Column at the right of the current column. */
+       RIGHT,
+       /** Current column. */
+       CENTER,
+       /** Column at the left of the current column. */
+       LEFT,
+    }
+    /**
+     * Vertical (along column) direction.
+     */
+    public enum VerticalDirection {
+        /** Row above the current row. */
+        UP,
+        /** Current row. */
+        CENTER,
+        /** Row below the current row. */
+        DOWN,
+    }
+
+    /**
      * Constructor with restricted access, solely used for deserialization.
      *
      * @param wrapRowDim Whether to wrap the first dimension (i.e the first
@@ -204,12 +227,16 @@ public class NeuronSquareMesh2D implements Serializable {
 
     /**
      * Retrieves the neuron at location {@code (i, j)} in the map.
+     * The neuron at position {@code (0, 0)} is located at the upper-left
+     * corner of the map.
      *
      * @param i Row index.
      * @param j Column index.
      * @return the neuron at {@code (i, j)}.
      * @throws OutOfRangeException if {@code i} or {@code j} is
      * out of range.
+     *
+     * @see #getNeuron(int,int,HorizontalDirection,VerticalDirection)
      */
     public Neuron getNeuron(int i,
                             int j) {
@@ -226,6 +253,110 @@ public class NeuronSquareMesh2D implements Serializable {
     }
 
     /**
+     * Retrieves the neuron at {@code (location[0], location[1])} in the map.
+     * The neuron at position {@code (0, 0)} is located at the upper-left
+     * corner of the map.
+     *
+     * @param row Row index.
+     * @param col Column index.
+     * @param alongRowDir Direction along the given {@code row} (i.e. an
+     * offset will be added to the given <em>column</em> index.
+     * @param alongColDir Direction along the given {@code col} (i.e. an
+     * offset will be added to the given <em>row</em> index.
+     * @return the neuron at the requested location, or {@code null} if
+     * the location is not on the map.
+     *
+     * @see #getNeuron(int,int)
+     */
+    public Neuron getNeuron(int row,
+                            int col,
+                            HorizontalDirection alongRowDir,
+                            VerticalDirection alongColDir) {
+        final int[] location = getLocation(row, col, alongRowDir, alongColDir);
+
+        return location == null ? null : getNeuron(location[0], location[1]);
+    }
+
+    /**
+     * Computes the location of a neighbouring neuron.
+     * It will return {@code null} if the resulting location is not part
+     * of the map.
+     * Position {@code (0, 0)} is at the upper-left corner of the map.
+     *
+     * @param row Row index.
+     * @param col Column index.
+     * @param alongRowDir Direction along the given {@code row} (i.e. an
+     * offset will be added to the given <em>column</em> index.
+     * @param alongColDir Direction along the given {@code col} (i.e. an
+     * offset will be added to the given <em>row</em> index.
+     * @return an array of length 2 containing the indices of the requested
+     * location, or {@code null} if that location is not part of the map.
+     *
+     * @see #getNeuron(int,int)
+     */
+    private int[] getLocation(int row,
+                              int col,
+                              HorizontalDirection alongRowDir,
+                              VerticalDirection alongColDir) {
+        final int colOffset;
+        switch (alongRowDir) {
+        case LEFT:
+            colOffset = -1;
+            break;
+        case RIGHT:
+            colOffset = 1;
+            break;
+        case CENTER:
+            colOffset = 0;
+            break;
+        default:
+            // Should never happen.
+            throw new MathInternalError();
+        }
+        int colIndex = col + colOffset;
+        if (wrapColumns) {
+            if (colIndex < 0) {
+                colIndex += numberOfColumns;
+            } else {
+                colIndex %= numberOfColumns;
+            }
+        }
+
+        final int rowOffset;
+        switch (alongColDir) {
+        case UP:
+            rowOffset = -1;
+            break;
+        case DOWN:
+            rowOffset = 1;
+            break;
+        case CENTER:
+            rowOffset = 0;
+            break;
+        default:
+            // Should never happen.
+            throw new MathInternalError();
+        }
+        int rowIndex = row + rowOffset;
+        if (wrapRows) {
+            if (rowIndex < 0) {
+                rowIndex += numberOfRows;
+            } else {
+                rowIndex %= numberOfRows;
+            }
+        }
+
+        if (rowIndex < 0 ||
+            rowIndex >= numberOfRows ||
+            colIndex < 0 ||
+            colIndex >= numberOfColumns) {
+            return null;
+        } else {
+            return new int[] { rowIndex, colIndex };
+        }
+     }
+
+    /**
      * Creates the neighbour relationships between neurons.
      */
     private void createLinks() {

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2762c660/src/test/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2DTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2DTest.java b/src/test/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2DTest.java
index 9d5f21c..1e4d3ea 100644
--- a/src/test/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2DTest.java
+++ b/src/test/java/org/apache/commons/math3/ml/neuralnet/twod/NeuronSquareMesh2DTest.java
@@ -26,6 +26,7 @@ import java.util.Collection;
 import java.util.HashSet;
 
 import org.apache.commons.math3.exception.NumberIsTooSmallException;
+import org.apache.commons.math3.exception.OutOfRangeException;
 import org.apache.commons.math3.ml.neuralnet.FeatureInitializer;
 import org.apache.commons.math3.ml.neuralnet.FeatureInitializerFactory;
 import org.apache.commons.math3.ml.neuralnet.Network;
@@ -681,4 +682,166 @@ public class NeuronSquareMesh2DTest {
             }
         }
     }
+
+    /*
+     * Test assumes that the network is
+     *
+     *  0-----1
+     *  |     |
+     *  |     |
+     *  2-----3
+     */
+    @Test
+    public void testGetNeuron() {
+        final FeatureInitializer[] initArray = { init };
+        final NeuronSquareMesh2D net = new NeuronSquareMesh2D(2, false,
+                                                              2, true,
+                                                              SquareNeighbourhood.VON_NEUMANN,
+                                                              initArray);
+        Assert.assertEquals(0, net.getNeuron(0, 0).getIdentifier());
+        Assert.assertEquals(1, net.getNeuron(0, 1).getIdentifier());
+        Assert.assertEquals(2, net.getNeuron(1, 0).getIdentifier());
+        Assert.assertEquals(3, net.getNeuron(1, 1).getIdentifier());
+
+        try {
+            net.getNeuron(2, 0);
+            Assert.fail("exception expected");
+        } catch (OutOfRangeException e) {
+            // Expected.
+        }
+        try {
+            net.getNeuron(0, 2);
+            Assert.fail("exception expected");
+        } catch (OutOfRangeException e) {
+            // Expected.
+        }
+        try {
+            net.getNeuron(-1, 0);
+            Assert.fail("exception expected");
+        } catch (OutOfRangeException e) {
+            // Expected.
+        }
+        try {
+            net.getNeuron(0, -1);
+            Assert.fail("exception expected");
+        } catch (OutOfRangeException e) {
+            // Expected.
+        }
+    }
+
+    /*
+     * Test assumes that the network is
+     *
+     *  0-----1-----2
+     *  |     |     |
+     *  |     |     |
+     *  3-----4-----5
+     *  |     |     |
+     *  |     |     |
+     *  6-----7-----8
+     */
+    @Test
+    public void testGetNeuronAlongDirection() {
+        final FeatureInitializer[] initArray = { init };
+        final NeuronSquareMesh2D net = new NeuronSquareMesh2D(3, false,
+                                                              3, false,
+                                                              SquareNeighbourhood.VON_NEUMANN,
+                                                              initArray);
+        Assert.assertEquals(0, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.LEFT,
+                                             NeuronSquareMesh2D.VerticalDirection.UP).getIdentifier());
+        Assert.assertEquals(1, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.CENTER,
+                                             NeuronSquareMesh2D.VerticalDirection.UP).getIdentifier());
+        Assert.assertEquals(2, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.RIGHT,
+                                             NeuronSquareMesh2D.VerticalDirection.UP).getIdentifier());
+        Assert.assertEquals(3, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.LEFT,
+                                             NeuronSquareMesh2D.VerticalDirection.CENTER).getIdentifier());
+        Assert.assertEquals(4, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.CENTER,
+                                             NeuronSquareMesh2D.VerticalDirection.CENTER).getIdentifier());
+        Assert.assertEquals(5, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.RIGHT,
+                                             NeuronSquareMesh2D.VerticalDirection.CENTER).getIdentifier());
+        Assert.assertEquals(6, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.LEFT,
+                                             NeuronSquareMesh2D.VerticalDirection.DOWN).getIdentifier());
+        Assert.assertEquals(7, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.CENTER,
+                                             NeuronSquareMesh2D.VerticalDirection.DOWN).getIdentifier());
+        Assert.assertEquals(8, net.getNeuron(1, 1,
+                                             NeuronSquareMesh2D.HorizontalDirection.RIGHT,
+                                             NeuronSquareMesh2D.VerticalDirection.DOWN).getIdentifier());
+
+        // Locations not in map.
+        Assert.assertNull(net.getNeuron(0, 1,
+                                        NeuronSquareMesh2D.HorizontalDirection.CENTER,
+                                        NeuronSquareMesh2D.VerticalDirection.UP));
+        Assert.assertNull(net.getNeuron(1, 0,
+                                        NeuronSquareMesh2D.HorizontalDirection.LEFT,
+                                        NeuronSquareMesh2D.VerticalDirection.CENTER));
+        Assert.assertNull(net.getNeuron(2, 1,
+                                        NeuronSquareMesh2D.HorizontalDirection.CENTER,
+                                        NeuronSquareMesh2D.VerticalDirection.DOWN));
+        Assert.assertNull(net.getNeuron(1, 2,
+                                        NeuronSquareMesh2D.HorizontalDirection.RIGHT,
+                                        NeuronSquareMesh2D.VerticalDirection.CENTER));
+    }
+
+    /*
+     * Test assumes that the network is
+     *
+     *  0-----1-----2
+     *  |     |     |
+     *  |     |     |
+     *  3-----4-----5
+     *  |     |     |
+     *  |     |     |
+     *  6-----7-----8
+     */
+    @Test
+    public void testGetNeuronAlongDirectionWrappedMap() {
+        final FeatureInitializer[] initArray = { init };
+        final NeuronSquareMesh2D net = new NeuronSquareMesh2D(3, true,
+                                                              3, true,
+                                                              SquareNeighbourhood.VON_NEUMANN,
+                                                              initArray);
+        // No wrapping.
+        Assert.assertEquals(3, net.getNeuron(0, 0,
+                                             NeuronSquareMesh2D.HorizontalDirection.CENTER,
+                                             NeuronSquareMesh2D.VerticalDirection.DOWN).getIdentifier());
+        // With wrapping.
+        Assert.assertEquals(2, net.getNeuron(0, 0,
+                                             NeuronSquareMesh2D.HorizontalDirection.LEFT,
+                                             NeuronSquareMesh2D.VerticalDirection.CENTER).getIdentifier());
+        Assert.assertEquals(7, net.getNeuron(0, 0,
+                                             NeuronSquareMesh2D.HorizontalDirection.RIGHT,
+                                             NeuronSquareMesh2D.VerticalDirection.UP).getIdentifier());
+        Assert.assertEquals(8, net.getNeuron(0, 0,
+                                             NeuronSquareMesh2D.HorizontalDirection.LEFT,
+                                             NeuronSquareMesh2D.VerticalDirection.UP).getIdentifier());
+        Assert.assertEquals(6, net.getNeuron(0, 0,
+                                             NeuronSquareMesh2D.HorizontalDirection.CENTER,
+                                             NeuronSquareMesh2D.VerticalDirection.UP).getIdentifier());
+        Assert.assertEquals(5, net.getNeuron(0, 0,
+                                             NeuronSquareMesh2D.HorizontalDirection.LEFT,
+                                             NeuronSquareMesh2D.VerticalDirection.DOWN).getIdentifier());
+
+        // No wrapping.
+        Assert.assertEquals(1, net.getNeuron(1, 2,
+                                             NeuronSquareMesh2D.HorizontalDirection.LEFT,
+                                             NeuronSquareMesh2D.VerticalDirection.UP).getIdentifier());
+        // With wrapping.
+        Assert.assertEquals(0, net.getNeuron(1, 2,
+                                             NeuronSquareMesh2D.HorizontalDirection.RIGHT,
+                                             NeuronSquareMesh2D.VerticalDirection.UP).getIdentifier());
+        Assert.assertEquals(3, net.getNeuron(1, 2,
+                                             NeuronSquareMesh2D.HorizontalDirection.RIGHT,
+                                             NeuronSquareMesh2D.VerticalDirection.CENTER).getIdentifier());
+        Assert.assertEquals(6, net.getNeuron(1, 2,
+                                             NeuronSquareMesh2D.HorizontalDirection.RIGHT,
+                                             NeuronSquareMesh2D.VerticalDirection.DOWN).getIdentifier());
+    }
 }