0

遺伝的アルゴリズムに非常に似たものを実装しています。したがって、集団の複数の世代を通過します。世代の終わりに、「ランダム」、「突然変異」、および「クロスオーバー」の 3 つの異なる方法で新しい集団を作成します。

現在、確率は静的ですが、突然変異の確率が徐々に増加するようにする必要があります。少し行き詰まっているので、どんな方向性でも感謝します..

これは私が持っているものです:

int random = generator.nextInt(10);
if (random < 1)  
    randomlyCreate() 
else if (random > 1 && random < 9 )
    crossover(); 
else  
    mutate();

ありがとうございました。

4

3 に答える 3

1

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
}
于 2013-11-19T19:35:34.160 に答える
0

演算子の遺伝的確率の選択は任意です (確率を増減する関数を使用する場合にも有効です)。染色体内で演算子を成文化する方がよい。たとえば、いくつかのビットを追加して、使用するすべての演算子をコード化できます。子を生成するときは、母集団のすべての要素についてこれらのビットを確認し、グローバルに考慮して母集団全体の演算子の現在の状況に等しい確率で演算子を適用します。

例えば:

void adaptive_probabilities(GA *ga, long chromosome_length) {
    register int i, mut = 1, xover = 1, uxover = 1, ixover = 1, pop;
    char bit1, bit2;

    for (i = 0; i < ga->npop; i++) {
        bit1 = ga->pop[i]->chromosome[chromosome_length - 2];
        bit2 = ga->pop[i]->chromosome[chromosome_length - 1];

        if (bit1 == '0' && bit2 == '0') {
            mut++;
        } else if (bit1 == '0' && bit2 == '1') {
            xover++;
        } else if (bit1 == '1' && bit2 == '0') {
            uxover++;
        } else if (bit1 == '1' && bit2 == '1') {
            ixover++;
        }
    }

    pop = ga->npop + 4;

    ga->prob[0] = mut / (float)pop;
    ga->prob[1] = xover / (float)pop;
    ga->prob[2] = uxover / (float)pop;
    ga->prob[3] = ixover / (float)pop;
}

私の場合、染色体が 4 つの演算子 (3 種類の交叉 + 突然変異) を成文化するため、2 ビットを使用します。オペレーター用のビットは、染色体の最後にあります。すべての確率は > 0 (演算子のカウンターは 1 から始まります) であり、すべての確率を次のように正しく正規化する必要があります。

pop = ga->npop + 4;

次に、配列 ga->prob に保存されている計算された確率に基づいて演算子を選択するための乱数を生成します。新しい子の最後のビットは、使用された演算子を反映するように変更されます。

このメカニズムにより、GA による二重検索が保証されます。つまり、エラー領域 (通常どおり) と演算子領域です。確率は自動的に変更され、最適化されます。これは、計算のどの時点でも最適な演算子を使用して子がより高い確率で生成されるためです。

于 2014-02-06T12:40:29.293 に答える
0

現在 を使用している変数を使用し9、(たとえば)が発生し0.9ない限り、すべての反復でmutate()それを乗算します3。そうすれば、突然変異の可能性はゆっくりと、しかし指数関数的に増加し (そうです、可能です)、それらが実際に突然変異するまで、その時点で別の突然変異の可能性はレンガのように低下​​し、プロセスが最初からやり直されます。

これらの値は完全にランダムであり、突然変異に関する知識に基づいているわけではありませんが、毎回変数値を持つように操作する方法を示しているだけです。また、先ほど使用したものを使用する場合、変数の値が 10 を超えた場合は、変数の値が 10 に設定されていることを確認してください。

于 2013-11-19T15:43:33.323 に答える