if ステートメントで、ハードコードされた数値を変数に置き換え、各世代の開始時にそれらを更新します。
if ステートメントは、間隔 0 から 10 を 3 つのビンに効果的に分割します。mutate()
vs crossover()
vsを呼び出す確率はrandomlyCreate()
、各ビンのサイズによって異なります。ビンの境界を徐々に移動することで、突然変異率を調整できます。
あなたのコードでmutate()
は、20% の確率で呼び出され (ランダム = 9 または 1 の場合)、randomlyCreate()
10% の確率で呼び出され (ランダム = 0 の場合) crossover()
、残りの 70% の確率で呼び出されます。
以下のコードは、世代 0 でこれらと同じ比率で開始しますが、突然変異率は世代ごとに 1% ずつ増加します。したがって、世代 1 の突然変異率は 21%、世代 2 の突然変異率は 22% などです。は、突然変異率に関係なく、 の 1/7 のrandomlyCreate()
頻度で呼び出されます。crossover()
を変更することで、突然変異率を二次、指数、または任意の形式で増加させることができますgetMutationBoundary()
。
以下のコードではフロートを使用しました。ダブルスも同様に機能します。
突然変異率が最も関心のあるものである場合は、突然変異ビンを最初に [0, 2] になるように移動し、そこから上限 (2.1、2.2 など) を増やす方が直感的かもしれません。次に、突然変異率を簡単に読み取ることができます (21%、22% など)。
void mainLoop() {
// make lots of generations
for (int generation = 0; generation < MAX_GEN; generation++) {
float mutationBoundary = getMutationBoundary(generation);
float creationBoundary = getCreationBoundary(mutationBoundary);
createNewGeneration(mutationBoundary, creationBoundary);
// Do some stuff with this generation, e.g. measure fitness
}
}
void createNewGeneration(float mutationBoundary, float creationBoundary) {
// create each member of this generation
for (int i = 0; i < MAX_POP; i++) {
createNewMember(mutationBoundary, creationBoundary);
}
}
void createNewMember(float mutationBoundary, float creationBoundary) {
float random = 10 * generator.nextFloat();
if (random > mutationBoundary) {
mutate();
}
else {
if (random < creationBoundary) {
randomlyCreate();
}
else {
crossover();
}
}
}
float getMutationBoundary(int generation) {
// Mutation bin is is initially between [8, 10].
// Lower bound slides down linearly, so it becomes [7.9, 10], [7.8, 10], etc.
// Subtracting 0.1 each generation makes the bin grow in size.
// Initially the bin is 10 - 8 = 2.0 units wide, then 10 - 7.9 = 2.1 units wide,
// and so on. So the probability of mutation grows from 2 / 10 = 20%
// to 2.1 / 10 = 21% and so on.
float boundary = 8 - 0.1f * generation;
if (boundary < 0) {
boundary = 0;
}
return boundary;
}
float getCreationBoundary(float creationBoundary) {
return creationBoundary / 8; // fixed ratio
}