遺伝的アルゴリズム( TSP )

データ例,プログラム,MT.h

  以下,複数のファイル構成になっています.ファイル間の区切りを「---・・・」で示します.このプログラム例においては,ヘッダファイル MT.h に記述されたメルセンヌ・ツイスタを使用していまが,C++11 で記述可能であれば,C++ の標準ライブラリであるメルセンヌ・ツイスター法による擬似乱数生成エンジンを使用できます.

------------------------ケーススタディデータ------
3
12345 data\species.10 data\data10.tsp
123 data\species.10 data\data10.tsp
1 data\species.10 data\data10.tsp

------------------------Species記述データ---------
対立遺伝子上限 9 対立遺伝子下限 0
最大遺伝子長 10 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
遺伝子の重複 0 個体の重複(同じ染色体の個体) 0
集団サイズ 10 子供 10

------------------------TSP記述データ-------------
出力レベル(負はファイル) 10 出力方法(0:適応度+順番,1:適応度) 0
出力ファイル名 result\kekka 表示間隔 10
交叉方法 1 交叉確率 1.0 点 5 位置 0 方法 1 バイアス 0 ステップ 1
突然変異方法 1 突然変異率 0.03 幅 1 平均 0.0 標準偏差 1.0
エリート 2 方法 1 バイアス 0 ステップ 1
都市数 10 最大世代交代数 2000
近傍探索(0:行わない,1:行う) 0 近傍(2or3) 2
選択方法(0:最良,1:最初) 1
-58 37
55 -19
6 -79
27 -30
44 -94
33 -58
-94 87
-9 3
33 69
43 -57

------------------------species.h-----------------
/***************************/
/* クラスSpeciesの定義 */
/***************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

class Species {

	protected:

		double max;   // 最大適応度
		double mean;   // 平均適応度
		double *pi;   // 適応度
		double *ro;   // ルーレット板
		int allele_u;   // 対立遺伝子上限
		int allele_l;   // 対立遺伝子下限
		int size;   // 個体総数
		int max_ch;   // 子供の数の最大値
		int max_len;   // 最大遺伝子長
		int min_len;   // 最小遺伝子長(負の時は,最大遺伝子長で固定)
		int max_n;   // 最大適応度の個体番号
		int dup_a;   // 遺伝子の重複
                     //   =0 : 重複を許さない
                     //   =1 : 重複を許す
		int dup_s;   // 個体の重複(同じ染色体の個体)
                     //   =0 : 重複を許さない
                     //   =1 : 重複を許す
		int **ind;   // 集団(個体の集まり)
		int *len;   // 各個体の遺伝子長
		int *kou1;   // 交叉・突然変異用作業場所1
		int *kou2;   // 交叉・突然変異用作業場所2
		int *s_w;   // 淘汰用指標(選択された回数)
		int **edge;   // エッジ組み替え交叉用ワークエリア
		char *pi_w;   // 適応度計算指標
                     //   =0 : 未使用
                     //   =1 : 適応度計算前(突然変異はこの個体だけに適用)
                     //   =2 : 適応度計算済み(交叉時に親とみなす)

		int Position(int);
		int Select(int method=-1, double bias=0.0, double step=1.0);

	public:
					// コンストラクタ
		Species(char *, long);
					// デストラクタ
		~Species();
					// 標準的な初期設定
		void Init_std();
					// 標準的な出力
		void Out_std(int, int, int, char *);
					// 交叉
						// 親のコピー
		void C_copy(int method=2, int pair=0, int k_method=-1,
                    double k_bias=0.0, double k_step=1.0);
						// 多点交叉
		void C_point(double, int k_point=1, int k_vr=0, int k_method=-1,
                     double k_bias=0.0, double k_step=1.0);
						// 一様交叉
		void C_uniform(double, int k_method=-1, double k_bias=0.0,
                       double k_step=1.0);
						// 平均化交叉
		void C_mean(double, int k_method=-1, double k_bias=0.0,
                    double k_step=1.0);
						// 循環交叉
		void C_cycle(double, int k_method=-1, double k_bias=0.0,
                     double k_step=1.0);
						// 部分的交叉
		void C_part(double, int k_method=-1, double k_bias=0.0,
                    double k_step=1.0);
						// 順序交叉
		void C_seq(double, int k_method=-1, double k_bias=0.0,
                   double k_step=1.0);
						// 一様順序交叉
		void C_useq(double, int k_method=-1, double k_bias=0.0,
                    double k_step=1.0);
						// 一様位置交叉
		void C_upos(double, int k_method=-1, double k_bias=0.0,
                    double k_step=1.0);
						// エッジ組み替え交叉
		void C_edge(double, int k_method=-1, double k_bias=0.0,
                    double k_step=1.0);
						// サブツアー交叉
		void C_sub(double, int count=10);
					// 突然変異
						// 対立遺伝子への置換
		void M_alle(double);
						// 移動
		void M_move(double);
						// 逆位
		void M_inv(double, int wd=0);
						// スクランブル
		void M_scram(double pr, int wd=0);
						// 転座
		void M_chg(double pr, int wd=0);
						// 重複
		void M_dup(double pr, int wd=0);
						// 摂動
		void M_per(double pr, int method=0, double m=0.0, double s=1.0);
						// 挿入
		void M_ins(double pr, int wd=0);
						// 削除
		void M_del(double pr, int wd=0);
                    // エリート・ルーレット選択
		void S_roul(int elite=0, int s_method=1, double s_bias=0.0,
                    double s_step=1.0);
};

------------------------Speciesのメンバー関数-----
/*******************************/
/* クラスSpeciesのメンバー関数 */
/*******************************/
#include "species.h"
#include "MT.h"

double norm_d(double, double);

/****************************/
/* コンストラクタ           */
/*      name : ファイル名   */
/*      seed : 乱数の初期値 */
/****************************/
Species::Species(char *name, long seed)
{
	int i1, kind, num;
	FILE *in;
/*
     データの入力
*/
	in = fopen(name, "r");

	fscanf(in,"%*s %d %*s %d", &allele_u, &allele_l);
	fscanf(in,"%*s %d %*s %d", &max_len, &min_len);
	fscanf(in,"%*s %d %*s %d", &dup_a, &dup_s);
	fscanf(in,"%*s %d %*s %d", &size, &max_ch);
/*
     データのチェック
*/
	if (size <= 0) {
		printf("***error  個体総数≦0 (Constructor)\n");
		exit(1);
	}

	if (max_ch < 0) {
		printf("***error  子供の数<0 (Constructor)\n");
		exit(1);
	}

	if (max_len <= 0 || min_len == 0) {
		printf("***error  遺伝子長≦0 (Constructor)\n");
		exit(1);
	}

	if (max_len < min_len) {
		printf("***error  最大遺伝子長<最小遺伝子長 (Constructor)\n");
		exit(1);
	}

	if (allele_u <= allele_l) {
		printf("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)\n");
		exit(1);
	}

	kind = allele_u - allele_l + 1;
	if (dup_a == 0 && max_len > kind) {
		printf("***error  遺伝子の重複を防ぐことはできない (Constructor)\n");
		exit(1);
	}
/*
     領域の確保
*/
	num = size + max_ch;

	ind = new int * [num];
	for (i1 = 0; i1 < num; i1++)
		ind[i1] = new int [max_len];

	edge = new int * [max_len];
	for (i1 = 0; i1 < max_len; i1++)
		edge[i1] = new int [5];

	pi   = new double [num];
	ro   = new double [num];
	len  = new int [num];
	kou1 = new int [max_len];
	kou2 = new int [max_len];
	s_w  = new int [num];
	pi_w = new char [num];
/*
     乱数の初期設定
*/
	init_genrand(seed);
}

/****************/
/* デストラクタ */
/****************/
Species::~Species()
{
	int i1;

	for (i1 = 0; i1 < size+max_ch; i1++)
		delete [] ind[i1];
	delete [] ind;

	for (i1 = 0; i1 < max_len; i1++)
		delete [] edge[i1];
	delete [] edge;

	delete [] pi;
	delete [] len;
	delete [] kou1;
	delete [] kou2;
	delete [] pi_w;
	delete [] s_w;
	delete [] ro;
}

/**************************************************/
/* 場所を探す                                     */
/*      n : >=0 : n番目の親を捜す                 */
/*          -1 : 空いている場所を探す             */
/*      return : 親の場所,または,空いている場所 */
/*               (存在しないときは負の値)       */
/**************************************************/
int Species::Position(int n)
{
	int i1, k = -1, sw = 0;
/*
     空いている場所を探す
*/
	if (n < 0) {
		for (i1 = 0; i1 < size+max_ch && k < 0; i1++) {
			if (pi_w[i1] == 0)
				k = i1;
		}
		if (k < 0) {
			printf("***error  空いている場所がない --Position--\n");
			exit(1);
		}
	}
/*
     n番目の親(pi_w[i]=2)を捜す
*/
	else {
		for (i1 = 0; i1 < size+max_ch && sw == 0; i1++) {
			if (pi_w[i1] == 2) {
				k++;
				if (k == n) {
					sw = 1;
					k  = i1;
				}
			}
		}
	}

	return k;
}

/*******************************************************************/
/* 個体の選択                                                      */
/*      method : 選択方法                                          */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      bias : α,または,method=2の場合は初期値(default=0)       */
/*      step : β(default=1)                                       */
/*      return : 個体番号                                          */
/*******************************************************************/
int Species::Select(int method, double bias, double step)
{
	double sum = 0.0, x;
	int i1, k, min, n, sw;
					// ルーレット板の用意
	switch (method) {
						// ランダム
		case -1:
			n = 0;
			for (i1 = 0; i1 < size+max_ch; i1++) {
				if (pi_w[i1] > 1)
					n++;
			}
			sum = 1.0 / n;
			for (i1 = 0; i1 < size+max_ch; i1++) {
				if (pi_w[i1] > 1)
					ro[i1] = sum;
			}
			break;
						// 評価値をそのまま利用
		case 0:
			n = 0;
			for (i1 = 0; i1 < size+max_ch; i1++) {
				if (pi_w[i1] > 1) {
					sum += pi[i1];
					n++;
				}
			}
			if (fabs(sum) > 1.0e-10) {
				sum = 1.0 / fabs(sum);
				for (i1 = 0; i1 < size+max_ch; i1++) {
					if (pi_w[i1] > 1)
						ro[i1] = pi[i1] * sum;
				}
			}
			else {
				sum = 1.0 / n;
				for (i1 = 0; i1 < size+max_ch; i1++) {
					if (pi_w[i1] > 1)
						ro[i1] = sum;
				}
			}
			break;
						// 最小値からの差
		case 1:
			min = -1;
			n   = 0;
			for (i1 = 0; i1 < size+max_ch; i1++) {
				if (pi_w[i1] > 1) {
					n++;
					if (min < 0 || pi[i1] < pi[min])
						min = i1;
				}
			}
			for (i1 = 0; i1 < size+max_ch; i1++) {
				if (pi_w[i1] > 1) {
					ro[i1] = pi[i1] - pi[min];
					if (ro[i1] < bias)
						ro[i1] = bias;
					sum += ro[i1];
				}
			}
			if (sum > 1.0e-10) {
				sum = 1.0 / sum;
				for (i1 = 0; i1 < size+max_ch; i1++) {
					if (pi_w[i1] > 1)
						ro[i1] *= sum;
				}
			}
			else {
				sum = 1.0 / n;
				for (i1 = 0; i1 < size+max_ch; i1++) {
					if (pi_w[i1] > 1)
						ro[i1] = sum;
				}
			}
			break;
						// 線形化
		case 2:
			n = 0;
			for (i1 = 0; i1 < size+max_ch; i1++) {
				if (pi_w[i1] > 1) {
					ro[i1] = -1.0;
					n++;
				}
				else
					ro[i1] = 1.0;
			}
			sw  = 0;
			sum = bias;
			while (sw == 0) {
				min = -1;
				for (i1 = 0; i1 < size+max_ch; i1++) {
					if (ro[i1] < 0.0 && (min < 0 || pi[i1] < pi[min]))
						min = i1;
				}
				if (min < 0)
					sw = 1;
				else {
					ro[min]  = sum;
					sum     += step;
				}
			}
			sum = 1.0 / (0.5 * (2.0 * bias + step * (n - 1)) * n);
			for (i1 = 0; i1 < size+max_ch; i1++) {
				if (pi_w[i1] > 1)
					ro[i1] *= sum;
			}
			break;
	}

	sum = 0.0;
	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (pi_w[i1] > 1) {
			sum    += ro[i1];
			ro[i1]  = sum;
		}
	}
					// 選択
	x  = genrand_real3();
	sw = 0;
	k  = 0;
	for (i1 = 0; i1 < size+max_ch && sw == 0; i1++) {
		if (pi_w[i1] > 1) {
			if (x <= ro[i1]) {
				sw = 1;
				k  = i1;
			}
		}
	}

	return k;
}

