/* * Encog(tm) Core v3.4 - Java Version * http://www.heatonresearch.com/encog/ * https://github.com/encog/encog-java-core * 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.neural.neat.training.species; import org.encog.ml.ea.genome.Genome; import org.encog.ml.ea.species.ThresholdSpeciation; import org.encog.neural.neat.training.NEATGenome; /** * The original NEAT Speciation Strategy. This is currently the only speciation * strategy implemented by Encog. There are other speciation strategies that * have been proposed (and implemented) for NEAT. One example is k-means. * * NEAT starts up by creating an initial population of genomes with randomly * generated connections between input and output nodes. Not every input neuron * is necessarily connected, this allows NEAT to determine which input neurons * to use. Once the population has been generated it is speciated by iterating * over this population of genomes. The first genome is placed in its own * species. * * The second genome is then compared to the first genome. If the compatibility * is below the threshold then the genome is placed into the same species as the * first. If not, the second genome founds a new species of its own. The * remaining genomes follow this same process. * * ----------------------------------------------------------------------------- * http://www.cs.ucf.edu/~kstanley/ Encog's NEAT implementation was drawn from * the following three Journal Articles. For more complete BibTeX sources, see * NEATNetwork.java. * * Evolving Neural Networks Through Augmenting Topologies * * Generating Large-Scale Neural Networks Through Discovering Geometric * Regularities * * Automatic feature selection in neuroevolution */ public class OriginalNEATSpeciation extends ThresholdSpeciation { /** * The serial id */ private static final long serialVersionUID = 1L; /** * The adjustment factor for disjoint genes. */ private double constDisjoint = 1; /** * The adjustment factor for excess genes. */ private double constExcess = 1; /** * The adjustment factor for matched genes. */ private double constMatched = 0.4; /** * {@inheritDoc} */ @Override public double getCompatibilityScore(final Genome gen1, final Genome gen2) { double numDisjoint = 0; double numExcess = 0; double numMatched = 0; double weightDifference = 0; final NEATGenome genome1 = (NEATGenome)gen1; final NEATGenome genome2 = (NEATGenome)gen2; final int genome1Size = genome1.getLinksChromosome().size(); final int genome2Size = genome2.getLinksChromosome().size(); final int n = 1;// Math.max(genome1Size, genome2Size); int g1 = 0; int g2 = 0; while ((g1 < genome1Size) || (g2 < genome2Size)) { if (g1 == genome1Size) { g2++; numExcess++; continue; } if (g2 == genome2Size) { g1++; numExcess++; continue; } // get innovation numbers for each gene at this point final long id1 = genome1.getLinksChromosome().get(g1) .getInnovationId(); final long id2 = genome2.getLinksChromosome().get(g2) .getInnovationId(); // innovation numbers are identical so increase the matched score if (id1 == id2) { // get the weight difference between these two genes weightDifference += Math.abs(genome1.getLinksChromosome() .get(g1).getWeight() - genome2.getLinksChromosome().get(g2).getWeight()); g1++; g2++; numMatched++; } // innovation numbers are different so increment the disjoint score if (id1 < id2) { numDisjoint++; g1++; } if (id1 > id2) { ++numDisjoint; ++g2; } } final double score = ((this.constExcess * numExcess) / n) + ((this.constDisjoint * numDisjoint) / n) + (this.constMatched * (weightDifference / numMatched)); return score; } /** * @return the constDisjoint */ public double getConstDisjoint() { return this.constDisjoint; } /** * @return the constExcess */ public double getConstExcess() { return this.constExcess; } /** * @return the constMatched */ public double getConstMatched() { return this.constMatched; } /** * @param constDisjoint * the constDisjoint to set */ public void setConstDisjoint(final double constDisjoint) { this.constDisjoint = constDisjoint; } /** * @param constExcess * the constExcess to set */ public void setConstExcess(final double constExcess) { this.constExcess = constExcess; } /** * @param constMatched * the constMatched to set */ public void setConstMatched(final double constMatched) { this.constMatched = constMatched; } }