/*
* Encog(tm) Core v3.3 - Java Version
* http://www.heatonresearch.com/encog/
* https://github.com/encog/encog-java-core
* Copyright 2008-2014 Heaton Research, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/
package org.encog.mathutil.randomize;
import java.util.Random;
import org.encog.mathutil.matrices.Matrix;
import org.encog.mathutil.randomize.generate.GenerateRandom;
import org.encog.mathutil.randomize.generate.MersenneTwisterGenerateRandom;
import org.encog.ml.MLEncodable;
import org.encog.ml.MLMethod;
import org.encog.neural.networks.BasicNetwork;
/**
* Provides basic functionality that most randomizers will need.
*
* @author jheaton
*
*/
public abstract class BasicRandomizer implements Randomizer {
/**
* The random number generator.
*/
private GenerateRandom random;
/**
* Construct a random number generator with a random(current time) seed. If
* you want to set your own seed, just call "getRandom().setSeed".
*/
public BasicRandomizer() {
this.random = new MersenneTwisterGenerateRandom(System.nanoTime());
}
/**
* @return The random number generator in use. Use this to set the seed, if
* desired.
*/
public final GenerateRandom getRandom() {
return this.random;
}
/**
* @return The next double.
*/
public final double nextDouble() {
return this.random.nextDouble();
}
/**
* Generate a random number in the specified range.
*
* @param min
* The minimum value.
* @param max
* The maximum value.
* @return A random number.
*/
public final double nextDouble(final double min, final double max) {
final double range = max - min;
return (range * this.random.nextDouble()) + min;
}
/**
* Randomize one level of a neural network.
*
* @param network
* The network to randomize
* @param fromLayer
* The from level to randomize.
*/
public void randomize(final BasicNetwork network,
final int fromLayer) {
final int fromCount = network.getLayerTotalNeuronCount(fromLayer);
final int toCount = network.getLayerNeuronCount(fromLayer + 1);
for (int fromNeuron = 0; fromNeuron < fromCount; fromNeuron++) {
for (int toNeuron = 0; toNeuron < toCount; toNeuron++) {
double v = network.getWeight(fromLayer, fromNeuron, toNeuron);
v = randomize(v);
network.setWeight(fromLayer, fromNeuron, toNeuron, v);
}
}
}
/**
* Randomize the array based on an array, modify the array. Previous values
* may be used, or they may be discarded, depending on the randomizer.
*
* @param d
* An array to randomize.
*/
@Override
public void randomize(final double[] d) {
randomize(d, 0, d.length);
}
/**
* Randomize the array based on an array, modify the array. Previous values
* may be used, or they may be discarded, depending on the randomizer.
*
* @param d
* An array to randomize.
* @param begin
* The beginning element of the array.
* @param size
* The size of the array to copy.
*/
@Override
public void randomize(final double[] d, final int begin,
final int size) {
for (int i = 0; i < size; i++) {
d[begin + i] = randomize(d[begin + i]);
}
}
/**
* Randomize the 2d array based on an array, modify the array. Previous
* values may be used, or they may be discarded, depending on the
* randomizer.
*
* @param d
* An array to randomize.
*/
@Override
public void randomize(final double[][] d) {
for (int r = 0; r < d.length; r++) {
for (int c = 0; c < d[0].length; c++) {
d[r][c] = randomize(d[r][c]);
}
}
}
/**
* Randomize the matrix based on an array, modify the array. Previous values
* may be used, or they may be discarded, depending on the randomizer.
*
* @param m
* A matrix to randomize.
*/
@Override
public void randomize(final Matrix m) {
final double[][] d = m.getData();
for (int r = 0; r < m.getRows(); r++) {
for (int c = 0; c < m.getCols(); c++) {
d[r][c] = randomize(d[r][c]);
}
}
}
/**
* Randomize the synapses and biases in the basic network based on an array,
* modify the array. Previous values may be used, or they may be discarded,
* depending on the randomizer.
*
* @param method
* A network to randomize.
*/
@Override
public void randomize(final MLMethod method) {
if (method instanceof BasicNetwork) {
final BasicNetwork network = (BasicNetwork) method;
for (int i = 0; i < network.getLayerCount() - 1; i++) {
randomize(network, i);
}
} else if (method instanceof MLEncodable) {
final MLEncodable encode = (MLEncodable) method;
final double[] encoded = new double[encode.encodedArrayLength()];
encode.encodeToArray(encoded);
randomize(encoded);
encode.decodeFromArray(encoded);
}
}
/**
* @param theRandom
* the random to set
*/
public final void setRandom(final GenerateRandom theRandom) {
this.random = theRandom;
}
}