遺伝的アルゴリズムでの適応度の出力について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
すちょ

遺伝的アルゴリズムでの適応度の出力について

#1

投稿記事 by すちょ » 13年前

現在遺伝的アルゴリズムで、各個体の2進数で出力された値で、1の数が多いほど適応度が高くなるというプログラムを作っています。
しかし、このプログラムをコンパイルして実行すると、

48:
10101 : 13
11110 : 13
10100 : 13
10111 : 13
49:
10101 : 16
11110 : 16
11111 : 16
10111 : 16
max: 20.00 min: 6.00 avg: 12.96

のように、各個体ごとの1の数の合計が適応度として出力されます。

48:
10101 : 3
11110 : 4
10100 : 2
10111 : 4
49:
10101 : 3
11110 : 4
11111 : 5
10111 : 4

これを上のように、1行(5ビット)ごとの適応度(1の数)を出力させるにはどうしたらよいのでしょうか??

開発環境は、microsoft visual c++ 2010 です。
長々とすみません。よろしくお願いします。

以下にソースコードを添付します。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define N 5   // 遺伝子長
#define M 50   // 個体数
#define ml 4   //音符数  
#define T 1000   // 世代数
#define Pc 0.30  // 交叉確率
#define Pm 0.10   // 突然変異確率

// 遺伝子型の定義
struct genotype {
 int gene[ml][N];   // 遺伝子
 float fitness;   // 適応度 
};

float evaluation(int *a);   //適応度計算
void one_point_crossover(struct genotype *ind);   //交叉
void mutation(struct genotype *ind);   //突然変異
void roulette_selection(struct genotype *ind);   //選択
int flip(float prob);   //
void print_process(struct genotype *ind, int generation);   //出力


int main(int argc, char *argv[]) {
 int i;   // 個体インデックス
 int j;   // 遺伝子座インデックス
 int s;   // 音符数インデックス
 int t;   // 世代インデックス
 struct genotype individual[M];      // 個体
 struct genotype erito; //エリート
 
 
 // 乱数seedの設定
 if(argc < 2) {   // プログラムの引数が足りない場合
   printf("Usage: %s [SEED_NUMBER]\n", argv[0]);
   exit(1);
 }
 else {
   srand(atoi(argv[1]));
 }
 
 // ステップ1 (0世代目)
 for(i=0; i<M; i++) {
	 for(s=0; s<ml; s++){
		for(j=0; j<N; j++) {
			individual[i].gene[s][j] = flip(0.5);
			
   }
   individual[i].fitness = evaluation(individual[i].gene); // 個体の適応度計算
	 }
 }
 print_process(individual, 0); // 初期世代の個体群を表示
 
 //0世代目のエリート選択
 for(i=1;i<M;i++){
   if(individual[0].fitness < individual[i].fitness){  
     individual[0] = individual[i];  
   }
   erito = individual[0];
}

 // ステップ2 (1~T世代)
 for(t=1; t<=T; t++) {

     // 交叉
   one_point_crossover(individual);
   // 突然変異
   mutation(individual);
   // 子個体の適応度値計算
   for(i=0; i<M; i++) {
     individual[i].fitness = evaluation(individual[i].gene);
   }

// ルーレット選択
   roulette_selection(individual);

   

   individual[0] = erito; //エリート挿入
   
 
  for(i=1;i<M;i++){
    if(individual[0].fitness < individual[i].fitness){
      individual[0] = individual[i];
    }
    erito = individual[0]; //更新
  }
  print_process(individual, t);
 }
 return(0);
}   // End of main()


// 個体の適応度計算
float evaluation(int *a) {
 int j;   // 遺伝子座インデックス
 int count = 0;   // 遺伝子中の`1'の数

 for(j=0; j<ml*N; j++) {
   count += a[j];
 }
 return((float)count);
}   // End of evaluation()