/********************/
/* 標準的な初期設定 */
/********************/
void Species::Init_std()
{
	int i1, i2, i3, length, lid, sw1, sw2;
/*
     初期設定
*/
	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (i1 < size)
			pi_w[i1] = 1;   // 適応度の計算前
		else
			pi_w[i1] = 0;   // 未使用
	}
/*
     遺伝子の決定
*/
	for (i1 = 0; i1 < size; i1++) {

		sw1 = 0;

		while (sw1 == 0) {
					// 遺伝子長の決定
			if (min_len < 0)
				length = max_len;
			else {
				length = (int)(genrand_real3() * (max_len - min_len + 1) + min_len);
				if (length > max_len)
					length = max_len;
			}
			len[i1] = length;
					// 遺伝子の決定
			for (i2 = 0; i2 < length; i2++) {
				sw2 = 0;
				while (sw2 == 0) {
					lid = (int)(genrand_real3() * (allele_u - allele_l + 1) + allele_l);
					if (lid > allele_u)
						lid = allele_u;
					ind[i1][i2] = lid;
						// 重複遺伝子のチェック
					sw2 = 1;
					if (dup_a == 0) {
						for (i3 = 0; i3 < i2 && sw2 > 0; i3++) {
							if (lid == ind[i1][i3])
								sw2 = 0;
						}
					}
				}
			}
					// 重複個体のチェック
			sw1 = 1;
			if (dup_s == 0) {
				for (i2 = 0; i2 < i1 && sw1 > 0; i2++) {
					if (len[i1] == len[i2]) {
						sw2 = 0;
						for (i3 = 0; i3 < len[i1] && sw2 == 0; i3++) {
							if (ind[i1][i3] != ind[i2][i3])
								sw2 = 1;
						}
						if (sw2 == 0)
							sw1 = 0;
					}
				}
			}
		}
	}
}

