分類:[C/C++]
2019/01/08(Tue) 13:36:59 編集(投稿者)
2019/01/08(Tue) 13:36:38 編集(投稿者)
2019/01/08(Tue) 11:53:43 編集(投稿者)
2019/01/08(Tue) 11:50:09 編集(投稿者)
<pre><pre>visual studio 2017
C言語
おおまかに
「遺伝的アルゴリズムを用いて、個体の遺伝子の合計値が、一番大きい個体を生成(出力)する
プログラムを作成せよ。」
といった問題なのですが
以下のプログラムを実行すると、出力される値の合計値が
下がるときがあります。
エリート個体が遺伝されてないのかな?
とか考えましたが、とくにソースに気になる点が見つかりません。
どこがおかしいでしょうか?
用いている手法は
エリート選択・ルーレット選択
2点交叉
です。
==============================================================================
#include "pch.h"
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define N 10//個体数
#define L 5//遺伝子長
#define MAX 10//遺伝子の構成単位に入る値の最大値
void roulette(int fit[], int ro[], int elite);
int main(void)
{
int now[N][L],//現在の世代
next[N][L],//次世代
fit[N],//各個体の適応度
r[3],//乱数格納用
ro[2];//ルーレット選択で選ばれた2個体を格納
int best, elite, h, i, j, ge, st, en;
srand(time(NULL));
printf("Generation = ");
scanf_s("%d", &ge);
for (i = 0; i < N; i++) {
printf("N_%d = ", i + 1);
for (j = 0; j < L; j++) {
now[i][j] = rand() % MAX + 1;//適当な値で個体の遺伝子を構成
printf("%d ", now[i][j]);
}
printf("\n");
}
printf("\n");
for (h = 0; h < ge; h++) {
elite = 0;
for (i = 0; i < N; i++) {
for (j = 0, fit[i] = 0; j < L; j++) fit[i] += now[i][j];
//保持する値の合計が大きいものが優秀
}
for (i = 1, best = fit[0]; i < N; i++) {//エリート選択法
if (fit[i] > best) {
best = fit[i];
elite = i;//最優秀の個体の番号を得る
}
}
for (j = 0; j < L; j++) next[0][j] = now[elite][j];
//最優秀の個体は次世代にそのままコピー
printf("Generation = %d, elite = ", h + 1);
for (j = 0; j < L; j++) printf("%d ", now[elite][j]);//世代中最優秀の個体を表示
printf("\n");
for (i = 1; i < N; i++) {
r[0] = rand() % 100 + 1;
if (r[0] == 1) {//1%の確率で突然変異
roulette(fit, ro, elite);//ルーレット選択法
now[ro[0]][rand() % L] = rand() % MAX + 1;
//適当な遺伝子座の値が適当に書き換わる
for (j = 0; j < L; j++) next[i][j] = now[i][j];
}
else {//99%の確率で二点交叉
roulette(fit, ro, elite);
do {
st = rand() % L;//交叉の始点
en = rand() % L;//終点
} while (st >= en);
for (j = 0; j < L; j++) next[i][j] = now[ro[0]][j];//一旦個体1の遺伝子をコピー
for (j = st; j < en; j++) next[i][j] = now[ro[1]][j];//個体2の遺伝子の一部をコピー
}
}
memcpy(now, next, sizeof(now));//次世代を現在の世代とする.
}
return 0;
}
void roulette(int fit[], int ro[], int elite)
{
int i;
double sumf, p[N];
fit[elite] = 0;//エリート選択で選ばれたものは選択対象外に
for (i = 0, sumf = 0; i < N; i++) sumf += fit[i];
for (i = 0; i < N; i++) p[i] = fit[i] / sumf * 100;//ルーレット選択の公式
for (i = 0; i < N; i++) {//一つ目
if (p[i] <= rand() % 100 + 1) {//例えば確率10%なら乱数が10以下なら良い
ro[0] = i;
break;
}
}
for (i = 0; i < N; i++) {//二つ目
if (p[i] <= rand() % 100 + 1 && i != ro[0]) {
ro[1] = i;
break;
}
}
}
============================================================================================</pre></pre>