Added an abstraction over individual initialization methods.

This commit is contained in:
Marcel Kronfeld 2011-01-17 13:30:34 +00:00
parent d357bbfe98
commit 726a3cc6bf
5 changed files with 212 additions and 2 deletions

View File

@ -13,6 +13,8 @@ import eva2.server.go.individuals.codings.gp.InterfaceProgram;
import eva2.server.go.operators.constraint.InterfaceConstraint;
import eva2.server.go.operators.crossover.InterfaceCrossover;
import eva2.server.go.operators.crossover.NoCrossover;
import eva2.server.go.operators.initialization.DefaultInitialization;
import eva2.server.go.operators.initialization.InterfaceInitialization;
import eva2.server.go.operators.mutation.InterfaceMutation;
import eva2.server.go.operators.mutation.NoMutation;
import eva2.server.go.populations.Population;
@ -58,6 +60,8 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
protected double m_MutationProbability = 0.2;
protected InterfaceMutation m_MutationOperator = new NoMutation();
protected InterfaceCrossover m_CrossoverOperator = new NoCrossover();
protected InterfaceInitialization m_InitOperator = new DefaultInitialization();
// protected String[] m_Identifiers = new String[m_ObjectIncrement];
// protected Object[] m_Objects = new Object[m_ObjectIncrement];
protected HashMap<String,Object> m_dataHash = new HashMap<String,Object>();
@ -148,6 +152,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
m_Marked = individual.m_Marked;
m_isPenalized = individual.m_isPenalized;
individualIndex = individual.individualIndex;
m_InitOperator = individual.m_InitOperator.clone();
if (individual.parentIDs != null) {
parentIDs = new Long[individual.parentIDs.length];
System.arraycopy(individual.parentIDs, 0, parentIDs, 0, parentIDs.length);
@ -271,7 +276,8 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
* @param opt The optimization problem that is to be solved.
*/
public void init(InterfaceOptimizationProblem opt) {
this.defaultInit(opt);
m_InitOperator.initialize(this, opt);
// this.defaultInit(opt);
this.m_MutationOperator.init(this, opt);
this.m_CrossoverOperator.init(this, opt);
}
@ -815,6 +821,16 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
return "The chance that crossover occurs.";
}
public InterfaceInitialization getInitOperator() {
return m_InitOperator;
}
public void setInitOperator(InterfaceInitialization mInitOperator) {
m_InitOperator = mInitOperator;
}
public String initOperatorTipText() {
return "An initialization method for the individual";
}
/** This method allows you to store an arbitrary value under an arbitrary
* name.
* @param name The identifying name.

View File

@ -0,0 +1,32 @@
package eva2.server.go.operators.initialization;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.problems.InterfaceOptimizationProblem;
/**
* A dummy initialization method which only calls the default init method of the individual.
*
* @author mkron
*
*/
public class DefaultInitialization implements InterfaceInitialization, java.io.Serializable {
private static final long serialVersionUID = 1L;
public DefaultInitialization() {}
public void initialize(AbstractEAIndividual indy, InterfaceOptimizationProblem problem) {
indy.defaultInit(problem);
}
public InterfaceInitialization clone() {
return new DefaultInitialization();
}
public String getName() {
return "DefaultInitialization";
}
public String globalInfo() {
return "Uses the standard initialization of the individual implementation";
}
}

View File