/****************************************************/
/* 標準的な出力                                     */
/*      sw : 出力レベル                             */
/*             =0 : 最終出力だけ                    */
/*             n>0 : n世代毎に出力(負はファイル) */
/*      out_m : 出力方法                            */
/*                =0 : すべての個体を出力           */
/*                =1 : 最大適応度の個体だけを出力   */
/*      gen : 現在の世代番号                        */
/*      name : 出力ファイル名                       */
/****************************************************/
void Species::Out_std(int sw, int out_m, int gen, char *name)
{
	int i1, i2, k = 0, pr;
	char *now;
	time_t aclock;
	FILE *out;

	if (sw >= 0) {
		printf("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
		scanf("%d", &pr);
	}
	else
		pr = -1;

	if (pr != 0) {
					// 出力先の決定と評価値の出力
		if (pr > 0) {
			out = stdout;
			getchar();
		}
		else {
			time(&aclock);
			now = ctime(&aclock);
			out = fopen(name, "a");
			fprintf(out, "***世代 %d 適応度 max %f (%d) mean %f 時間 %s\n",
                    gen, max, max_n, mean, now);
		}
					// 詳細出力
		for (i1 = 0; i1 < size+max_ch; i1++) {
			if ((pi_w[i1] > 1) && (out_m ==0 || out_m == 1 && i1 == max_n)) {
				fprintf(out, "%d allele", i1);
				for (i2 = 0; i2 < len[i1]; i2++)
					fprintf(out, " %d", ind[i1][i2]);
				fprintf(out, " value %f\n", pi[i1]);
				if (pr > 0) {
					k++;
					if (k == pr) {
						getchar();
						k = 0;
					}
				}
			}
		}

		if (pr < 0)
			fclose(out);
	}
}

/*******************************************************************/
/* 交叉(親のコピー)                                              */
/*      method : =2 : 有性(2つの親から2つの子供)(default)      */
/*               =1 : 1つの親から1つの子供                       */
/*      pair : method=2 の時は親のペア数(default=max_ch/2)         */
/*             method=1 の時は親の数(=子供の数)                 */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_copy(int method, int pair, int k_method,
                     double k_bias, double k_step)
{
   int i1, i2, i3, k, p, p1, p2, sw;
/*
     初期設定とデータチェック
*/
	if (method != 1)
		method = 2;

	if (pair <= 0)
		pair = (method==2) ? max_ch/2 : max_ch;
	else {
		if (method == 2 && 2*pair > max_ch || method == 1 && pair > max_ch) {
			printf("***error  子供が多すぎる (C_copy)\n");
			exit(1);
		}
	}
/*
     実行
*/
	for (i1 = 0; i1 < pair; i1++) {
					// 親の選択
		p1 = Select(k_method, k_bias, k_step);
		sw = 0;

		while (sw == 0) {
			p2 = Select(k_method, k_bias, k_step);
			if (p1 != p2)
				sw = 1;
		}
					// コピー
		for (i2 = 0; i2 < method; i2++) {
			p       = (i2 == 0) ? p1 : p2;
			k       = Position(-1);
			len[k]  = len[p];
			pi_w[k] = 1;
			for (i3 = 0; i3 < len[k]; i3++)
				ind[k][i3] = ind[p][i3];
		}
	}
}

/*******************************************************************/
/* 交叉(多点交叉)                                                */
/*      kosa : 交叉確率                                            */
/*      k_point : 交叉点の数(default=1)                            */
/*                (負の時は,1から-k_point間のランダム)          */
/*      k_vr : =0 : 両親とも同じ位置で交叉(default)                */
/*             =1 : 両親が異なる位置で交叉(遺伝子長は可変)       */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_point(double kosa, int k_point, int k_vr, int k_method,
                      double k_bias, double k_step)
{
	int abs_p, c1, c2, i1, i2, i3, k1, k2, mn = 0, num, p1, p2, pair,
        sw, t11, t12, t21, t22;
/*
     初期設定とデータのチェック
*/
	pair = max_ch / 2;

	if (dup_a == 0) {
		printf("***error  交叉方法が不適当 (C_point)\n");
		exit(1);
	}

	abs_p = abs(k_point);
	if (abs_p == 0 || abs_p > max_len-1 || min_len > 0 && abs_p > min_len-1) {
		printf("***error  交叉点の数が不適当 (C_point)\n");
		exit(1);
	}

	if (k_vr > 0 && min_len < 0) {
		printf("***error  遺伝子長は可変でなければならない (C_point)\n");
		exit(1);
	}
/*
     交叉
*/
	num = k_point;

	for (i1 = 0; i1 < pair; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(2, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 交叉位置の数の決定
			if (k_point < 0) {
				num = (int)(genrand_real3() * abs_p + 1);
				if (num > abs_p)
					num = abs_p;
			}
						// 交叉位置の決定(点の後ろで交叉)
			for (i2 = 0; i2 < num; i2++) {
							// 親1の交叉位置
				sw = 0;
				while (sw == 0) {
					sw       = 1;
					kou1[i2] = (int)(genrand_real3() * (len[p1] - 1));
					if (kou1[i2] > len[p1]-2)
						kou1[i2] = len[p1] - 2;
					if (k_vr == 0 && kou1[i2] > len[p2]-2)
						kou1[i2] = len[p2] - 2;
					for (i3 = 0; i3 < i2 && sw > 0; i3++) {
						if (kou1[i3] == kou1[i2])
							sw = 0;
					}
				}
							// 親2の交叉位置
				if (k_vr > 0) {
					sw = 0;
					while (sw == 0) {
						sw       = 1;
						kou2[i2] = (int)(genrand_real3() * (len[p2] - 1));
						if (kou2[i2] > len[p2]-2)
							kou2[i2] = len[p2] - 2;
						for (i3 = 0; i3 < i2 && sw > 0; i3++) {
							if (kou2[i3] == kou2[i2])
								sw = 0;
						}
					}
				}
			}
						// 交叉の実行
						//   親1のt11からt12を子1のc1へコピー
						//   親2のt21からt22を子2のc2へコピー
						//     次は,
						//   親1のt11からt12を子2のc2へコピー
						//   親2のt21からt22を子1のc1へコピー
						//     ・・・・・
			c1  = 0;
			c2  = 0;
			t11 = 0;
			t21 = 0;
							// 遺伝子長
			k1       = Position(-1);
			pi_w[k1] = 1;
			len[k1]  = len[p1];
			k2       = Position(-1);
			pi_w[k2] = 1;
			len[k2]  = len[p2];

			for (i2 = 0; i2 < num+1; i2++ ) {
							// 次の交叉位置を求める
				if (i2 == num) {            // 最後
					t12 = len[p1];
					t22 = len[p2];
				}
				else {
								// 親1
					t12 = max_len;
					for (i3 = 0; i3 < num; i3++) {
						if (kou1[i3] >= 0 && kou1[i3] <= t12) {
							t12 = kou1[i3];
							mn  = i3;
						}
					}
					kou1[mn] = -1;
					t12++;
								// 親2
					if (k_vr == 0)
						t22 = t12;
					else {
						t22 = max_len;
						for (i3 = 0; i3 < num; i3++) {
							if (kou2[i3] >= 0 && kou2[i3] <= t22) {
								t22 = kou2[i3];
								mn  = i3;
							}
						}
						kou2[mn] = -1;
						t22++;
					}
				}
							// 指定箇所のコピー
				for (i3 = t11; i3 < t12; i3++) {
					if (i2%2 == 0) {
						if (c1 < max_len) {
							ind[k1][c1] = ind[p1][i3];
							c1++;
						}
					}
					else {
						if (c2 < max_len) {
							ind[k2][c2] = ind[p1][i3];
							c2++;
						}
					}
				}

				for (i3 = t21; i3 < t22; i3++) {
					if (i2%2 == 0) {
						if (c2 < max_len) {
							ind[k2][c2] = ind[p2][i3];
							c2++;
						}
					}
					else {
						if (c1 < max_len) {
							ind[k1][c1] = ind[p2][i3];
							c1++;
						}
					}
				}
							// 交叉位置の移動
				t11 = t12;
				t21 = t22;
			}
		}
	}
}

/*******************************************************************/
/* 交叉(一様交叉.[0,1]を等確率で発生させ,1であれば,            */
/*       親1,0であれば親2の遺伝子を子1が受け継ぐ)             */
/*      kosa : 交叉確率                                            */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_uniform(double kosa, int k_method, double k_bias,
                        double k_step)
{
	int i1, i2, k1, k2, p1, p2, pair, sw;
/*
     初期設定とデータのチェック
*/
	pair = max_ch / 2;

	if (dup_a == 0) {
		printf("***error  交叉方法が不適当 (C_uniform)\n");
		exit(1);
	}

	if (min_len > 0) {
		printf("***error  遺伝子長は固定長でなければならない (C_uniform)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < pair; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(2, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 遺伝子長
			k1       = Position(-1);
			pi_w[k1] = 1;
			len[k1]  = len[p1];
			k2       = Position(-1);
			pi_w[k2] = 1;
			len[k2]  = len[p2];
						// 交叉
			for (i2 = 0; i2 < len[p1]; i2++) {
				if (genrand_real3() > 0.5) {
					ind[k1][i2] = ind[p1][i2];
					ind[k2][i2] = ind[p2][i2];
				}
				else {
					ind[k1][i2] = ind[p2][i2];
					ind[k2][i2] = ind[p1][i2];
				}
			}
		}
	}
}

/*******************************************************************/
/* 交叉(平均化交叉.2つの親の平均値を受け継ぐ)                  */
/*      kosa : 交叉確率                                            */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_mean(double kosa, int k_method, double k_bias,
                     double k_step)
{
	int i1, i2, k, p1, p2, sw;
/*
     初期設定とデータのチェック
*/
	if (min_len > 0) {
		printf("***error  遺伝子長は固定長でなければならない (C_mean)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < max_ch; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(1, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 遺伝子長
			k       = Position(-1);
			len[k]  = len[p1];
			pi_w[k] = 1;
						// 交叉
			for (i2 = 0; i2 < len[k]; i2++)
				ind[k][i2] = (ind[p1][i2] + ind[p2][i2]) / 2;
		}
	}
}

/*******************************************************************/
/* 交叉(循環交叉.ランダムに1点を選択し,その位置にある遺伝子を  */
/*       そのまま各子供が選択する.その位置にある親2(1)の遺伝  */
/*       子を,その遺伝子の親1(2)の場所に,子1(2)が受け継  */
/*       ぐ(ただし,doubleの場合は,この手続きをのぞく).この手  */
/*       続きを,すでに受け継いだ遺伝子の位置が選択されるまで繰り  */
/*       返し,残りの遺伝子については,子1(2)は,親2(1)の  */
/*       遺伝子をその順番通りに受け継ぐ)                          */
/*         2 4 1 3 6 5    + + 1 + + 5    3 2 1 4 6 5               */
/*             *       →             →                           */
/*         3 2 5 4 1 6    + + 5 + 1 +    2 4 5 3 1 6               */
/*      kosa : 交叉確率                                            */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_cycle(double kosa, int k_method, double k_bias,
                      double k_step)
{
   int i1, i2, i3, k1, k2, p, pair, p1, p2, sw;
/*
     初期設定とデータのチェック
*/
	pair = max_ch / 2;

	if (dup_a != 0) {
		printf("***error  交叉方法が不適当 (C_cycle)\n");
		exit(1);
	}

	if (min_len > 0) {
		printf("***error  遺伝子長は固定長でなければならない (C_cycle)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < pair; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(2, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 初期設定
			for (i2 = 0; i2 < len[p1]; i2++) {
				kou1[i2] = 0;
				kou2[i2] = 0;
			}
						// 遺伝子長
			k1       = Position(-1);
			pi_w[k1] = 1;
			len[k1]  = len[p1];
			k2       = Position(-1);
			pi_w[k2] = 1;
			len[k2]  = len[p2];
						// 交叉
			sw = 0;

			while (sw == 0) {
				sw = 1;
				p  = (int)(genrand_real3() * len[p1]);
				if (p >= len[p1])
					p = len[p1] - 1;
				if (kou1[p] == 0 && kou2[p] == 0) {
					kou1[p]    = 1;
					kou2[p]    = 1;
					ind[k1][p] = ind[p1][p];
					ind[k2][p] = ind[p2][p];
					for (i2 = 0; i2 < len[p1] && sw > 0; i2++) {
						if (ind[p2][p] == ind[p1][i2]) {
							ind[k1][i2] = ind[p1][i2];
							kou1[i2]    = 1;
							sw          = 0;
						}
					}
					sw = 1;
					for (i2 = 0; i2 < len[p2] && sw > 0; i2++) {
						if (ind[p1][p] == ind[p2][i2]) {
							ind[k2][i2] = ind[p2][i2];
							kou2[i2]    = 1;
							sw          = 0;
						}
					}
				}
			}

			sw = 0;
			i2 = 0;
			i3 = 0;
			while (sw == 0) {
				while (sw == 0 && i2 < len[p1]) {
					if (kou1[i2] == 0)
						sw = 1;
					else
						i2++;
				}
				sw = 0;
				while (sw == 0 && i3 < len[p2]) {
					if (kou2[i3] == 0)
						sw = 1;
					else
						i3++;
				}
				if (i2 < len[p1] && i3 < len[p2]) {
					ind[k1][i2] = ind[p2][i3];
					ind[k2][i3] = ind[p1][i2];
					sw          = 0;
					i2++;
					i3++;
				}
				else
					sw = 1;
			}
		}
	}
}

/*******************************************************************/
/* 交叉(部分的交叉.ランダムに1点を選択し,その位置にある親1と  */
/*       親2の遺伝子を取り出す.次に,親1と親2の染色体上で,こ  */
/*       の2つの遺伝子の位置を交換する.この操作を,選択した点よ  */
/*       り右にあるすべての遺伝子に対して実施する                  */
/*         2 4 1 3 6 5    2 4 5 3 6 1                              */
/*             *       →             → ・・・・・                     */
/*         3 2 5 4 1 6    3 2 1 4 5 6                              */
/*      kosa : 交叉確率                                            */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_part(double kosa, int k_method, double k_bias,
                     double k_step)
{
	int i1, i2, i3, k1, k2, lv, p, pair, p1, p2, sw;
/*
     初期設定とデータのチェック
*/
	pair = max_ch / 2;

	if (dup_a != 0) {
		printf("***error  交叉方法が不適当 (C_part)\n");
		exit(1);
	}

	if (min_len > 0) {
		printf("***error  遺伝子長は固定長でなければならない (C_part)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < pair; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(2, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 遺伝子長
			k1       = Position(-1);
			pi_w[k1] = 1;
			len[k1]  = len[p1];
			k2       = Position(-1);
			pi_w[k2] = 1;
			len[k2]  = len[p2];
						// 交叉
			p = (int)(genrand_real3() * len[p1]);
			if (p >= len[p1])
				p = len[p1] - 1;

			for (i2 = 0; i2 < len[p1]; i2++) {
				ind[k1][i2] = ind[p1][i2];
				ind[k2][i2] = ind[p2][i2];
			}

			for (i2 = p; i2 < len[p1]; i2++) {
				sw = 0;
				lv = ind[k1][i2];
				for (i3 = 0; i3 < len[p1] && sw == 0; i3++) {
					if (ind[k2][i2] == ind[k1][i3]) {
						ind[k1][i2] = ind[k1][i3];
						ind[k1][i3] = lv;
						sw          = 1;
					}
				}
				sw = 0;
				for (i3 = 0; i3 < len[p1] && sw == 0; i3++) {
					if (lv == ind[k2][i3]) {
						ind[k2][i3] = ind[k2][i2];
						ind[k2][i2] = lv;
						sw          = 1;
					}
				}
			}
		}
	}
}

/*******************************************************************/
/* 交叉(順序交叉.ランダムに切れ目を決定し,子1に対し,切れ目の  */
/*       左側では,親1の遺伝子をそのまま受け継ぎ,右側では,親1  */
/*       の遺伝子を親2の遺伝子の出現順序に並べ替える.            */
/*         2 4 1 3 6 5    2 4 1 3 5 6                              */
/*             *       →                                          */
/*         3 2 5 4 1 6    3 2 5 4 1 6                              */
/*      kosa : 交叉確率                                            */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_seq(double kosa, int k_method, double k_bias,
                    double k_step)
{
	int i1, i2, i3, i4, k1, k2, p, pair, pp, p1, p2, sw;
/*
     初期設定とデータのチェック
*/
	pair = max_ch / 2;

	if (dup_a != 0) {
		printf("***error  交叉方法が不適当 (C_seq)\n");
		exit(1);
	}

	if (min_len > 0) {
		printf("***error  遺伝子長は固定長でなければならない (C_seq)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < pair; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(2, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 遺伝子長
			k1       = Position(-1);
			pi_w[k1] = 1;
			len[k1]  = len[p1];
			k2       = Position(-1);
			pi_w[k2] = 1;
			len[k2]  = len[p2];
						// 交叉
			p = (int)(genrand_real3() * (len[p1] - 1));
			if (p >= len[p1]-1)
				p = len[p1] - 2;

			for (i2 = 0; i2 <= p; i2++) {
				ind[k1][i2] = ind[p1][i2];
				ind[k2][i2] = ind[p2][i2];
			}

			pp = 0;
			for (i2 = p+1; i2 < len[p1]; i2++) {
				sw = 0;
				for (i3 = pp; i3 < len[p2] && sw == 0; i3++) {
					for (i4 = p+1; i4 < len[p1] && sw == 0; i4++) {
						if (ind[p2][i3] == ind[p1][i4]) {
							sw          = 1;
							pp          = i3 + 1;
							ind[k1][i2] = ind[p1][i4];
						}
					}
				}
			}
			pp = 0;
			for (i2 = p+1; i2 < len[p2]; i2++) {
				sw = 0;
				for (i3 = pp; i3 < len[p1] && sw == 0; i3++) {
					for (i4 = p+1; i4 < len[p2] && sw == 0; i4++) {
						if (ind[p1][i3] == ind[p2][i4]) {
							sw          = 1;
							pp          = i3 + 1;
							ind[k2][i2] = ind[p2][i4];
						}
					}
				}
			}
		}
	}
}

/*******************************************************************/
/* 交叉(一様順序交叉.位置の集合をランダムに選択し,一方の親の選  */
/*       択された位置における遺伝子の順序に従って,他の親の遺伝子  */
/*       を並べ替える                                              */
/*         2 4 1 3 6 5    2 4 1 3 6 5                              */
/*           *   *     →                                          */
/*         3 2 5 4 1 6    4 2 5 3 1 6                              */
/*      kosa : 交叉確率                                            */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_useq(double kosa, int k_method, double k_bias,
                     double k_step)
{
   int i1, i2, i3, i4, k1, k2, p, pair, p1, p2, sw;
/*
     初期設定とデータのチェック
*/
	pair = max_ch / 2;

	if (dup_a != 0) {
		printf("***error  交叉方法が不適当 (C_useq)\n");
		exit(1);
	}

	if (min_len > 0) {
		printf("***error  遺伝子長は固定長でなければならない (C_useq)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < pair; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(2, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 遺伝子長
			k1       = Position(-1);
			pi_w[k1] = 1;
			len[k1]  = len[p1];
			k2       = Position(-1);
			pi_w[k2] = 1;
			len[k2]  = len[p2];
						// 交叉
			for (i2 = 0; i2 < len[p1]; i2++) {
				ind[k1][i2] = ind[p1][i2];
				ind[k2][i2] = ind[p2][i2];
				kou1[i2]    = (genrand_real3() < 0.5) ? 0 : 1;
			}

			p = 0;
			for (i2 = 0; i2 < len[p1]; i2++) {
				if (kou1[i2] > 0) {
					sw = 0;
					for (i3 = p; i3 < len[p2] && sw == 0; i3++) {
						for (i4 = 0; i4 < len[p1] && sw == 0; i4++) {
							if (ind[p2][i3] == ind[p1][i4] && kou1[i4] > 0) {
								sw          = 1;
								p           = i3 + 1;
								ind[k1][i2] = ind[p1][i4];
							}
						}
					}
				}
			}
			p = 0;
			for (i2 = 0; i2 < len[p2]; i2++) {
				if (kou1[i2] > 0) {
					sw = 0;
					for (i3 = p; i3 < len[p1] && sw == 0; i3++) {
						for (i4 = 0; i4 < len[p2] && sw == 0; i4++) {
							if (ind[p1][i3] == ind[p2][i4] && kou1[i4] > 0) {
								sw          = 1;
								p           = i3 + 1;
								ind[k2][i2] = ind[p2][i4];
							}
						}
					}
				}
			}
		}
	}
}

/*******************************************************************/
/* 交叉(一様位置交叉.位置の集合をランダムに選択し,一方の親の選  */
/*       択された位置における遺伝子の位置に,他の親の同じ遺伝子を  */
/*       配置する.残りの遺伝子は,親と同じ順序に配置する.        */
/*         2 4 1 3 6 5    + + 5 + 1 +    2 4 5 3 1 6               */
/*             *   *   →             →                           */
/*         3 2 5 4 1 6    + + 1 + 6 +    3 2 1 5 6 4               */
/*      kosa : 交叉確率                                            */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_upos(double kosa, int k_method, double k_bias,
                     double k_step)
{
   int i1, i2, i3, k1, k2, p, pair, p1, p2, sw;
/*
     初期設定とデータのチェック
*/
	pair = max_ch / 2;

	if (dup_a != 0) {
		printf("***error  交叉方法が不適当 (C_upos)\n");
		exit(1);
	}

	if (min_len > 0) {
		printf("***error  遺伝子長は固定長でなければならない (C_upos)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < pair; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(2, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 遺伝子長
			k1       = Position(-1);
			pi_w[k1] = 1;
			len[k1]  = len[p1];
			k2       = Position(-1);
			pi_w[k2] = 1;
			len[k2]  = len[p2];
						// 交叉
			for (i2 = 0; i2 < len[p1]; i2++) {
				kou1[i2] = (genrand_real3() < 0.5) ? 0 : 1;
				if (kou1[i2] > 0) {
					ind[k1][i2] = ind[p2][i2];
					ind[k2][i2] = ind[p1][i2];
				}
			}

			p = 0;
			for (i2 = 0; i2 < len[p1]; i2++) {
				sw = 0;
				for (i3 = 0; i3 < len[p1] && sw == 0; i3++) {
					if (kou1[i3] > 0 && ind[p1][i2] == ind[k1][i3])
						sw = 1;
				}
				if (sw == 0) {
					for (i3 = p; i3 < len[p1] && sw == 0; i3++) {
						if (kou1[i3] == 0) {
							ind[k1][i3] = ind[p1][i2];
							p           = i3 + 1;
							sw          = 1;
						}
					}
				}
			}
			p = 0;
			for (i2 = 0; i2 < len[p2]; i2++) {
				sw = 0;
				for (i3 = 0; i3 < len[p2] && sw == 0; i3++) {
					if (kou1[i3] > 0 && ind[p2][i2] == ind[k2][i3])
						sw = 1;
				}
				if (sw == 0) {
					for (i3 = p; i3 < len[p2] && sw == 0; i3++) {
						if (kou1[i3] == 0) {
							ind[k2][i3] = ind[p2][i2];
							p           = i3 + 1;
							sw          = 1;
						}
					}
				}
			}
		}
	}
}

/*******************************************************************/
/* 交叉(エッジ組み替え交叉.以下の手順に従って行う.対立遺伝子は  */
/*       0~(max_len-1)である必要がある)                          */
/*         (0) エッジマップを作成する.エッジマップとは,2つの親  */
/*             を見て,ノードがどこに接続されているのかを表すもの  */
/*             であり,例えば,2つの親が,                        */
/*                 [A B C D E F]                                   */
/*                 [B D C A E F]                                   */
/*             である場合は,                                      */
/*                 A : B F C E                                     */
/*                 B : A C D F                                     */
/*                 C : B D A                                       */
/*                 D : C E B                                       */
/*                 E : D F A                                       */
/*                 F : A E B                                       */
/*             となる.                                            */
/*         (1) 両親の2つの出発点の内1つで初期化する.ランダムま  */
/*             たはステップ(4)の基準に従って選ぶ(現在のノード)   */
/*         (2) エッジマップから,現在のノードを除く                */
/*         (3) 現在のノードが接続先のノードを持っていたら,(4)に   */
/*             進む.さもなければ,(5)に進む                       */
/*         (4) 現在のノードが持っている接続先ノードの内,最も少な  */
/*             い接続先ノードを持ったノードを選択し(同じ条件の場  */
/*             合は,ランダム),それを現在のノードとし,(2)に進む */
/*         (5) 未接続のノードが残っていればランダムに選択し,(2)に */
/*             戻る.さもなければ,終了する                        */
/*      kosa : 交叉確率                                            */
/*      k_method : 選択方法                                        */
/*                 =-1 : ランダム(default)                         */
/*                 =0 : 適応度をそのまま使用                       */
/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
/*      k_step : β(default=1)                                     */
/*******************************************************************/
void Species::C_edge(double kosa, int k_method, double k_bias,
                     double k_step)
{
	int e[2], i1, i2, i3, i4, i5, k, kk, k0 = 0, k1, k2, min, num,
        p, pair, p1, p2, sw;
/*
     初期設定とデータのチェック
*/
	pair = max_ch;

	if (dup_a != 0) {
		printf("***error  交叉方法が不適当 (C_edge)\n");
		exit(1);
	}

	if (min_len > 0) {
		printf("***error  遺伝子長は固定長でなければならない (C_edge)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < pair; i1++) {
					// 交叉しない場合
		if (genrand_real3() > kosa)
			C_copy(1, 1);
					// 交叉する場合
		else {
						// 親の選択
			p1 = Select(k_method, k_bias, k_step);
			sw = 0;
			while (sw == 0) {
				p2 = Select(k_method, k_bias, k_step);
				if (p1 != p2)
					sw = 1;
			}
						// 遺伝子長
			k       = Position(-1);
			pi_w[k] = 1;
			len[k]  = len[p1];
						// エッジマップの初期化
			for (i2 = 0; i2 < len[k]; i2++) {
				edge[i2][0] = 0;
				for (i3 = 1; i3 <= 4; i3++)
					edge[i2][i3] = -1;
			}
						// 交叉
							// エッジマップの作成
			for (i2 = 0; i2 < len[k]; i2++) {

				sw = 0;
				for (i3 = 0; i3 < len[k] && sw == 0; i3++) {
					if (i2 == ind[p1][i3]) {
						sw = 1;
						if (i3 == 0) {
							e[0] = ind[p1][len[k]-1];
							e[1] = ind[p1][1];
						}
						else {
							if (i3 == len[k]-1) {
								e[0] = ind[p1][i3-1];
								e[1] = ind[p1][0];
							}
							else {
								e[0] = ind[p1][i3-1];
								e[1] = ind[p1][i3+1];
							}
						}
						for (i4 = 0; i4 < 2; i4++) {
							edge[i2][0]++;
							edge[i2][edge[i2][0]] = e[i4];
						}
					}
				}

				sw = 0;
				for (i3 = 0; i3 < len[k] && sw == 0; i3++) {
					if (i2 == ind[p2][i3]) {
						sw = 1;
						if (i3 == 0) {
							e[0] = ind[p2][len[k]-1];
							e[1] = ind[p2][1];
						}
						else {
							if (i3 == len[k]-1) {
								e[0] = ind[p2][i3-1];
								e[1] = ind[p2][0];
							}
							else {
								e[0] = ind[p2][i3-1];
								e[1] = ind[p2][i3+1];
							}
						}
						for (i4 = 0; i4 < 2; i4++) {
							sw = 1;
							for (i5 = 1; i5 <= edge[i2][0] && sw == 1; i5++) {
								if (edge[i2][i5] == e[i4])
									sw = 2;
							}
							if (sw == 1) {
								edge[i2][0]++;
								edge[i2][edge[i2][0]] = e[i4];
							}
						}
					}
				}
			}
							// 交叉の実行
								// 出発点の決定
			k1 = ind[p1][0];
			k2 = ind[p2][0];
			if (edge[k1][0] == edge[k2][0])
				kk = (genrand_real3() > 0.5) ? k2 : k1;
			else
				kk = (edge[k1][0] < edge[k2][0]) ? k1 : k2;
			ind[k][0] = kk;
			p         = 1;

			while (p < len[k]) {
								// ノードの除去
				for (i2 = 0; i2 < len[k]; i2++) {
					sw = 0;
					if (edge[i2][0] > 0) {
						for (i3 = 1; i3 <= 4 && sw == 0; i3++) {
							if (edge[i2][i3] == kk) {
								sw           = 1;
								edge[i2][i3] = -1;
								edge[i2][0]--;
							}
						}
					}
				}
								// 次の現在ノードの選択
				min = 10;
				num = 0;
				for (i2 = 1; i2 <= 4; i2++) {
					if (edge[kk][i2] >= 0) {
						k1 = edge[kk][i2];
						if (edge[k1][0] >= 0 && edge[k1][0] < min) {
							num = 1;
							min = edge[k1][0];
							k0  = k1;
						}
						else {
							if (edge[k1][0] == min)
								num++;
						}
					}
				}
				if (num > 1) {
					k1 = (int)(genrand_real3() * num) + 1;
					if (k1 > num)
						k1 = num;
					k2 = 0;
					k0 = -1;
					for (i2 = 1; i2 <= 4 && k0 < 0; i2++) {
						if (edge[kk][i2] >= 0) {
							if (edge[edge[kk][i2]][0] == min) {
								k2++;
								if (k1 == k2)
									k0 = edge[kk][i2];
							}
						}
					}
				}
				else {
					if (num <= 0) {
						num = 0;
						for (i2 = 0; i2 < len[k]; i2++) {
							if (i2 != kk && edge[i2][0] >= 0)
								num++;
						}
						if (num <= 0) {
							printf("***error  invalid data (C_edge)\n");
							exit(1);
						}
						else {
							k1 = (int)(genrand_real3() * num) + 1;
							if (k1 > num)
								k1 = num;
							k2 = 0;
							k0 = -1;
							for (i2 = 0; i2 < len[k] && k0 < 0; i2++) {
								if (i2 != kk && edge[i2][0] >= 0) {
									k2++;
									if (k1 == k2)
										k0 = i2;
								}
							}
						}
					}
				}
				edge[kk][0] = -1;
				ind[k][p]   = k0;
				kk          = k0;
				p++;
			}
		}
	}
}

/*************************************************************/
/* 交叉(サブツアー交叉.2点交叉の拡張である.ただし,相手に*/
/*       同じ遺伝子のグループがない限り実行されない.たとえば*/
/*         ***abcd**                                         */
/*         *cdab****                                         */
/*       のような両親の時実行され,以下の4つの子供が生成され*/
/*       る)                                                */
/*         ***cdab**                                         */
/*         *abcd****                                         */
/*         ***badc**                                         */
/*         *dcba****                                         */
/*       最大,4*交叉回数*個体総数*(個体総数-1) 個の子 */
/*       供が生成される可能性があるので,子供の数としてこの値*/
/*       以上のデータを入力しておく必要がある.              */
/*      kosa : 交叉確率                                      */
/*      count : 1つのペアーに対する交差回数(default=10)     */
/*************************************************************/
void Species::C_sub(double kosa, int count)
{
	int i1, i2, i3, i4, i5, k1, k2, k3, k4, p1, p2,
        t11, t12, t21, t22 = 0, sw;
/*
     初期設定とデータのチェック
*/
	if ((4*count*size*(size-1)) > max_ch) {
		printf("***error  子供が多すぎる (C_sub)\n");
		exit(1);
	}
/*
     交叉
*/
	for (i1 = 0; i1 < size-1; i1++) {
					// 親1
		p1 = Position(i1);

		if (p1 >= 0) {

			for (i2 = i1; i2 < size; i2++) {
					// 親2
				p2 = Position(i2);

				if (p2 >= 0) {
					// 交叉しない場合
					if (genrand_real3() > kosa)
						C_copy(2, 1);
					// 交叉する場合
					else {
						// 交叉回数の制御
						for (i3 = 0; i3 < count; i3++) {
							// 交叉位置の決定(点の後ろで交叉)
								// 親1の交叉位置
							t11 = (int)(genrand_real3() * len[p1]);
							if (t11 > (len[p1]-1))
								t11 = len[p1] - 1;
							sw = 0;
							while (sw == 0) {
								t12 = (int)(genrand_real3() * len[p1]);
								if (t12 > (len[p1]-1))
									t12 = len[p1] - 1;
								if (t12 != t11)
									sw = 1;
							}
							if (t11 > t12) {
								k1  = t11;
								t11 = t12;
								t12 = k1;
							}
								// 親2の交叉位置
							sw  = 0;
							t21 = -1;
							for (i4 = 0; i4 < len[p2] && t21 < 0; i4++) {
								for (i5 = t11; i5 <= t12 && t21 < 0; i5++) {
									if (ind[p2][i4] == ind[p1][i5])
										t21 = i4;
								}
							}
							if (t21 >= 0) {
								t22 = t21 + t12 - t11;
								if (t22 < len[p2]) {
									sw = 1;
									for (i4 = t21+1; i4 <= t22 && sw > 0; i4++) {
										sw = 0;
										for (i5 = t11; i5 <= t12 && sw == 0; i5++) {
											if (ind[p2][i4] == ind[p1][i5])
												sw = 1;
										}
									}
								}
							}
								// 交叉の実行
							if (sw > 0) {

								k1       = Position(-1);
								pi_w[k1] = 1;
								len[k1]  = len[p1];
								k2       = Position(-1);
								pi_w[k2] = 1;
								len[k2]  = len[p1];
								k3       = Position(-1);
								pi_w[k3] = 1;
								len[k3]  = len[p2];
								k4       = Position(-1);
								pi_w[k4] = 1;
								len[k4]  = len[p2];

								for (i4 = 0; i4 < t11; i4++) {
									ind[k1][i4] = ind[p1][i4];
									ind[k2][i4] = ind[p1][i4];
								}
								for (i4 = t11; i4 <= t12; i4++) {
									ind[k1][i4] = ind[p2][t21+i4-t11];
									ind[k2][i4] = ind[p2][t22-i4+t11];
								}
								for (i4 = t12+1; i4 < len[p1]; i4++) {
									ind[k1][i4] = ind[p1][i4];
									ind[k2][i4] = ind[p1][i4];
								}
								for (i4 = 0; i4 < t21; i4++) {
									ind[k3][i4] = ind[p2][i4];
									ind[k4][i4] = ind[p2][i4];
								}
								for (i4 = t21; i4 <= t22; i4++) {
									ind[k3][i4] = ind[p1][t11+i4-t21];
									ind[k4][i4] = ind[p1][t12-i4+t21];
								}
								for (i4 = t22+1; i4 < len[p2]; i4++) {
									ind[k3][i4] = ind[p2][i4];
									ind[k4][i4] = ind[p2][i4];
								}
							}
						}
					}
				}
			}
		}
	}
}

/**************************************/
/* 突然変異(対立遺伝子との置き換え) */
/*      pr : 突然変異率               */
/**************************************/
void Species::M_alle(double pr)
{
	int i1, i2, lid;
/*
     データのチェックと初期設定
*/
	if (dup_a == 0) {
		printf("***error  突然変異方法が不適当 (M_alle)\n");
		exit(1);
	}
/*
     実行
*/
	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (pi_w[i1] == 1) {
			for (i2 = 0; i2 < len[i1]; i2++) {
				if (genrand_real3() <= pr) {
					lid = (int)(genrand_real3() * (allele_u - allele_l + 1) + allele_l);
					if (lid > allele_u)
						lid = allele_u;
					if (lid != ind[i1][i2])
						ind[i1][i2] = lid;
				}
			}
		}
	}
}

/**********************************************************************/
/* 突然変異(移動.2点を選択し,2番目の遺伝子を1番目の遺伝子の前に */
/*           移動する)                                               */
/*      pr : 突然変異率                                               */
/**********************************************************************/
void Species::M_move(double pr)
{
	int i1, i2, ld, p1, p2, sw;

	for (i1 = 0; i1 < size+max_ch; i1++) {

		if (pi_w[i1] == 1 && genrand_real3() <= pr) {
/*
     位置の決定
*/
					// p1
			p1 = (int)(genrand_real3() * len[i1]);
			if (p1 >= len[i1])
				p1 = len[i1] - 1;
					// p2
			sw = 0;
			while (sw == 0) {
				p2 = (int)(genrand_real3() * len[i1]);
				if (p2 >= len[i1])
					p2 = len[i1] - 1;
				if (p2 != p1)
					sw = 1;
			}
/*
     実行
*/
			if (p2 > p1) {
				ld = ind[i1][p2];
				for (i2 = p2; i2 > p1; i2--)
					ind[i1][i2] = ind[i1][i2-1];
				ind[i1][p1] = ld;
			}
			else {
				ld = ind[i1][p2];
				for (i2 = p2; i2 < p1-1; i2++)
					ind[i1][i2] = ind[i1][i2+1];
				ind[i1][p1-1] = ld;
			}
		}
	}
}

/********************************************************/
/* 突然変異(逆位.2点間の遺伝子順序を逆に並べ替える) */
/*      pr : 突然変異率                                 */
/*      wd : >0 : 幅を固定                              */
/*           =0 : 幅をランダム(default)                 */
/********************************************************/
void Species::M_inv(double pr, int wd)
{
	int i1, lid, p, p1, p2, sw;

	for (i1 = 0; i1 < size+max_ch; i1++) {

		if (pi_w[i1] == 1 && genrand_real3() <= pr) {
/*
     区間の決定
*/
			if (wd == 0) {
				p1 = (int)(genrand_real3() * len[i1]);
				if (p1 >= len[i1])
					p1 = len[i1] - 1;
				sw = 0;
				while (sw == 0) {
					p2 = (int)(genrand_real3() * len[i1]);
					if (p2 >= len[i1])
						p2 = len[i1] - 1;
					if (p2 != p1)
						sw = 1;
				}
				if (p1 > p2) {
					p  = p1;
					p1 = p2;
					p2 = p;
				}
			}

			else {
				p1 = len[i1];
				while (p1 > len[i1]-2)
					p1 = (int)(genrand_real3() * len[i1]);
				p2 = p1 + wd - 1;
				if (p2 >= len[i1])
					p2 = len[i1] - 1;
			}
/*
     実行
*/
			sw = 0;
			while (sw == 0) {
				lid         = ind[i1][p1];
				ind[i1][p1] = ind[i1][p2];
				ind[i1][p2] = lid;
				p1++;
				p2--;
				if (p1 >= p2)
					sw = 1;
			}
		}
	}
}

/**********************************************************************/
/* 突然変異(スクランブル.2点間の遺伝子順序をランダムに並べ替える) */
/*      pr : 突然変異率                                               */
/*      wd : >0 : 幅を固定                                            */
/*           =0 : 幅をランダム(default)                               */
/**********************************************************************/
void Species::M_scram(double pr, int wd)
{
	int i1, i2, ld, p, p1, p2, sw;

	for (i1 = 0; i1 < size+max_ch; i1++) {

		if (pi_w[i1] == 1 && genrand_real3() <= pr) {
/*
     区間の決定
*/
			if (wd == 0) {
				p1 = (int)(genrand_real3() * len[i1]);
				if (p1 >= len[i1])
					p1 = len[i1] - 1;
				sw = 0;
				while (sw == 0) {
					p2 = (int)(genrand_real3() * len[i1]);
					if (p2 >= len[i1])
						p2 = len[i1] - 1;
					if (p2 != p1)
						sw = 1;
				}
				if (p1 > p2) {
					p  = p1;
					p1 = p2;
					p2 = p;
				}
			}

			else {
				p1 = len[i1];
				while (p1 > len[i1]-2)
					p1 = (int)(genrand_real3() * len[i1]);
				p2 = p1 + wd - 1;
				if (p2 >= len[i1])
					p2 = len[i1] - 1;
			}
/*
     実行
*/
			for (i2 = p1; i2 <= p2; i2++) {
				p = (int)(genrand_real3() * (p2 - p1 + 1) + p1);
				if (p > p2)
					p = p2;
				ld          = ind[i1][i2];
				ind[i1][i2] = ind[i1][p];
				ind[i1][p]  = ld;
			}
		}
	}
}

/**********************************************************************/
/* 突然変異(転座.2点間の遺伝子を他の位置のものと置き換える.ただし */
/*           重複部分はそのままとする)                               */
/*      pr : 突然変異率                                               */
/*      wd : >0 : 幅を固定                                            */
/*           =0 : 幅をランダム(default)                               */
/**********************************************************************/
void Species::M_chg(double pr, int wd)
{
	int i1, i2, ld, p, p1, p2, p3, p4, sw;

	for (i1 = 0; i1 < size+max_ch; i1++) {

		if (pi_w[i1] == 1 && genrand_real3() <= pr) {
/*
     区間等の決定([p1,p2]と[p3,p4]の入れ替え)
*/
					// p1
			p1 = (int)(genrand_real3() * len[i1]);
			if (p1 >= len[i1])
				p1 = len[i1] - 1;
					// p3
			sw = 0;
			while (sw == 0) {
				p3 = (int)(genrand_real3() * len[i1]);
				if (p3 >= len[i1])
					p3 = len[i1] - 1;
				if (p3 != p1)
					sw = 1;
			}
					// 小さい方をp1,p2にする
			if (p1 > p3) {
				p  = p1;
				p1 = p3;
				p3 = p;
			}
					// p4, p2
			p4 = (wd == 0) ? (int)(genrand_real3() * (len[i1] - p3)) + p3 :
                             p1 + wd - 1;
			if (p4 >= len[i1])
				p4 = len[i1] - 1;
			p2 = p1 + (p4 - p3);
					// 重複部分のチェック
			if (p2 >= p3) {
				p  = p3 - 1;
				p3 = p2 + 1;
				p2 = p;
				p4 = p3 + (p2 - p1);
			}
/*
     実行
*/
			p = p3;
			for (i2 = p1; i2 <= p2; i2++) {
				ld          = ind[i1][i2];
				ind[i1][i2] = ind[i1][p];
				ind[i1][p]  = ld;
				p++;
			}
		}
	}
}

/**********************************************************************/
/* 突然変異(重複.2点間の遺伝子を他の位置にコピーする               */
/*      pr : 突然変異率                                               */
/*      wd : >0 : 幅を固定                                            */
/*           =0 : 幅をランダム(deafult)                               */
/**********************************************************************/
void Species::M_dup(double pr, int wd)
{
	int i1, i2, p, p1, p2, p3, p4, sw;
/*
     データのチェック
*/
	if (dup_a == 0) {
		printf("***error  突然変異方法が不適当 (M_dup)\n");
		exit(1);
	}
/*
     実行
*/
	for (i1 = 0; i1 < size+max_ch; i1++) {

		if (pi_w[i1] == 1 && genrand_real3() <= pr) {
					// 区間の決定([p1,p2]を[p3,p4]にコピー)
						// p1
			p1 = (int)(genrand_real3() * len[i1]);
			if (p1 >= len[i1])
				p1 = len[i1] - 1;
						// p3
			sw = 0;
			while (sw == 0) {
				p3 = (int)(genrand_real3() * len[i1]);
				if (p3 >= len[i1])
					p3 = len[i1] - 1;
				if (p3 != p1)
					sw = 1;
			}
						// 区間を決める
			if (p3 > p1) {
				p4 = (wd == 0) ? (int)(genrand_real3() * (len[i1] - p3)) + p3 :
                                 p3 + wd - 1;
				if (p4 >= len[i1])
					p4 = len[i1] - 1;
				p2 = p1 + (p4 - p3);
			}
			else {
				p2 = (wd == 0) ? (int)(genrand_real3() * (len[i1] - p1)) + p1 :
                                 p1 + wd - 1;
				if (p2 >= len[i1])
					p2 = len[i1] - 1;
				p4 = p3 + (p2 - p1);
			}
					// 実行
			p = p4;
			for (i2 = p2; i2 >= p1; i2--) {
				ind[i1][p] = ind[i1][i2];
				p--;
			}
		}
	}
}

/******************************************************/
/* 突然変異(摂動.値をある量だけ変化させる)         */
/*      pr : 突然変異率                               */
/*      method : =0 : 正規分布(default)               */
/*               =1 : 一様分布                        */
/*      m : 平均または一様分布の下限(default=0.0)     */
/*      s : 標準偏差または一様分布の上限(default=1.0) */
/******************************************************/
void Species::M_per(double pr, int method, double m, double s)
{
	double w, wd = 0.0, x1;
	int i1, i2;
/*
     データのチェックと初期設定
*/
	if (dup_a == 0) {
		printf("***error  突然変異方法が不適当 (M_per)\n");
		exit(1);
	}

	if (method > 0)
		wd = s - m;
/*
     実行
*/
	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (pi_w[i1] == 1) {
			for (i2 = 0; i2 < len[i1]; i2++) {
				if (genrand_real3() <= pr) {
					if (method == 0)
						w = norm_d(m, s);
					else {
						w = genrand_real3() * wd;
						if (genrand_real3() < 0.5)
							w = -w;
					}
					x1 = (double)ind[i1][i2] + w;
					if (x1 > allele_u)
						x1 = allele_u;
					else {
						if (x1 < allele_l)
							x1 = allele_l;
					}
					ind[i1][i2] = (int)x1;
				}
			}
		}
	}
}

