C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

遺伝的アルゴリズム問題に関して /タコカカオ (19/01/08(Tue) 11:49) #89846
Re[1]: 遺伝的アルゴリズム問題に関して /タコカカオ (19/01/08(Tue) 13:43) #89848 解決済み


親記事 / ▼[ 89848 ]
■89846 / 親階層)  遺伝的アルゴリズム問題に関して
□投稿者/ タコカカオ (7回)-(2019/01/08(Tue) 11:49:19)

分類:[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>

[ □ Tree ] 返信 編集キー/

▲[ 89846 ] / 返信無し
■89848 / 1階層)  Re[1]: 遺伝的アルゴリズム問題に関して
□投稿者/ タコカカオ (8回)-(2019/01/08(Tue) 13:43:44)
すみません
自己解決しました。
解決済み
[ 親 89846 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -