JGAP
Java Genetic Algorithm Package "JGAP"
http://jgap.sourceforge.net/
を用いて,Rastrign 関数の最適化を試みるプログラム.
import java.io.*;
import org.jgap.*;
import org.jgap.impl.DoubleGene;
import org.jgap.impl.DefaultConfiguration;
public class GAsample {
private static final int MAX_ALLOWED_EVOLUTIONS = 140;
public static void main(String[] args) throws Exception {
//GAのパラメータ設定などのコンフィギュレーション
Configuration conf = new DefaultConfiguration();
//最大適合度をもつ個体を保存する
conf.setPreservFittestIndividual(true);
final int dimension = 3;
//適合度関数の定義
FitnessFunction myFunc =
new GAsampleFitnessFunction(dimension); //引数:次元数
conf.setFitnessFunction(myFunc); //適合度関数の登録
//遺伝子の定義
Gene[] sampleGenes = new Gene[dimension];
for (int i = 0; i < dimension; i++) {
sampleGenes[i] = new DoubleGene(conf, //コンフィギュレーション
-5.12, //遺伝子のとりうる値の下限
5.12); //遺伝子のとりうる値の上限
}
//染色体の定義
//(メモ)第2引数 : 初期遺伝子集合
IChromosome sampleChromosome = new Chromosome(conf,
sampleGenes);
conf.setSampleChromosome(sampleChromosome); //染色体の登録
//集団(染色体)サイズの設定
conf.setPopulationSize(1000);
//遺伝子型・・・遺伝子型は,染色体の固定長集団である.
//遺伝子型の集団をランダムに生成する
Genotype population;
population = Genotype.randomInitialGenotype(conf);
//進化させる
for (int i = 0; i < MAX_ALLOWED_EVOLUTIONS; i++) {
population.evolve();
}
//最大の適合度を有する染色体を得る.
IChromosome bestSolutionSoFar = population.getFittestChromosome();
System.out.println("Fitness value of the best solution : " +
bestSolutionSoFar.getFitnessValue()); //適合度の値を得る
System.out.println("Value of parameters: ");
double[] x = new double[dimension];
for (int i = 0; i < bestSolutionSoFar.size(); i++) {
//(メモ) IChromosome.getGene(i) i番目の遺伝子座の遺伝子を得る
//(メモ) Gene.getAllele() この遺伝子によって表される値(Object型)を得る.
x[i] = ((Double) bestSolutionSoFar.getGene(i).getAllele()).doubleValue();
}
for(int i = 0; i < dimension; i++){
System.out.printf("x[%d]=%f\n", i, x[i]);
}
}
//適合度関数
static class GAsampleFitnessFunction extends FitnessFunction {
private final int m_dimension;
public GAsampleFitnessFunction(int dimension) {
m_dimension = dimension;
}
public double evaluate(IChromosome a_subject) {
double fitness;
//Rastrign関数
double functionValue = 10 * m_dimension;
for (int i = 0; i < a_subject.size(); i++) {
double x = ((Double) a_subject.getGene(i).getAllele()).doubleValue();
functionValue += (x * x - 10 * Math.cos(2 * Math.PI * x));
}
fitness = 1000-functionValue; //最小化問題だからひっくり返す
return fitness;
}
}
}実行結果は以下のとおり:
Fitness value of the best solution : 999.9998905747874 Value of parameters: x[0]=-0.000309 x[1]=0.000648 x[2]=-0.000192
Rastrign関数は x=(0, 0, ..., 0) で最小値(最大適合度)をとるから,よい感じに収まっているみたいですね.
現実には複数回の試行が必要だし,パラメータ設定もきちんとやるべきだが,とりあえずの最適化はできているみたいだ.
JGAP における交叉確率,突然変異確率の設定
DefaultConfiguration() ではダメっぽいため,Configuration を自前で設定した上で Configuration.addGeneticOperator() により設定する.
Configuration conf = new Configuration(); conf.setBreeder(new GABreeder()); conf.setRandomGenerator(new StockRandomGenerator()); conf.setEventManager(new EventManager()); conf.setSelectFromPrevGen(1.0d); conf.setKeepPopulationSizeConstant(true); conf.setFitnessEvaluator(new DefaultFitnessEvaluator()); conf.setChromosomePool(new ChromosomePool()); conf.addGeneticOperator(new CrossoverOperator(conf, 0.35d)); conf.addGeneticOperator(new MutationOperator(conf, 5));
JGAP におけるルーレット戦略の実装および実行
以下のように NaturalSelector を設定すると,実行時に例外が発生する.
WeightedRouletteSelector weightedRouletteSelector = new WeightedRouletteSelector(conf); weightedRouletteSelector.setDoubletteChromosomesAllowed(true); conf.addNaturalSelector(weightedRouletteSelector, true);
例外の内容は以下のとおり:
Exception in thread "main" java.lang.NoClassDefFoundError: gnu/trove/THashMap at org.jgap.impl.WeightedRouletteSelector.<init>(WeightedRouletteSelector.java:48) at Sample.main(Sample.java:31) Caused by: java.lang.ClassNotFoundException: gnu.trove.THashMap at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) ... 2 more
Ubuntu Synaptic パッケージマネージャで "trove" を検索すると,
libtrove-java 2.1.0-1ubuntu1 と libtrove-java-doc を発見.パッケージの説明には "high performance collections for java" とある.
これをインストールして,次のように実行時に trove.jar をクラスパスに加えると,OK.
java -cp jgap.jar:/usr/share/java/trove.jar:. Sample 99
・・・と思っていたら,JGAP の lib ディレクトリの中に trove-2.0.2.jar が入っていました.