/**********************************************************************/
/* 突然変異(挿入.ある長さの遺伝子を挿入する)                       */
/*      pr : 突然変異率                                               */
/*      wd : >0 : 幅を固定                                            */
/*           =0 : 幅をランダム(default)                               */
/**********************************************************************/
void Species::M_ins(double pr, int wd)
{
	int i1, i2, l, ld, p;
/*
     データのチェック
*/
	if (dup_a == 0 || min_len < 0) {
		printf("***error  突然変異方法が不適当 (M_ins)\n");
		exit(1);
	}
/*
     実行
*/
	for (i1 = 0; i1 < size+max_ch; i1++) {

		if (pi_w[i1] == 1 && genrand_real3() <= pr) {
					// 挿入位置の決定
			p = (int)(genrand_real3() * (len[i1]+1));
			if (p > len[i1])
				p = len[i1];
					// 挿入する遺伝子長の決定
			l = (wd == 0) ? (int)(genrand_real3() * (max_len - len[i1] + 1)) : wd;
			if (l > max_len-len[i1])
				l = max_len - len[i1];
			else {
				if (l <= 0)
					l = 1;
			}
					// 実行
						// 挿入場所の確保
			if (p < len[i1]) {
				for (i2 = len[i1]+l-1; i2 >= p; i2--)
					ind[i1][i2] = ind[i1][i2-l];
			}
						// 挿入場所の遺伝子の決定
			for (i2 = p; i2 < p+l; i2++) {
				ld = (int)(genrand_real3() * (allele_u - allele_l + 1) + allele_l);
				if (ld > allele_u)
					ld = allele_u;
				ind[i1][i2] = ld;
			}

			len[i1]  += l;
		}
	}
}