// 一点交叉
void one_point_crossover(struct genotype *ind) {
 int i, ia, ib;   // 個体インデックス
 int s;   //音符数インデックス
 int j;   // 遺伝子座インデックス
 int c;   // 交叉点
 int test[M];   // 個体の利用フラグ
 int temp[N];   // 遺伝子を入れ替えるための仮変数
 int r;   // 乱数値
 
 for(i=0; i<M; i++) test[i] = 0;

 ia = ib = 0;
 for(i=0; i<M/2; i++) {
   // 個体をランダムにペアリング (親個体ia,ibを選ぶ)
   // 親iaを決定
   for(; test[ia]==1; ia=(ia+1)%M);
   test[ia] = 1;
   r = rand() % (M-2*i) + 1;
   // (iaとは異なる)親ibを決定
   while(r>0) {
     ib=(ib+1)%M;
     for(; test[ib]==1; ib=(ib+1)%M);
     r--;
   }
   test[ib] = 1;
   // 個体iaとibの遺伝子を入れ替える
   if(flip(Pc)) {
     c = rand() % N;
	 for(s=0; s<ml; s++){
		for(j=0; j<c; j++) {
       temp[j] = ind[ia].gene[s][j];
       ind[ia].gene[s][j] = ind[ib].gene[s][j];
       ind[ib].gene[s][j] = temp[j];
		}
     }
   }
 }
}   // End of one_point_crossover()


// 突然変異
void mutation(struct genotype *ind) {
 int i;   // 個体インデックス
 int s;   //音符数インデックス
 int j;   // 遺伝子座インデックス
 
 for(i=0; i<M; i++)
	 for(s=0; s<ml; s++)
		for(j=0; j<N; j++)
			if(flip(Pm)) {
				ind[i].gene[s][j] = (ind[i].gene[s][j] + 1) % 2;
     }
 
}   // End of mutation()


// ルーレット選択
void roulette_selection(struct genotype *ind) {
 int h, i, j;   // 個体インデックス
 float total_fitness;   // 適応度の合計値
 float dart;   // 矢
 float wheel;  // ルーレット・ホイール
 struct genotype ind_new[M];   // 選択操作後の個体集合
 
 // 適応度の合計値を計算
 total_fitness = 0;
 for(i=0; i<M; i++) total_fitness += ind[i].fitness;

 // ルーレット・ホイールに従って次世代(ind_new[])を決定
 for(i=0; i<M; i++) {
   dart = (float)rand() / RAND_MAX;
   h = 0;
   wheel = ind[h].fitness / total_fitness;
   while(dart > wheel && h < M-1) {
     h++;
     wheel += ind[h].fitness / total_fitness;
   }
   ind_new[i] = ind[h];
 }

 // 個体集合の更新
 for(i=0; i<M; i++) {
  
   ind[i] = ind_new[i];
    
 }
}   // End of roulette_selection()


// 引数`prob'の確率で1を返す
int flip(float prob) {
 float x = (float)rand() / (float)RAND_MAX;
   
 if(x<prob) return(1);
 else return(0);
}   // End of flip()


// 個体の中身や適応度値を画面に出力
void print_process(struct genotype *ind, int generation) {
 int i;   // 個体インデックス
 int s;   //音符数インデックス
 int j;   // 遺伝子座インデックス
 float max_fit, min_fit, avg_fit;   // 最大,最小,平均適応度

   // 各個体の中身を出力
 printf("\nGeneration: %d\n", generation);
 for(i=0; i<M; i++) {
   printf("%d:\n ", i);
   for(s=0; s<ml; s++){
	for(j=0; j<N; j++) {
     if(ind[i].gene[s][j] == 0) printf("%c", '0');
     else printf("%c", '1');
	}
	printf(" : %.0f\n", ind[i].fitness);
	}
 }
 
 // 個体集団の最大,最小,平均適応度を求める
 max_fit = min_fit = ind[0].fitness;
 avg_fit = ind[0].fitness / M;
 for(i=1; i<M; i++) {
   if(max_fit < ind[i].fitness) max_fit = ind[i].fitness;
   if(min_fit > ind[i].fitness) min_fit = ind[i].fitness;
   avg_fit += ind[i].fitness / M;
 }
 printf("max: %.2f  min: %.2f  avg: %.2f\n", max_fit, min_fit, avg_fit);

}  

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: 遺伝的アルゴリズムでの適応度の出力について

#2

投稿記事 by ISLe » 13年前

詳しく見てませんが、45~53行目のインデントを整えてみると何か分かるのではないかと思います。

たいちう
記事: 418
登録日時: 15年前

Re: 遺伝的アルゴリズムでの適応度の出力について

#3

投稿記事 by たいちう » 13年前

213から224行目を変更すれば良さそうだけど、全く理解できていませんか?
fitnessの代わりにjのループを集計した値を表示するだけだと思いますが。

閉鎖

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