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 18 package org.apache.commons.math4.neuralnet.oned; 19 20 import org.apache.commons.math4.neuralnet.internal.NeuralNetException; 21 import org.apache.commons.math4.neuralnet.FeatureInitializer; 22 import org.apache.commons.math4.neuralnet.Network; 23 24 /** 25 * Neural network with the topology of a one-dimensional line. 26 * Each neuron defines one point on the line. 27 * 28 * @since 3.3 29 */ 30 public class NeuronString { 31 /** Minimal number of neurons. */ 32 private static final int MIN_NEURONS = 2; 33 /** Underlying network. */ 34 private final Network network; 35 /** Number of neurons. */ 36 private final int size; 37 /** Wrap. */ 38 private final boolean wrap; 39 40 /** 41 * Mapping of the 1D coordinate to the neuron identifiers 42 * (attributed by the {@link #network} instance). 43 */ 44 private final long[] identifiers; 45 46 /** 47 * Constructor with restricted access, solely used for deserialization. 48 * 49 * @param wrap Whether to wrap the dimension (i.e the first and last 50 * neurons will be linked together). 51 * @param featuresList Arrays that will initialize the features sets of 52 * the network's neurons. 53 * @throws IllegalArgumentException if {@code num < 2}. 54 */ 55 NeuronString(boolean wrap, 56 double[][] featuresList) { 57 size = featuresList.length; 58 59 if (size < MIN_NEURONS) { 60 throw new NeuralNetException(NeuralNetException.TOO_SMALL, size, MIN_NEURONS); 61 } 62 63 this.wrap = wrap; 64 65 final int fLen = featuresList[0].length; 66 network = new Network(0, fLen); 67 identifiers = new long[size]; 68 69 // Add neurons. 70 for (int i = 0; i < size; i++) { 71 identifiers[i] = network.createNeuron(featuresList[i]); 72 } 73 74 // Add links. 75 createLinks(); 76 } 77 78 /** 79 * Creates a one-dimensional network: 80 * Each neuron not located on the border of the mesh has two 81 * neurons linked to it. 82 * <br> 83 * The links are bi-directional. 84 * Neurons created successively are neighbours (i.e. there are 85 * links between them). 86 * <br> 87 * The topology of the network can also be a circle (if the 88 * dimension is wrapped). 89 * 90 * @param num Number of neurons. 91 * @param wrap Whether to wrap the dimension (i.e the first and last 92 * neurons will be linked together). 93 * @param featureInit Arrays that will initialize the features sets of 94 * the network's neurons. 95 * @throws IllegalArgumentException if {@code num < 2}. 96 */ 97 public NeuronString(int num, 98 boolean wrap, 99 FeatureInitializer[] featureInit) { 100 if (num < MIN_NEURONS) { 101 throw new NeuralNetException(NeuralNetException.TOO_SMALL, num, MIN_NEURONS); 102 } 103 104 size = num; 105 this.wrap = wrap; 106 identifiers = new long[num]; 107 108 final int fLen = featureInit.length; 109 network = new Network(0, fLen); 110 111 // Add neurons. 112 for (int i = 0; i < num; i++) { 113 final double[] features = new double[fLen]; 114 for (int fIndex = 0; fIndex < fLen; fIndex++) { 115 features[fIndex] = featureInit[fIndex].value(); 116 } 117 identifiers[i] = network.createNeuron(features); 118 } 119 120 // Add links. 121 createLinks(); 122 } 123 124 /** 125 * Retrieves the underlying network. 126 * A reference is returned (enabling, for example, the network to be 127 * trained). 128 * This also implies that calling methods that modify the {@link Network} 129 * topology may cause this class to become inconsistent. 130 * 131 * @return the network. 132 */ 133 public Network getNetwork() { 134 return network; 135 } 136 137 /** 138 * Gets the number of neurons. 139 * 140 * @return the number of neurons. 141 */ 142 public int getSize() { 143 return size; 144 } 145 146 /** 147 * Indicates whether the line of neurons is wrapped. 148 * 149 * @return {@code true} if the last neuron is linked to the first neuron. 150 */ 151 public boolean isWrapped() { 152 return wrap; 153 } 154 155 /** 156 * Retrieves the features set from the neuron at location 157 * {@code i} in the map. 158 * 159 * @param i Neuron index. 160 * @return the features of the neuron at index {@code i}. 161 * @throws IllegalArgumentException if {@code i} is out of range. 162 */ 163 public double[] getFeatures(int i) { 164 if (i < 0 || 165 i >= size) { 166 throw new NeuralNetException(NeuralNetException.OUT_OF_RANGE, i, 0, size - 1); 167 } 168 169 return network.getNeuron(identifiers[i]).getFeatures(); 170 } 171 172 /** 173 * Creates the neighbour relationships between neurons. 174 */ 175 private void createLinks() { 176 for (int i = 0; i < size - 1; i++) { 177 network.addLink(network.getNeuron(i), network.getNeuron(i + 1)); 178 } 179 for (int i = size - 1; i > 0; i--) { 180 network.addLink(network.getNeuron(i), network.getNeuron(i - 1)); 181 } 182 if (wrap) { 183 network.addLink(network.getNeuron(0), network.getNeuron(size - 1)); 184 network.addLink(network.getNeuron(size - 1), network.getNeuron(0)); 185 } 186 } 187 }