/**********************************************************************/
/* 突然変異(削除.ある長さの遺伝子を削除する)                       */
/*      pr : 突然変異率                                               */
/*      wd : >0 : 幅を固定                                            */
/*           =0 : 幅をランダム(default)                               */
/**********************************************************************/
void Species::M_del(double pr, int wd)
{
	int i1, i2, l, max, p;
/*
     データのチェック
*/
	if (dup_a == 0 || min_len < 0) {
		printf("***error  突然変異方法が不適当 (M_del)\n");
		exit(1);
	}
/*
     実行
*/
	for (i1 = 0; i1 < size+max_ch; i1++) {

		if (pi_w[i1] == 1 && genrand_real3() <= pr) {
					// 削除位置の決定
			p = (int)(genrand_real3() * len[i1]);
			if (p >= len[i1])
				p = len[i1] - 1;
					// 削除する遺伝子長の決定
			max = (len[i1]-min_len < len[i1]-p) ? len[i1] - min_len : len[i1] - p;
			l   = (wd == 0) ? (int)(genrand_real3() * max + 1) : wd;
			if (l > max)
				l = max;
					// 実行
			for (i2 = 0; i2 < len[i1]-p-l; i2++)
				ind[i1][p+i2] = ind[i1][p+i2+l];

			len[i1]  -= l;
		}
	}
}

