遺伝的アルゴリズムのトーナメント選択について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
絵にかいた餅
記事: 13
登録日時: 1年前

遺伝的アルゴリズムのトーナメント選択について

#1

投稿記事 by 絵にかいた餅 » 1年前

閲覧ありがとうございます。現在自分は遺伝的アルゴリズムの勉強をしています。その中でトーナメント選択で今詰まっております。ナーススケジューリング問題です。init_value(gene_chrom, v)は評価の値を格納するものでしっかりと動いているのは確認できました。見やすいようにトーナメント選択のみに関係するコードしか書いておりません。
出力結果をみるとエリート選択は問題ないと思われます。デバックで値の動き等を見てみましたが原因が見つかりません。わかる方がいましたらご助言をいただけると嬉しいです。

コード:

const int G_number = 4, G_length = 10;//遺伝子の数、長さ
const int N = 4;//個体数
const int s = 2;//トーナメントサイズ

//重複しない乱数の生成
void shuffle(int array[], int size)
{
	int i = size;
	while (i > 1) {
		int j = rand() % i;
		i--;
		int t = array[i];
		array[i] = array[j];
		array[j] = t;
	}
}

void tournament(int gene_chrom[N * G_number][G_length], int gene_new_chrom[N * G_number][G_length], double v[N]) {
	int tm[s * G_number][G_length];//一時的に選択した遺伝子を格納するもの
	double vtm[s];//上記の評価値を格納
	int tmp;
	double vmp;
	int i, j, k;
	int p, q;
	int data[N];//ランダム変数の格納
	//エリート選択
	for (p = 1; p <= N; p++) {
		q = p;
		while (q >= 1 && v[q - 1] < v[q]) {
			for (i = 0; i < G_number; i++) {
				for (j = 0; j < G_length; j++) {
					tmp = gene_chrom[(q - 1) * G_number + i][j];
					gene_chrom[(q - 1) * G_number + i][j] = gene_chrom[q * G_number + i][j];
					gene_chrom[q * G_number + i][j] = tmp;
				}
			}
			vmp = v[q - 1];
			v[q - 1] = v[q];
			v[q] = vmp;
			q--;
		}
	}
	//一番最初に評価値が一番高い個体を格納
	for (i = 0; i < G_number; i++) {
		for (j = 0; j < G_length; j++) {
			gene_new_chrom[i][j] = gene_chrom[i][j];
		}
	}
	//トーナメント選択
	for (i = 0; i < N; i++) {
		data[i] = i;
	}

	for (k = 1; k < N; k++) {
		shuffle(data, N);//重複しない乱数を生成
		//ランダムに選ばれた個体を一時的に格納
		for (i = 0; i < s; i++) {
			for (k = 0; k < G_number; k++) {
				for (j = 0; j < G_length; j++) {
					tm[i * G_number + k][j] = gene_chrom[data[i] * G_number + k][j];
				}
			}
			vtm[i] = v[data[i]];
		}
		//評価値が高い順にする
		for (p = 1; p <= s; p++) {
			q = p;
			while (q >= 1 && vtm[q - 1] < vtm[q]) {
				for (i = 0; i < G_number; i++) {
					for (j = 0; j < G_length; j++) {
						tmp = tm[(q - 1) * G_number + i][j];
						tm[(q - 1) * G_number + i][j] = tm[q * G_number + i][j];
						tm[q * G_number + i][j] = tmp;
					}
				}
				vmp = vtm[q - 1];
				vtm[q - 1] = vtm[q];
				vtm[q] = vmp;
				q--;
			}
		}
		//一番評価値が高いものを格納
		for (i = 0; i < G_number; i++) {
			for (j = 0; j < G_length; j++) {
				gene_new_chrom[k * G_number + i][j] = tm[i][j];
			}
		}
		v[k] = vtm[0];
	}
}
int main() {
	//int x;
	int i;
	int j;
	int p;
	int k;
	int chrom[G_number][G_length];
	int gene_chrom[N * G_number][G_length];
	int gene_new_chrom[N * G_number][G_length];
	int data[N];
	double v[N];

	srand((unsigned int)time(NULL));//乱数の種を変える
	
	//トーナメント選択の試行
	for (p = 0; p < N; p++) {
		createInitialvalue(chrom);
		for (i = 0; i < G_number; i++) {
			for (j = 0; j < G_length; j++) {
				gene_chrom[p * G_number + i][j] = chrom[i][j];
			}
		}
	}

	init_value(gene_chrom, v);

	for (p = 0; p < N; p++) {
		for (i = 0; i < G_number; i++) {
			for (j = 0; j < G_length; j++) {
				printf("%d ", gene_chrom[p * G_number + i][j]);
			}
			printf("\n");
		}
		printf("\n");
	}
	for (i = 0; i < N; i++) {
		printf("%lf ", v[i]);
	}
	printf("\n");

	tournament(gene_chrom, gene_new_chrom, v);

	for (p = 0; p < N; p++) {
		for (i = 0; i < G_number; i++) {
			for (j = 0; j < G_length; j++) {
				printf("%d ", gene_new_chrom[p * G_number + i][j]);
			}
			printf("\n");
		}
		printf("\n");
	}
	for (i = 0; i < N; i++) {
		printf("%lf ", v[i]);
	}
	printf("\n");

	return 0;
}
出力結果
2 2 1 2 2 2 0 1 1 3
1 2 0 2 0 0 2 1 1 2
2 3 1 1 1 2 0 2 3 1
2 3 0 0 0 0 3 2 2 0

