NeuronString.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.math4.neuralnet.oned;

  18. import org.apache.commons.math4.neuralnet.internal.NeuralNetException;
  19. import org.apache.commons.math4.neuralnet.FeatureInitializer;
  20. import org.apache.commons.math4.neuralnet.Network;

  21. /**
  22.  * Neural network with the topology of a one-dimensional line.
  23.  * Each neuron defines one point on the line.
  24.  *
  25.  * @since 3.3
  26.  */
  27. public class NeuronString {
  28.     /** Minimal number of neurons. */
  29.     private static final int MIN_NEURONS = 2;
  30.     /** Underlying network. */
  31.     private final Network network;
  32.     /** Number of neurons. */
  33.     private final int size;
  34.     /** Wrap. */
  35.     private final boolean wrap;

  36.     /**
  37.      * Mapping of the 1D coordinate to the neuron identifiers
  38.      * (attributed by the {@link #network} instance).
  39.      */
  40.     private final long[] identifiers;

  41.     /**
  42.      * Constructor with restricted access, solely used for deserialization.
  43.      *
  44.      * @param wrap Whether to wrap the dimension (i.e the first and last
  45.      * neurons will be linked together).
  46.      * @param featuresList Arrays that will initialize the features sets of
  47.      * the network's neurons.
  48.      * @throws IllegalArgumentException if {@code num < 2}.
  49.      */
  50.     NeuronString(boolean wrap,
  51.                  double[][] featuresList) {
  52.         size = featuresList.length;

  53.         if (size < MIN_NEURONS) {
  54.             throw new NeuralNetException(NeuralNetException.TOO_SMALL, size, MIN_NEURONS);
  55.         }

  56.         this.wrap = wrap;

  57.         final int fLen = featuresList[0].length;
  58.         network = new Network(0, fLen);
  59.         identifiers = new long[size];

  60.         // Add neurons.
  61.         for (int i = 0; i < size; i++) {
  62.             identifiers[i] = network.createNeuron(featuresList[i]);
  63.         }

  64.         // Add links.
  65.         createLinks();
  66.     }

  67.     /**
  68.      * Creates a one-dimensional network:
  69.      * Each neuron not located on the border of the mesh has two
  70.      * neurons linked to it.
  71.      * <br>
  72.      * The links are bi-directional.
  73.      * Neurons created successively are neighbours (i.e. there are
  74.      * links between them).
  75.      * <br>
  76.      * The topology of the network can also be a circle (if the
  77.      * dimension is wrapped).
  78.      *
  79.      * @param num Number of neurons.
  80.      * @param wrap Whether to wrap the dimension (i.e the first and last
  81.      * neurons will be linked together).
  82.      * @param featureInit Arrays that will initialize the features sets of
  83.      * the network's neurons.
  84.      * @throws IllegalArgumentException if {@code num < 2}.
  85.      */
  86.     public NeuronString(int num,
  87.                         boolean wrap,
  88.                         FeatureInitializer[] featureInit) {
  89.         if (num < MIN_NEURONS) {
  90.             throw new NeuralNetException(NeuralNetException.TOO_SMALL, num, MIN_NEURONS);
  91.         }

  92.         size = num;
  93.         this.wrap = wrap;
  94.         identifiers = new long[num];

  95.         final int fLen = featureInit.length;
  96.         network = new Network(0, fLen);

  97.         // Add neurons.
  98.         for (int i = 0; i < num; i++) {
  99.             final double[] features = new double[fLen];
  100.             for (int fIndex = 0; fIndex < fLen; fIndex++) {
  101.                 features[fIndex] = featureInit[fIndex].value();
  102.             }
  103.             identifiers[i] = network.createNeuron(features);
  104.         }

  105.         // Add links.
  106.         createLinks();
  107.     }

  108.     /**
  109.      * Retrieves the underlying network.
  110.      * A reference is returned (enabling, for example, the network to be
  111.      * trained).
  112.      * This also implies that calling methods that modify the {@link Network}
  113.      * topology may cause this class to become inconsistent.
  114.      *
  115.      * @return the network.
  116.      */
  117.     public Network getNetwork() {
  118.         return network;
  119.     }

  120.     /**
  121.      * Gets the number of neurons.
  122.      *
  123.      * @return the number of neurons.
  124.      */
  125.     public int getSize() {
  126.         return size;
  127.     }

  128.     /**
  129.      * Indicates whether the line of neurons is wrapped.
  130.      *
  131.      * @return {@code true} if the last neuron is linked to the first neuron.
  132.      */
  133.     public boolean isWrapped() {
  134.         return wrap;
  135.     }

  136.     /**
  137.      * Retrieves the features set from the neuron at location
  138.      * {@code i} in the map.
  139.      *
  140.      * @param i Neuron index.
  141.      * @return the features of the neuron at index {@code i}.
  142.      * @throws IllegalArgumentException if {@code i} is out of range.
  143.      */
  144.     public double[] getFeatures(int i) {
  145.         if (i < 0 ||
  146.             i >= size) {
  147.             throw new NeuralNetException(NeuralNetException.OUT_OF_RANGE, i, 0, size - 1);
  148.         }

  149.         return network.getNeuron(identifiers[i]).getFeatures();
  150.     }

  151.     /**
  152.      * Creates the neighbour relationships between neurons.
  153.      */
  154.     private void createLinks() {
  155.         for (int i = 0; i < size - 1; i++) {
  156.             network.addLink(network.getNeuron(i), network.getNeuron(i + 1));
  157.         }
  158.         for (int i = size - 1; i > 0; i--) {
  159.             network.addLink(network.getNeuron(i), network.getNeuron(i - 1));
  160.         }
  161.         if (wrap) {
  162.             network.addLink(network.getNeuron(0), network.getNeuron(size - 1));
  163.             network.addLink(network.getNeuron(size - 1), network.getNeuron(0));
  164.         }
  165.     }
  166. }