/*********************************************************************/
/* 淘汰(エリート・ルーレット選択)                                  */
/*      elite : エリートで残す個体数(default=0)                      */
/*      s_method : ルーレット板の作成方法(default=1)                 */
/*                   =0 : 適応度をそのまま使用                       */
/*                   =1 : 最小値からの差(ただし,α以下の場合はα) */
/*                   =2 : 評価値に順位をつけ,減少率βで線形化       */
/*      s_bias : α,または,method=2の場合は初期値(default=0)       */
/*      s_step : β(default=1)                                       */
/*********************************************************************/
void Species::S_roul(int elite, int s_method, double s_bias, double s_step)
{
	int count = 0, i1, i2, i3, k = 0, max, n = 0, p, sw;
/*
     値のチェックと初期設定
*/
	if (s_method != 0 && s_method != 2)
		s_method = 1;

	if (elite > size) {
		printf("***error  エリートで残す数が多すぎる (S_roul)\n");
		exit(1);
	}

	if (s_method == 2 && s_step <= 0.0)
		s_step = 1.0;

	for (i1 = 0; i1 < size+max_ch; i1++)
		s_w[i1] = 0;
/*
     重複個体を削除
*/
	if (dup_s == 0) {
		for (i1 = 0; i1 < size+max_ch; i1++) {
			if (pi_w[i1] > 0) {
				for (i2 = i1+1; i2 < size+max_ch; i2++) {
					if (pi_w[i2] > 0 && len[i1] == len[i2]) {
						sw = 0;
						for (i3 = 0; i3 < len[i1] && sw == 0; i3++) {
							if (ind[i1][i3] != ind[i2][i3])
								sw = 1;
						}
						if (sw == 0)
							pi_w[i2] = 0;
					}
				}
			}
		}
	}

	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (pi_w[i1] > 1)
			n++;
	}

	if (n < 0 || dup_s == 0 && n < size) {
		printf("***error  残す個体がない (S_roul)\n");
		exit(1);
	}
/*
     淘汰して残す個体を選ぶ
*/
					// エリートの選択
	sw = 0;

	while (k < elite && k < n && sw == 0) {
		max = -1;
		for (i1 = 0; i1 < size+max_ch; i1++) {
			if (pi_w[i1] > 1 && s_w[i1] == 0) {
				if (max < 0 || pi[i1] > pi[max])
					max = i1;
			}
		}
		if (max < 0)
			sw = 1;
		else {
			s_w[max] = 1;
			k++;
		}
	}
					// ルーレット選択
	while (count < size+max_ch && k < size) {
		p = Select(s_method, s_bias, s_step);
		if (dup_s == 0 && s_w[p] > 0)
			count++;
		else {
			count = 0;
			s_w[p]++;
			k++;
		}
	}
						// 選択に失敗した場合の処理
	if (dup_s == 0 && k < size) {
		for (i1 = 0; i1 < size+max_ch && k < size; i1++) {
			if (pi_w[i1] > 1 && s_w[i1] == 0) {
				s_w[i1] = 1;
				k++;
			}
		}
	}
						// 複数回選択されたものの処理
	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (s_w[i1] == 0)
			pi_w[i1] = 0;
	}

	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (s_w[i1] > 0) {
			if (s_w[i1] > 1) {
				for (i2 = 2; i2 <= s_w[i1]; i2++) {
					k       = Position(-1);
					len[k]  = len[i1];
					pi_w[k] = 2;
					pi[k]   = pi[i1];
					for (i3 = 0; i3 < len[i1]; i3++)
						ind[k][i3] = ind[i1][i3];
				}
			}
		}
	}
}

------------------------norm_d.cpp----------------
/***********************************/
/* 正規分布変量の発生              */
/*      m : 平均                   */
/*      s : 標準偏差               */
/*           return : 正規分布変量 */
/***********************************/
#include "MT.h"

double norm_d(double m, double s)
{
	double x = 0.0;
	int i1;

	for (i1 = 0; i1 < 12; i1++)
		x += genrand_real3();

	x = s * (x - 6.0) + m;

	return x;
}

------------------------tsp.h---------------------
/*******************/
/* クラスTSPの定義 */
/*******************/
#include "species.h"

class TSP : public Species {

		int max_gen;   // 最大世代交代数
		int kosa_m;   // 交叉方法
                      //   =-1 : 交叉を使用しない
                      //   =0 : 親のコピー
                      //   =1 : 循環交叉
                      //   =2 : 部分的交叉
                      //   =3 : 順序交叉
                      //   =4 : 一様順序交叉
                      //   =5 : 一様位置交叉
                      //   =6 : エッジ組み替え交叉
                      //   =7 : サブツアー交叉
		double kosa;   // 交叉確率
		int k_point;   // 交差点の数(負の時は,1から-k_point間のランダム)
		int k_vr;   // =0 : 両親とも同じ位置で交叉
                    // =1 : 両親が異なる位置で交叉(遺伝子長は可変)
		int k_method;   // 交叉の時の親の選択方法
                        //   =-1 : ランダム
                        //   =0 : 適応度をそのまま使用
                        //   =1 : 最小値からの差(ただし,α以下の場合はα)
                        //   =2 : 評価値に順位をつけ,減少率βで線形化
		double k_bias;   // α,または,method=2の場合は初期値
		double k_step;   // β
		int mute_m;   // 突然変異方法
                      //   =-1 : 突然変異を使用しない
                      //   =0 : 移動
                      //   =1 : 逆位
                      //   =2 : スクランブル
                      //   =3 : 転座
		double mute;   // 突然変異率
		int wd;   // 突然変異に使用する部分遺伝子長
		double m_mean;   // 摂動の平均値
		double m_std;   // 摂動の標準偏差
		int elite;   // エリート選択で残す数
		int s_method;   // ルーレット板の作成方法
                        //   =0 : 適応度をそのまま使用
                        //   =1 : 最小値からの差(ただし,α以下の場合はα)
                        //   =2 : 評価値に順位をつけ,減少率βで線形化
		double s_bias;   // α,または,s_method=2の場合は初期値
		double s_step;   // β
		int out_d;   // 表示間隔
		int out_lvl;   // 出力レベル
                       //   =0 : 最終出力だけ
                       //   n>0 : n世代毎に出力(負の時はファイル)
		int out_m;   // 出力方法
                     //   =0 : すべてを出力
                     //   =1 : 最大適応度の個体だけを出力
		char o_file[100];   // 出力ファイル名
		int **city;   //都市の位置データ
		int n_city;   // 都市の数
		int **rg;   // 都市間の距離
		int kinbo;   // 近傍探索(0:行わない,1:行う)
		int neib;   // 近傍(2 or 3)
		int sel;   // エッジの選択方法
                   //   =0 : 最良のものを選択
                   //   =1 : 最初のものを選択

	public:
					// コンストラクタ
		TSP (char *, char *, long);
					// デストラクタ
		~TSP ();
					// 全体の実行制御
		void Control();
					// 距離の計算
		int Kyori(int, int*);
					// 適応度の計算
		void Adap();
					// 枝の入れ替え
		int Change(int, int *, int *);
					// 近傍の探索
		void Kinbo();
					// 出力
		void Output(int);
};

------------------------TSPのメンバー関数---------
/***************************/
/* クラスTSPのメンバー関数 */
/***************************/
#include "tsp.h"
#include "MT.h"

/***************************************/
/* コンストラクタ                      */
/*      name1 : Species定義ファイル名  */
/*      name2 : TSP定義ファイル名      */
/*      seed : 乱数の初期値            */
/***************************************/
TSP::TSP (char *name1, char *name2, long seed) : Species (name1, seed)
{
	double x, y;
	int i1, i2;
	FILE *in;
					// 基本データの入力
	in = fopen(name2, "r");

	fscanf(in, "%*s %d %*s %d", &out_lvl, &out_m);
	fscanf(in, "%*s %s %*s %d", o_file, &out_d);
	fscanf(in, "%*s %d %*s %lf %*s %d %*s %d %*s %d %*s %lf %*s %lf",
           &kosa_m, &kosa, &k_point, &k_vr, &k_method, &k_bias, &k_step);
	fscanf(in, "%*s %d %*s %lf %*s %d %*s %lf %*s %lf",
           &mute_m, &mute, &wd, &m_mean, &m_std);
	fscanf(in, "%*s %d %*s %d %*s %lf %*s %lf",
           &elite, &s_method, &s_bias, &s_step);
	fscanf(in, "%*s %d %*s %d", &n_city, &max_gen);
	fscanf(in, "%*s %d %*s %d", &kinbo, &neib);
	fscanf(in, "%*s %d", &sel);

	if (kinbo > 0 && neib != 2 && neib != 3) {
		printf("***error  近傍の値が不適当 \n");
		exit(1);
	}

	if (n_city != max_len) {
		printf("***error  都市数が不適当 \n");
		exit(1);
	}
					// 都市の位置データ
	city = new int * [n_city];
	for (i1 = 0; i1 < n_city; i1++) {
		city[i1] = new int [2];
		fscanf(in, "%d %d", &city[i1][0], &city[i1][1]);
	}
					// 距離テーブル
	rg = new int * [n_city];

	for (i1 = 0; i1 < n_city; i1++) {
		rg[i1] = new int [n_city];
		for (i2 = i1+1; i2 < n_city; i2++) {
			x          = city[i2][0] - city[i1][0];
			y          = city[i2][1] - city[i1][1];
			rg[i1][i2] = (int)(sqrt(x * x + y * y) + 0.5);
		}
	}

	for (i1 = 1; i1 < n_city; i1++) {
		for (i2 = 0; i2 < i1; i2++)
			rg[i1][i2] = rg[i2][i1];
	}

	fclose(in);
}

/****************/
/* デストラクタ */
/****************/
TSP::~TSP()
{
	int i1;

	for (i1 = 0; i1 < size+max_ch; i1++)
		delete [] ind[i1];
	delete [] ind;

	for (i1 = 0; i1 < max_len; i1++)
		delete [] edge[i1];
	delete [] edge;

	delete [] pi;
	delete [] len;
	delete [] kou1;
	delete [] kou2;
	delete [] pi_w;
	delete [] s_w;
	delete [] ro;

	for (i1 = 0; i1 < n_city; i1++) {
		delete [] city[i1];
		delete [] rg[i1];
	}
	delete [] city;
	delete [] rg;
}

