#include #include #include "tsp.h" #define ELETE_SELECTION NO /* エリート戦略で選択 */ /* 距離(または適合度)でソートするための比較関数 */ int compare_fitness(const void *a, const void *b) { Gene_set *ga = (Gene_set *)a; Gene_set *gb = (Gene_set *)b; // 適合度が良い(小さい)順に並べる if (ga->fitness < gb->fitness) return -1; if (ga->fitness > gb->fitness) return 1; return 0; } /* 遺伝子集団 gene_group の中で突然変異を起こす */ void mutation(Gene_set gene_group[GENE_NUM]) { int i, target; /* どの遺伝子を変異させるか */ #if ELETE_SELECTION /* 1/2 */ for (i = ELETE; i < GENE_NUM; i++ ) #else for (i = 0; i < GENE_NUM; i++ ) #endif /* ELETE_SELECTION 1/2 */ { /* その遺伝子が突然変異対象に選ばれたら */ if ((rand() / (double)RAND_MAX) < MUTATION_RATIO) { /* どの位置を変異させるか */ target = rand() % CITY_NUM; /* 残っている都市の数以内でランダムに選ぶ */ gene_group[i].gene[target] = rand() % (CITY_NUM - target); } } } /* 遺伝子集団 gene_group の中で選択を行う */ void selection(Gene_set gene_group[GENE_NUM]) { #if ELETE_SELECTION /* 2/2 */ elete(gene_group); #else tournament(gene_group); #endif /* ELETE_SELECTION 2/2 */ } void tournament(Gene_set gene_group[GENE_NUM]) { int i, j, k, l; int min_fitness_index; int random_gene_index[SELECT_NUM]; Gene_set next_gene_group[GENE_NUM]; /* すべての候補がそろうまで */ for (i = 0; i < GENE_NUM; i++) { for (j = 0; j < SELECT_NUM; j++) { /* 全遺伝子の中からランダムに被らないよう複数選ぶ */ while (1) { k = rand() % GENE_NUM; for (l = 0; l < j; l++) { if (k == random_gene_index[l]) { break; } } /* 最後まで一致しなかったら採用 */ if (l == j) break; } random_gene_index[j] = k; } min_fitness_index = random_gene_index[0]; /* 選んだ個体の中から適合度が最も良い(小さい)ものを選び,次の世代とする */ for (j = 1; j < SELECT_NUM; j++) { if (gene_group[min_fitness_index].fitness > gene_group[random_gene_index[j]].fitness) { min_fitness_index = random_gene_index[j]; } } copy_gene_set(&next_gene_group[i], &gene_group[min_fitness_index]); } copy_gene_group(gene_group, next_gene_group); } void elete(Gene_set gene_group[GENE_NUM]) { int i, j, k, l; int min_fitness_index; int random_gene_index[SELECT_NUM]; Gene_set next_gene_group[GENE_NUM]; /* 全個体を適合度の良い順(小さい順)に並び替える */ qsort(gene_group, GENE_NUM, sizeof(Gene_set), compare_fitness); /* 上位 ELETE 個を次世代にコピーする */ for (i = 0; i < ELETE; i++) { copy_gene_set(&next_gene_group[i], &gene_group[i]); } /* 残りの枠(ELETE ~ GENE_NUM)をトーナメント方式で埋める */ for (i = ELETE; i < GENE_NUM; i++) { for (j = 0; j < SELECT_NUM; j++) { while (1) { k = rand() % GENE_NUM; for (l = 0; l < j; l++) { if (k == random_gene_index[l]) break; } if (l == j) break; } random_gene_index[j] = k; } min_fitness_index = random_gene_index[0]; for (j = 1; j < SELECT_NUM; j++) { if (gene_group[min_fitness_index].fitness > gene_group[random_gene_index[j]].fitness) { min_fitness_index = random_gene_index[j]; } } copy_gene_set(&next_gene_group[i], &gene_group[min_fitness_index]); } copy_gene_group(gene_group, next_gene_group); } void copy_gene_set(Gene_set *gene_set_to, Gene_set *gene_set_from) { int i; for (i = 0; i < CITY_NUM; i++) { gene_set_to->gene[i] = gene_set_from->gene[i]; } gene_set_to->length = gene_set_from->length; gene_set_to->fitness = gene_set_from->fitness; } void copy_gene_group(Gene_set gene_group_to[GENE_NUM], Gene_set gene_group_from[GENE_NUM]) { int i; for (i = 0; i < GENE_NUM; i++) { copy_gene_set(&gene_group_to[i], &gene_group_from[i]); } }