@ -0,0 +1,125 @@
package eva2.server.go.operators.initialization;
import java.util.BitSet;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceGAIndividual;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import eva2.tools.EVAERROR;
import eva2.tools.math.RNG;
/**
* An initialization method which sets a fixed number of bits per segment,
* where a segment is a connected subsequence of the genotype.
* This is usable for GA individuals only.
*
* The initialization may be parameterized in two ways, where each takes a fixed
* segment length s. Firstly, a fixed number of bits (k<=s) is set per segment,
* so each segment has equal cardinality.
* Secondly, an int-array can be specified which defines possibly varying k_i for
* each segment i, so different segments may have different cardinaltiy. The array
* must comply to the binary genotype length of the problem. The array definition
* has strict priority over the fixed cardinality definition.
*
* @author mkron
*
*/
public class GAInitializeSegmentwise implements InterfaceInitialization, java.io.Serializable {
protected int[] bitsPerSegmentArray = new int[0];
private int bitsPerSegment=1;
private int segmentLength=4;
public GAInitializeSegmentwise() {}
public GAInitializeSegmentwise(GAInitializeSegmentwise o) {
bitsPerSegment = o.bitsPerSegment;
segmentLength = o.segmentLength;
if (o.bitsPerSegmentArray!=null) {
bitsPerSegmentArray = new int[o.bitsPerSegmentArray.length];
System.arraycopy(o.bitsPerSegmentArray, 0, bitsPerSegmentArray, 0, bitsPerSegmentArray.length);
}
}
public GAInitializeSegmentwise(int segLen, int[] bitsPerSeg) {
segmentLength = segLen;
bitsPerSegmentArray = bitsPerSeg;
}
public InterfaceInitialization clone() {
return new GAInitializeSegmentwise(this);
}
@Override
public void initialize(AbstractEAIndividual indy,
InterfaceOptimizationProblem problem) {
if (indy instanceof InterfaceGAIndividual) {
InterfaceGAIndividual gaIndy = ((InterfaceGAIndividual)indy);
int genotypeLen = gaIndy.getGenotypeLength();
BitSet genotype = gaIndy.getBGenotype();
if (bitsPerSegmentArray==null || (bitsPerSegmentArray.length==0)) {
// regard only a fixed number of bits per segment
for (int i=0; i<genotypeLen; i+=segmentLength) {
// create the next segment
BitSet nextSeg=RNG.randomBitSet(bitsPerSegment, segmentLength);
for (int k=i;k<i+segmentLength; k++) {
// transfer the new segment to the genotype
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.
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!");
for (int s=0; s<bitsPerSegmentArray.length; s++) {
// look at each segment individually
BitSet nextSeg=RNG.randomBitSet(bitsPerSegmentArray[s], bitsPerSegment);
for (int k=(s)*bitsPerSegment; k<(s+1)*bitsPerSegment; k++) {
if (k<genotypeLen) genotype.set(k, nextSeg.get(k-(s*bitsPerSegment)));
}
}
}
} else throw new RuntimeException("Error: "+ this.getClass() + " must be used with individuals of type " + InterfaceGAIndividual.class + "!");
}
public int[] getBitsPerSegmentArray() {
return bitsPerSegmentArray;
}
public void setBitsPerSegmentArray(int[] bitsPerSegmentArray) {
this.bitsPerSegmentArray = bitsPerSegmentArray;
}
public String bitsPerSegmentArrayTipText() {
return "A value per segment defining the number of bits to set for that segment, or null if fixed";
}
public int getBitsPerSegment() {
return bitsPerSegment;
}
public void setBitsPerSegment(int bitsPerSegment) {
this.bitsPerSegment = bitsPerSegment;
}
public String bitsPerSegmentTipText() {
return "If not array-wise defined, this fixed number of bits is set per segment";
}
public int getSegmentLength() {
return segmentLength;
}
public void setSegmentLength(int segmentLength) {
this.segmentLength = segmentLength;
}
public String segmentLengthTipText() {
return "The fixed length of a segment, which is a substring of the binary genotype";
}
////////
public String getName() {
return "GA segment-wise init";
}
public String globalInfo() {
return "A method which initializes a fixed number of bits per binary segment, which is a fixed number" +
"of bits for substrings of equal length";
}
}

View File

@ -0,0 +1,31 @@
package eva2.server.go.operators.initialization;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.problems.InterfaceOptimizationProblem;
/**
* An abstraction over individual initialization methods in analogy
* to mutation and crossover. It is member of every abstract individual
* but the specific implementation may depend on the data type of the
* individual.
*
* @author mkron
*
*/
public interface InterfaceInitialization {
/**
* Perform initialization of a given individual, which may potentially depend on
* a problem instance.
*
* @param indy the target individual to initialize
* @param problem the problem instance under consideration
*/
public void initialize(AbstractEAIndividual indy, InterfaceOptimizationProblem problem);
/**
* A specific cloning method.
* @return
*/
public InterfaceInitialization clone();
}

View File

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.BitSet;
import java.util.Random;
import eva2.tools.EVAERROR;
public class RNG {
private static Random random;
@ -289,6 +291,10 @@ public class RNG {
* Create a random bitset with given cardinality and lengths,
*/
public static BitSet randomBitSet(int cardinality, int length) {
if (cardinality>length) {
EVAERROR.errorMsgOnce("Error, invalid cardinality " + cardinality + " requested for bit length "+ length +", cardinality will be reduced.");
cardinality=length;
}
BitSet bs = new BitSet(length);
int[] perm = randomPerm(length);
for (int i=0; i<cardinality; i++) {