1 1 2 3 3 0 0 2 2 0
0 1 2 3 3 1 2 3 1 2
1 3 2 2 0 3 1 3 0 0
1 2 3 2 2 0 2 1 3 1

0 1 0 2 2 2 2 3 2 2
2 2 0 1 2 2 3 0 2 0
0 1 3 2 0 1 1 1 3 2
2 0 1 3 0 1 0 2 0 3

3 1 1 1 1 3 2 3 0 1
0 2 3 3 2 1 2 0 2 1
2 3 1 0 0 2 2 1 2 1
3 3 0 2 3 0 3 2 2 0

-6649.008980 -6959.004444 -7029.003460 -8389.022222
2 2 1 2 2 2 0 1 1 3
1 2 0 2 0 0 2 1 1 2
2 3 1 1 1 2 0 2 3 1
2 3 0 0 0 0 3 2 2 0

-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460

-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460

-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460

0.000000 0.000000 0.000000 0.000000

アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

Re: 遺伝的アルゴリズムのトーナメント選択について

#2

投稿記事 by 幸尚 » 1年前

こんばんは。

要は出力結果後半を見ると
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460

-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460

-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
という風にあり得ない数値が出ていますがこれが問題ということですか?

理解力がなく申し訳ないです。
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

Re: 遺伝的アルゴリズムのトーナメント選択について

#3

投稿記事 by 幸尚 » 1年前

もし差し支えなければすべてのソースをアップしていただけませんか?
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 遺伝的アルゴリズムのトーナメント選択について

#4

投稿記事 by みけCAT » 1年前

-858993460 = 0xCCCCCCCC

未初期化の値を参照している可能性がありますね。

デバッグ版の未初期化メモリパターン - Qiita
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

絵にかいた餅
記事: 13
登録日時: 1年前

Re: 遺伝的アルゴリズムのトーナメント選択について

#5

投稿記事 by 絵にかいた餅 » 1年前

言葉足らずで申し訳ありません。そうです本来ならばここに0,1,2,3の数字が入らなければいけません。ここでしたいことは、前半の出力結果にあるシフト表が個体数N(今だと4個)に対してトーナメントサイズs個(今だと2個)ランダムに選択されたシフト表を評価値配列vの値の大きさ順にシフト表と評価値を並び変えたいのですが。そこのトーナメント選択がうまくいってません。(よく見ると評価値の値もすべて0になっています。)main関数に載っているinit_value(gene_chrom, v)とcreateInitialvalue関数を追加で書いときます。

コード:

void createInitialvalue(int shift[G_number][G_length]) {
	int ind, item;  /* ループカウンタ */
	int nurse, day;
	int i;

	/* 0から3までの数字をランダムに格納する */
	for (ind = 0; ind < G_number; ind++) {
		for (item = 0; item < G_length; item++) {
			shift[ind][item] = nrand(3);
		}
	}
}
//評価値を格納する関数
void init_value(int gene_chrom[N * G_number][G_length], double v[N]) {
	int i, j, k;
	int chrom[G_number][G_length];
	/*全体の勤務表の個体を一個の勤務表に格納。評価*/
	for (i = 1; i <= N; i++) {
		for (k = 0; k < G_number; k++) {
			for (j = 0; j < G_length; j++) {
				chrom[k][j] = gene_chrom[G_number * (i - 1) + k][j];
			}
		}
		v[i - 1] = banIndividual(chrom) + workValue(chrom);
	}
}

絵にかいた餅
記事: 13
登録日時: 1年前

Re: 遺伝的アルゴリズムのトーナメント選択について

#6

投稿記事 by 絵にかいた餅 » 1年前

未初期化ということはgene_new_chromに値がしっかり入ってないということでしょうか?デバックをしてみるとしっかり入っているように思えるのですが。

絵にかいた餅
記事: 13
登録日時: 1年前

Re: 遺伝的アルゴリズムのトーナメント選択について

#7

投稿記事 by 絵にかいた餅 » 1年前

申し訳ありません!こちら解決しました!!ループカウンタで同じ文字を使ってたことに問題があったみたいです。返信くださった方ありがとうございました。

返信

“C言語何でも質問掲示板” へ戻る