![JAR search and dependency download from the Maven repository](/logo.png)
org.jgap.gp.impl.BranchTypingCross Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jgap Show documentation
Show all versions of jgap Show documentation
JGAP is a Genetic Algorithms and Genetic Programming component provided as a Java framework.
The newest version!
/*
* This file is part of JGAP.
*
* JGAP offers a dual license model containing the LGPL as well as the MPL.
*
* For licensing information please see the file license.txt included with JGAP
* or have a look at the top of class org.jgap.Chromosome which representatively
* includes the JGAP license policy applicable for any file delivered with JGAP.
*/
package org.jgap.gp.impl;
import java.io.*;
import org.jgap.*;
import org.jgap.gp.*;
/**
* Crossing over for GP ProgramChromosomes.
*
* @author Klaus Meffert
* @since 3.0
*/
public class BranchTypingCross
extends CrossMethod implements Serializable, Comparable, Cloneable {
/** String containing the CVS revision. Read out via reflection!*/
private final static String CVS_REVISION = "$Revision: 1.19 $";
private boolean m_simpleChromosomeSelection;
/**
* Standard constructor.
*
* @param a_config the configuration to use
*/
public BranchTypingCross(GPConfiguration a_config) {
this(a_config, false);
}
/**
*
* @param a_config the configuration to use
* @param a_simpleChromosomeSelection true: plainly select chromosomes,
* false: select chromosomes proportionally to their size (=number of nodes
* within a chromosome)
*
* @author Klaus Meffert
* @since 3.4
*/
public BranchTypingCross(GPConfiguration a_config,
boolean a_simpleChromosomeSelection) {
super(a_config);
m_simpleChromosomeSelection = a_simpleChromosomeSelection;
}
/**
* Crosses two individuals. A random chromosome is chosen for crossing based
* on the proportion of nodes in each chromosome in the first individual.
*
* @param a_i1 the first individual to cross
* @param a_i2 the second individual to cross
* @return an array of the two resulting individuals
*
* @author Klaus Meffert
* @since 3.0
*/
public IGPProgram[] operate(final IGPProgram a_i1,
final IGPProgram a_i2) {
try {
int chromosomeNum;
if (!m_simpleChromosomeSelection) {
// Determine which chromosome we'll cross, probabilistically determined
// by the sizes of the chromosomes of the first individual.
// This is equivalent to Koza's branch typing.
// Advantage over plain selection: proportion of the chromosomes' sizes
// is cared about.
// --------------------------------------------------------------------
int[] sizes = new int[a_i1.size()];
int totalSize = 0;
for (int i = 0; i < a_i1.size(); i++) {
// Size of a chromosome = number of nodes.
// ---------------------------------------
sizes[i] = a_i1.getChromosome(i).getSize(0);
totalSize += sizes[i];
}
int nodeNum = getConfiguration().getRandomGenerator().nextInt(
totalSize);
// Select the chromosome in which node "nodeNum" resides.
// ------------------------------------------------------
for (chromosomeNum = 0; chromosomeNum < a_i1.size(); chromosomeNum++) {
nodeNum -= sizes[chromosomeNum];
if (nodeNum < 0) {
break;
}
}
} else {
// Select a chromosome directly.
// -----------------------------
chromosomeNum = getConfiguration().getRandomGenerator().
nextInt(a_i1.size());
}
// Cross the selected chromosomes.
// -------------------------------
/**@todo try to ensure uniqueness for unique commands:
* after selecting first node, check if there is a unique node in the sub
* tree. If so, check if it appears in the sub tree of the second node.
*/
ProgramChromosome[] newChromosomes = doCross(
a_i1.getChromosome(chromosomeNum),
a_i2.getChromosome(chromosomeNum));
// Create the new individuals by copying the uncrossed chromosomes
// and setting the crossed chromosome. There's no need to deep-copy
// the uncrossed chromosomes because they don't change. That is,
// even if two individuals' chromosomes point to the same chromosome,
// the only change in a chromosome is crossing, which generates
// deep-copied chromosomes anyway.
// ------------------------------------------------------------------
IGPProgram[] newIndividuals = {
new GPProgram(a_i1), new GPProgram(a_i1)};
for (int i = 0; i < a_i1.size(); i++)
if (i != chromosomeNum) {
// Unchanged, not crossed, chromosomes.
// ------------------------------------
newIndividuals[0].setChromosome(i, a_i1.getChromosome(i));
newIndividuals[1].setChromosome(i, a_i2.getChromosome(i));
}
else {
// The crossed chromosomes.
// ------------------------
newIndividuals[0].setChromosome(i, newChromosomes[0]);
newIndividuals[1].setChromosome(i, newChromosomes[1]);
}
return newIndividuals;
} catch (InvalidConfigurationException iex) {
return null;
}
}
/**
* Crosses two chromsomes using branch-typing.
* A random point in the first chromosome is chosen, with a certain probability
* it will be a function and with a rest probability it will be a terminal. A
* random point in the second chromosome is chosen using the same probability
* distribution, but the node chosen must be of the same type as the chosen
* node in the first chromosome.
* If a suitable point in the second chromosome couldn't be found then the
* chromosomes are not crossed.
* If a resulting chromosome's depth is larger than the maximum crossover
* depth then that chromosome is simply copied from the original
* rather than crossed.
*
* @param a_c0 the first chromosome to cross
* @param a_c1 the second chromosome to cross
* @return an array of the two resulting chromosomes
* @throws InvalidConfigurationException
*
* @author Klaus Meffert
* @since 3.0
*/
protected ProgramChromosome[] doCross(ProgramChromosome a_c0,
ProgramChromosome a_c1)
throws InvalidConfigurationException {
ProgramChromosome[] c = {
a_c0, a_c1};
// Choose a point in c1.
// ---------------------
int p0;
RandomGenerator random = getConfiguration().getRandomGenerator();
if (random.nextFloat() < getConfiguration().getFunctionProb()) {
// Choose a function.
// ------------------
int nf = a_c0.numFunctions();
if (nf == 0) {
// No functions there.
// -------------------
return c;
}
int fctIndex = random.nextInt(nf);
p0 = a_c0.getFunction(fctIndex);
}
else {
// Choose a terminal.
// ------------------
p0 = a_c0.getTerminal(random.nextInt(a_c0.numTerminals()));
// Mutate the command's value.
// ----------------------------
CommandGene command = a_c0.getNode(p0);
if (random.nextDouble() <= getConfiguration().getMutationProb()) {
if (IMutateable.class.isInstance(command)) {
IMutateable term = (IMutateable) command;
command = term.applyMutation(0, 0.3d);
if (command != null) {
// Check if mutant's function is allowed.
// --------------------------------------
if (a_c0.getCommandOfClass(0, command.getClass()) >= 0) {
a_c0.setGene(p0, command);
}
}
}
}
}
// Choose a point in c2 matching the type and subtype of p0.
// ---------------------------------------------------------
int p1;
CommandGene nodeP0 = a_c0.getNode(p0);
Class type_ = nodeP0.getReturnType();
int subType = nodeP0.getSubReturnType();
if (random.nextFloat() < getConfiguration().getFunctionProb()) {
// Choose a function.
// ------------------
int nf = a_c1.numFunctions(type_, subType);
if (nf == 0) {
// No functions of that type.
// --------------------------
return c;
}
p1 = a_c1.getFunction(random.nextInt(nf), type_, subType);
}
else {
// Choose a terminal.
// ------------------
int nt = a_c1.numTerminals(type_, subType);
if (nt == 0) {
// No terminals of that type.
// --------------------------
return c;
}
p1 = a_c1.getTerminal(random.nextInt(a_c1.numTerminals(type_, subType)),
type_, subType);
// Mutate the command's value.
// ----------------------------
CommandGene command = a_c1.getNode(p1);
if (random.nextDouble() <= getConfiguration().getMutationProb()) {
if (IMutateable.class.isInstance(command)) {
IMutateable term = (IMutateable) command;
command = term.applyMutation(0, 0.3d);
if (command != null) {
// Check if mutant's function is allowed.
// --------------------------------------
if (a_c0.getCommandOfClass(0, command.getClass()) >= 0) {
a_c1.setGene(p1, command);
}
}
}
}
}
/**@todo solve in general*/
if (org.jgap.gp.function.SubProgram.class.isAssignableFrom(a_c1.getFunctions()[p1].getClass())) {
((IMutateable)a_c1.getFunctions()[p1]).applyMutation(0, 0.5d);
}
int s0 = a_c0.getSize(p0); //Number of nodes in c0 from index p0
int s1 = a_c1.getSize(p1); //Number of nodes in c1 from index p1
int d0 = a_c0.getDepth(p0); //Depth of c0 from index p0
int d1 = a_c1.getDepth(p1); //Depth of c1 from index p1
int c0s = a_c0.getSize(0); //Number of nodes in c0
int c1s = a_c1.getSize(0); //Number of nodes in c1
// Check for depth constraint for p1 inserted into c0.
// ---------------------------------------------------
if (d0 - 1 + d1/*s1*/ > getConfiguration().getMaxCrossoverDepth()
|| c0s - p0 - s0 < 0
|| p0 + s1 + c0s - p0 - s0 >= a_c0.getFunctions().length) {
// Choose the other parent.
// ------------------------
c[0] = a_c1;
}
else {
c[0] = new ProgramChromosome(getConfiguration(),
a_c0.getFunctions().length,
c[0].getFunctionSet(),
c[0].getArgTypes(),
a_c0.getIndividual());
System.arraycopy(a_c0.getFunctions(), 0, c[0].getFunctions(), 0, p0);
System.arraycopy(a_c1.getFunctions(), p1, c[0].getFunctions(), p0, s1);
System.arraycopy(a_c0.getFunctions(), p0 + s0, c[0].getFunctions(),
p0 + s1, c0s - p0 - s0);
c[0].redepth();
}
// Check for depth constraint for p0 inserted into c1.
// ---------------------------------------------------
if (d1 - 1 + d0/*s0*/ > getConfiguration().getMaxCrossoverDepth()
|| c1s - p1 - s1 < 0
|| p1 + s0 + c1s - p1 - s1 >= a_c1.getFunctions().length) {
// Choose the other parent.
// ------------------------
c[1] = a_c0;
}
else {
c[1] = new ProgramChromosome(getConfiguration(),
a_c1.getFunctions().length,
c[1].getFunctionSet(),
c[1].getArgTypes(),
a_c1.getIndividual());
System.arraycopy(a_c1.getFunctions(), 0, c[1].getFunctions(), 0, p1);
System.arraycopy(a_c0.getFunctions(), p0, c[1].getFunctions(), p1, s0);
System.arraycopy(a_c1.getFunctions(), p1 + s1, c[1].getFunctions(),
p1 + s0, c1s - p1 - s1);
c[1].redepth();
}
return c;
}
/**
* The compareTo-method.
*
* @param a_other the other object to compare
* @return 0 or 1 in this case, as BranchTypingCross objects keep no state
*
* @author Klaus Meffert
* @since 3.0
*/
public int compareTo(Object a_other) {
BranchTypingCross other = (BranchTypingCross) a_other;
if (other == null) {
return 1;
}
return 0;
}
/**
* The equals-method.
*
* @param a_other the other object to compare
* @return always true for non-null BranchTypingCross objects because they
* keep no state
*
* @author Klaus Meffert
* @since 3.0
*/
public boolean equals(Object a_other) {
try {
BranchTypingCross other = (BranchTypingCross) a_other;
if (other == null) {
return false;
}
else {
return true;
}
} catch (ClassCastException cex) {
return false;
}
}
/**
* @return deep clone of this instance
*
* @author Klaus Meffert
* @since 3.2
*/
public Object clone() {
BranchTypingCross result = new BranchTypingCross(getConfiguration());
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy