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 が入っていました.