/*
* Encog(tm) Java Examples v3.4
* http://www.heatonresearch.com/encog/
* https://github.com/encog/encog-java-examples
*
* Copyright 2008-2016 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.examples.neural.neat.boxes;
import java.util.Random;
import org.encog.mathutil.IntPair;
import org.encog.ml.CalculateScore;
import org.encog.ml.MLMethod;
/**
* The objective function for the boxes experiment. This score is described as
* follows in Kenneth O. Stanley's
* "A Hypercube-Based Indirect Encoding for Evolving Large-Scale Neural Networks"
* .
*
* The field coordinates range between [-1, 1] in the x and y dimensions.
* However, the resolution within this range, i.e. the node density, can be
* varied. During evolution, the resolution of each field is fixed at 11 x 11.
* Thus the connective CPPN must learn to correctly connect a visual field of
* 121 inputs to a target field of 121 outputs, a total of 14,641 potential
* connection strengths.
*
* During evolution, each individual in the population is evaluated for its
* ability to find the center of the bigger object. If the connectivity is not
* highly accurate, it is likely the substrate will often incorrectly choose the
* small object over the large one. Each individual evaluation thus includes 75
* trials, where each trial places the two objects at different locations. The
* trials are organized as follows. The small object appears at 25 uniformly
* distributed locations such that it is always completely within the visual
* field. For each of these 25 locations, the larger object is placed five units
* to the right, down, and diagonally, once per trial. The large object wraps
* around to the other side of the field when it hits the border. If the larger
* object is not completely within the visual field, it is moved the smallest
* distance possible that places it fully in view. Because of wrapping, this
* method of evaluation tests cases where the small object is on all possible
* sides of the large object. Thus many relative positions (though not all) are
* tested for a total number of 75 trials on the 11 by 11 substrate for each
* evaluation during evolution.
*
* Within each trial, the substrate is activated over the entire visual field.
* The unit with the highest activation in the target field is interpreted as
* the substrate's selection. Fitness is calculated from the sum of the squared
* distances between the target and the point of highest activation over all 75
* trials. This fitness function rewards generalization and provides a smooth
* gradient for solutions that are close but not perfect.
*
*/
public class BoxesScore implements CalculateScore {
public static final double EDGE_LEN = 2.0;
public static final double SQR_LEN = 0.5772;
public static final double DIMENSIONS = 3;
private final int resolution;
private final double pixelSize;
public BoxesScore(int theResolution) {
resolution = theResolution;
pixelSize = EDGE_LEN / theResolution;
}
@Override
public double calculateScore(MLMethod phenotype) {
BoxTrialCase test = new BoxTrialCase(new Random());
TrialEvaluation eval = new TrialEvaluation(phenotype, test);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 25; j++) {
IntPair targetPos = eval.getTest().initTestCase(i);
IntPair actualPos = eval.query(this.resolution);
eval.accumulate(
calcRealDistanceSquared(targetPos, actualPos),
Math.max(
0.0,
eval.getMaxActivation()
- eval.getMinActivation()));
}
}
return eval.calculateFitness();
}
private double calcRealDistanceSquared(IntPair a, IntPair b) {
double xdelta = (a.getX() - b.getX()) * pixelSize;
double ydelta = (a.getY() - b.getY()) * pixelSize;
return xdelta * xdelta + ydelta * ydelta;
}
@Override
public boolean shouldMinimize() {
return false;
}
@Override
public boolean requireSingleThreaded() {
return false;
}
}