/**************/
/* 全体の制御 */
/**************/
void TSP::Control()
{
	int gen = 1, k1;
					// 初期集団の発生
	Init_std();
					// 評価
	if (kinbo > 0)
		Kinbo();
	else
		Adap();
					// 出力
	printf("***世代 %d 適応度 max %f (%d) mean %f\n",
           gen, max, max_n, mean);

	if (abs(out_lvl) > 0)
		Output(gen);
					// 世代交代
	for (gen = 2; gen <= max_gen; gen++) {
						// 交叉
		switch (kosa_m) {
			case -1:
				break;
			case 0:
				C_copy();   // 親のコピー
				break;
			case 1:
				C_cycle(kosa);   // 循環交叉
				break;
			case 2:
				C_part(kosa);   // 部分的交叉
				break;
			case 3:
				C_seq(kosa);   // 順序交叉
				break;
			case 4:
				C_useq(kosa);   // 一様順序交叉
				break;
			case 5:
				C_upos(kosa);   // 一様位置交叉
				break;
			case 6:
				C_edge(kosa);   // エッジ組み替え交叉
				break;
			case 7:
				C_sub(kosa, k_point);   // サブツアー交叉
				break;
			default:
				break;
		}
						// 突然変異
		switch (mute_m) {
			case -1:
				break;
			case 0:
				M_move(mute);   // 移動
				break;
			case 1:
				M_inv(mute);   // 逆位
				break;
			case 2:
				M_scram(mute);   // スクランブル
				break;
			case 3:
				M_chg(mute);   // 転座
				break;
			default:
				break;
		}
						// 適応度
		if (kinbo > 0)
			Kinbo();
		else
			Adap();
						// 淘汰
		S_roul(elite);
						// 出力
		if (gen%out_d == 0)
			printf("***世代 %d 適応度 max %f (%d) mean %f\n",
                   gen, max, max_n, mean);

		if (abs(out_lvl) > 0) {
			if (gen%abs(out_lvl) == 0)
				Output(gen);
		}
	}

	gen--;
	k1    = out_m;
	out_m = 0;
	printf("***世代 %d 適応度 max %f (%d) mean %f\n",
            gen, max, max_n, mean);
	Output(gen);
	out_m = k1;
}

/*********************************/
/* 距離の計算                    */
/*      n_c : 都市の数           */
/*      p : 都市番号             */
/*      return : 距離(負)      */
/*********************************/
int TSP::Kyori(int n_c, int *p)
{
	int i1, n1, n2, range = 0;

	n1 = p[0];

	for (i1 = 1; i1 < n_c; i1++) {
		n2     = p[i1];
		range -= rg[n1][n2];
		n1     = n2;
	}

	n2     = p[0];
	range -= rg[n1][n2];

	return range;
}

/****************/
/* 適応度の計算 */
/****************/
void TSP::Adap()
{
	int i1, k = 0;

	mean  = 0.0;
	max   = 0.0;
	max_n = -1;

	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (pi_w[i1] == 1) {
			pi_w[i1] = 2;
			pi[i1]   = Kyori(len[i1], ind[i1]);
		}
		if (pi_w[i1] > 0) {
			k++;
			mean += pi[i1];
			if (max_n < 0 || pi[i1] > max) {
				max   = pi[i1];
				max_n = i1;
			}
		}
	}

	if (k > 0)
		mean /= k;
}

/**************************************/
/* エッジの入れ替え                   */
/*      n_city : 都市の数             */
/*      seq : 訪問する順番            */
/*      r_m : 距離の負値              */
/*      return : =0 : 改善がなかった  */
/*               =1 : 改善があった    */
/**************************************/
int TSP::Change(int n_city, int *seq, int *r_m)
{
	int ch = 0, i1, i2, i3, i4, k, k1, k2, max, n1, n2, n3, nn, r, sw = 0;

	max = *r_m;

	n3  = (int)(genrand_real3() * (n_city - 2));
	if (n3 > n_city-3)
		n3 = n_city - 3;
                         // 2近傍
	for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {

		if (n3 == 0)
			n1 = n_city - 2;
		else
			n1 = n_city - 1;

		for (i2 = n3+2; i2 <= n1 && ch == 0; i2++) {
                              // 枝の場所((n3,n3+1), (k1,k2))
			k1 = i2;
			if (i2 == n_city-1)
				k2 = 0;
			else
				k2 = i2 + 1;
                              // 枝の入れ替え
			kou1[0] = seq[n3];
			k       = 1;
			for (i3 = k1; i3 >= n3+1; i3--) {
				kou1[k] = seq[i3];
				k++;
			}

			nn = k2;
			while (nn != n3) {
				kou1[k] = seq[nn];
				k++;
				nn++;
				if (nn > n_city-1)
					nn = 0;
			}
                              // 評価
			r = Kyori(n_city, kou1);

			if (r > max) {
				max = r;
				sw  = 1;
				for (i3 = 0; i3 < n_city; i3++)
					kou2[i3] = kou1[i3];
				if (sel > 0)
					ch = 1;
			}
		}

		n3++;
		if (n3 > n_city-3)
			n3 = 0;
	}
                         // 3近傍
	if (neib == 3 && ch == 0) {

		for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {

			n1 = n_city - 2;
			n2 = n_city - 1;

			for (i2 = n3+1; i2 <= n1 && ch == 0; i2++) {

				for (i3 = i2+1; i3 <= n2 && ch == 0; i3++) {
                              // 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
					k1 = i3;
					if (i3 == n_city-1)
						k2 = 0;
					else
						k2 = i3 + 1;
                              // 枝の入れ替えと評価
                                   // 入れ替え(その1)
					kou1[0] = seq[n3];
					k       = 1;
					for (i4 = i2; i4 >= n3+1; i4--) {
						kou1[k] = seq[i4];
						k++;
					}

					for (i4 = k1; i4 >= i2+1; i4--) {
						kou1[k] = seq[i4];
						k++;
					}

					nn = k2;
					while (nn != n3) {
						kou1[k] = seq[nn];
						k++;
						nn++;
						if (nn > n_city-1)
							nn = 0;
					}
                                   // 評価(その1)
					r = Kyori(n_city, kou1);

					if (r > max) {
						max = r;
						sw  = 1;
						for (i3 = 0; i3 < n_city; i3++)
							kou2[i3] = kou1[i3];
						if (sel > 0)
							ch = 1;
					}
                                   // 入れ替え(その2)
					kou1[0] = seq[n3];
					k       = 1;
					for (i4 = k1; i4 >= i2+1; i4--) {
						kou1[k] = seq[i4];
						k++;
					}

					for (i4 = n3+1; i4 <= i2; i4++) {
						kou1[k] = seq[i4];
						k++;
					}

					nn = k2;
					while (nn != n3) {
						kou1[k] = seq[nn];
						k++;
						nn++;
						if (nn > n_city-1)
							nn = 0;
					}
                                   // 評価(その2)
					r = Kyori(n_city, kou1);

					if (r > max) {
						max = r;
						sw  = 1;
						for (i3 = 0; i3 < n_city; i3++)
							kou2[i3] = kou1[i3];
						if (sel > 0)
							ch = 1;
					}
                                   // 入れ替え(その3)
					kou1[0] = seq[n3];
					k       = 1;
					for (i4 = i2+1; i4 <= k1; i4++) {
						kou1[k] = seq[i4];
						k++;
					}

					for (i4 = i2; i4 >= n3+1; i4--) {
						kou1[k] = seq[i4];
						k++;
					}

					nn = k2;
					while (nn != n3) {
						kou1[k] = seq[nn];
						k++;
						nn++;
						if (nn > n_city-1)
							nn = 0;
					}
                                   // 評価(その3)
					r = Kyori(n_city, kou1);

					if (r > max) {
						max = r;
						sw  = 1;
						for (i3 = 0; i3 < n_city; i3++)
							kou2[i3] = kou1[i3];
						if (sel > 0)
							ch = 1;
					}
                                   // 入れ替え(その4)
					kou1[0] = seq[n3];
					k       = 1;
					for (i4 = i2+1; i4 <= k1; i4++) {
						kou1[k] = seq[i4];
						k++;
					}

					for (i4 = n3+1; i4 <= i2; i4++) {
						kou1[k] = seq[i4];
						k++;
					}

					nn = k2;
					while (nn != n3) {
						kou1[k] = seq[nn];
						k++;
						nn++;
						if (nn > n_city-1)
							nn = 0;
					}
                                   // 評価(その4)
					r = Kyori(n_city, kou1);

					if (r > max) {
						max = r;
						sw  = 1;
						for (i3 = 0; i3 < n_city; i3++)
							kou2[i3] = kou1[i3];
						if (sel > 0)
							ch = 1;
					}
				}
			}

			n3++;
			if (n3 > n_city-3)
				n3 = 0;
		}
	}
                         // 設定
	if (sw > 0) {
		*r_m = max;
		for (i1 = 0; i1 < n_city; i1++)
			seq[i1] = kou2[i1];
	}

	return sw;
}

/**************/
/* 近傍の探索 */
/**************/
void TSP::Kinbo()
{
	int i1, k = 0, r, sw;

	max   = 0.0;
	max_n = -1;
	mean  = 0.0;

	for (i1 = 0; i1 < size+max_ch; i1++) {
		if (pi_w[i1] == 1) {
			pi_w[i1] = 2;
			sw       = 1;
			r        = Kyori(len[i1], ind[i1]);
			while (sw > 0)
				sw = Change(len[i1], ind[i1], &r);
			pi[i1] = r;
		}
		if (pi_w[i1] > 0) {
			k++;
			mean += pi[i1];
			if (max_n < 0 || pi[i1] > max) {
				max   = pi[i1];
				max_n = i1;
			}
		}
	}

	if (k > 0)
		mean /= k;
}

