Additional integer mutation operator

This commit is contained in:
Marcel Kronfeld
2011-01-27 10:02:10 +00:00
parent e0e78a1ad3
commit 9dfcf4d71a
2 changed files with 176 additions and 12 deletions

View File

@@ -10,11 +10,12 @@ import eva2.tools.EVAERROR;
import eva2.tools.math.RNG; import eva2.tools.math.RNG;
/** /**
* An initialization method which sets a fixed number of specified values per segment, * An initialization method which sets a fixed number of specified target elements per segment,
* where a segment is a connected subsequence of the genotype. * where a segment is a connected subsequence of the genotype.
* This is usable for binary and integer individuals only. * This is usable for binary and integer individuals only.
* For binary individuals, this allows to control the number of bits per segment. For * For binary individuals, this allows to control the number of bits per segment by
* integer individuals, it allows to control the number of occurences of a certain integer * setting the target element to '1'. For
* integer individuals, it allows to control the number of occurrences of a certain integer
* per segment. It may also be used to initialize with subsets of integers (by setting 0 * per segment. It may also be used to initialize with subsets of integers (by setting 0
* elements to a certain type and all to a subset of the range). * elements to a certain type and all to a subset of the range).
* *
@@ -27,7 +28,6 @@ import eva2.tools.math.RNG;
* has strict priority over the fixed cardinality definition. * has strict priority over the fixed cardinality definition.
* *
* @author mkron * @author mkron
*
*/ */
public class GAGIInitializeSegmentwise implements InterfaceInitialization, java.io.Serializable { public class GAGIInitializeSegmentwise implements InterfaceInitialization, java.io.Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -178,24 +178,24 @@ public class GAGIInitializeSegmentwise implements InterfaceInitialization, java.
else return (targetElement!=1); else return (targetElement!=1);
} }
public int[] getBitsPerSegmentArray() { public int[] getTargetElementsPerSegmentArray() {
return bitsPerSegmentArray; return bitsPerSegmentArray;
} }
public void setBitsPerSegmentArray(int[] bitsPerSegmentArray) { public void setTargetElementsPerSegmentArray(int[] bitsPerSegmentArray) {
this.bitsPerSegmentArray = bitsPerSegmentArray; this.bitsPerSegmentArray = bitsPerSegmentArray;
} }
public String bitsPerSegmentArrayTipText() { public String targetElementsPerSegmentArrayTipText() {
return "A value per segment defining the number of bits to set for that segment, or null if fixed"; return "A value per segment defining the number of target elements to set for that segment, or null if fixed";
} }
public int getBitsPerSegment() { public int getTargetElementsPerSegment() {
return bitsPerSegment; return bitsPerSegment;
} }
public void setBitsPerSegment(int bitsPerSegment) { public void setTargetElementsPerSegment(int bitsPerSegment) {
this.bitsPerSegment = bitsPerSegment; this.bitsPerSegment = bitsPerSegment;
} }
public String bitsPerSegmentTipText() { public String targetElementsPerSegmentTipText() {
return "If not array-wise defined, this fixed number of bits is set per segment"; return "If not defined as an array, this fixed number of target elements is set per segment";
} }
public int getSegmentLength() { public int getSegmentLength() {

View File

@@ -0,0 +1,164 @@
package eva2.server.go.operators.mutation;
import java.io.Serializable;
import eva2.gui.BeanInspector;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceGIIndividual;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import eva2.tools.EVAERROR;
import eva2.tools.math.RNG;
/**
* An integer mutation operator which switches elements within a given subset only.
*
* @author mkron
*
*/
public class MutateGISubset implements InterfaceMutation, Serializable {
private int[] mutableSet = new int[]{0,1};
private int minNumMutations = 1;
private int maxNumMutations = 3;
private boolean enforceMutablePositions = true;
public MutateGISubset() {}
public MutateGISubset(MutateGISubset o) {
this.minNumMutations = o.minNumMutations;
this.maxNumMutations = o.maxNumMutations;
this.enforceMutablePositions = o.enforceMutablePositions;
if (o.mutableSet!=null) {
this.mutableSet=new int[o.mutableSet.length];
System.arraycopy(o.mutableSet, 0, this.mutableSet, 0, o.mutableSet.length);
}
}
public MutateGISubset(int[] muteSet, int minMutes, int maxMutes) {
setMutableSet(muteSet);
setMinNumMutations(minMutes);
setMaxNumMutations(maxMutes);
}
public Object clone() {
return new MutateGISubset(this);
}
public void crossoverOnStrategyParameters(AbstractEAIndividual indy1,
Population partners) {
// nothing to do
}
public String getStringRepresentation() {
return "GI subset mutation in " + BeanInspector.toString(mutableSet);
}
public void init(AbstractEAIndividual individual,
InterfaceOptimizationProblem opt) {
// nothing to do
}
public void mutate(AbstractEAIndividual individual) {
if (individual instanceof InterfaceGIIndividual) {
InterfaceGIIndividual giIndy = (InterfaceGIIndividual)individual;
int[] genotype = giIndy.getIGenotype();
int[][] range = giIndy.getIntRange();
int numMutes=RNG.randomInt(minNumMutations, maxNumMutations);
for (int i=0; i<numMutes; i++) {
maybePerformSingleMutation(genotype, range, genotype.length/numMutes);
}
}
}
private void maybePerformSingleMutation(int[] genotype, int[][] range, int maxTries) {
int index=RNG.randomInt(genotype.length);
if (enforceMutablePositions && !(isMutable(genotype[index]))) {
// if the mutation event should be forced, search a mutable element with a max. no. tries
do {
index=RNG.randomInt(genotype.length);
maxTries--;
} while (maxTries>0 && (!isMutable(genotype[index])));
}
if (isMutable(genotype[index])) { // if it is in the mutable subset
genotype[index]=randomValidElement(range, index, genotype[index]);
}
}
/**
* Return a randomly chosen element of the mutable subset lying in the range
* or the old value if the randomly chosen value
* @param range
* @param index
* @param oldVal
* @return
*/
private int randomValidElement(int[][] range, int index, int oldVal) {
int v = mutableSet[RNG.randomInt(mutableSet.length)];
if (v>=range[index][0] && (v<=range[index][1])) return v;
else {
EVAERROR.errorMsgOnce("Warning, mutation subset violates range definition!");
return oldVal;
}
}
/**
* Return true if the given value is member of the mutable subset, otherwise false.
* @param v
* @return
*/
private boolean isMutable(int v) {
for (int i=0; i<mutableSet.length; i++) {
if (mutableSet[i]==v) return true;
}
return false;
}
public static String globalInfo() {
return "A mutation operator which switches positions within a given subset only. A random " +
"position is chosen but mutated only if its allele is contained" +
" in the mutable set. The new allele is chosen from this set as well." +
" In case the random positions do not contain a mutable allele, the switching is skipped. " +
"This means that fewer switches may occur than expected from the minimal bound.";
}
public int[] getMutableSet() {
return mutableSet;
}
public void setMutableSet(int[] mutationSubset) {
this.mutableSet = mutationSubset;
}
public String mutableSetTipText() {
return "A subset of integers among which mutations may occur.";
}
public int getMinNumMutations() {
return minNumMutations;
}
public void setMinNumMutations(int minNumMutations) {
this.minNumMutations = minNumMutations;
}
public String minNumMutationsTipText() {
return "A lower bound for the number of positions changed per mutation event";
}
public int getMaxNumMutations() {
return maxNumMutations;
}
public void setMaxNumMutations(int maxNumMutations) {
this.maxNumMutations = maxNumMutations;
}
public String maxNumMutationsTipText() {
return "An upper bound for the number of positions changed per mutation event";
}
public boolean isEnforceMutablePositions() {
return enforceMutablePositions;
}
public void setEnforceMutablePositions(boolean enforceMutablePositions) {
this.enforceMutablePositions = enforceMutablePositions;
}
public String enforceMutablePositionsTipText() {
return "If true, the probability to hit a mutable position in a mutation event is increased by trying multiple times.";
}
}