New GA mutation and crossover operators with subsegment-maintenance
This commit is contained in:
parent
af42465438
commit
e8c14b0aa8
@ -92,6 +92,23 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
|
|||||||
*/
|
*/
|
||||||
public abstract Object clone();
|
public abstract Object clone();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the init/mutation/crossover operator and probabilities to the given values.
|
||||||
|
*
|
||||||
|
* @param initOp
|
||||||
|
* @param mutOp
|
||||||
|
* @param pMut
|
||||||
|
* @param coOp
|
||||||
|
* @param pCross
|
||||||
|
*/
|
||||||
|
public void setOperators(InterfaceInitialization initOp, InterfaceMutation mutOp, double pMut, InterfaceCrossover coOp, double pCross) {
|
||||||
|
m_InitOperator = initOp;
|
||||||
|
m_MutationProbability = pMut;
|
||||||
|
m_MutationOperator = mutOp;
|
||||||
|
m_CrossoverProbability = pCross;
|
||||||
|
m_CrossoverOperator = coOp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the mutation/crossover operator and probabilities to the given values.
|
* Set the mutation/crossover operator and probabilities to the given values.
|
||||||
*
|
*
|
||||||
@ -101,10 +118,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
|
|||||||
* @param pCross
|
* @param pCross
|
||||||
*/
|
*/
|
||||||
public void setOperators(InterfaceMutation mutOp, double pMut, InterfaceCrossover coOp, double pCross) {
|
public void setOperators(InterfaceMutation mutOp, double pMut, InterfaceCrossover coOp, double pCross) {
|
||||||
m_MutationProbability = pMut;
|
setOperators(new DefaultInitialization(), mutOp, pMut, coOp, pCross);
|
||||||
m_MutationOperator = mutOp;
|
|
||||||
m_CrossoverProbability = pCross;
|
|
||||||
m_CrossoverOperator = coOp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,6 +32,11 @@ public class GAIndividualBinaryData extends AbstractEAIndividual implements Inte
|
|||||||
this.m_Genotype = new BitSet();
|
this.m_Genotype = new BitSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GAIndividualBinaryData(int genotypeLen) {
|
||||||
|
this();
|
||||||
|
this.setBinaryDataLength(genotypeLen);
|
||||||
|
}
|
||||||
|
|
||||||
public GAIndividualBinaryData(GAIndividualBinaryData individual) {
|
public GAIndividualBinaryData(GAIndividualBinaryData individual) {
|
||||||
if (individual.m_Phenotype != null)
|
if (individual.m_Phenotype != null)
|
||||||
this.m_Phenotype = (BitSet) individual.m_Phenotype.clone();
|
this.m_Phenotype = (BitSet) individual.m_Phenotype.clone();
|
||||||
@ -131,7 +136,7 @@ public class GAIndividualBinaryData extends AbstractEAIndividual implements Inte
|
|||||||
result += "})\n Value: ";
|
result += "})\n Value: ";
|
||||||
result += "{";
|
result += "{";
|
||||||
for (int i = 0; i < this.m_GenotypeLength; i++) {
|
for (int i = 0; i < this.m_GenotypeLength; i++) {
|
||||||
if (i%10==0) result+="|";
|
if (i%8==0) result+="|";
|
||||||
if (this.m_Genotype.get(i)) result += "1";
|
if (this.m_Genotype.get(i)) result += "1";
|
||||||
else result += "0";
|
else result += "0";
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,15 @@ import eva2.server.go.problems.InterfaceOptimizationProblem;
|
|||||||
import eva2.tools.math.RNG;
|
import eva2.tools.math.RNG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by IntelliJ IDEA.
|
* The famous n-point crossover operator on a binary genotype. Genotypes of
|
||||||
* User: streiche
|
* parent individuals are recombined by exchanging subsegments within randomly
|
||||||
* Date: 18.03.2003
|
* selected points. Therefore, far-away allels (larger GA schemas) are more likely to be split
|
||||||
* Time: 12:45:06
|
* between individuals.
|
||||||
* To change this template use Options | File Templates.
|
*
|
||||||
|
* @author mkron, streiche
|
||||||
*/
|
*/
|
||||||
public class CrossoverGANPoint implements InterfaceCrossover, java.io.Serializable {
|
public class CrossoverGANPoint implements InterfaceCrossover, java.io.Serializable {
|
||||||
private InterfaceOptimizationProblem m_OptimizationProblem;
|
// private InterfaceOptimizationProblem m_OptimizationProblem;
|
||||||
private int m_NumberOfCrossovers = 3;
|
private int m_NumberOfCrossovers = 3;
|
||||||
|
|
||||||
public CrossoverGANPoint() {
|
public CrossoverGANPoint() {
|
||||||
@ -30,7 +31,7 @@ public class CrossoverGANPoint implements InterfaceCrossover, java.io.Serializab
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CrossoverGANPoint(CrossoverGANPoint mutator) {
|
public CrossoverGANPoint(CrossoverGANPoint mutator) {
|
||||||
this.m_OptimizationProblem = mutator.m_OptimizationProblem;
|
// this.m_OptimizationProblem = mutator.m_OptimizationProblem;
|
||||||
this.m_NumberOfCrossovers = mutator.m_NumberOfCrossovers;
|
this.m_NumberOfCrossovers = mutator.m_NumberOfCrossovers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ public class CrossoverGANPoint implements InterfaceCrossover, java.io.Serializab
|
|||||||
return new CrossoverGANPoint(this);
|
return new CrossoverGANPoint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This method performs crossover on two individuals. If the individuals do
|
/** This method performs crossover on multiple individuals. If the individuals do
|
||||||
* not implement InterfaceGAIndividual, then nothing will happen.
|
* not implement InterfaceGAIndividual, then nothing will happen.
|
||||||
* @param indy1 The first individual
|
* @param indy1 The first individual
|
||||||
* @param partners The second individual
|
* @param partners The second individual
|
||||||
@ -58,7 +59,7 @@ public class CrossoverGANPoint implements InterfaceCrossover, java.io.Serializab
|
|||||||
if ((indy1 instanceof InterfaceGAIndividual) && (partners.get(0) instanceof InterfaceGAIndividual)) {
|
if ((indy1 instanceof InterfaceGAIndividual) && (partners.get(0) instanceof InterfaceGAIndividual)) {
|
||||||
int length = ((InterfaceGAIndividual)indy1).getGenotypeLength();
|
int length = ((InterfaceGAIndividual)indy1).getGenotypeLength();
|
||||||
int mixer = RNG.randomInt(0, partners.size());
|
int mixer = RNG.randomInt(0, partners.size());
|
||||||
int[] crossoverPoints = new int[this.m_NumberOfCrossovers];
|
int[] crossoverPoints = null;
|
||||||
BitSet[][] tmpBitSet = new BitSet[2][partners.size()+1];
|
BitSet[][] tmpBitSet = new BitSet[2][partners.size()+1];
|
||||||
|
|
||||||
tmpBitSet[0][0] = ((InterfaceGAIndividual)indy1).getBGenotype();
|
tmpBitSet[0][0] = ((InterfaceGAIndividual)indy1).getBGenotype();
|
||||||
@ -69,10 +70,8 @@ public class CrossoverGANPoint implements InterfaceCrossover, java.io.Serializab
|
|||||||
length = Math.max(length, ((InterfaceGAIndividual)partners.get(i)).getGenotypeLength());
|
length = Math.max(length, ((InterfaceGAIndividual)partners.get(i)).getGenotypeLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < this.m_NumberOfCrossovers; i++) {
|
crossoverPoints=getCrossoverPoints(length, m_NumberOfCrossovers);
|
||||||
crossoverPoints[i] = RNG.randomInt(0, length-1);
|
|
||||||
//System.out.println("crpoint: "+crossoverPoints[i]);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
for (int j = 0; j < this.m_NumberOfCrossovers; j++) {
|
for (int j = 0; j < this.m_NumberOfCrossovers; j++) {
|
||||||
if (i == crossoverPoints[j]) mixer++;
|
if (i == crossoverPoints[j]) mixer++;
|
||||||
@ -88,13 +87,27 @@ public class CrossoverGANPoint implements InterfaceCrossover, java.io.Serializab
|
|||||||
|
|
||||||
for (int i = 0; i < result.length; i++) ((InterfaceGAIndividual)result[i]).SetBGenotype(tmpBitSet[1][i]);
|
for (int i = 0; i < result.length; i++) ((InterfaceGAIndividual)result[i]).SetBGenotype(tmpBitSet[1][i]);
|
||||||
}
|
}
|
||||||
//in case the crossover was successfull lets give the mutation operators a chance to mate the strategy parameters
|
//in case the crossover was successful lets give the mutation operators a chance to mate the strategy parameters
|
||||||
for (int i = 0; i < result.length; i++) result[i].getMutationOperator().crossoverOnStrategyParameters(indy1, partners);
|
for (int i = 0; i < result.length; i++) result[i].getMutationOperator().crossoverOnStrategyParameters(indy1, partners);
|
||||||
//for (int i = 0; i < result.length; i++) System.out.println("After Crossover: " +result[i].getSolutionRepresentationFor());
|
//for (int i = 0; i < result.length; i++) System.out.println("After Crossover: " +result[i].getSolutionRepresentationFor());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This method allows you to evaluate wether two crossover operators
|
/**
|
||||||
|
* Select the crossover points within the genotype of given length.
|
||||||
|
* @param length
|
||||||
|
* @param numberOfCrossovers
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected int[] getCrossoverPoints(int length, int numberOfCrossovers) {
|
||||||
|
int[] crossoverPoints = new int[numberOfCrossovers];
|
||||||
|
for (int i = 0; i < numberOfCrossovers; i++) {
|
||||||
|
crossoverPoints[i] = RNG.randomInt(0, length-1);
|
||||||
|
}
|
||||||
|
return crossoverPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This method allows you to evaluate wether two crossover operators
|
||||||
* are actually the same.
|
* are actually the same.
|
||||||
* @param crossover The other crossover operator
|
* @param crossover The other crossover operator
|
||||||
*/
|
*/
|
||||||
@ -114,7 +127,7 @@ public class CrossoverGANPoint implements InterfaceCrossover, java.io.Serializab
|
|||||||
* @param opt The optimization problem.
|
* @param opt The optimization problem.
|
||||||
*/
|
*/
|
||||||
public void init(AbstractEAIndividual individual, InterfaceOptimizationProblem opt) {
|
public void init(AbstractEAIndividual individual, InterfaceOptimizationProblem opt) {
|
||||||
this.m_OptimizationProblem = opt;
|
// this.m_OptimizationProblem = opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStringRepresentation() {
|
public String getStringRepresentation() {
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
package eva2.server.go.operators.crossover;
|
||||||
|
|
||||||
|
import eva2.tools.math.RNG;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variation of the GA n-point crossover. Restricts crossover to segment bounds
|
||||||
|
* of fixed length, so crossings occur at multiples of the segment length only. Segments
|
||||||
|
* will not be destroyed.
|
||||||
|
*
|
||||||
|
* @author mkron
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CrossoverGANPointSegmentwise extends CrossoverGANPoint {
|
||||||
|
int segmentLength=8;
|
||||||
|
|
||||||
|
public CrossoverGANPointSegmentwise() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrossoverGANPointSegmentwise(CrossoverGANPointSegmentwise o) {
|
||||||
|
super(o);
|
||||||
|
this.segmentLength=o.segmentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrossoverGANPointSegmentwise(int nPoints, int segmentLen) {
|
||||||
|
super(nPoints);
|
||||||
|
setSegmentLength(segmentLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object clone() {
|
||||||
|
return new CrossoverGANPointSegmentwise(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object crossover) {
|
||||||
|
if (super.equals(crossover) && (crossover instanceof CrossoverGANPointSegmentwise)) {
|
||||||
|
return ((CrossoverGANPointSegmentwise)crossover).segmentLength==this.segmentLength;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int[] getCrossoverPoints(int length, int numberOfCrossovers) {
|
||||||
|
int[] cPoints = new int[numberOfCrossovers];
|
||||||
|
int i=0;
|
||||||
|
while (i<numberOfCrossovers && (i<length/segmentLength)) {
|
||||||
|
cPoints[i]=segmentLength*RNG.randomInt(length/segmentLength);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return cPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return "GA N-Point segment-wise crossover";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String globalInfo() {
|
||||||
|
return "This is an n-point crossover between m individuals which also splits at certain segment limits. Crossover points are selected from multiples of the segment length.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSegmentLength() {
|
||||||
|
return segmentLength;
|
||||||
|
}
|
||||||
|
public void setSegmentLength(int segmentLength) {
|
||||||
|
this.segmentLength = segmentLength;
|
||||||
|
}
|
||||||
|
public String segmentLengthTipText() {
|
||||||
|
return "The fixed length of segments (genes) which are not split by crossover.";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,6 +4,7 @@ import java.util.BitSet;
|
|||||||
|
|
||||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||||
import eva2.server.go.individuals.InterfaceGAIndividual;
|
import eva2.server.go.individuals.InterfaceGAIndividual;
|
||||||
|
import eva2.server.go.individuals.InterfaceGIIndividual;
|
||||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||||
import eva2.tools.EVAERROR;
|
import eva2.tools.EVAERROR;
|
||||||
import eva2.tools.math.RNG;
|
import eva2.tools.math.RNG;
|
||||||
@ -65,23 +66,25 @@ public class GAInitializeSegmentwise implements InterfaceInitialization, java.io
|
|||||||
if (k<genotypeLen) genotype.set(k, nextSeg.get(k-i));
|
if (k<genotypeLen) genotype.set(k, nextSeg.get(k-i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// write back the genotype (it may have been cloned, who knows...)
|
|
||||||
gaIndy.SetBGenotype(genotype);
|
|
||||||
} else { // the number of bits to set may vary from segment to segment.
|
} else { // the number of bits to set may vary from segment to segment.
|
||||||
if (bitsPerSegmentArray.length * segmentLength != genotypeLen) EVAERROR.errorMsgOnce("Warning, potential mismatch between segment lengths and genotype length in " + this.getClass());
|
if (bitsPerSegmentArray.length * segmentLength != genotypeLen) EVAERROR.errorMsgOnce("Warning, potential mismatch between segment lengths and genotype length in " + this.getClass());
|
||||||
if (bitsPerSegmentArray.length * segmentLength < genotypeLen) System.err.println("Warning, " + (genotypeLen - bitsPerSegmentArray.length * segmentLength) + " bits will not be initialized!");
|
if (bitsPerSegmentArray.length * segmentLength < genotypeLen) System.err.println("Warning, " + (genotypeLen - bitsPerSegmentArray.length * segmentLength) + " bits will not be initialized!");
|
||||||
for (int s=0; s<bitsPerSegmentArray.length; s++) {
|
for (int s=0; s<bitsPerSegmentArray.length; s++) {
|
||||||
// look at each segment individually
|
// look at each segment individually
|
||||||
BitSet nextSeg=RNG.randomBitSet(bitsPerSegmentArray[s], bitsPerSegment);
|
BitSet nextSeg=RNG.randomBitSet(bitsPerSegmentArray[s], segmentLength);
|
||||||
for (int k=(s)*bitsPerSegment; k<(s+1)*bitsPerSegment; k++) {
|
for (int k=(s)*segmentLength; k<(s+1)*segmentLength; k++) {
|
||||||
if (k<genotypeLen) genotype.set(k, nextSeg.get(k-(s*bitsPerSegment)));
|
if (k<genotypeLen) genotype.set(k, nextSeg.get(k-(s*segmentLength)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// write back the genotype (it may have been cloned, who knows...)
|
||||||
|
gaIndy.SetBGenotype(genotype);
|
||||||
|
// System.out.println(genotype.cardinality());
|
||||||
|
} else if (indy instanceof InterfaceGIIndividual) {
|
||||||
|
// TODO ADD INTEGER IMPLEMENTATION???
|
||||||
} else throw new RuntimeException("Error: "+ this.getClass() + " must be used with individuals of type " + InterfaceGAIndividual.class + "!");
|
} else throw new RuntimeException("Error: "+ this.getClass() + " must be used with individuals of type " + InterfaceGAIndividual.class + "!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int[] getBitsPerSegmentArray() {
|
public int[] getBitsPerSegmentArray() {
|
||||||
return bitsPerSegmentArray;
|
return bitsPerSegmentArray;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,219 @@
|
|||||||
|
package eva2.server.go.operators.mutation;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||||
|
import eva2.server.go.individuals.InterfaceGAIndividual;
|
||||||
|
import eva2.server.go.populations.Population;
|
||||||
|
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||||
|
import eva2.tools.EVAERROR;
|
||||||
|
import eva2.tools.math.RNG;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap two random bits of a GA individual within subsequences (segments) of fixed length.
|
||||||
|
* If preferPairs is true, unequal pairs
|
||||||
|
* are picked with some preference (by trying for >= s/2 times, where s is the binary
|
||||||
|
* segment length).
|
||||||
|
* Multiple mutations per segment can occur if the boolean switch is activated, meaning
|
||||||
|
* that further mutations are performed recursively with p_mut. Thus, the probability
|
||||||
|
* to perform k mutations per segment is (p_mut)^k. However, more than s mutations per segment will
|
||||||
|
* never be performed.
|
||||||
|
*
|
||||||
|
* User: mkron
|
||||||
|
* Date: 05.08.2004
|
||||||
|
* Time: 17:45:36
|
||||||
|
* To change this template use File | Settings | File Templates.
|
||||||
|
*/
|
||||||
|
public class MutateGASwapBitsSegmentwise implements InterfaceMutation, java.io.Serializable {
|
||||||
|
private double mutationProbPerSegment = 0.7;
|
||||||
|
private boolean multiplesPerSegment = false;
|
||||||
|
private int segmentLength = 8;
|
||||||
|
private boolean preferPairs = true; // if true, pairs of (1,0) are swapped with higher probability
|
||||||
|
|
||||||
|
public MutateGASwapBitsSegmentwise() {
|
||||||
|
|
||||||
|
}
|
||||||
|
public MutateGASwapBitsSegmentwise(MutateGASwapBitsSegmentwise mutator) {
|
||||||
|
this.mutationProbPerSegment = mutator.mutationProbPerSegment;
|
||||||
|
this.setPreferTrueChange(mutator.isPreferTrueChange());
|
||||||
|
this.multiplesPerSegment = mutator.multiplesPerSegment;
|
||||||
|
this.segmentLength = mutator.segmentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A constructor setting all properties.
|
||||||
|
*
|
||||||
|
* @param p_mut
|
||||||
|
* @param multPerSeg
|
||||||
|
* @param segmentLen
|
||||||
|
* @param prefPairs
|
||||||
|
*/
|
||||||
|
public MutateGASwapBitsSegmentwise(double p_mut, boolean multPerSeg, int segmentLen, boolean prefPairs) {
|
||||||
|
mutationProbPerSegment=p_mut;
|
||||||
|
multiplesPerSegment=multPerSeg;
|
||||||
|
segmentLength=segmentLen;
|
||||||
|
preferPairs=prefPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This method will enable you to clone a given mutation operator
|
||||||
|
* @return The clone
|
||||||
|
*/
|
||||||
|
public Object clone() {
|
||||||
|
return new MutateGASwapBitsSegmentwise(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This method allows you to evaluate wether two mutation operators
|
||||||
|
* are actually the same.
|
||||||
|
* @param mutator The other mutation operator
|
||||||
|
*/
|
||||||
|
public boolean equals(Object mutator) {
|
||||||
|
if (mutator instanceof MutateGASwapBitsSegmentwise) {
|
||||||
|
MutateGASwapBitsSegmentwise mut = (MutateGASwapBitsSegmentwise)mutator;
|
||||||
|
if (this.mutationProbPerSegment != mut.mutationProbPerSegment) return false;
|
||||||
|
if (this.segmentLength != mut.segmentLength) return false;
|
||||||
|
if (this.multiplesPerSegment != mut.multiplesPerSegment) return false;
|
||||||
|
if (this.preferPairs != mut.preferPairs) return false;
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This method allows you to init the mutation operator
|
||||||
|
* @param individual The individual that will be mutated.
|
||||||
|
* @param opt The optimization problem.
|
||||||
|
*/
|
||||||
|
public void init(AbstractEAIndividual individual, InterfaceOptimizationProblem opt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This method allows you to perform either crossover on the strategy parameters
|
||||||
|
* or to deal in some other way with the crossover event.
|
||||||
|
* @param indy1 The original mother
|
||||||
|
* @param partners The original partners
|
||||||
|
*/
|
||||||
|
public void crossoverOnStrategyParameters(AbstractEAIndividual indy1, Population partners) {
|
||||||
|
// nothing to do here
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This method will mutate a given AbstractEAIndividual. If the individual
|
||||||
|
* doesn't implement InterfaceGAIndividual nothing happens.
|
||||||
|
* @param individual The individual that is to be mutated
|
||||||
|
*/
|
||||||
|
public void mutate(AbstractEAIndividual individual) {
|
||||||
|
//System.out.println("Before Mutate: " +((GAIndividual)individual).getSolutionRepresentationFor());
|
||||||
|
if (individual instanceof InterfaceGAIndividual) {
|
||||||
|
BitSet tmpBitSet = ((InterfaceGAIndividual)individual).getBGenotype();
|
||||||
|
int genLen=((InterfaceGAIndividual)individual).getGenotypeLength();
|
||||||
|
for (int i=0; i<genLen; i+=segmentLength) {
|
||||||
|
if (i+segmentLength>genLen) { // avoid to violate genotype length in a segment mutation
|
||||||
|
EVAERROR.errorMsgOnce("Warning, genotype length is not a multiple of the segment length.. ignoring last bits in " + this.getClass());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (RNG.flipCoin(mutationProbPerSegment)) {
|
||||||
|
int cntMutes=0;
|
||||||
|
// swap bits within a segment within certain probability
|
||||||
|
do { // this may happen multiple times depending on the settings
|
||||||
|
swapBitsInSegmentAt(tmpBitSet, i, segmentLength);
|
||||||
|
cntMutes++;
|
||||||
|
// multiples only if the corresponding switch is true and another flipCoin succeeds.
|
||||||
|
// more than segmentLength mutations will never be performed per segment
|
||||||
|
} while(multiplesPerSegment && cntMutes<segmentLength && RNG.flipCoin(mutationProbPerSegment));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
((InterfaceGAIndividual)individual).SetBGenotype(tmpBitSet); // write back the genotype
|
||||||
|
}
|
||||||
|
//System.out.println("After Mutate: " +((GAIndividual)individual).getSolutionRepresentationFor());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap one pair of bits within an indicated segment.
|
||||||
|
*
|
||||||
|
* @param tmpBitSet
|
||||||
|
* @param i
|
||||||
|
* @param segmentLength2
|
||||||
|
*/
|
||||||
|
private void swapBitsInSegmentAt(BitSet bs, int i, int segLen) {
|
||||||
|
int indexOne = getRandomIndex(bs, i, segLen, true); // may prefer true bits
|
||||||
|
int indexTwo = getRandomIndex(bs, i, segLen, false); // may prefer false bits
|
||||||
|
|
||||||
|
boolean tmpBit = bs.get(indexTwo);
|
||||||
|
bs.set(indexTwo, bs.get(indexOne));
|
||||||
|
bs.set(indexOne, tmpBit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getRandomIndex(BitSet bs, int offset, int len, boolean maybePrefered) {
|
||||||
|
int k = RNG.randomInt(offset, offset+len-1);
|
||||||
|
if (isPreferTrueChange()) {
|
||||||
|
int maxTries=(1+len)/2;
|
||||||
|
while (!(maybePrefered==bs.get(k)) && (maxTries>=0)) {
|
||||||
|
k=RNG.randomInt(offset, offset+len-1); ; // try next random position
|
||||||
|
maxTries--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private int getRandomSecondIndex(int firstIndex, AbstractEAIndividual individual) {
|
||||||
|
// int genoLen = ((InterfaceGAIndividual)individual).getGenotypeLength();
|
||||||
|
// return RNG.randomInt(0, genoLen);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/** This method allows you to get a string representation of the mutation
|
||||||
|
* operator
|
||||||
|
* @return A descriptive string.
|
||||||
|
*/
|
||||||
|
public String getStringRepresentation() {
|
||||||
|
return "GA swap bits segment-wise mutation";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************
|
||||||
|
* These are for GUI
|
||||||
|
*/
|
||||||
|
/** This method allows the CommonJavaObjectEditorPanel to read the
|
||||||
|
* name to the current object.
|
||||||
|
* @return The name.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return "GA swap bits segment-wise mutation";
|
||||||
|
}
|
||||||
|
/** This method returns a global info string
|
||||||
|
* @return description
|
||||||
|
*/
|
||||||
|
public static String globalInfo() {
|
||||||
|
return "This mutation operator swaps bits in subsegments of the genotype.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreferTrueChange(boolean preferPairs) {
|
||||||
|
this.preferPairs = preferPairs;
|
||||||
|
}
|
||||||
|
public boolean isPreferTrueChange() {
|
||||||
|
return preferPairs;
|
||||||
|
}
|
||||||
|
public String preferTrueChangeTipText() {
|
||||||
|
return "If set to true, mutation events will prefer swapping 1 and 0";
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMutationProbPerSegment() {
|
||||||
|
return mutationProbPerSegment;
|
||||||
|
}
|
||||||
|
public void setMutationProbPerSegment(double mutationProbPerSegment) {
|
||||||
|
this.mutationProbPerSegment = mutationProbPerSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMultiplesPerSegment() {
|
||||||
|
return multiplesPerSegment;
|
||||||
|
}
|
||||||
|
public void setMultiplesPerSegment(boolean multiplesPerSegment) {
|
||||||
|
this.multiplesPerSegment = multiplesPerSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSegmentLength() {
|
||||||
|
return segmentLength;
|
||||||
|
}
|
||||||
|
public void setSegmentLength(int segmentLength) {
|
||||||
|
this.segmentLength = segmentLength;
|
||||||
|
}
|
||||||
|
public String segmentLengthTipText() {
|
||||||
|
return "The length of sub-segments to regard (substrings of the GA genotype)";
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user