/*****************************/
/* 結果の出力                */
/*      gen : 現在の世代番号 */
/*****************************/
void TSP::Output(int gen)
{
	int i1, k = 0, n, pr;
	char *now;
	time_t aclock;
	FILE *out;

	if (out_lvl >= 0) {
		printf("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
		scanf("%d", &pr);
	}
	else
		pr = -1;

	if (pr != 0) {
					// 出力先の決定と評価値の出力
		if (pr > 0) {
			out = stdout;
			getchar();
		}
		else {
			time(&aclock);
			now = ctime(&aclock);
			out = fopen(o_file, "a");
			fprintf(out, "***世代 %d 適応度 max %f (%d) mean %f 時間 %s\n",
                    gen, max, max_n, mean, now);
		}
					// 巡回順序の出力
		if (out_m == 0) {
			for (i1 = 0; i1 < len[max_n]; i1++) {
				n = ind[max_n][i1];
				fprintf(out, "%d %d %d\n", n, city[n][0], city[n][1]);
				if (pr > 0) {
					k++;
					if (k == pr) {
						getchar();
						k = 0;
					}
				}
			}
		}

		if (pr < 0)
			fclose(out);
	}
}

------------------------main----------------------
/***********************************/
/* 遺伝的アルゴリズムによるTSPの解 */
/*      coded by Y.Suganuma        */
/***********************************/
#include "tsp.h"

/****************/
/* main program */
/****************/
int main(int argc, char *argv[])
{
	long *seed;
	int i1, n;
	char **i_file1, **i_file2;
	FILE *in;
	TSP *tsp;
					// 入力ミス
	if (argc <= 1) {
		printf("***error  ファイル名を入力して下さい\n");
		exit(1);
	}
					// 入力OK
	else {
						// ファイルのオープン
		in = fopen(argv[1], "r");
		if (in == NULL) {
			printf("***error  ファイル名が不適当です\n");
			exit(1);
		}
						// 乱数の初期値と入力データファイル名の入力
		fscanf(in, "%d", &n);   // データの数

		seed    = new long [n];
		i_file1 = new char * [n];
		i_file2 = new char * [n];

		for (i1 = 0; i1 < n; i1++) {
			i_file1[i1] = new char [100];
			i_file2[i1] = new char [100];
			fscanf(in, "%ld %s %s", &seed[i1], i_file1[i1], i_file2[i1]);
		}

		fclose(in);
						// 実行(乱数の初期値を変える)
		for (i1 = 0; i1 < n; i1++) {

			printf("\n+++++ケース %d+++++\n", i1+1);

			tsp = new TSP (i_file1[i1], i_file2[i1], seed[i1]);

			tsp->Control();
		}
	}

	return 0;
}

-----------------------MT.h--------------------

/*
   A C-program for MT19937, with initialization improved 2002/1/26.
   Coded by Takuji Nishimura and Makoto Matsumoto.

   Before using, initialize the state by using init_genrand(seed)  
   or init_by_array(init_key, key_length).

   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
   All rights reserved.                          

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.

     2. Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.

     3. The names of its contributors may not be used to endorse or promote 
        products derived from this software without specific prior written 
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


   Any feedback is very welcome.
   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/

/*
   The original version of http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c was modified by Takahiro Omi as
   - delete line 47 "#include<stdio.h>"
   - delete line 174 int main(void){...}
   - change N -> MT_N
   - change N -> MT_N
   - change the file name "mt19937ar.c" -> "MT.h"
*/


/* Period parameters */  
#define MT_N 624
#define MT_M 397
#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */

static unsigned long mt[MT_N]; /* the array for the state vector  */
static int mti=MT_N+1; /* mti==MT_N+1 means mt[MT_N] is not initialized */

/* initializes mt[MT_N] with a seed */
void init_genrand(unsigned long s)
{
    mt[0]= s & 0xffffffffUL;
    for (mti=1; mti<MT_N; mti++) {
        mt[mti] = 
	    (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 
        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
        /* In the previous versions, MSBs of the seed affect   */
        /* only MSBs of the array mt[].                        */
        /* 2002/01/09 modified by Makoto Matsumoto             */
        mt[mti] &= 0xffffffffUL;
        /* for >32 bit machines */
    }
}

/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
void init_by_array(unsigned long init_key[], int key_length)
{
    int i, j, k;
    init_genrand(19650218UL);
    i=1; j=0;
    k = (MT_N>key_length ? MT_N : key_length);
    for (; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
          + init_key[j] + j; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++; j++;
        if (i>=MT_N) { mt[0] = mt[MT_N-1]; i=1; }
        if (j>=key_length) j=0;
    }
    for (k=MT_N-1; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
          - i; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++;
        if (i>=MT_N) { mt[0] = mt[MT_N-1]; i=1; }
    }

    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
}

/* generates a random number on [0,0xffffffff]-interval */
unsigned long genrand_int32(void)
{
    unsigned long y;
    static unsigned long mag01[2]={0x0UL, MATRIX_A};
    /* mag01[x] = x * MATRIX_A  for x=0,1 */

    if (mti >= MT_N) { /* generate N words at one time */
        int kk;

        if (mti == MT_N+1)   /* if init_genrand() has not been called, */
            init_genrand(5489UL); /* a default initial seed is used */

        for (kk=0;kk<MT_N-MT_M;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+MT_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        for (;kk<MT_N-1;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+(MT_M-MT_N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        y = (mt[MT_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
        mt[MT_N-1] = mt[MT_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];

        mti = 0;
    }
  
    y = mt[mti++];

    /* Tempering */
    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680UL;
    y ^= (y << 15) & 0xefc60000UL;
    y ^= (y >> 18);

    return y;
}

/* generates a random number on [0,0x7fffffff]-interval */
long genrand_int31(void)
{
    return (long)(genrand_int32()>>1);
}

/* generates a random number on [0,1]-real-interval */
double genrand_real1(void)
{
    return genrand_int32()*(1.0/4294967295.0); 
    /* divided by 2^32-1 */ 
}

/* generates a random number on [0,1)-real-interval */
double genrand_real2(void)
{
    return genrand_int32()*(1.0/4294967296.0); 
    /* divided by 2^32 */
}

/* generates a random number on (0,1)-real-interval */
double genrand_real3(void)
{
    return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); 
    /* divided by 2^32 */
}

/* generates a random number on [0,1) with 53-bit resolution*/
double genrand_res53(void) 
{ 
    unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 
    return(a*67108864.0+b)*(1.0/9007199254740992.0); 
} 
/* These real versions are due to Isaku Wada, 2002/01/09 added */

		

  コンパイルした後,

実行可能ファイル名 ケーススタディファイル名

と入力してやれば実行できます.ケーススタディファイルは,たとえば,同じ問題を乱数の初期値を変えて実行したいような場合に効果的であり,たとえば以下のような形式で作成します.
3
12345 data/species.10 data/data10.tsp
123 data/species.10 data/data10.tsp
1 data/species.10 data/data10.tsp		
  最初の数字はケーススタディの数(この場合は 3 ケース)であり,2 行目以降が各ケーススタディのデータになります.各行の最初の数字が乱数の初期値,2 番目が Species 記述ファイル名,および,3 番目が TSP 記述ファイル名です.

  Specific 記述ファイルは,遺伝的アルゴリズムに対する基本事項を記述するためのファイルであり,たとえば以下のように記述します.
対立遺伝子上限 9 対立遺伝子下限 0
最大遺伝子長 10 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
遺伝子の重複 0 個体の重複(同じ染色体の個体) 0
集団サイズ 10 子供 10		
  日本語で記述した部分(「対立遺伝子上限」,「対立遺伝子下限」等)は,次に続くデータの説明ですのでどのように修正しても構いませんが,削除したり,または,複数の文(間に半角のスペースを入れる)にするようなことはしないでください.また,以下の説明においても同様ですが,入力データによっては,そのケースには不必要なデータが現れることがあります.その場合においても,データの説明とデータは削除せず残しておいてください(内部的には,使用されません).各データの意味は以下に示す通りです.

対立遺伝子上限と対立遺伝子下限

  説明通り,対立遺伝子上限と対立遺伝子下限を入力します.プログラム内では,初期集団の発生や突然変異操作の中で使用されます.たとえば,染色体を 0 と 1 の組み合わせで表現したいときは,1 と 0 を入力します.また,TSP のような場合で,かつ,標準的な初期集団発生手続きを使用する場合は,上限と下限の間の数字(上限と下限を含む)の数が,都市の数と一致する必要がある点に注意してください.なお,一つの遺伝子の値に対して int を使用していますので,int で表現できない上限や下限を入力しないでください.

最大遺伝子長と最小遺伝子長(負の時は,最大遺伝子長で固定)

  このプログラムでは,可変長の染色体を使用できます.そのような場合,遺伝子長の上限と下限を入力します.最小遺伝子長に負の値を入力すると,最大遺伝子長で与えた固定長の染色体となります.

遺伝子の重複

  一つの染色体の中に同じ遺伝子を複数個含むことができるか否かを入力します.1 を入力すると可能になり,0 を入力すると不可能になります.TSP のような場合は,0 を入力します.

個体の重複(同じ染色体の個体)

  個体集団の中に同じ遺伝子の並びを持った個体が複数存在することを許すか否かを入力します.1 を入力すると許し,0 を入力すると許しません.

集団サイズ

  集団サイズを入力します.このプログラムでは,集団サイズは固定です.

子供

  交叉により発生させる子供の数を入力します.たとえば,1 点交叉のように,2 つの親から 2 つの子供を生成する交叉においては,ここで入力された値の半分の回数だけ交叉が実行されます.
  TSP 記述ファイルは,TSP を解くために必要なデータ(クラス TSP に関するデータ)を記述するファイルであり,たとえば以下のように記述します.なお,クラス TSP は,クラス Species の派生クラス(導出クラス)になっています.Species で定義した値と矛盾しないように注意してください.たとえば,都市の数は,最大遺伝子長と等しくなければなりません.
出力レベル(負はファイル) 10 出力方法(0:適応度+順番,1:適応度) 0
出力ファイル名 result/kekka 表示間隔 10
交叉方法 1 交叉確率 1.0 点 5 位置 0 方法 1 バイアス 0 ステップ 1
突然変異方法 1 突然変異率 0.03 幅 1 平均 0.0 標準偏差 1.0
エリート 2 方法 1 バイアス 0 ステップ 1
都市数 10 最大世代交代数 2000
近傍探索(0:行わない,1:行う) 0 近傍(2or3) 2
選択方法(0:最良,1:最初) 1
-58 37
55 -19
・・・		
  各データの意味は,以下に示すとおりです.

出力レベル(負はファイル)

  結果の出力方法を入力します.
=0 : 最終結果だけを出力します.
=n : n 回毎に出力します.なお,n が負の場合は,-n 回毎に,ファイルに追加形式( append )で出力されます.n が正の場合は,出力するたびに,出力を行うか否か,および,どこに出力するかを聞いてきます.したがって,この段階において,出力先をファイルに変更することも可能です( n = 0 の場合も同様).

出力方法(0:適応度+順番,1:適応度)

  結果の出力方法を入力します.
=0 : 経路長と巡回する都市の順番を出力します.
=1 : 得られた経路長だけを出力します.ただし,最終結果だけは,都市の順番も出力します.

出力ファイル名

  結果を保存するファイル名です.

表示間隔

  計算がどこまで進んでいるのかを示すため,結果の概略を画面に表示しますが,それを何世代毎に行うのかを入力します.

交叉方法

  交叉方法を入力します.以下の方法から選択できます.内容の詳細については,クラス Species の対応するメンバー関数を参照してください.
=-1 : 交叉を使用しない
=0 : 親のコピー
=1 : 循環交叉
=2 : 部分的交叉
=3 : 順序交叉
=4 : 一様順序交叉
=5 : 一様位置交叉
=6 : エッジ組み替え交叉
=7 : サブツアー交叉
  その他,このプログラムでは使用していませんが,クラス Species には以下の交叉方法も定義してあります.
  • 多点交叉
  • 一様交叉
  • 平均化交叉

交叉確率

  交叉確率を入力します.

  多点交叉の場合は何点交叉かを(たとえば,1 点交叉の場合は 1 ),また,サブツアー交叉の場合は,1 つのペアーに対する交叉回数を入力します.それ以外の場合は,利用されません.

位置

  多点交叉の場合だけに利用され,2 つの親の交叉点を同じにするか否かを示します.0 を入力すると同じ,また,1 を入力すると異なる交叉点が使われます.交叉点が異なる場合,子供の遺伝子長が可変になりますので,Species 記述ファイルにおいて遺伝子長を可変長にしておいてください( TSP の場合はあり得ませんが).

方法

  このデータを含め以下,3 つのデータ(「ステップ」までのデータ)は,サブツアー以外の交叉において利用されます.まず,このデータは,交叉における親の選択方法を指定します.
=-1 : ランダムに選択
=0 : 適応度に比例した確率で選択
=1 : 最小値からの差(ただし,α以下の場合はα)に比例した確率で選択
=2 : 評価値に順位をつけ,適応度の値を減少率βで線形化し,その値に応じた確率で選択

バイアス

  方法が 1 の場合はα,また,方法が 2 の場合は初期値

ステップ

  方法が 2 の場合においてβ

突然変異方法

  突然変異方法を入力します.以下の方法から選択できます.内容の詳細については,クラス Species の対応するメンバー関数を参照してください.
=-1 : 突然変異を使用しない
=0 : 移動
=1 : 逆位
=2 : スクランブル
=3 : 転座
  その他,このプログラムでは使用していませんが,クラス Species には以下の突然変異方法も定義してあります.
  • 対立遺伝子への置換
  • 重複
  • 摂動
  • 挿入
  • 削除

突然変異率

  突然変異率を入力します

  突然変異方法が,スクランブル,転座,重複,挿入,および,削除であるとき利用され,突然変異を起こす幅(染色体の部分列であり,遺伝子長より短い必要がある)を入力します.0 を入力すると幅がランダムに決められます.
  また,突然変異方法が摂動であるときは,摂動の確率分布を入力します.0 のときは正規分布,また,1 のときは一様分布となります.

平均

  突然変異方法として摂動を使用するとき利用されます.正規分布の時は平均,また,一様分布の時は分布の下限を入力します.

標準偏差

  突然変異方法として摂動を使用するとき利用されます.正規分布の時は標準偏差,また,一様分布の時は分布の上限を入力します.

エリート

  このプログラムでは,エリート選択とルーレット選択を利用しています.つまり,エリート選択によってここで指定した数だけの個体を選択した後,残りをルーレット選択で選択します.

方法

  ルーレット板の作成方法を入力します.
=-1 : ランダムに選択
=0 : 適応度に比例した確率で選択
=1 : 最小値からの差(ただし,α以下の場合はα)に比例した確率で選択
=2 : 評価値に順位をつけ,適応度の値を減少率βで線形化し,その値に応じた確率で選択

バイアス

  方法が 1 の場合はα,また,方法が 2 の場合は初期値

ステップ

  方法が 2 の場合においてβ

都市数

  都市の数を入力します.Species 記述データで指定した最大遺伝子長と一致する必要があります.

最大世代交代数

  最大世代交代数を入力します.

近傍探索(0:行わない,1:行う)

  1 を入力すると,各世代の各個体に対して,逐次改善法により近似解を求めます.なお,この場合は,個体の重複を許すように設定しておいた方が安全だと思います(許さないようにすると,指定した集団サイズだけの個体が存在しなくなる可能性があります).また,0 を入力すると近似解を求める操作を行いません.

近傍(2or3)と選択方法(0:最良,1:最初)

  逐次改善法においては,λ近傍(λの値が近傍に対する入力値)に含まれる(λ本の)枝を入れ替えるという作業を距離の改善がなされなくなるまで続けることによって,解を求めます.各ステップにおいて,どのλ本の枝を入れ替えるかを探索していきますが,選択方法に 0 を入力すると,λ本の枝を入れ替えるすべての組み合わせの内,最も改善度が高いものを選択します.また,1 を入力すると,最初に見つかったλ本の枝をすぐ入れ替えます.通常,1 で良いと思います.

-58 37
55 -19
・・・

  以下,各都市の x 座標と y 座標です.都市の数だけ必要になります.この入力された順番が,その都市の都市番号になります( 0 から始まる).