静岡理工科大学 菅沼ホーム 目次 索引

遺伝的アルゴリズム( TSP,関数の最大値)

    1. A. C++
    2. B. Java
    3. C. PHP
    4. D. Ruby
    5. E. Python
    6. F. C#
    7. G. VB

  このプログラムは,巡回セールスマン問題( TSP )を遺伝的アルゴリズムによって解くためのものです.遺伝的アルゴリズムの基本事項を定義したクラス Species は,巡回セールスマン問題だけに適用できるわけではありません.後一つの例として,関数,

f(x) = sin(3*x) + 0.5 * sin(9*x) + sin(15*x+50)

の [0, 1] 区間における最大値を求めるためのプログラムも添付しておきます.いずれの場合に対しても,使用方法を参考にして実行してみてください.なお,このプログラムは,クラスとその継承を使用して記述しています.

  1. C++

      C++11 においては,「メルセンヌ・ツイスター法による擬似乱数生成エンジン」を使用することができます.

    TSP
    /***********************************/
    /* 遺伝的アルゴリズムによるTSPの解 */
    /*      coded by Y.Suganuma        */
    /***********************************/
    
    /***********************/
    /* クラスSpeciesの定義 */
    /***********************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    #include "MT.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);
    };
    
    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];
    				}
    			}
    		}
    	}
    }
    
    /***********************************/
    /* 正規分布変量の発生              */
    /*      m : 平均                   */
    /*      s : 標準偏差               */
    /*           return : 正規分布変量 */
    /***********************************/
    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の定義 */
    /*******************/
    
    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);
    };
    
    /***************************************/
    /* コンストラクタ                      */
    /*      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 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];
    			seed[i1]    = 1000 * i1 + 1234567;
    			fscanf(in, "%s %s", 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;
    }
    
    //----------------ケーススタディデータ(data_ct.txt)------
    /*
    3
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    */
    
    //---------------Species記述データ(data1_t.txt)---------
    /*
    対立遺伝子上限 9 対立遺伝子下限 0
    最大遺伝子長 10 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 0 個体の重複(同じ染色体の個体) 0
    集団サイズ 10 子供 10
    */
    
    //---------------TSP記述データ(data2_t.txt)--------
    /*
    出力レベル(負はファイル) 10 出力方法(0:適応度+順番,1:適応度) 0
    出力ファイル名 out1.txt 表示間隔 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
    */
    
    //---------------------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
    */
    			
    関数の最大値
    /********************************************************************/
    /* f(x) = sin(3.0*x) + 0.5 * sin(9.0*x) + sin(15.0*x + 50) の最大値 */
    /*      coded by Y.Suganuma                                         */
    /********************************************************************/
    
    /***********************/
    /* クラスSpeciesの定義 */
    /***********************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    #include "MT.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);
    };
    
    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];
    				}
    			}
    		}
    	}
    }
    
    /***********************************/
    /* 正規分布変量の発生              */
    /*      m : 平均                   */
    /*      s : 標準偏差               */
    /*           return : 正規分布変量 */
    /***********************************/
    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;
    }
    
    /************************/
    /* クラスFunctionの定義 */
    /************************/
    class Function : public Species {
    
    		double cv;   // 2進数を10進数の変換する係数
    		int max_gen;   // 最大世代交代数
    		int kosa_m;   // 交叉方法
                          //   =-1 : 交叉を使用しない
                          //   =0 : 親のコピー
                          //   =1 : 多点交叉
                          //   =2 : 一様交叉
                          //   =3 : 平均化交叉
    		double kosa;   // 交叉確率
    		int k_point;   // 交差点の数(負の時は,1から-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 : スクランブル
                          //   =4 : 転座
                          //   =5 : 重複
                          //   =6 : 摂動
    		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];   // 出力ファイル名
    
    	public:
    					// コンストラクタ
    		Function (char *, char *, long);
    					// デストラクタ
    		~Function ();
    					// 全体の実行制御
    		void Control();
    					// 適応度の計算
    		void Adap();
    					// 出力
    		void Output(int);
    };
    
    /***************************************/
    /* コンストラクタ                      */
    /*      name1 : Species定義ファイル名  */
    /*      name2 : Function定義ファイル名 */
    /*      seed : 乱数の初期値            */
    /***************************************/
    Function::Function (char *name1, char *name2, long seed) : Species (name1, seed)
    {
    	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", &max_gen);
    
    	cv = 1.0 / (pow(2.0, (double)max_len) - 1.0);
    
    	fclose(in);
    }
    
    /****************/
    /* デストラクタ */
    /****************/
    Function::~Function()
    {
    	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;
    }
    
    /**************/
    /* 全体の制御 */
    /**************/
    void Function::Control()
    {
    	int gen = 1, k1;
    					// 初期集団の発生
    	Init_std();
    					// 評価
    	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_point(kosa, k_point);   // 多点交叉
    				break;
    			case 2:
    				C_uniform(kosa);   // 一様交叉
    				break;
    			case 3:
    				C_mean(kosa);   // 平均化交叉
    				break;
    			default:
    				break;
    		}
    						// 突然変異
    		switch (mute_m) {
    			case -1:
    				break;
    			case 0:
    				M_alle(mute);   // 対立遺伝子への置換
    				break;
    			case 1:
    				M_move(mute);   // 移動
    				break;
    			case 2:
    				M_inv(mute, wd);   // 逆位
    				break;
    			case 3:
    				M_scram(mute, wd);   // スクランブル
    				break;
    			case 4:
    				M_chg(mute, wd);   // 転座
    				break;
    			case 5:
    				M_dup(mute, wd);   // 重複
    				break;
    			case 6:
    				M_per(mute, wd, m_mean, m_std);   // 摂動
    				break;
    			default:
    				break;
    		}
    						// 適応度
    		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;
    }
    
    /****************/
    /* 適応度の計算 */
    /****************/
    void Function::Adap()
    {
    	double x, y;
    	int i1, i2, n = 0;
    
    	max   = 0.0;
    	max_n = -1;
    	mean  = 0.0;
    
    	for (i1 = 0; i1 < size+max_ch; i1++) {
    
    		if (pi_w[i1] == 1) {
    			x = 0.0;
    			y = 0.0;
    			for (i2 = len[i1]-1; i2 >= 0; i2--) {
    				if (ind[i1][i2] > 0)
    					x += pow(2.0, y);
    				y += 1.0;
    			}
    			x        *= cv;
    			pi[i1]    = sin(3.0*x) + 0.5 * sin(9.0*x) + sin(15.0*x+50.0);
    			pi_w[i1]  = 2;
    		}
    
    		if (pi_w[i1] > 0) {
    			mean += pi[i1];
    			n++;
    			if (max_n < 0 || pi[i1] > max) {
    				max   = pi[i1];
    				max_n = i1;
    			}
    		}
    	}
    
    	mean /= n;
    }
    
    /*****************************/
    /* 結果の出力                */
    /*      gen : 現在の世代番号 */
    /*****************************/
    void Function::Output(int gen)
    {
    	double x, y;
    	int i1, i2, k = 0, 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);
    		}
    					// 詳細出力
    		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]);
    				x = 0.0;
    				y = 0.0;
    				for (i2 = len[i1]-1; i2 >= 0; i2--) {
    					if (ind[i1][i2] > 0)
    						x += pow(2.0, y);
    					y += 1.0;
    				}
    				x *= cv;
    				fprintf(out, " x %f y %f\n", x, pi[i1]);
    				if (pr > 0) {
    					k++;
    					if (k == pr) {
    						getchar();
    						k = 0;
    					}
    				}
    			}
    		}
    
    		if (pr < 0)
    			fclose(out);
    	}
    }
    
    /****************/
    /* main program */
    /****************/
    int main(int argc, char *argv[])
    {
    	long *seed;
    	int i1, n;
    	char **i_file1, **i_file2;
    	FILE *in;
    	Function *fn;
    					// 入力ミス
    	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];
    			seed[i1]    = 1000 * i1 + 1234567;
    			fscanf(in, "%s %s", i_file1[i1], i_file2[i1]);
    		}
    
    		fclose(in);
    						// 実行(乱数の初期値を変える)
    		for (i1 = 0; i1 < n; i1++) {
    
    			printf("\n+++++ケース %d+++++\n", i1+1);
    
    			fn = new Function (i_file1[i1], i_file2[i1], seed[i1]);
    
    			fn->Control();
    		}
    	}
    
    	return 0;
    }
    
    //------------------ケーススタディデータ(data_cf.txt)------
    /*
    3
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    */
    
    //------------------Species記述データ(data1_f.txt)---------
    /*
    対立遺伝子上限 1 対立遺伝子下限 0
    最大遺伝子長 15 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 1 個体の重複(同じ染色体の個体) 0
    集団サイズ 20 子供 20
    */
    
    //------------------Function記述データ(data2_f.txt)--------
    /*
    出力レベル(負はファイル) 20 出力方法(0:すべて,1:最大) 0
    出力ファイル名 out1.txt 表示間隔 1
    交叉方法 1 交叉確率 1.0 点 2 位置 0 方法 1 バイアス 0 ステップ 1
    突然変異方法 0 突然変異率 0.05 幅 1 平均 0.0 標準偏差 1.0
    エリート 2 方法 1 バイアス 0 ステップ 1
    最大世代交代数 200
    */
    
    //---------------------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
    */
    			

  2. Java

    TSP
    /***********************************/
    /* 遺伝的アルゴリズムによるTSPの解 */
    /*      coded by Y.Suganuma        */
    /***********************************/
    import java.io.*;
    import java.util.Random;
    import java.util.Date;
    import java.util.StringTokenizer;
    import java.awt.*;
    import java.awt.event.*;
    
    /***********************/
    /* クラスSpeciesの定義 */
    /***********************/
    class Species {
    
    	protected double max;   // 最大適応度
    	protected double mean;   // 平均適応度
    	protected double [] pi;   // 適応度
    	protected double [] ro;   // ルーレット板
    	protected int allele_u;   // 対立遺伝子上限
    	protected int allele_l;   // 対立遺伝子下限
    	protected int size;   // 個体総数
    	protected int max_ch;   // 子供の数の最大値
    	protected int max_len;   // 最大遺伝子長
    	protected int min_len;   // 最小遺伝子長(負の時は,最大遺伝子長で固定)
    	protected int max_n;   // 最大適応度の個体番号
    	protected int dup_a;   // 遺伝子の重複
                               //   =0 : 重複を許さない
                               //   =1 : 重複を許す
    	protected int dup_s;   // 個体の重複(同じ染色体の個体)
                               //   =0 : 重複を許さない
                               //   =1 : 重複を許す
    	protected int [][] ind;   // 集団(個体の集まり)
    	protected int [] len;   // 各個体の遺伝子長
    	protected int [] kou1;   // 交叉・突然変異用作業場所1
    	protected int [] kou2;   // 交叉・突然変異用作業場所2
    	protected int [] s_w;   // 淘汰用指標(選択された回数)
    	protected int [][] edge;   // エッジ組み替え交叉用ワークエリア
    	protected byte [] pi_w;   // 適応度計算指標
                                  //   =0 : 未使用
                                  //   =1 : 適応度計算前(突然変異はこの個体だけに適用)
                                  //   =2 : 適応度計算済み(交叉時に親とみなす)
    	protected Random rn;   // 乱数
    
    	/***********************************/
    	/* 正規分布変量の発生              */
    	/*      m : 平均                   */
    	/*      s : 標準偏差               */
    	/*           return : 正規分布変量 */
    	/***********************************/
    	double norm_d(double m, double s)
    	{
    		double x = 0.0;
    		int i1;
    
    		for (i1 = 0; i1 < 12; i1++)
    			x += rn.nextDouble();
    
    		x = s * (x - 6.0) + m;
    
    		return x;
    	}
    
    	/**************************************************/
    	/* 場所を探す                                     */
    	/*      n : >=0 : n番目の親を捜す                 */
    	/*          -1 : 空いている場所を探す             */
    	/*      return : 親の場所,または,空いている場所 */
    	/*               (存在しないときは負の値)       */
    	/**************************************************/
    	int 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) {
    				System.out.print("***error  空いている場所がない --Position--\n");
    				System.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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      bias : α,または,method=2の場合は初期値                  */
    	/*      step : β                                                  */
    	/*      return : 個体番号                                          */
    	/*******************************************************************/
    	int 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 (Math.abs(sum) > 1.0e-10) {
    					sum = 1.0 / Math.abs(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  = rn.nextDouble();
    		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;
    	}
    
    	/****************************/
    	/* コンストラクタ           */
    	/*      name : ファイル名   */
    	/*      seed : 乱数の初期値 */
    	/****************************/
    	Species (String name, int seed) throws IOException, FileNotFoundException
    	{
    		int kind, num;
    		String line;
    		StringTokenizer dt;
    		BufferedReader in = new BufferedReader(new FileReader(name));
    	/*
    	     データの入力
    	*/
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		allele_u = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		allele_l = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		max_len = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		min_len = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		dup_a = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		dup_s = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		size = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		max_ch = Integer.parseInt(dt.nextToken());
    	/*
    	     データのチェック
    	*/
    		if (size <= 0) {
    			System.out.print("***error  個体総数≦0 (Constructor)\n");
    			System.exit(1);
    		}
    
    		if (max_ch < 0) {
    			System.out.print("***error  子供の数<0 (Constructor)\n");
    			System.exit(1);
    		}
    
    		if (max_len <= 0 || min_len == 0) {
    			System.out.print("***error  遺伝子長≦0 (Constructor)\n");
    			System.exit(1);
    		}
    
    		if (max_len < min_len) {
    			System.out.print("***error  最大遺伝子長<最小遺伝子長 (Constructor)\n");
    			System.exit(1);
    		}
    
    		if (allele_u <= allele_l) {
    			System.out.print("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)\n");
    			System.exit(1);
    		}
    
    		kind = allele_u - allele_l + 1;
    		if (dup_a == 0 && max_len > kind) {
    			System.out.print("***error  遺伝子の重複を防ぐことはできない (Constructor)\n");
    			System.exit(1);
    		}
    	/*
    	     領域の確保
    	*/
    		num  = size + max_ch;
    
    		ind  = new int [num][max_len];
    		edge = new int [max_len][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 byte [num];
    	/*
    	     乱数の初期設定
    	*/
    		rn = new Random (seed);
    	}
    
    	/********************/
    	/* 標準的な初期設定 */
    	/********************/
    	void 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)(rn.nextDouble() * (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)(rn.nextDouble() * (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 Out_std(int sw, int out_m, int gen, String name) throws IOException, FileNotFoundException
    	{
    		int i1, i2, k = 0, pr;
    		String now;
    		PrintStream out = null;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    		if (sw >= 0) {
    			System.out.print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = Integer.parseInt(in.readLine());
    		}
    		else
    			pr = -1;
    
    		if (pr != 0) {
    						// 出力先の決定と評価値の出力
    			if (pr > 0)
    				out = System.out;
    			else {
    				Date newtime = new Date();   // 現在時刻の獲得
    				now = newtime.toString();    // 文字列への変換
    				out = new PrintStream(new FileOutputStream(name, true));
    				out.println("***世代 " + gen + " 適応度 max " + max +
                                " (" + max_n + ") mean " + mean + " 時間 " + now);
    			}
    						// 詳細出力
    			for (i1 = 0; i1 < size+max_ch; i1++) {
    				if ((pi_w[i1] > 1) && (out_m ==0 || out_m == 1 && i1 == max_n)) {
    					out.print(i1 + " allele");
    					for (i2 = 0; i2 < len[i1]; i2++)
    						out.print(" " + ind[i1][i2]);
    					out.println(" value " + pi[i1]);
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							in.readLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			if (pr < 0)
    				out.close();
    		}
    	}
    
    	/*******************************************************************/
    	/* 交叉(親のコピー)                                              */
    	/*      method : =2 : 有性(2つの親から2つの子供)               */
    	/*               =1 : 1つの親から1つの子供                       */
    	/*      pair : method=2 の時は親のペア数                           */
    	/*             method=1 の時は親の数(=子供の数)                 */
    	/*      k_method : 選択方法                                        */
    	/*                 =-1 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_copy(int method, int pair, int k_method, double k_bias,
                    double k_step)
    	{
    	   int i1, i2, i3, k, p, p1, p2 = 0, 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) {
    				System.out.print("***error  子供が多すぎる (C_copy)\n");
    				System.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 : 交叉点の数                                       */
    	/*                (負の時は,1から-k_point間のランダム)          */
    	/*      k_vr : =0 : 両親とも同じ位置で交叉                         */
    	/*             =1 : 両親が異なる位置で交叉(遺伝子長は可変)       */
    	/*      k_method : 選択方法                                        */
    	/*                 =-1 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void 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 = 0,
                pair, sw, t11, t12, t21, t22;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    
    		if (dup_a == 0) {
    			System.out.print("***error  交叉方法が不適当 (C_point)\n");
    			System.exit(1);
    		}
    
    		abs_p = Math.abs(k_point);
    		if (abs_p == 0 || abs_p > max_len-1 || min_len > 0 && abs_p > min_len-1) {
    			System.out.print("***error  交叉点の数が不適当 (C_point)\n");
    			System.exit(1);
    		}
    
    		if (k_vr > 0 && min_len < 0) {
    			System.out.print("***error  遺伝子長は可変でなければならない (C_point)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		num = k_point;
    
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.nextDouble() * 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)(rn.nextDouble() * (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)(rn.nextDouble() * (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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_uniform(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, k1, k2, p1, p2 = 0, pair, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    
    		if (dup_a == 0) {
    			System.out.print("***error  交叉方法が不適当 (C_uniform)\n");
    			System.exit(1);
    		}
    
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_uniform)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 (rn.nextDouble() > 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_mean(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, k, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_mean)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < max_ch; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(1, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_cycle(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_cycle)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_cycle)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.nextDouble() * 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_part(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, i3, k1, k2, lv, p, pair, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_part)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_part)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.nextDouble() * 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void 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 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_seq)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_seq)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.nextDouble() * (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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_useq(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, i4, k1, k2, p, pair, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_useq)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_useq)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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]    = (rn.nextDouble() < 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_upos(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_upos)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_upos)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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] = (rn.nextDouble() < 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_edge(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, i3, i4, i5, k, kk, k0 = 0, k1, k2, min, num,
    	        p, pair, p1, p2 = 0, sw;
    		int e[] = new int [2];
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_edge)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_edge)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(1, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 = (rn.nextDouble() > 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)(rn.nextDouble() * 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) {
    								System.out.print("***error  invalid data (C_edge)\n");
    								System.exit(1);
    							}
    							else {
    								k1 = (int)(rn.nextDouble() * 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つのペアーに対する交差回数                 */
    	/*************************************************************/
    	void C_sub(double kosa, int count)
    	{
    		int i1, i2, i3, i4, i5, k1, k2, k3, k4, p1, p2,
    	        t11, t12 = 0, t21, t22 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		if ((4*count*size*(size-1)) > max_ch) {
    			System.out.print("***error  子供が多すぎる (C_sub)\n");
    			System.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 (rn.nextDouble() > kosa)
    							C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    						else {
    							// 交叉回数の制御
    							for (i3 = 0; i3 < count; i3++) {
    								// 交叉位置の決定(点の後ろで交叉)
    									// 親1の交叉位置
    								t11 = (int)(rn.nextDouble() * len[p1]);
    								if (t11 > (len[p1]-1))
    									t11 = len[p1] - 1;
    								sw = 0;
    								while (sw == 0) {
    									t12 = (int)(rn.nextDouble() * 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 M_alle(double pr)
    	{
    		int i1, i2, lid;
    	/*
    	     データのチェックと初期設定
    	*/
    		if (dup_a == 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_alle)\n");
    			System.exit(1);
    		}
    	/*
    	     実行
    	*/
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    			if (pi_w[i1] == 1) {
    				for (i2 = 0; i2 < len[i1]; i2++) {
    					if (rn.nextDouble() <= pr) {
    						lid = (int)(rn.nextDouble() * (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 M_move(double pr)
    	{
    		int i1, i2, ld, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    	/*
    	     位置の決定
    	*/
    						// p1
    				p1 = (int)(rn.nextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    						// p2
    				sw = 0;
    				while (sw == 0) {
    					p2 = (int)(rn.nextDouble() * 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 : 幅をランダム                          */
    	/********************************************************/
    	void M_inv(double pr, int wd)
    	{
    		int i1, lid, p, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    	/*
    	     区間の決定
    	*/
    				if (wd == 0) {
    					p1 = (int)(rn.nextDouble() * len[i1]);
    					if (p1 >= len[i1])
    						p1 = len[i1] - 1;
    					sw = 0;
    					while (sw == 0) {
    						p2 = (int)(rn.nextDouble() * 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)(rn.nextDouble() * 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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_scram(double pr, int wd)
    	{
    		int i1, i2, ld, p, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    	/*
    	     区間の決定
    	*/
    				if (wd == 0) {
    					p1 = (int)(rn.nextDouble() * len[i1]);
    					if (p1 >= len[i1])
    						p1 = len[i1] - 1;
    					sw = 0;
    					while (sw == 0) {
    						p2 = (int)(rn.nextDouble() * 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)(rn.nextDouble() * len[i1]);
    					p2 = p1 + wd - 1;
    					if (p2 >= len[i1])
    						p2 = len[i1] - 1;
    				}
    	/*
    	     実行
    	*/
    				for (i2 = p1; i2 <= p2; i2++) {
    					p = (int)(rn.nextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_chg(double pr, int wd)
    	{
    		int i1, i2, ld, p, p1, p2, p3 = 0, p4, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    	/*
    	     区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    	*/
    						// p1
    				p1 = (int)(rn.nextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    						// p3
    				sw = 0;
    				while (sw == 0) {
    					p3 = (int)(rn.nextDouble() * 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)(rn.nextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_dup(double pr, int wd)
    	{
    		int i1, i2, p, p1, p2, p3 = 0, p4, sw;
    	/*
    	     データのチェック
    	*/
    		if (dup_a == 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_dup)\n");
    			System.exit(1);
    		}
    	/*
    	     実行
    	*/
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    						// 区間の決定([p1,p2]を[p3,p4]にコピー)
    							// p1
    				p1 = (int)(rn.nextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    							// p3
    				sw = 0;
    				while (sw == 0) {
    					p3 = (int)(rn.nextDouble() * len[i1]);
    					if (p3 >= len[i1])
    						p3 = len[i1] - 1;
    					if (p3 != p1)
    						sw = 1;
    				}
    							// 区間を決める
    				if (p3 > p1) {
    					p4 = (wd == 0) ? (int)(rn.nextDouble() * (len[i1] - p3)) + p3 :
                                         p3 + wd - 1;
    					if (p4 >= len[i1])
    						p4 = len[i1] - 1;
    					p2 = p1 + (p4 - p3);
    				}
    				else {
    					p2 = (wd == 0) ? (int)(rn.nextDouble() * (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 : 正規分布                        */
    	/*               =1 : 一様分布                        */
    	/*      m : 平均または一様分布の下限                  */
    	/*      s : 標準偏差または一様分布の上限              */
    	/******************************************************/
    	void M_per(double pr, int method, double m, double s)
    	{
    		double w, wd = 0.0, x1;
    		int i1, i2;
    	/*
    	     データのチェックと初期設定
    	*/
    		if (dup_a == 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_per)\n");
    			System.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 (rn.nextDouble() <= pr) {
    						if (method == 0)
    							w = norm_d(m, s);
    						else {
    							w = rn.nextDouble() * wd;
    							if (rn.nextDouble() < 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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_ins(double pr, int wd)
    	{
    		int i1, i2, l, ld, p;
    	/*
    	     データのチェック
    	*/
    		if (dup_a == 0 || min_len < 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_ins)\n");
    			System.exit(1);
    		}
    	/*
    	     実行
    	*/
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    						// 挿入位置の決定
    				p = (int)(rn.nextDouble() * (len[i1]+1));
    				if (p > len[i1])
    					p = len[i1];
    						// 挿入する遺伝子長の決定
    				l = (wd == 0) ? (int)(rn.nextDouble() * (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)(rn.nextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_del(double pr, int wd)
    	{
    		int i1, i2, l, max, p;
    	/*
    	     データのチェック
    	*/
    		if (dup_a == 0 || min_len < 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_del)\n");
    			System.exit(1);
    		}
    	/*
    	     実行
    	*/
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    						// 削除位置の決定
    				p = (int)(rn.nextDouble() * 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)(rn.nextDouble() * 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 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) {
    			System.out.print("***error  エリートで残す数が多すぎる (S_roul)\n");
    			System.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) {
    			System.out.print("***error  残す個体がない (S_roul)\n");
    			System.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];
    					}
    				}
    			}
    		}
    	}
    }
    
    /*******************/
    /* クラスTSPの定義 */
    /*******************/
    class TSP extends Species {
    
    	private int max_gen;   // 最大世代交代数
    	private int kosa_m;   // 交叉方法
                              //   =-1 : 交叉を使用しない
                              //   =0 : 親のコピー
                              //   =1 : 循環交叉
                              //   =2 : 部分的交叉
                              //   =3 : 順序交叉
                              //   =4 : 一様順序交叉
                              //   =5 : 一様位置交叉
                              //   =6 : エッジ組み替え交叉
                              //   =7 : サブツアー交叉
    	private double kosa;   // 交叉確率
    	private int k_point;   // 交差点の数(負の時は,1から-point間のランダム)
    	private int k_vr;   // =0 : 両親とも同じ位置で交叉
                            // =1 : 両親が異なる位置で交叉(遺伝子長は可変)
    	private int k_method;   // 交叉の時の親の選択方法
                                //   =-1 : ランダム
                                //   =0 : 適応度をそのまま使用
                                //   =1 : 最小値からの差(ただし,α以下の場合はα)
                                //   =2 : 評価値に順位をつけ,減少率βで線形化
    	private double k_bias;   // α,または,method=2の場合は初期値
    	private double k_step;   // β
    	private int mute_m;   // 突然変異方法
                              //   =-1 : 突然変異を使用しない
                              //   =0 : 移動
                              //   =1 : 逆位
                              //   =2 : スクランブル
                              //   =3 : 転座
    	private double mute;   // 突然変異率
    	private int wd;   // 突然変異に使用する部分遺伝子長
    	private double m_mean;   // 摂動の平均値
    	private double m_std;   // 摂動の標準偏差
    	private int elite;   // エリート選択で残す数
    	private int s_method;   // ルーレット板の作成方法
                                //   =0 : 適応度をそのまま使用
                                //   =1 : 最小値からの差(ただし,α以下の場合はα)
                                //   =2 : 評価値に順位をつけ,減少率βで線形化
    	private double s_bias;   // α,または,s_method=2の場合は初期値
    	private double s_step;   // β
    	private int out_d;   // 表示間隔
    	private int out_lvl;   // 出力レベル
                               //   =0 : 最終出力だけ
                               //   n>0 : n世代毎に出力(負の時はファイル)
    	private int out_m;   // 出力方法
                             //   =0 : すべてを出力
                             //   =1 : 最大適応度の個体だけを出力
    	private String o_file;   // 出力ファイル名
    	private int n_city;   // 都市の数
    	private int [][] rg;   // 都市間の距離
    	private int kinbo;   // 近傍探索(0:行わない,1:行う)
    	private int neib;   // 近傍(2 or 3)
    	private int sel;   // エッジの選択方法
                           //   =0 : 最良のものを選択
                           //   =1 : 最初のものを選択
    	private Win wn;   // Winオブジェクト
    
    	int [][] city;   //都市の位置データ
    	int display;   // 画面表示
                       //   =0 : 画面表示を行わない
                       //   =1 : 結果だけを表示
                       //   =2 : 初期状態と結果を表示
                       //   =3 : out_lvlで指定された世代毎に表示
    
    	/***************************************/
    	/* コンストラクタ                      */
    	/*      name1 : Species定義ファイル名  */
    	/*      name2 : TSP定義ファイル名      */
    	/*      seed : 乱数の初期値            */
    	/***************************************/
    	TSP (String name1, String name2, int seed) throws IOException, FileNotFoundException
    	{
    		super (name1, seed);
    
    		double x, y;
    		int i1, i2;
    		String line;
    		StringTokenizer dt;
    		BufferedReader in = new BufferedReader(new FileReader(name2));
    					// 基本データの入力
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		out_lvl = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		out_m = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		o_file = dt.nextToken();
    		dt.nextToken();
    		out_d = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		kosa_m = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		kosa = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		k_point = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		k_vr = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		k_method = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		k_bias = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		k_step = Double.parseDouble(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		mute_m = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		mute = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		wd = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		m_mean = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		m_std = Double.parseDouble(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		elite = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		s_method = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		s_bias = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		s_step = Double.parseDouble(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		n_city = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		max_gen = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		kinbo = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		neib = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		sel = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		display = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		int font = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		int width = Integer.parseInt(dt.nextToken());
    		int height = Integer.parseInt(dt.nextToken());
    
    		if (kinbo > 0 && neib != 2 && neib != 3) {
    			System.out.print("***error  近傍の値が不適当 \n");
    			System.exit(1);
    		}
    
    		if (n_city != max_len) {
    			System.out.print("***error  都市数が不適当 \n");
    			System.exit(1);
    		}
    					// 都市の位置データ
    		city = new int [n_city][2];
    		for (i1 = 0; i1 < n_city; i1++) {
    			line = in.readLine();
    			dt   = new StringTokenizer(line, " ");
    			city[i1][0] = Integer.parseInt(dt.nextToken());
    			city[i1][1] = Integer.parseInt(dt.nextToken());
    		}
    					// 距離テーブル
    		rg = new int [n_city][n_city];
    
    		for (i1 = 0; i1 < n_city; i1++) {
    			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)(Math.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];
    		}
    
    		in.close();
    					// Windowの生成
    		if (display > 0)
    			wn = new Win (this, font, width, height, n_city);
    	}
    
    	/**************/
    	/* 全体の制御 */
    	/**************/
    	void Control() throws IOException, FileNotFoundException
    	{
    		int gen = 1, k1;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    						// 初期集団の発生
    		Init_std();
    						// 評価
    		if (kinbo > 0)
    			Kinbo();
    		else
    			Adap();
    						// 画面表示
    		System.out.println("***世代 " + gen + " 適応度 max " + max +
                               " (" + max_n + ") mean " + mean);
    						// 初期状態の出力(図)
    		if (display >= 2) {
    			wn.Draw(max, ind[max_n]);
    			System.out.println("      図を確認したらreturnキーを押してください");
    			in.readLine();
    		}
    						// 出力
    		if (Math.abs(out_lvl) > 0)
    			Output(gen);
    						// 世代交代
    		for (gen = 2; gen <= max_gen; gen++) {
    							// 交叉
    			switch (kosa_m) {
    				case -1:
    					break;
    				case 0:
    					C_copy(2, max_ch/2, k_method, k_bias, k_step);   // 親のコピー
    					break;
    				case 1:
    					C_cycle(kosa, k_method, k_bias, k_step);   // 循環交叉
    					break;
    				case 2:
    					C_part(kosa, k_method, k_bias, k_step);   // 部分的交叉
    					break;
    				case 3:
    					C_seq(kosa, k_method, k_bias, k_step);   // 順序交叉
    					break;
    				case 4:
    					C_useq(kosa, k_method, k_bias, k_step);   // 一様順序交叉
    					break;
    				case 5:
    					C_upos(kosa, k_method, k_bias, k_step);   // 一様位置交叉
    					break;
    				case 6:
    					C_edge(kosa, k_method, k_bias, k_step);   // エッジ組み替え交叉
    					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, wd);   // 逆位
    					break;
    				case 2:
    					M_scram(mute, wd);   // スクランブル
    					break;
    				case 3:
    					M_chg(mute, wd);   // 転座
    					break;
    				default:
    					break;
    			}
    							// 適応度
    			if (kinbo > 0)
    				Kinbo();
    			else
    				Adap();
    							// 淘汰
    			S_roul(elite, s_method, s_bias, s_step);
    							// 画面表示
    			if (gen%out_d == 0)
    				System.out.println("***世代 " + gen + " 適応度 max " + max +
                                       " (" + max_n + ") mean " + mean);
    							// 文字出力と図示
    			if (Math.abs(out_lvl) > 0) {
    				if (gen%Math.abs(out_lvl) == 0) {
    					if (display == 3) {
    						wn.Draw(max, ind[max_n]);
    						System.out.println("      図を確認したらreturnキーを押してください");
    						in.readLine();
    					}
    					Output(gen);
    				}
    			}
    		}
    
    		gen--;
    		k1    = out_m;
    		out_m = 0;
    		System.out.println("***世代 " + gen + " 適応度 max " + max +
                               " (" + max_n + ") mean " + mean);
    		if (display >= 1) {
    			wn.Draw(max, ind[max_n]);
    			System.out.println("      図を確認したらreturnキーを押してください");
    			in.readLine();
    		}
    		Output(gen);
    		out_m = k1;
    	}
    
    	/*********************************/
    	/* 距離の計算                    */
    	/*      n_c : 都市の数           */
    	/*      p : 都市番号             */
    	/*      return : 距離(負)      */
    	/*********************************/
    	int 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 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 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[0];
    	
    		n3  = (int)(rn.nextDouble() * (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[0] = max;
    			for (i1 = 0; i1 < n_city; i1++)
    				seq[i1] = kou2[i1];
    		}
    	
    		return sw;
    	}
    	
    	/**************/
    	/* 近傍の探索 */
    	/**************/
    	void Kinbo()
    	{
    		int i1, k = 0, sw;
    		int r [] = new int [1];
    		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[0]     = Kyori(len[i1], ind[i1]);
    				while (sw > 0)
    					sw = Change(len[i1], ind[i1], r);
    				pi[i1] = r[0];
    			}
    			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 Output(int gen) throws IOException, FileNotFoundException
    	{
    		double x, y;
    		int i1, i2, k = 0, n, pr;
    		String now;
    		PrintStream out = null;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    		if (out_lvl >= 0) {
    			System.out.print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = Integer.parseInt(in.readLine());
    		}
    		else
    			pr = -1;
    
    		if (pr != 0) {
    						// 出力先の決定と評価値の出力
    			if (pr > 0)
    				out = System.out;
    			else {
    				Date newtime = new Date();   // 現在時刻の獲得
    				now = newtime.toString();    // 文字列への変換
    				out = new PrintStream(new FileOutputStream(o_file, true));
    				out.println("***世代 " + gen + " 適応度 max " + max +
                                " (" + max_n + ") mean " + mean + " 時間 " + now);
    			}
    					// 巡回順序の出力
    			if (out_m == 0) {
    				for (i1 = 0; i1 < len[max_n]; i1++) {
    					n = ind[max_n][i1];
    					out.println(n + " " + city[n][0] + " " + city[n][1]);
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							in.readLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			if (pr < 0)
    				out.close();
    		}
    	}
    }
    
    /*******************/
    /* クラスWinの定義 */
    /*******************/
    class Win extends Frame {
    
    	double ritu;   // 表示倍率
    	private int font;   // フォントサイズ
    	private int min_x, max_x, min_y, max_y;   // 都市の存在範囲
    	private int next, yoyu_x, yoyu_y;   // 表示位置
    	private int n_city;   // 都市の数
    	private int [] seq;   // 都市を訪問する順番
    	private int range;   // 距離
    	private TSP tsp;
    
    	/*************************************/
    	/* コンストラクタ                    */
    	/*      tsp_i : TSPのオブジェクト    */
    	/*      city_i : 都市の位置データ    */
    	/*      font_i : フォントサイズ      */
    	/*      width,height : 表示範囲      */
    	/*      nc : 都市の数                */
    	/*************************************/
    	Win (TSP tsp_i, int font_i, int width, int height, int nc)
    	{
    					// Frameクラスのコンストラクタの呼び出し
    		super("巡回セールスマン問題");
    					// 値の設定と領域の確保
    		double k1, k2;
    		int i1;
    
    		tsp     = tsp_i;
    		font    = font_i;
    		next    = 70;
    		yoyu_x  = 30;
    		yoyu_y  = 80;
    		n_city  = nc;
    		seq     = new int [n_city];
    					// 描画領域の計算
    		min_x = tsp.city[0][0];
    		max_x = tsp.city[0][0];
    		min_y = tsp.city[0][1];
    		max_y = tsp.city[0][1];
    
    		for (i1 = 1; i1 < n_city; i1++) {
    			if (tsp.city[i1][0] < min_x)
    				min_x = tsp.city[i1][0];
    			else {
    				if (tsp.city[i1][0] > max_x)
    					max_x = tsp.city[i1][0];
    			}
    			if (tsp.city[i1][1] < min_y)
    				min_y = tsp.city[i1][1];
    			else {
    				if (tsp.city[i1][1] > max_y)
    					max_y = tsp.city[i1][1];
    			}
    		}
    
    		k1 = (double)(width - 2 * yoyu_x) / (max_x - min_x);
    		k2 = (double)(height - yoyu_y - yoyu_x) / (max_y - min_y);
    		ritu = (k1 < k2) ? k1 : k2;
    					// ボタンの設定とWindowサイズ
    						// 指定された大きさにWindowサイズを変更
    		width  = 2 * yoyu_x + (int)(ritu * (max_x - min_x));
    		height = yoyu_y + yoyu_x + (int)(ritu * (max_y - min_y));
    
    		setSize(width, height);
    					// ウィンドウを表示
    		setVisible(true);
    					// イベントアダプタ
    		addWindowListener(new WinEnd());
    	}
    
    	/*****************************/
    	/* 描画指示                  */
    	/*      max : 距離の負値     */
    	/*      seq_i : 訪問する順序 */
    	/*****************************/
    	void Draw(double max, int [] seq_i)
    	{
    		int i1;
    
    		range = (int)(-max + 0.5);
    
    		for (i1 = 0; i1 < n_city; i1++)
    			seq[i1] = seq_i[i1];
    
    		repaint();
    	}
    
    	/********/
    	/* 描画 */
    	/********/
    	public void paint (Graphics g)
    	{
    		int i1, k, n1, n2, size = 6, x1, x2, y1, y2;
    		Font f;
    						// 距離の表示
    		f = new Font("TimesRoman", Font.BOLD, 25);
    		g.setFont(f);
    		g.drawString("Length : "+Integer.toString(range), yoyu_x, yoyu_y-30);
    						// 都市番号のフォントサイズ
    		if (font > 0) {
    			f = new Font("TimesRoman", Font.PLAIN, font);
    			g.setFont(f);
    		}
    					// 点と直線のプロット
    		k = size / 2;
    
    		for (i1 = 0; i1 < n_city; i1++) {
    
    			n2 = seq[i1];
    			x2 = yoyu_x + (int)(ritu * (tsp.city[n2][0] - min_x));
    			y2 = yoyu_y + (int)(ritu * (max_y - tsp.city[n2][1]));
    
    			g.fillOval(x2, y2, size, size);
    
    			if (font > 0)
    				g.drawString(Integer.toString(n2), x2+k, y2-k);
    
    			if (i1 > 0) {
    				n1 = seq[i1-1];
    				x1 = yoyu_x + (int)(ritu * (tsp.city[n1][0] - min_x));
    				y1 = yoyu_y + (int)(ritu * (max_y - tsp.city[n1][1]));
    				g.drawLine(x1+k, y1+k, x2+k, y2+k);
    				if (i1 == n_city-1) {
    					n1 = seq[0];
    					x1 = yoyu_x + (int)(ritu * (tsp.city[n1][0] - min_x));
    					y1 = yoyu_y + (int)(ritu * (max_y - tsp.city[n1][1]));
    					g.drawLine(x1+k, y1+k, x2+k, y2+k);
    				}
    			}
    		}
    	}
    
    	/************/
    	/* 終了処理 */
    	/************/
    	class WinEnd extends WindowAdapter
    	{
    		public void windowClosing(WindowEvent e) {
    			System.exit(0);
    		}
    	}
    }
    
    class Test_t {
    
    	/****************/
    	/* main program */
    	/****************/
    	public static void main(String args[]) throws IOException, FileNotFoundException
    	{
    		int i1, n;
    		String i_file1[], i_file2[], line;
    		TSP tsp;
    		StringTokenizer dt;
    		BufferedReader in = new BufferedReader(new FileReader(args[0]));
    						// 入力ミス
    		if (args.length == 0) {
    			System.out.print("***error  ファイル名を入力して下さい\n");
    			System.exit(1);
    		}
    						// 入力OK
    		else {
    							// 入力データファイル名の入力
    			n      = Integer.parseInt(in.readLine());
    
    			i_file1 = new String [n];
    			i_file2 = new String [n];
    
    			for (i1 = 0; i1 < n; i1++) {
    				line = in.readLine();
    				dt   = new StringTokenizer(line, " ");
    				i_file1[i1] = dt.nextToken();
    				i_file2[i1] = dt.nextToken();
    			}
    
    			in.close();
    							// 実行(乱数の初期値を変える)
    			for (i1 = 0; i1 < n; i1++) {
    				System.out.print("\n+++++ケース " + (i1+1) + "+++++\n");
    								// 入力と初期設定
    				tsp = new TSP (i_file1[i1], i_file2[i1], 1000 * i1 + 1234567);
    								// 最適化
    				tsp.Control();
    			}
    		}
    	}
    }
    
    //----------------ケーススタディデータ(data_ctj.txt)------
    /*
    3
    data1_tj.txt data2_tj.txt
    data1_tj.txt data2_tj.txt
    data1_tj.txt data2_tj.txt
    */
    
    //---------------Species記述データ(data1_tj.txt)---------
    /*
    対立遺伝子上限 9 対立遺伝子下限 0
    最大遺伝子長 10 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 0 個体の重複(同じ染色体の個体) 0
    集団サイズ 10 子供 10
    */
    
    //---------------TSP記述データ(data2_tj.txt)--------
    /*
    出力レベル(負はファイル) 10 出力方法(0:適応度+順番,1:適応度) 0
    出力ファイル名 out1.txt 表示間隔 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
    図示(0:しない,1:結果,2:初期状態と結果,3:ステップ) 3
    都市番号 0 図の大きさ(幅,高さ) 1000 750
    -58 37
    55 -19
    6 -79
    27 -30
    44 -94
    33 -58
    -94 87
    -9 3
    33 69
    43 -57
    */
    			
    関数の最大値
    /********************************************************************/
    /* f(x) = sin(3.0*x) + 0.5 * sin(9.0*x) + sin(15.0*x + 50) の最大値 */
    /*      coded by Y.Suganuma                                         */
    /********************************************************************/
    import java.io.*;
    import java.util.Random;
    import java.util.Date;
    import java.util.StringTokenizer;
    
    /***********************/
    /* クラスSpeciesの定義 */
    /***********************/
    class Species {
    
    	protected double max;   // 最大適応度
    	protected double mean;   // 平均適応度
    	protected double [] pi;   // 適応度
    	protected double [] ro;   // ルーレット板
    	protected int allele_u;   // 対立遺伝子上限
    	protected int allele_l;   // 対立遺伝子下限
    	protected int size;   // 個体総数
    	protected int max_ch;   // 子供の数の最大値
    	protected int max_len;   // 最大遺伝子長
    	protected int min_len;   // 最小遺伝子長(負の時は,最大遺伝子長で固定)
    	protected int max_n;   // 最大適応度の個体番号
    	protected int dup_a;   // 遺伝子の重複
                               //   =0 : 重複を許さない
                               //   =1 : 重複を許す
    	protected int dup_s;   // 個体の重複(同じ染色体の個体)
                               //   =0 : 重複を許さない
                               //   =1 : 重複を許す
    	protected int [][] ind;   // 集団(個体の集まり)
    	protected int [] len;   // 各個体の遺伝子長
    	protected int [] kou1;   // 交叉・突然変異用作業場所1
    	protected int [] kou2;   // 交叉・突然変異用作業場所2
    	protected int [] s_w;   // 淘汰用指標(選択された回数)
    	protected int [][] edge;   // エッジ組み替え交叉用ワークエリア
    	protected byte [] pi_w;   // 適応度計算指標
                                  //   =0 : 未使用
                                  //   =1 : 適応度計算前(突然変異はこの個体だけに適用)
                                  //   =2 : 適応度計算済み(交叉時に親とみなす)
    	protected Random rn;   // 乱数
    
    	/***********************************/
    	/* 正規分布変量の発生              */
    	/*      m : 平均                   */
    	/*      s : 標準偏差               */
    	/*           return : 正規分布変量 */
    	/***********************************/
    	double norm_d(double m, double s)
    	{
    		double x = 0.0;
    		int i1;
    
    		for (i1 = 0; i1 < 12; i1++)
    			x += rn.nextDouble();
    
    		x = s * (x - 6.0) + m;
    
    		return x;
    	}
    
    	/**************************************************/
    	/* 場所を探す                                     */
    	/*      n : >=0 : n番目の親を捜す                 */
    	/*          -1 : 空いている場所を探す             */
    	/*      return : 親の場所,または,空いている場所 */
    	/*               (存在しないときは負の値)       */
    	/**************************************************/
    	int 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) {
    				System.out.print("***error  空いている場所がない --Position--\n");
    				System.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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      bias : α,または,method=2の場合は初期値                  */
    	/*      step : β                                                  */
    	/*      return : 個体番号                                          */
    	/*******************************************************************/
    	int 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 (Math.abs(sum) > 1.0e-10) {
    					sum = 1.0 / Math.abs(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  = rn.nextDouble();
    		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;
    	}
    
    	/****************************/
    	/* コンストラクタ           */
    	/*      name : ファイル名   */
    	/*      seed : 乱数の初期値 */
    	/****************************/
    	Species (String name, int seed) throws IOException, FileNotFoundException
    	{
    		int kind, num;
    		String line;
    		StringTokenizer dt;
    		BufferedReader in = new BufferedReader(new FileReader(name));
    	/*
    	     データの入力
    	*/
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		allele_u = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		allele_l = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		max_len = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		min_len = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		dup_a = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		dup_s = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		size = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		max_ch = Integer.parseInt(dt.nextToken());
    	/*
    	     データのチェック
    	*/
    		if (size <= 0) {
    			System.out.print("***error  個体総数≦0 (Constructor)\n");
    			System.exit(1);
    		}
    
    		if (max_ch < 0) {
    			System.out.print("***error  子供の数<0 (Constructor)\n");
    			System.exit(1);
    		}
    
    		if (max_len <= 0 || min_len == 0) {
    			System.out.print("***error  遺伝子長≦0 (Constructor)\n");
    			System.exit(1);
    		}
    
    		if (max_len < min_len) {
    			System.out.print("***error  最大遺伝子長<最小遺伝子長 (Constructor)\n");
    			System.exit(1);
    		}
    
    		if (allele_u <= allele_l) {
    			System.out.print("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)\n");
    			System.exit(1);
    		}
    
    		kind = allele_u - allele_l + 1;
    		if (dup_a == 0 && max_len > kind) {
    			System.out.print("***error  遺伝子の重複を防ぐことはできない (Constructor)\n");
    			System.exit(1);
    		}
    	/*
    	     領域の確保
    	*/
    		num  = size + max_ch;
    
    		ind  = new int [num][max_len];
    		edge = new int [max_len][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 byte [num];
    	/*
    	     乱数の初期設定
    	*/
    		rn = new Random (seed);
    	}
    
    	/********************/
    	/* 標準的な初期設定 */
    	/********************/
    	void 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)(rn.nextDouble() * (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)(rn.nextDouble() * (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 Out_std(int sw, int out_m, int gen, String name) throws IOException, FileNotFoundException
    	{
    		int i1, i2, k = 0, pr;
    		String now;
    		PrintStream out = null;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    		if (sw >= 0) {
    			System.out.print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = Integer.parseInt(in.readLine());
    		}
    		else
    			pr = -1;
    
    		if (pr != 0) {
    						// 出力先の決定と評価値の出力
    			if (pr > 0)
    				out = System.out;
    			else {
    				Date newtime = new Date();   // 現在時刻の獲得
    				now = newtime.toString();    // 文字列への変換
    				out = new PrintStream(new FileOutputStream(name, true));
    				out.println("***世代 " + gen + " 適応度 max " + max +
                                " (" + max_n + ") mean " + mean + " 時間 " + now);
    			}
    						// 詳細出力
    			for (i1 = 0; i1 < size+max_ch; i1++) {
    				if ((pi_w[i1] > 1) && (out_m ==0 || out_m == 1 && i1 == max_n)) {
    					out.print(i1 + " allele");
    					for (i2 = 0; i2 < len[i1]; i2++)
    						out.print(" " + ind[i1][i2]);
    					out.println(" value " + pi[i1]);
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							in.readLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			if (pr < 0)
    				out.close();
    		}
    	}
    
    	/*******************************************************************/
    	/* 交叉(親のコピー)                                              */
    	/*      method : =2 : 有性(2つの親から2つの子供)               */
    	/*               =1 : 1つの親から1つの子供                       */
    	/*      pair : method=2 の時は親のペア数                           */
    	/*             method=1 の時は親の数(=子供の数)                 */
    	/*      k_method : 選択方法                                        */
    	/*                 =-1 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_copy(int method, int pair, int k_method, double k_bias,
                    double k_step)
    	{
    	   int i1, i2, i3, k, p, p1, p2 = 0, 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) {
    				System.out.print("***error  子供が多すぎる (C_copy)\n");
    				System.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 : 交叉点の数                                       */
    	/*                (負の時は,1から-k_point間のランダム)          */
    	/*      k_vr : =0 : 両親とも同じ位置で交叉                         */
    	/*             =1 : 両親が異なる位置で交叉(遺伝子長は可変)       */
    	/*      k_method : 選択方法                                        */
    	/*                 =-1 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void 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 = 0,
                pair, sw, t11, t12, t21, t22;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    
    		if (dup_a == 0) {
    			System.out.print("***error  交叉方法が不適当 (C_point)\n");
    			System.exit(1);
    		}
    
    		abs_p = Math.abs(k_point);
    		if (abs_p == 0 || abs_p > max_len-1 || min_len > 0 && abs_p > min_len-1) {
    			System.out.print("***error  交叉点の数が不適当 (C_point)\n");
    			System.exit(1);
    		}
    
    		if (k_vr > 0 && min_len < 0) {
    			System.out.print("***error  遺伝子長は可変でなければならない (C_point)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		num = k_point;
    
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.nextDouble() * 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)(rn.nextDouble() * (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)(rn.nextDouble() * (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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_uniform(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, k1, k2, p1, p2 = 0, pair, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    
    		if (dup_a == 0) {
    			System.out.print("***error  交叉方法が不適当 (C_uniform)\n");
    			System.exit(1);
    		}
    
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_uniform)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 (rn.nextDouble() > 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_mean(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, k, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_mean)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < max_ch; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(1, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_cycle(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_cycle)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_cycle)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.nextDouble() * 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_part(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, i3, k1, k2, lv, p, pair, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_part)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_part)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.nextDouble() * 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void 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 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_seq)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_seq)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.nextDouble() * (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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_useq(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, i4, k1, k2, p, pair, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_useq)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_useq)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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]    = (rn.nextDouble() < 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_upos(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_upos)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_upos)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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] = (rn.nextDouble() < 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	void C_edge(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, i3, i4, i5, k, kk, k0 = 0, k1, k2, min, num,
    	        p, pair, p1, p2 = 0, sw;
    		int e[] = new int [2];
    	/*
    	     初期設定とデータのチェック
    	*/
    		pair = max_ch;
    	
    		if (dup_a != 0) {
    			System.out.print("***error  交叉方法が不適当 (C_edge)\n");
    			System.exit(1);
    		}
    	
    		if (min_len > 0) {
    			System.out.print("***error  遺伝子長は固定長でなければならない (C_edge)\n");
    			System.exit(1);
    		}
    	/*
    	     交叉
    	*/
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.nextDouble() > kosa)
    				C_copy(1, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 = (rn.nextDouble() > 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)(rn.nextDouble() * 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) {
    								System.out.print("***error  invalid data (C_edge)\n");
    								System.exit(1);
    							}
    							else {
    								k1 = (int)(rn.nextDouble() * 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つのペアーに対する交差回数                 */
    	/*************************************************************/
    	void C_sub(double kosa, int count)
    	{
    		int i1, i2, i3, i4, i5, k1, k2, k3, k4, p1, p2,
    	        t11, t12 = 0, t21, t22 = 0, sw;
    	/*
    	     初期設定とデータのチェック
    	*/
    		if ((4*count*size*(size-1)) > max_ch) {
    			System.out.print("***error  子供が多すぎる (C_sub)\n");
    			System.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 (rn.nextDouble() > kosa)
    							C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    						else {
    							// 交叉回数の制御
    							for (i3 = 0; i3 < count; i3++) {
    								// 交叉位置の決定(点の後ろで交叉)
    									// 親1の交叉位置
    								t11 = (int)(rn.nextDouble() * len[p1]);
    								if (t11 > (len[p1]-1))
    									t11 = len[p1] - 1;
    								sw = 0;
    								while (sw == 0) {
    									t12 = (int)(rn.nextDouble() * 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 M_alle(double pr)
    	{
    		int i1, i2, lid;
    	/*
    	     データのチェックと初期設定
    	*/
    		if (dup_a == 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_alle)\n");
    			System.exit(1);
    		}
    	/*
    	     実行
    	*/
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    			if (pi_w[i1] == 1) {
    				for (i2 = 0; i2 < len[i1]; i2++) {
    					if (rn.nextDouble() <= pr) {
    						lid = (int)(rn.nextDouble() * (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 M_move(double pr)
    	{
    		int i1, i2, ld, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    	/*
    	     位置の決定
    	*/
    						// p1
    				p1 = (int)(rn.nextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    						// p2
    				sw = 0;
    				while (sw == 0) {
    					p2 = (int)(rn.nextDouble() * 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 : 幅をランダム                          */
    	/********************************************************/
    	void M_inv(double pr, int wd)
    	{
    		int i1, lid, p, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    	/*
    	     区間の決定
    	*/
    				if (wd == 0) {
    					p1 = (int)(rn.nextDouble() * len[i1]);
    					if (p1 >= len[i1])
    						p1 = len[i1] - 1;
    					sw = 0;
    					while (sw == 0) {
    						p2 = (int)(rn.nextDouble() * 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)(rn.nextDouble() * 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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_scram(double pr, int wd)
    	{
    		int i1, i2, ld, p, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    	/*
    	     区間の決定
    	*/
    				if (wd == 0) {
    					p1 = (int)(rn.nextDouble() * len[i1]);
    					if (p1 >= len[i1])
    						p1 = len[i1] - 1;
    					sw = 0;
    					while (sw == 0) {
    						p2 = (int)(rn.nextDouble() * 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)(rn.nextDouble() * len[i1]);
    					p2 = p1 + wd - 1;
    					if (p2 >= len[i1])
    						p2 = len[i1] - 1;
    				}
    	/*
    	     実行
    	*/
    				for (i2 = p1; i2 <= p2; i2++) {
    					p = (int)(rn.nextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_chg(double pr, int wd)
    	{
    		int i1, i2, ld, p, p1, p2, p3 = 0, p4, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    	/*
    	     区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    	*/
    						// p1
    				p1 = (int)(rn.nextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    						// p3
    				sw = 0;
    				while (sw == 0) {
    					p3 = (int)(rn.nextDouble() * 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)(rn.nextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_dup(double pr, int wd)
    	{
    		int i1, i2, p, p1, p2, p3 = 0, p4, sw;
    	/*
    	     データのチェック
    	*/
    		if (dup_a == 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_dup)\n");
    			System.exit(1);
    		}
    	/*
    	     実行
    	*/
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    						// 区間の決定([p1,p2]を[p3,p4]にコピー)
    							// p1
    				p1 = (int)(rn.nextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    							// p3
    				sw = 0;
    				while (sw == 0) {
    					p3 = (int)(rn.nextDouble() * len[i1]);
    					if (p3 >= len[i1])
    						p3 = len[i1] - 1;
    					if (p3 != p1)
    						sw = 1;
    				}
    							// 区間を決める
    				if (p3 > p1) {
    					p4 = (wd == 0) ? (int)(rn.nextDouble() * (len[i1] - p3)) + p3 :
                                         p3 + wd - 1;
    					if (p4 >= len[i1])
    						p4 = len[i1] - 1;
    					p2 = p1 + (p4 - p3);
    				}
    				else {
    					p2 = (wd == 0) ? (int)(rn.nextDouble() * (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 : 正規分布                        */
    	/*               =1 : 一様分布                        */
    	/*      m : 平均または一様分布の下限                  */
    	/*      s : 標準偏差または一様分布の上限              */
    	/******************************************************/
    	void M_per(double pr, int method, double m, double s)
    	{
    		double w, wd = 0.0, x1;
    		int i1, i2;
    	/*
    	     データのチェックと初期設定
    	*/
    		if (dup_a == 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_per)\n");
    			System.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 (rn.nextDouble() <= pr) {
    						if (method == 0)
    							w = norm_d(m, s);
    						else {
    							w = rn.nextDouble() * wd;
    							if (rn.nextDouble() < 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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_ins(double pr, int wd)
    	{
    		int i1, i2, l, ld, p;
    	/*
    	     データのチェック
    	*/
    		if (dup_a == 0 || min_len < 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_ins)\n");
    			System.exit(1);
    		}
    	/*
    	     実行
    	*/
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    						// 挿入位置の決定
    				p = (int)(rn.nextDouble() * (len[i1]+1));
    				if (p > len[i1])
    					p = len[i1];
    						// 挿入する遺伝子長の決定
    				l = (wd == 0) ? (int)(rn.nextDouble() * (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)(rn.nextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	void M_del(double pr, int wd)
    	{
    		int i1, i2, l, max, p;
    	/*
    	     データのチェック
    	*/
    		if (dup_a == 0 || min_len < 0) {
    			System.out.print("***error  突然変異方法が不適当 (M_del)\n");
    			System.exit(1);
    		}
    	/*
    	     実行
    	*/
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
    						// 削除位置の決定
    				p = (int)(rn.nextDouble() * 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)(rn.nextDouble() * 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 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) {
    			System.out.print("***error  エリートで残す数が多すぎる (S_roul)\n");
    			System.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) {
    			System.out.print("***error  残す個体がない (S_roul)\n");
    			System.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];
    					}
    				}
    			}
    		}
    	}
    }
    
    /************************/
    /* クラスFunctionの定義 */
    /************************/
    class Function extends Species {
    
    	private double cv;   // 2進数を10進数の変換する係数
    	private int max_gen;   // 最大世代交代数
    	private int kosa_m;   // 交叉方法
                              //   =-1 : 交叉を使用しない
                              //   =0 : 親のコピー
                              //   =1 : 多点交叉
                              //   =2 : 一様交叉
                              //   =3 : 平均化交叉
    	private double kosa;   // 交叉確率
    	private int k_point;   // 交差点の数(負の時は,1から-point間のランダム)
    	private int k_vr;   // =0 : 両親とも同じ位置で交叉
                            // =1 : 両親が異なる位置で交叉(遺伝子長は可変)
    	private int k_method;   // 交叉の時の親の選択方法
                                //   =-1 : ランダム
                                //   =0 : 適応度をそのまま使用
                                //   =1 : 最小値からの差(ただし,α以下の場合はα)
                                //   =2 : 評価値に順位をつけ,減少率βで線形化
    	private double k_bias;   // α,または,method=2の場合は初期値
    	private double k_step;   // β
    	private int mute_m;   // 突然変異方法
                              //   =-1 : 突然変異を使用しない
                              //   =0 : 対立遺伝子への置換
                              //   =1 : 移動
                              //   =2 : 逆位
                              //   =3 : スクランブル
                              //   =4 : 転座
                              //   =5 : 重複
                              //   =6 : 摂動
    	private double mute;   // 突然変異率
    	private int wd;   // 突然変異に使用する部分遺伝子長
    	private double m_mean;   // 摂動の平均値
    	private double m_std;   // 摂動の標準偏差
    	private int elite;   // エリート選択で残す数
    	private int s_method;   // ルーレット板の作成方法
                                //   =0 : 適応度をそのまま使用
                                //   =1 : 最小値からの差(ただし,α以下の場合はα)
                                //   =2 : 評価値に順位をつけ,減少率βで線形化
    	private double s_bias;   // α,または,s_method=2の場合は初期値
    	private double s_step;   // β
    	private int out_d;   // 表示間隔
    	private int out_lvl;   // 出力レベル
                               //   =0 : 最終出力だけ
                               //   n>0 : n世代毎に出力(負の時はファイル)
    	private int out_m;   // 出力方法
                             //   =0 : すべてを出力
                             //   =1 : 最大適応度の個体だけを出力
    	private String o_file;   // 出力ファイル名
    
    	/***************************************/
    	/* コンストラクタ                      */
    	/*      name1 : Species定義ファイル名  */
    	/*      name2 : Function定義ファイル名 */
    	/*      seed : 乱数の初期値            */
    	/***************************************/
    	Function (String name1, String name2, int seed) throws IOException, FileNotFoundException
    	{
    		super (name1, seed);
    
    		String line;
    		StringTokenizer dt;
    		BufferedReader in = new BufferedReader(new FileReader(name2));
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		out_lvl = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		out_m = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		o_file = dt.nextToken();
    		dt.nextToken();
    		out_d = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		kosa_m = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		kosa = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		k_point = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		k_vr = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		k_method = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		k_bias = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		k_step = Double.parseDouble(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		mute_m = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		mute = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		wd = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		m_mean = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		m_std = Double.parseDouble(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		elite = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		s_method = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		s_bias = Double.parseDouble(dt.nextToken());
    		dt.nextToken();
    		s_step = Double.parseDouble(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		max_gen = Integer.parseInt(dt.nextToken());
    
    		cv = 1.0 / (Math.pow(2.0, (double)max_len) - 1.0);
    
    		in.close();
    	}
    
    	/**************/
    	/* 全体の制御 */
    	/**************/
    	void Control() throws IOException, FileNotFoundException
    	{
    		int gen = 1, k1;
    						// 初期集団の発生
    		Init_std();
    						// 評価
    		Adap();
    						// 出力
    		System.out.println("***世代 " + gen + " 適応度 max " + max +
                               " (" + max_n + ") mean " + mean);
    
    		if (Math.abs(out_lvl) > 0)
    			Output(gen);
    						// 世代交代
    		for (gen = 2; gen <= max_gen; gen++) {
    							// 交叉
    			switch (kosa_m) {
    				case -1:
    					break;
    				case 0:
    					C_copy(2, max_ch/2, k_method, k_bias, k_step);   // 親のコピー
    					break;
    				case 1:
    					C_point(kosa, k_point, k_vr, k_method, k_bias, k_step);   // 多点交叉
    					break;
    				case 2:
    					C_uniform(kosa, k_method, k_bias, k_step);   // 一様交叉
    					break;
    				case 3:
    					C_mean(kosa, k_method, k_bias, k_step);   // 平均化交叉
    					break;
    				default:
    					break;
    			}
    							// 突然変異
    			switch (mute_m) {
    				case -1:
    					break;
    				case 0:
    					M_alle(mute);   // 対立遺伝子への置換
    					break;
    				case 1:
    					M_move(mute);   // 移動
    					break;
    				case 2:
    					M_inv(mute, wd);   // 逆位
    					break;
    				case 3:
    					M_scram(mute, wd);   // スクランブル
    					break;
    				case 4:
    					M_chg(mute, wd);   // 転座
    					break;
    				case 5:
    					M_dup(mute, wd);   // 重複
    					break;
    				case 6:
    					M_per(mute, wd, m_mean, m_std);   // 摂動
    					break;
    				default:
    					break;
    			}
    							// 適応度
    			Adap();
    							// 淘汰
    			S_roul(elite, s_method, s_bias, s_step);
    							// 出力
    			if (gen%out_d == 0)
    				System.out.println("***世代 " + gen + " 適応度 max " + max +
                                       " (" + max_n + ") mean " + mean);
    
    			if (Math.abs(out_lvl) > 0) {
    				if (gen%Math.abs(out_lvl) == 0)
    					Output(gen);
    			}
    		}
    
    		gen--;
    		k1    = out_m;
    		out_m = 0;
    		System.out.println("***世代 " + gen + " 適応度 max " + max +
                               " (" + max_n + ") mean " + mean);
    		Output(gen);
    		out_m = k1;
    	}
    
    	/****************/
    	/* 適応度の計算 */
    	/****************/
    	void Adap()
    	{
    		double x, y;
    		int i1, i2, n = 0;
    
    		max   = 0.0;
    		max_n = -1;
    		mean  = 0.0;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1) {
    				x = 0.0;
    				y = 0.0;
    				for (i2 = len[i1]-1; i2 >= 0; i2--) {
    					if (ind[i1][i2] > 0)
    						x += Math.pow(2.0, y);
    					y += 1.0;
    				}
    				x        *= cv;
    				pi[i1]    = Math.sin(3.0*x) + 0.5 * Math.sin(9.0*x) +
                                Math.sin(15.0*x+50.0);
    				pi_w[i1]  = 2;
    			}
    
    			if (pi_w[i1] > 0) {
    				mean += pi[i1];
    				n++;
    				if (max_n < 0 || pi[i1] > max) {
    					max   = pi[i1];
    					max_n = i1;
    				}
    			}
    		}
    
    		mean /= n;
    	}
    
    	/*****************************/
    	/* 結果の出力                */
    	/*      gen : 現在の世代番号 */
    	/*****************************/
    	void Output(int gen) throws IOException, FileNotFoundException
    	{
    		double x, y;
    		int i1, i2, k = 0, pr;
    		String now;
    		PrintStream out = null;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    		if (out_lvl >= 0) {
    			System.out.print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = Integer.parseInt(in.readLine());
    		}
    		else
    			pr = -1;
    
    		if (pr != 0) {
    						// 出力先の決定と評価値の出力
    			if (pr > 0)
    				out = System.out;
    			else {
    				Date newtime = new Date();   // 現在時刻の獲得
    				now = newtime.toString();    // 文字列への変換
    				out = new PrintStream(new FileOutputStream(o_file, true));
    				out.println("***世代 " + gen + " 適応度 max " + max +
                                " (" + max_n + ") mean " + mean + " 時間 " + now);
    			}
    						// 詳細出力
    			for (i1 = 0; i1 < size+max_ch; i1++) {
    				if ((pi_w[i1] > 1) && (out_m ==0 || out_m == 1 && i1 == max_n)) {
    					out.print(i1 + " allele");
    					for (i2 = 0; i2 < len[i1]; i2++)
    						out.print(" " + ind[i1][i2]);
    					x = 0.0;
    					y = 0.0;
    					for (i2 = len[i1]-1; i2 >= 0; i2--) {
    						if (ind[i1][i2] > 0)
    							x += Math.pow(2.0, y);
    						y += 1.0;
    					}
    					x *= cv;
    					out.println(" x " + x + " y " + pi[i1]);
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							in.readLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			if (pr < 0)
    				out.close();
    		}
    	}
    }
    
    public class Test_f {
    
    	/****************/
    	/* main program */
    	/****************/
    	public static void main(String args[]) throws IOException, FileNotFoundException
    	{
    		int i1, n;
    		String i_file1[], i_file2[], line;
    		Function fn;
    		StringTokenizer dt;
    		BufferedReader in = new BufferedReader(new FileReader(args[0]));
    						// 入力ミス
    		if (args.length == 0) {
    			System.out.print("***error  ファイル名を入力して下さい\n");
    			System.exit(1);
    		}
    						// 入力OK
    		else {
    							// 入力データファイル名の入力
    			n      = Integer.parseInt(in.readLine());
    
    			i_file1 = new String [n];
    			i_file2 = new String [n];
    
    			for (i1 = 0; i1 < n; i1++) {
    				line = in.readLine();
    				dt   = new StringTokenizer(line, " ");
    				i_file1[i1] = dt.nextToken();
    				i_file2[i1] = dt.nextToken();
    			}
    
    			in.close();
    							// 実行(乱数の初期値を変える)
    			for (i1 = 0; i1 < n; i1++) {
    				System.out.print("\n+++++ケース " + (i1+1) + "+++++\n");
    								// 入力と初期設定
    				fn = new Function (i_file1[i1], i_file2[i1], 1000 * i1 + 1234567);
    								// 最適化
    				fn.Control();
    			}
    		}
    	}
    }
    
    //------------------ケーススタディデータ(data_cf.txt)------
    /*
    3
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    */
    
    //------------------Species記述データ(data1_f.txt)---------
    /*
    対立遺伝子上限 1 対立遺伝子下限 0
    最大遺伝子長 15 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 1 個体の重複(同じ染色体の個体) 0
    集団サイズ 20 子供 20
    */
    
    //------------------Function記述データ(data2_f.txt)--------
    /*
    出力レベル(負はファイル) 20 出力方法(0:すべて,1:最大) 0
    出力ファイル名 out1.txt 表示間隔 1
    交叉方法 1 交叉確率 1.0 点 2 位置 0 方法 1 バイアス 0 ステップ 1
    突然変異方法 0 突然変異率 0.05 幅 1 平均 0.0 標準偏差 1.0
    エリート 2 方法 1 バイアス 0 ステップ 1
    最大世代交代数 200
    */
    			

  3. PHP

    TSP
    <?php
    
    /***********************************/
    /* 遺伝的アルゴリズムによるTSPの解 */
    /*      coded by Y.Suganuma        */
    /***********************************/
    
    /***********************/
    /* クラスSpeciesの定義 */
    /***********************/
    
    class Species {
    
    	protected $max;   // 最大適応度
    	protected $mean;   // 平均適応度
    	protected $pi;   // 適応度
    	protected $ro;   // ルーレット板
    	protected $allele_u;   // 対立遺伝子上限
    	protected $allele_l;   // 対立遺伝子下限
    	protected $size;   // 個体総数
    	protected $max_ch;   // 子供の数の最大値
    	protected $max_len;   // 最大遺伝子長
    	protected $min_len;   // 最小遺伝子長(負の時は,最大遺伝子長で固定)
    	protected $max_n;   // 最大適応度の個体番号
    	protected $dup_a;   // 遺伝子の重複
                            //   =0 : 重複を許さない
                            //   =1 : 重複を許す
    	protected $dup_s;   // 個体の重複(同じ染色体の個体)
                            //   =0 : 重複を許さない
                            //   =1 : 重複を許す
    	protected $ind;   // 集団(個体の集まり)
    	protected $len;   // 各個体の遺伝子長
    	protected $kou1;   // 交叉・突然変異用作業場所1
    	protected $kou2;   // 交叉・突然変異用作業場所2
    	protected $s_w;   // 淘汰用指標(選択された回数)
    	protected $edge;   // エッジ組み替え交叉用ワークエリア
    	protected $pi_w;   // 適応度計算指標
                           //   =0 : 未使用
                           //   =1 : 適応度計算前(突然変異はこの個体だけに適用)
                           //   =2 : 適応度計算済み(交叉時に親とみなす)
    
    	/****************************/
    	/* コンストラクタ           */
    	/*      name : ファイル名   */
    	/*      seed : 乱数の初期値 */
    	/****************************/
    	function Species($name, $seed)
    	{
    	/*
    	     データの入力
    	*/
    		$in = fopen($name, "rb");
    	
    		fscanf($in, "%*s %d %*s %d", $this->allele_u, $this->allele_l);
    		fscanf($in, "%*s %d %*s %d", $this->max_len, $this->min_len);
        	fscanf($in, "%*s %d %*s %d", $this->dup_a, $this->dup_s);
        	fscanf($in, "%*s %d %*s %d", $this->size, $this->max_ch);
    	/*
             データのチェック
        */
    		if ($this->size <= 0)
    			exit("***error  個体総数≦0 (Constructor)\n");
    	
    		if ($this->max_ch < 0)
    			exit("***error  子供の数<0 (Constructor)\n");
        
    		if ($this->max_len <= 0 || $this->min_len == 0)
    			exit("***error  遺伝子長≦0 (Constructor)\n");
    	
    		if ($this->max_len < $this->min_len)
    			exit("***error  最大遺伝子長<最小遺伝子長 (Constructor)\n");
    	
    		if ($this->allele_u <= $this->allele_l)
    			exit("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)\n");
        
        	$kind = $this->allele_u - $this->allele_l + 1;
    		if ($this->dup_a == 0 && $this->max_len > $kind)
        		exit("***error  遺伝子の重複を防ぐことはできない (Constructor)\n");
    	/*
    	     領域の確保
    	*/
    		$num = $this->size + $this->max_ch;
    	
    		$this->ind = array($num);
        	for ($i1 = 0; $i1 < $num; $i1++)
        		$this->ind[$i1] = array($this->max_len);
        
    		$this->edge = array($this->max_len);
    		for ($i1 = 0; $i1 < $this->max_len; $i1++)
    			$this->edge[$i1] = array(5);
    	
    		$this->pi   = array($num);
    		$this->ro   = array($num);
    		$this->len  = array($num);
    		$this->kou1 = array($this->max_len);
    		$this->kou2 = array($this->max_len);
    		$this->s_w  = array($num);
    		$this->pi_w = array($num);
    	/*
    	     乱数の初期設定
    	*/
        	mt_srand($seed);
        }
    	
        /**************************************************/
        /* 場所を探す                                     */
    	/*      n : >=0 : n番目の親を捜す                 */
    	/*          -1 : 空いている場所を探す             */
    	/*      return : 親の場所,または,空いている場所 */
    	/*               (存在しないときは負の値)       */
    	/**************************************************/
    	function Position($n)
    	{
        	$k  = -1;
        	$sw = 0;
        /*
    	     空いている場所を探す
    	*/
    		if ($n < 0) {
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch && $k < 0; $i1++) {
    				if ($this->pi_w[$i1] == 0)
    					$k = $i1;
    			}
    			if ($k < 0)
    				exit("***error  空いている場所がない --Position--\n");
    		}
    	/*
    	     n番目の親($this->pi_w[i]=2)を捜す
        */
        	else {
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch && $sw == 0; $i1++) {
        			if ($this->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 : 個体番号                                          */
    	/*******************************************************************/
    	function Select($method = -1, $bias = 0.0, $step = 1.0)
    	{
        	$sum = 0.0;
        					// ルーレット板の用意
    		switch ($method) {
        						// ランダム
        		case -1:
    				$n = 0;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1)
    						$n++;
    				}
    				$sum = 1.0 / $n;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        				if ($this->pi_w[$i1] > 1)
        					$this->ro[$i1] = $sum;
        			}
    				break;
    							// 評価値をそのまま利用
    			case 0:
    				$n = 0;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1) {
    						$sum += $this->pi[$i1];
    						$n++;
    					}
    				}
    				if (abs($sum) > 1.0e-10) {
    					$sum = 1.0 / abs($sum);
    					for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    						if ($this->pi_w[$i1] > 1)
        						$this->ro[$i1] = $this->pi[$i1] * $sum;
        				}
    				}
        			else {
        				$sum = 1.0 / $n;
    					for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    						if ($this->pi_w[$i1] > 1)
    							$this->ro[$i1] = $sum;
    					}
    				}
    				break;
    							// 最小値からの差
        		case 1:
        			$min = -1;
        			$n   = 0;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1) {
    						$n++;
    						if ($min < 0 || $this->pi[$i1] < $this->pi[$min])
    							$min = $i1;
    					}
    				}
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1) {
    						$this->ro[$i1] = $this->pi[$i1] - $this->pi[$min];
    						if ($this->ro[$i1] < $bias)
    							$this->ro[$i1] = $bias;
    						$sum += $this->ro[$i1];
    					}
        			}
        			if ($sum > 1.0e-10) {
    					$sum = 1.0 / $sum;
        				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        					if ($this->pi_w[$i1] > 1)
    							$this->ro[$i1] *= $sum;
    					}
    				}
    				else {
    					$sum = 1.0 / $n;
    					for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    						if ($this->pi_w[$i1] > 1)
        						$this->ro[$i1] = $sum;
        				}
        			}
    				break;
    							// 線形化
    			case 2:
    				$n = 0;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1) {
    						$this->ro[$i1] = -1.0;
    						$n++;
    					}
    					else
    						$this->ro[$i1] = 1.0;
    				}
    				$sw  = 0;
    				$sum = $bias;
        			while ($sw == 0) {
        				$min = -1;
    					for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        					if ($this->ro[$i1] < 0.0 && ($min < 0 || $this->pi[$i1] < $this->pi[$min]))
        						$min = $i1;
    					}
    					if ($min < 0)
    						$sw = 1;
    					else {
    						$this->ro[$min]  = $sum;
    						$sum     += $step;
    					}
        			}
        			$sum = 1.0 / (0.5 * (2.0 * $bias + $step * ($n - 1)) * $n);
        			for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1)
    						$this->ro[$i1] *= $sum;
    				}
    				break;
    		}
    	
    		$sum = 0.0;
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($this->pi_w[$i1] > 1) {
    				$sum           += $this->ro[$i1];
    				$this->ro[$i1]  = $sum;
    			}
    		}
    						// 選択
        	$x  = uniform();
        	$sw = 0;
    		$k  = 0;
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch && $sw == 0; $i1++) {
        		if ($this->pi_w[$i1] > 1) {
    				if ($x <= $this->ro[$i1]) {
    					$sw = 1;
    					$k  = $i1;
    				}
    			}
    		}
    	
        	return $k;
        }
        
    	/********************/
    	/* 標準的な初期設定 */
    	/********************/
    	function Init_std()
    	{
    	/*
    	     初期設定
    	*/
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($i1 < $this->size)
    				$this->pi_w[$i1] = 1;   // 適応度の計算前
    			else
    				$this->pi_w[$i1] = 0;   // 未使用
    		}
        /*
             遺伝子の決定
    	*/
        	for ($i1 = 0; $i1 < $this->size; $i1++) {
        
    			$sw1 = 0;
    	
    			while ($sw1 == 0) {
    						// 遺伝子長の決定
    				if ($this->min_len < 0)
    					$length = $this->max_len;
    				else {
        				$length = intval(uniform() * ($this->max_len - $this->min_len + 1) + $this->min_len);
        				if ($length > $this->max_len)
        					$length = $this->max_len;
    				}
    				$this->len[$i1] = $length;
    						// 遺伝子の決定
    				for ($i2 = 0; $i2 < $length; $i2++) {
    					$sw2 = 0;
    					while ($sw2 == 0) {
    						$lid = intval(uniform() * ($this->allele_u - $this->allele_l + 1) + $this->allele_l);
    						if ($lid > $this->allele_u)
    							$lid = $this->allele_u;
    						$this->ind[$i1][$i2] = $lid;
    							// 重複遺伝子のチェック
    						$sw2 = 1;
    						if ($this->dup_a == 0) {
    							for ($i3 = 0; $i3 < $i2 && $sw2 > 0; $i3++) {
        							if ($lid == $this->ind[$i1][$i3])
        								$sw2 = 0;
    							}
        					}
        				}
    				}
    						// 重複個体のチェック
    				$sw1 = 1;
    				if ($this->dup_s == 0) {
    					for ($i2 = 0; $i2 < $i1 && $sw1 > 0; $i2++) {
    						if ($this->len[$i1] == $this->len[$i2]) {
    							$sw2 = 0;
        						for ($i3 = 0; $i3 < $this->len[$i1] && $sw2 == 0; $i3++) {
        							if ($this->ind[$i1][$i3] != $this->ind[$i2][$i3])
        								$sw2 = 1;
    							}
    							if ($sw2 == 0)
    								$sw1 = 0;
    						}
    					}
    				}
    			}
    		}
    	}
    	
    	/****************************************************/
    	/* 標準的な出力                                     */
    	/*      sw : 出力レベル                             */
    	/*             =0 : 最終出力だけ                    */
        /*             n>0 : n世代毎に出力(負はファイル) */
        /*      out_m : 出力方法                            */
    	/*                =0 : すべての個体を出力           */
        /*                =1 : 最大適応度の個体だけを出力   */
        /*      gen : 現在の世代番号                        */
    	/*      name : 出力ファイル名                       */
    	/****************************************************/
    	function Out_std($sw, $out_m, $gen, $name)
    	{
    		$k = 0;
    	
    		if ($sw >= 0) {
        		printf("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
        		fscanf(STDIN, "%d", $pr);
        	}
    		else
    			$pr = -1;
    	
    		if ($pr != 0) {
    						// 出力先の決定と評価値の出力
    			if ($pr > 0) {
    				$out = STDOUT;
    				fgets(STDIN);
    			}
    			else {
    				$x   = getdate();
    				$now = $x["hours"]."時".$x["minutes"]."分".$x["seconds"]."秒";
    				$out = fopen($name, "ab");
    				fwrite($out, "***世代 ".$gen." 適応度 max ".$this->max." (".$this->max_n.") mean ".$this->mean." 時間 ".$now."\n");
        		}
    						// 詳細出力
        		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        			if (($this->pi_w[$i1] > 1) && ($out_m == 0 || $out_m == 1 && $i1 == $this->max_n)) {
    					$str = $i1." allele";
    					for ($i2 = 0; $i2 < $this->len[$i1]; $i2++)
    						$str += " ".$this->ind[$i1][$i2];
    					$str += " value ".$this->pi[$i1];
    					fwrite($out, $str."\n");
    					if ($pr > 0) {
    						$k++;
    						if ($k == $pr) {
        						fgets(STDIN);
        						$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)                                     */
    	/*******************************************************************/
    	function C_copy($method = 2, $pair = 0, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    	/*
             初期設定とデータチェック
        */
        	if ($method != 1)
    			$method = 2;
    	
    		if ($pair <= 0)
    			$pair = ($method==2) ? intval($this->max_ch/2) : $this->max_ch;
    		else {
    			if ($method == 2 && 2*$pair > $this->max_ch || $method == 1 && $pair > $this->max_ch)
    				exit("***error  子供が多すぎる (C_copy)\n");
    		}
    	/*
    	     実行
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
        					// 親の選択
        		$p1 = $this->Select($k_method, $k_bias, $k_step);
    			$sw = 0;
        
        		while ($sw == 0) {
    				$p2 = $this->Select($k_method, $k_bias, $k_step);
    				if ($p1 != $p2)
    					$sw = 1;
    			}
    						// コピー
    			for ($i2 = 0; $i2 < $method; $i2++) {
    				$p       = ($i2 == 0) ? $p1 : $p2;
        			$k       = $this->Position(-1);
        			$this->len[$k]  = $this->len[$p];
        			$this->pi_w[$k] = 1;
    				for ($i3 = 0; $i3 < $this->len[$k]; $i3++)
    					$this->ind[$k][$i3] = $this->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)                                     */
    	/*******************************************************************/
    	function C_point($kosa, $k_point = 1, $k_vr = 0, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    		$mn = 0;
    	/*
    	     初期設定とデータのチェック
        */
        	$pair = $this->max_ch / 2;
        
    		if ($this->dup_a == 0)
    			exit("***error  交叉方法が不適当 (C_point)\n");
    	
    		$abs_p = abs($k_point);
    		if ($abs_p == 0 || $abs_p > $this->max_len-1 || $this->min_len > 0 && $abs_p > $this->min_len-1)
    			exit("***error  交叉点の数が不適当 (C_point)\n");
    	
    		if ($k_vr > 0 && $this->min_len < 0)
    			exit("***error  遺伝子長は可変でなければならない (C_point)\n");
        /*
    	     交叉
        */
        	$num = $k_point;
    	
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
        						// 親の選択
        			$p1 = $this->Select($k_method, $k_bias, $k_step);
        			$sw = 0;
    				while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
    					if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 交叉位置の数の決定
    				if ($k_point < 0) {
    					$num = intval(uniform() * $abs_p + 1);
    					if ($num > $abs_p)
    						$num = $abs_p;
    				}
    							// 交叉位置の決定(点の後ろで交叉)
    				for ($i2 = 0; $i2 < $num; $i2++) {
    								// 親1の交叉位置
        				$sw = 0;
        				while ($sw == 0) {
    						$sw              = 1;
        					$this->kou1[$i2] = intval(uniform() * ($this->len[$p1] - 1));
        					if ($this->kou1[$i2] > $this->len[$p1]-2)
    							$this->kou1[$i2] = $this->len[$p1] - 2;
    						if ($k_vr == 0 && $this->kou1[$i2] > $this->len[$p2]-2)
    							$this->kou1[$i2] = $this->len[$p2] - 2;
    						for ($i3 = 0; $i3 < $i2 && $sw > 0; $i3++) {
    							if ($this->kou1[$i3] == $this->kou1[$i2])
    								$sw = 0;
    						}
        				}
        							// 親2の交叉位置
        				if ($k_vr > 0) {
    						$sw = 0;
    						while ($sw == 0) {
    							$sw              = 1;
    							$this->kou2[$i2] = intval(uniform() * ($this->len[$p2] - 1));
    							if ($this->kou2[$i2] > $this->len[$p2]-2)
    								$this->kou2[$i2] = $this->len[$p2] - 2;
    							for ($i3 = 0; $i3 < $i2 && $sw > 0; $i3++) {
    								if ($this->kou2[$i3] == $this->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              = $this->Position(-1);
        			$this->pi_w[$k1] = 1;
        			$this->len[$k1]  = $this->len[$p1];
        			$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    	
    				for ($i2 = 0; $i2 < $num+1; $i2++ ) {
    								// 次の交叉位置を求める
    					if ($i2 == $num) {            // 最後
    						$t12 = $this->len[$p1];
    						$t22 = $this->len[$p2];
    					}
    					else {
    									// 親1
    						$t12 = $this->max_len;
    						for ($i3 = 0; $i3 < $num; $i3++) {
    							if ($this->kou1[$i3] >= 0 && $this->kou1[$i3] <= $t12) {
        							$t12 = $this->kou1[$i3];
        							$mn  = $i3;
    							}
        					}
        					$this->kou1[$mn] = -1;
    						$t12++;
    									// 親2
    						if ($k_vr == 0)
    							$t22 = $t12;
    						else {
    							$t22 = $this->max_len;
    							for ($i3 = 0; $i3 < $num; $i3++) {
        							if ($this->kou2[$i3] >= 0 && $this->kou2[$i3] <= $t22) {
        								$t22 = $this->kou2[$i3];
        								$mn  = $i3;
    								}
    							}
    							$this->kou2[$mn] = -1;
    							$t22++;
    						}
    					}
    								// 指定箇所のコピー
    					for ($i3 = $t11; $i3 < $t12; $i3++) {
    						if ($i2%2 == 0) {
    							if ($c1 < $this->max_len) {
    								$this->ind[$k1][$c1] = $this->ind[$p1][$i3];
    								$c1++;
    							}
    						}
        					else {
        						if ($c2 < $this->max_len) {
    								$this->ind[$k2][$c2] = $this->ind[$p1][$i3];
        							$c2++;
        						}
    						}
    					}
    	
    					for ($i3 = $t21; $i3 < $t22; $i3++) {
    						if ($i2%2 == 0) {
    							if ($c2 < $this->max_len) {
    								$this->ind[$k2][$c2] = $this->ind[$p2][$i3];
        							$c2++;
        						}
        					}
    						else {
    							if ($c1 < $this->max_len) {
    								$this->ind[$k1][$c1] = $this->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)                                     */
        /*******************************************************************/
        function C_uniform($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
        {
    	/*
    	     初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a == 0)
    			exit("***error  交叉方法が不適当 (C_uniform)\n");
    	
    		if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_uniform)\n");
        /*
             交叉
    	*/
        	for ($i1 = 0; $i1 < $pair; $i1++) {
        					// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
        			while ($sw == 0) {
        				$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
    				$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    							// 交叉
    				for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					if (uniform() > 0.5) {
    						$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    						$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
        				}
        				else {
    						$this->ind[$k1][$i2] = $this->ind[$p2][$i2];
        					$this->ind[$k2][$i2] = $this->ind[$p1][$i2];
        				}
    				}
    			}
    		}
    	}
    	
    	/*******************************************************************/
    	/* 交叉(平均化交叉.2つの親の平均値を受け継ぐ)                  */
        /*      kosa : 交叉確率                                            */
        /*      k_method : 選択方法                                        */
        /*                 =-1 : ランダム(default)                         */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
    	/*      k_step : β(default=1)                                     */
    	/*******************************************************************/
    	function C_mean($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    	/*
    	     初期設定とデータのチェック
    	*/
    		if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_mean)\n");
        /*
    	     交叉
        */
        	for ($i1 = 0; $i1 < $this->max_ch; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(1, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
        			$sw = 0;
        			while ($sw == 0) {
        				$p2 = $this->Select($k_method, $k_bias, $k_step);
    					if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 遺伝子長
    				$k             = $this->Position(-1);
    				$this->len[$k]  = $this->len[$p1];
    				$this->pi_w[$k] = 1;
    							// 交叉
    				for ($i2 = 0; $i2 < $this->len[$k]; $i2++)
    					$this->ind[$k][$i2] = ($this->ind[$p1][$i2] + $this->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)                                     */
    	/*******************************************************************/
    	function C_cycle($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    	/*
    	     初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_cycle)\n");
    	
        	if ($this->min_len > 0)
        		exit("***error  遺伝子長は固定長でなければならない (C_cycle)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
        		if (uniform() > $kosa)
        			$this->C_copy(2, 1);
        					// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
    					if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 初期設定
    				for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					$this->kou1[$i2] = 0;
    					$this->kou2[$i2] = 0;
    				}
        						// 遺伝子長
        			$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
        			$this->len[$k1]  = $this->len[$p1];
        			$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    							// 交叉
    				$sw = 0;
    	
    				while ($sw == 0) {
    					$sw = 1;
        				$p  = intval(uniform() * $this->len[$p1]);
        				if ($p >= $this->len[$p1])
        					$p = $this->len[$p1] - 1;
    					if ($this->kou1[$p] == 0 && $this->kou2[$p] == 0) {
    						$this->kou1[$p]     = 1;
    						$this->kou2[$p]     = 1;
    						$this->ind[$k1][$p] = $this->ind[$p1][$p];
    						$this->ind[$k2][$p] = $this->ind[$p2][$p];
    						for ($i2 = 0; $i2 < $this->len[$p1] && $sw > 0; $i2++) {
    							if ($this->ind[$p2][$p] == $this->ind[$p1][$i2]) {
    								$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    								$this->kou1[$i2]     = 1;
    								$sw                  = 0;
    							}
    						}
    						$sw = 1;
    						for ($i2 = 0; $i2 < $this->len[$p2] && $sw > 0; $i2++) {
        						if ($this->ind[$p1][$p] == $this->ind[$p2][$i2]) {
        							$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
    								$this->kou2[$i2]     = 1;
        							$sw                  = 0;
        						}
    						}
    					}
    				}
    	
    				$sw = 0;
    				$i2 = 0;
    				$i3 = 0;
        			while ($sw == 0) {
        				while ($sw == 0 && $i2 < $this->len[$p1]) {
        					if ($this->kou1[$i2] == 0)
    							$sw = 1;
    						else
    							$i2++;
    					}
    					$sw = 0;
    					while ($sw == 0 && $i3 < $this->len[$p2]) {
    						if ($this->kou2[$i3] == 0)
    							$sw = 1;
    						else
    							$i3++;
    					}
    					if ($i2 < $this->len[$p1] && $i3 < $this->len[$p2]) {
    						$this->ind[$k1][$i2] = $this->ind[$p2][$i3];
    						$this->ind[$k2][$i3] = $this->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)                                     */
    	/*******************************************************************/
    	function C_part($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
        {
    	/*
             初期設定とデータのチェック
        */
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_part)\n");
    	
        	if ($this->min_len > 0)
        		exit("***error  遺伝子長は固定長でなければならない (C_part)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
        				$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
    						$sw = 1;
        			}
        						// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
    				$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    							// 交叉
        			$p = intval(uniform() * $this->len[$p1]);
        			if ($p >= $this->len[$p1])
        				$p = $this->len[$p1] - 1;
    	
    				for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    					$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
    				}
    	
    				for ($i2 = $p; $i2 < $this->len[$p1]; $i2++) {
    					$sw = 0;
    					$lv = $this->ind[$k1][$i2];
    					for ($i3 = 0; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    						if ($this->ind[$k2][$i2] == $this->ind[$k1][$i3]) {
    							$this->ind[$k1][$i2] = $this->ind[$k1][$i3];
    							$this->ind[$k1][$i3] = $lv;
    							$sw                  = 1;
        					}
        				}
    					$sw = 0;
        				for ($i3 = 0; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
        					if ($lv == $this->ind[$k2][$i3]) {
    							$this->ind[$k2][$i3] = $this->ind[$k2][$i2];
    							$this->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)                                     */
        /*******************************************************************/
    	function C_seq($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
        {
        /*
    	     初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_seq)\n");
        
        	if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_seq)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
        			$sw = 0;
        			while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
        					$sw = 1;
    				}
    							// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
    				$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
        			$this->len[$k2]  = $this->len[$p2];
        						// 交叉
        			$p = intval(uniform() * ($this->len[$p1] - 1));
    				if ($p >= $this->len[$p1]-1)
    					$p = $this->len[$p1] - 2;
    	
    				for ($i2 = 0; $i2 <= $p; $i2++) {
    					$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    					$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
    				}
    	
    				$pp = 0;
    				for ($i2 = $p+1; $i2 < $this->len[$p1]; $i2++) {
    					$sw = 0;
    					for ($i3 = $pp; $i3 < $this->len[$p2] && $sw == 0; $i3++) {
    						for ($i4 = $p+1; $i4 < $this->len[$p1] && $sw == 0; $i4++) {
    							if ($this->ind[$p2][$i3] == $this->ind[$p1][$i4]) {
        							$sw                  = 1;
        							$pp                  = $i3 + 1;
    								$this->ind[$k1][$i2] = $this->ind[$p1][$i4];
        						}
        					}
    					}
    				}
    				$pp = 0;
    				for ($i2 = $p+1; $i2 < $this->len[$p2]; $i2++) {
    					$sw = 0;
    					for ($i3 = $pp; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    						for ($i4 = $p+1; $i4 < $this->len[$p2] && $sw == 0; $i4++) {
        						if ($this->ind[$p1][$i3] == $this->ind[$p2][$i4]) {
        							$sw                  = 1;
        							$pp                  = $i3 + 1;
    								$this->ind[$k2][$i2] = $this->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)                                     */
    	/*******************************************************************/
    	function C_useq($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
        {
        /*
             初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_useq)\n");
    	
    		if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_useq)\n");
    	/*
    	     交叉
        */
        	for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
        		if (uniform() > $kosa)
        			$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
        					$sw = 1;
        			}
    							// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
    				$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    							// 交叉
    				for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    					$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
    					$this->kou1[$i2]     = (uniform() < 0.5) ? 0 : 1;
    				}
    	
        			$p = 0;
        			for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					if ($this->kou1[$i2] > 0) {
        					$sw = 0;
        					for ($i3 = $p; $i3 < $this->len[$p2] && $sw == 0; $i3++) {
    							for ($i4 = 0; $i4 < $this->len[$p1] && $sw == 0; $i4++) {
    								if ($this->ind[$p2][$i3] == $this->ind[$p1][$i4] && $this->kou1[$i4] > 0) {
    									$sw                  = 1;
    									$p                   = $i3 + 1;
    									$this->ind[$k1][$i2] = $this->ind[$p1][$i4];
    								}
    							}
        					}
        				}
        			}
    				$p = 0;
    				for ($i2 = 0; $i2 < $this->len[$p2]; $i2++) {
    					if ($this->kou1[$i2] > 0) {
    						$sw = 0;
    						for ($i3 = $p; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    							for ($i4 = 0; $i4 < $this->len[$p2] && $sw == 0; $i4++) {
    								if ($this->ind[$p1][$i3] == $this->ind[$p2][$i4] && $this->kou1[$i4] > 0) {
    									$sw                  = 1;
    									$p                   = $i3 + 1;
    									$this->ind[$k2][$i2] = $this->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)                                     */
    	/*******************************************************************/
    	function C_upos($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    	/*
    	     初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
        		exit("***error  交叉方法が不適当 (C_upos)\n");
        
        	if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_upos)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
        					// 交叉しない場合
        		if (uniform() > $kosa)
        			$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
    					if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
        			$k2              = $this->Position(-1);
        			$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
        						// 交叉
        			for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					$this->kou1[$i2] = (uniform() < 0.5) ? 0 : 1;
    					if ($this->kou1[$i2] > 0) {
    						$this->ind[$k1][$i2] = $this->ind[$p2][$i2];
    						$this->ind[$k2][$i2] = $this->ind[$p1][$i2];
    					}
    				}
    	
        			$p = 0;
        			for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
        				$sw = 0;
    					for ($i3 = 0; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    						if ($this->kou1[$i3] > 0 && $this->ind[$p1][$i2] == $this->ind[$k1][$i3])
    							$sw = 1;
    					}
    					if ($sw == 0) {
    						for ($i3 = $p; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    							if ($this->kou1[$i3] == 0) {
    								$this->ind[$k1][$i3] = $this->ind[$p1][$i2];
    								$p                   = $i3 + 1;
    								$sw                  = 1;
    							}
    						}
    					}
    				}
        			$p = 0;
        			for ($i2 = 0; $i2 < $this->len[$p2]; $i2++) {
    					$sw = 0;
        				for ($i3 = 0; $i3 < $this->len[$p2] && $sw == 0; $i3++) {
        					if ($this->kou1[$i3] > 0 && $this->ind[$p2][$i2] == $this->ind[$k2][$i3])
    							$sw = 1;
    					}
    					if ($sw == 0) {
    						for ($i3 = $p; $i3 < $this->len[$p2] && $sw == 0; $i3++) {
    							if ($this->kou1[$i3] == 0) {
    								$this->ind[$k2][$i3] = $this->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)                                     */
    	/*******************************************************************/
    	function C_edge($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
        	$e  = array(2);
        	$k0 = 0;
    	/*
             初期設定とデータのチェック
        */
    		$pair = $this->max_ch;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_edge)\n");
    	
        	if ($this->min_len > 0)
        		exit("***error  遺伝子長は固定長でなければならない (C_edge)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(1, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
        				$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
    						$sw = 1;
        			}
        						// 遺伝子長
    				$k              = $this->Position(-1);
    				$this->pi_w[$k] = 1;
    				$this->len[$k]  = $this->len[$p1];
    							// エッジマップの初期化
    				for ($i2 = 0; $i2 < $this->len[$k]; $i2++) {
    					$this->edge[$i2][0] = 0;
    					for ($i3 = 1; $i3 <= 4; $i3++)
        					$this->edge[$i2][$i3] = -1;
        			}
        						// 交叉
    								// エッジマップの作成
    				for ($i2 = 0; $i2 < $this->len[$k]; $i2++) {
    	
    					$sw = 0;
    					for ($i3 = 0; $i3 < $this->len[$k] && $sw == 0; $i3++) {
    						if ($i2 == $this->ind[$p1][$i3]) {
    							$sw = 1;
    							if ($i3 == 0) {
    								$e[0] = $this->ind[$p1][$this->len[$k]-1];
    								$e[1] = $this->ind[$p1][1];
    							}
    							else {
    								if ($i3 == $this->len[$k]-1) {
    									$e[0] = $this->ind[$p1][$i3-1];
        								$e[1] = $this->ind[$p1][0];
        							}
    								else {
        								$e[0] = $this->ind[$p1][$i3-1];
        								$e[1] = $this->ind[$p1][$i3+1];
    								}
    							}
    							for ($i4 = 0; $i4 < 2; $i4++) {
    								$this->edge[$i2][0]++;
    								$this->edge[$i2][$this->edge[$i2][0]] = $e[$i4];
    							}
    						}
        				}
        
        				$sw = 0;
    					for ($i3 = 0; $i3 < $this->len[$k] && $sw == 0; $i3++) {
    						if ($i2 == $this->ind[$p2][$i3]) {
    							$sw = 1;
    							if ($i3 == 0) {
    								$e[0] = $this->ind[$p2][$this->len[$k]-1];
    								$e[1] = $this->ind[$p2][1];
    							}
    							else {
    								if ($i3 == $this->len[$k]-1) {
    									$e[0] = $this->ind[$p2][$i3-1];
    									$e[1] = $this->ind[$p2][0];
    								}
    								else {
    									$e[0] = $this->ind[$p2][$i3-1];
        								$e[1] = $this->ind[$p2][$i3+1];
        							}
    							}
        						for ($i4 = 0; $i4 < 2; $i4++) {
        							$sw = 1;
    								for ($i5 = 1; $i5 <= $this->edge[$i2][0] && $sw == 1; $i5++) {
    									if ($this->edge[$i2][$i5] == $e[$i4])
    										$sw = 2;
    								}
    								if ($sw == 1) {
    									$this->edge[$i2][0]++;
    									$this->edge[$i2][$this->edge[$i2][0]] = $e[$i4];
        							}
        						}
        					}
    					}
    				}
    								// 交叉の実行
    									// 出発点の決定
    				$k1 = $this->ind[$p1][0];
    				$k2 = $this->ind[$p2][0];
    				if ($this->edge[$k1][0] == $this->edge[$k2][0])
    					$kk = (uniform() > 0.5) ? $k2 : $k1;
    				else
    					$kk = ($this->edge[$k1][0] < $this->edge[$k2][0]) ? $k1 : $k2;
    				$this->ind[$k][0] = $kk;
    				$p                = 1;
    	
    				while ($p < $this->len[$k]) {
        								// ノードの除去
        				for ($i2 = 0; $i2 < $this->len[$k]; $i2++) {
    						$sw = 0;
        					if ($this->edge[$i2][0] > 0) {
        						for ($i3 = 1; $i3 <= 4 && $sw == 0; $i3++) {
    								if ($this->edge[$i2][$i3] == $kk) {
    									$sw                   = 1;
    									$this->edge[$i2][$i3] = -1;
    									$this->edge[$i2][0]--;
    								}
    							}
    						}
        				}
        								// 次の現在ノードの選択
        				$min = 10;
    					$num = 0;
    					for ($i2 = 1; $i2 <= 4; $i2++) {
    						if ($this->edge[$kk][$i2] >= 0) {
    							$k1 = $this->edge[$kk][$i2];
    							if ($this->edge[$k1][0] >= 0 && $this->edge[$k1][0] < $min) {
    								$num = 1;
    								$min = $this->edge[$k1][0];
    								$k0  = $k1;
    							}
    							else {
    								if ($this->edge[$k1][0] == $min)
    									$num++;
    							}
    						}
        				}
        				if ($num > 1) {
    						$k1 = intval(uniform() * $num) + 1;
        					if ($k1 > $num)
        						$k1 = $num;
    						$k2 = 0;
    						$k0 = -1;
    						for ($i2 = 1; $i2 <= 4 && $k0 < 0; $i2++) {
    							if ($this->edge[$kk][$i2] >= 0) {
    								if ($this->edge[$this->edge[$kk][$i2]][0] == $min) {
    									$k2++;
    									if ($k1 == $k2)
        									$k0 = $this->edge[$kk][$i2];
        							}
        						}
    						}
    					}
    					else {
    						if ($num <= 0) {
    							$num = 0;
    							for ($i2 = 0; $i2 < $this->len[$k]; $i2++) {
    								if ($i2 != $kk && $this->edge[$i2][0] >= 0)
    									$num++;
    							}
    							if ($num <= 0)
    								exit("***error  invalid data (C_edge)\n");
    							else {
        							$k1 = intval(uniform() * $num) + 1;
        							if ($k1 > $num)
    									$k1 = $num;
        							$k2 = 0;
        							$k0 = -1;
    								for ($i2 = 0; $i2 < $this->len[$k] && $k0 < 0; $i2++) {
    									if ($i2 != $kk && $this->edge[$i2][0] >= 0) {
    										$k2++;
    										if ($k1 == $k2)
    											$k0 = $i2;
    									}
    								}
        						}
        					}
        				}
    					$this->edge[$kk][0] = -1;
    					$this->ind[$k][$p]  = $k0;
    					$kk                 = $k0;
    					$p++;
    				}
    			}
    		}
    	}
    	
    	/*************************************************************/
    	/* 交叉(サブツアー交叉.2点交叉の拡張である.ただし,相手に*/
    	/*       同じ遺伝子のグループがない限り実行されない.たとえば*/
    	/*         ***abcd**                                         */
    	/*         *cdab****                                         */
        /*       のような両親の時実行され,以下の4つの子供が生成され*/
        /*       る)                                                */
    	/*         ***cdab**                                         */
        /*         *abcd****                                         */
        /*         ***badc**                                         */
    	/*         *dcba****                                         */
    	/*       最大,4*交叉回数*個体総数*(個体総数-1) 個の子 */
    	/*       供が生成される可能性があるので,子供の数としてこの値*/
    	/*       以上のデータを入力しておく必要がある.              */
    	/*      kosa : 交叉確率                                      */
    	/*      count : 1つのペアーに対する交差回数(default=10)     */
    	/*************************************************************/
        function C_sub($kosa, $count = 10)
        {
        	$t22 = 0;
    	/*
    	     初期設定とデータのチェック
    	*/
    		if ((4*$count*$this->size*($this->size-1)) > $this->max_ch)
    			exit("***error  子供が多すぎる (C_sub)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $this->size-1; $i1++) {
    						// 親1
    			$p1 = $this->Position($i1);
    	
        		if ($p1 >= 0) {
        
    				for ($i2 = $i1; $i2 < $this->size; $i2++) {
        					// 親2
        				$p2 = $this->Position($i2);
    	
    					if ($p2 >= 0) {
    						// 交叉しない場合
    						if (uniform() > $kosa)
    							$this->C_copy(2, 1);
    						// 交叉する場合
    						else {
        						// 交叉回数の制御
        						for ($i3 = 0; $i3 < $count; $i3++) {
        							// 交叉位置の決定(点の後ろで交叉)
    									// 親1の交叉位置
    								$t11 = intval(uniform() * $this->len[$p1]);
    								if ($t11 > ($this->len[$p1]-1))
    									$t11 = $this->len[$p1] - 1;
    								$sw = 0;
    								while ($sw == 0) {
    									$t12 = intval(uniform() * $this->len[$p1]);
    									if ($t12 > ($this->len[$p1]-1))
    										$t12 = $this->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 < $this->len[$p2] && $t21 < 0; $i4++) {
    									for ($i5 = $t11; $i5 <= $t12 && $t21 < 0; $i5++) {
    										if ($this->ind[$p2][$i4] == $this->ind[$p1][$i5])
    											$t21 = $i4;
    									}
    								}
        							if ($t21 >= 0) {
        								$t22 = $t21 + $t12 - $t11;
        								if ($t22 < $this->len[$p2]) {
    										$sw = 1;
    										for ($i4 = $t21+1; $i4 <= $t22 && $sw > 0; $i4++) {
    											$sw = 0;
    											for ($i5 = $t11; $i5 <= $t12 && $sw == 0; $i5++) {
    												if ($this->ind[$p2][$i4] == $this->ind[$p1][$i5])
    													$sw = 1;
    											}
    										}
    									}
    								}
    									// 交叉の実行
    								if ($sw > 0) {
    	
    									$k1              = $this->Position(-1);
        								$this->pi_w[$k1] = 1;
        								$this->len[$k1]  = $this->len[$p1];
    									$k2              = $this->Position(-1);
        								$this->pi_w[$k2] = 1;
        								$this->len[$k2]  = $this->len[$p1];
    									$k3              = $this->Position(-1);
    									$this->pi_w[$k3] = 1;
    									$this->len[$k3]  = $this->len[$p2];
    									$k4              = $this->Position(-1);
    									$this->pi_w[$k4] = 1;
    									$this->len[$k4]  = $this->len[$p2];
    	
        								for ($i4 = 0; $i4 < $t11; $i4++) {
        									$this->ind[$k1][$i4] = $this->ind[$p1][$i4];
        									$this->ind[$k2][$i4] = $this->ind[$p1][$i4];
    									}
    									for ($i4 = $t11; $i4 <= $t12; $i4++) {
    										$this->ind[$k1][$i4] = $this->ind[$p2][$t21+$i4-$t11];
    										$this->ind[$k2][$i4] = $this->ind[$p2][$t22-$i4+$t11];
    									}
    									for ($i4 = $t12+1; $i4 < $this->len[$p1]; $i4++) {
    										$this->ind[$k1][$i4] = $this->ind[$p1][$i4];
    										$this->ind[$k2][$i4] = $this->ind[$p1][$i4];
    									}
    									for ($i4 = 0; $i4 < $t21; $i4++) {
    										$this->ind[$k3][$i4] = $this->ind[$p2][$i4];
    										$this->ind[$k4][$i4] = $this->ind[$p2][$i4];
    									}
    									for ($i4 = $t21; $i4 <= $t22; $i4++) {
        									$this->ind[$k3][$i4] = $this->ind[$p1][$t11+$i4-$t21];
        									$this->ind[$k4][$i4] = $this->ind[$p1][$t12-$i4+$t21];
    									}
        								for ($i4 = $t22+1; $i4 < $this->len[$p2]; $i4++) {
        									$this->ind[$k3][$i4] = $this->ind[$p2][$i4];
    										$this->ind[$k4][$i4] = $this->ind[$p2][$i4];
    									}
    								}
    							}
    						}
    					}
    				}
        		}
        	}
        }
    	
    	/**************************************/
    	/* 突然変異(対立遺伝子との置き換え) */
    	/*      pr : 突然変異率               */
    	/**************************************/
    	function M_alle($pr)
    	{
    	/*
    	     データのチェックと初期設定
    	*/
    		if ($this->dup_a == 0)
    			exit("***error  突然変異方法が不適当 (M_alle)\n");
        /*
             実行
    	*/
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        		if ($this->pi_w[$i1] == 1) {
    				for ($i2 = 0; $i2 < $this->len[$i1]; $i2++) {
    					if (uniform() <= $pr) {
    						$lid = intval(uniform() * ($this->allele_u - $this->allele_l + 1) + $this->allele_l);
    						if ($lid > $this->allele_u)
    							$lid = $this->allele_u;
    						if ($lid != $this->ind[$i1][$i2])
    							$this->ind[$i1][$i2] = $lid;
        				}
        			}
        		}
    		}
    	}
    	
    	/**********************************************************************/
    	/* 突然変異(移動.2点を選択し,2番目の遺伝子を1番目の遺伝子の前に */
    	/*           移動する)                                               */
    	/*      pr : 突然変異率                                               */
    	/**********************************************************************/
    	function M_move($pr)
    	{
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    	/*
             位置の決定
        */
    						// p1
        			$p1 = intval(uniform() * $this->len[$i1]);
        			if ($p1 >= $this->len[$i1])
    					$p1 = $this->len[$i1] - 1;
    						// p2
    				$sw = 0;
    				while ($sw == 0) {
    					$p2 = intval(uniform() * $this->len[$i1]);
    					if ($p2 >= $this->len[$i1])
    						$p2 = $this->len[$i1] - 1;
        				if ($p2 != $p1)
        					$sw = 1;
        			}
    	/*
    	     実行
    	*/
    				if ($p2 > $p1) {
    					$ld = $this->ind[$i1][$p2];
    					for ($i2 = $p2; $i2 > $p1; $i2--)
    						$this->ind[$i1][$i2] = $this->ind[$i1][$i2-1];
    					$this->ind[$i1][$p1] = $ld;
    				}
    				else {
    					$ld = $this->ind[$i1][$p2];
    					for ($i2 = $p2; $i2 < $p1-1; $i2++)
    						$this->ind[$i1][$i2] = $this->ind[$i1][$i2+1];
    					$this->ind[$i1][$p1-1] = $ld;
        			}
        		}
    		}
        }
        
    	/********************************************************/
    	/* 突然変異(逆位.2点間の遺伝子順序を逆に並べ替える) */
    	/*      pr : 突然変異率                                 */
    	/*      wd : >0 : 幅を固定                              */
    	/*           =0 : 幅をランダム(default)                 */
    	/********************************************************/
    	function M_inv($pr, $wd = 0)
        {
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    	/*
    	     区間の決定
    	*/
    				if ($wd == 0) {
    					$p1 = intval(uniform() * $this->len[$i1]);
    					if ($p1 >= $this->len[$i1])
    						$p1 = $this->len[$i1] - 1;
    					$sw = 0;
    					while ($sw == 0) {
    						$p2 = intval(uniform() * $this->len[$i1]);
    						if ($p2 >= $this->len[$i1])
        						$p2 = $this->len[$i1] - 1;
        					if ($p2 != $p1)
    							$sw = 1;
        				}
        				if ($p1 > $p2) {
    						$p  = $p1;
    						$p1 = $p2;
    						$p2 = $p;
    					}
    				}
    	
    				else {
        				$p1 = $this->len[$i1];
        				while ($p1 > $this->len[$i1]-2)
        					$p1 = intval(uniform() * $this->len[$i1]);
    					$p2 = $p1 + $wd - 1;
    					if ($p2 >= $this->len[$i1])
    						$p2 = $this->len[$i1] - 1;
    				}
    	/*
    	     実行
    	*/
    				$sw = 0;
    				while ($sw == 0) {
    					$lid         = $this->ind[$i1][$p1];
    					$this->ind[$i1][$p1] = $this->ind[$i1][$p2];
    					$this->ind[$i1][$p2] = $lid;
    					$p1++;
    					$p2--;
        				if ($p1 >= $p2)
        					$sw = 1;
    				}
        		}
        	}
    	}
    	
    	/**********************************************************************/
    	/* 突然変異(スクランブル.2点間の遺伝子順序をランダムに並べ替える) */
    	/*      pr : 突然変異率                                               */
    	/*      wd : >0 : 幅を固定                                            */
    	/*           =0 : 幅をランダム(default)                               */
        /**********************************************************************/
        function M_scram($pr, $wd = 0)
        {
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    	/*
    	     区間の決定
    	*/
    				if ($wd == 0) {
    					$p1 = intval(uniform() * $this->len[$i1]);
    					if ($p1 >= $this->len[$i1])
    						$p1 = $this->len[$i1] - 1;
    					$sw = 0;
    					while ($sw == 0) {
    						$p2 = intval(uniform() * $this->len[$i1]);
    						if ($p2 >= $this->len[$i1])
        						$p2 = $this->len[$i1] - 1;
        					if ($p2 != $p1)
    							$sw = 1;
        				}
        				if ($p1 > $p2) {
    						$p  = $p1;
    						$p1 = $p2;
    						$p2 = $p;
    					}
    				}
    	
    				else {
        				$p1 = $this->len[$i1];
        				while ($p1 > $this->len[$i1]-2)
        					$p1 = intval(uniform() * $this->len[$i1]);
    					$p2 = $p1 + $wd - 1;
    					if ($p2 >= $this->len[$i1])
    						$p2 = $this->len[$i1] - 1;
    				}
    	/*
    	     実行
    	*/
    				for ($i2 = $p1; $i2 <= $p2; $i2++) {
    					$p = intval(uniform() * ($p2 - $p1 + 1) + $p1);
    					if ($p > $p2)
    						$p = $p2;
    					$ld                  = $this->ind[$i1][$i2];
    					$this->ind[$i1][$i2] = $this->ind[$i1][$p];
    					$this->ind[$i1][$p]  = $ld;
        			}
        		}
    		}
        }
        
    	/**********************************************************************/
    	/* 突然変異(転座.2点間の遺伝子を他の位置のものと置き換える.ただし */
    	/*           重複部分はそのままとする)                               */
    	/*      pr : 突然変異率                                               */
    	/*      wd : >0 : 幅を固定                                            */
    	/*           =0 : 幅をランダム(default)                               */
    	/**********************************************************************/
        function M_chg($pr, $wd = 0)
        {
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    	/*
    	     区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    	*/
    						// p1
    				$p1 = intval(uniform() * $this->len[$i1]);
    				if ($p1 >= $this->len[$i1])
    					$p1 = $this->len[$i1] - 1;
    						// p3
    				$sw = 0;
    				while ($sw == 0) {
    					$p3 = intval(uniform() * $this->len[$i1]);
    					if ($p3 >= $this->len[$i1])
        					$p3 = $this->len[$i1] - 1;
        				if ($p3 != $p1)
    						$sw = 1;
        			}
        					// 小さい方をp1,p2にする
    				if ($p1 > $p3) {
    					$p  = $p1;
    					$p1 = $p3;
    					$p3 = $p;
    				}
    						// p4, p2
    				$p4 = ($wd == 0) ? intval(uniform() * ($this->len[$i1] - $p3)) + $p3 : $p1 + $wd - 1;
        			if ($p4 >= $this->len[$i1])
        				$p4 = $this->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                  = $this->ind[$i1][$i2];
        				$this->ind[$i1][$i2] = $this->ind[$i1][$p];
        				$this->ind[$i1][$p]  = $ld;
    					$p++;
        			}
        		}
    		}
    	}
    	
    	/**********************************************************************/
    	/* 突然変異(重複.2点間の遺伝子を他の位置にコピーする               */
    	/*      pr : 突然変異率                                               */
    	/*      wd : >0 : 幅を固定                                            */
        /*           =0 : 幅をランダム(deafult)                               */
        /**********************************************************************/
        function M_dup($pr, $wd = 0)
    	{
    	/*
    	     データのチェック
    	*/
    		if ($this->dup_a == 0)
    			exit("***error  突然変異方法が不適当 (M_dup)\n");
    	/*
    	     実行
    	*/
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
        					// 区間の決定([p1,p2]を[p3,p4]にコピー)
        						// p1
    				$p1 = intval(uniform() * $this->len[$i1]);
        			if ($p1 >= $this->len[$i1])
        				$p1 = $this->len[$i1] - 1;
    							// p3
    				$sw = 0;
    				while ($sw == 0) {
    					$p3 = intval(uniform() * $this->len[$i1]);
    					if ($p3 >= $this->len[$i1])
    						$p3 = $this->len[$i1] - 1;
    					if ($p3 != $p1)
        					$sw = 1;
        			}
        						// 区間を決める
    				if ($p3 > $p1) {
    					$p4 = ($wd == 0) ? intval(uniform() * ($this->len[$i1] - $p3)) + $p3 : $p3 + $wd - 1;
    					if ($p4 >= $this->len[$i1])
    						$p4 = $this->len[$i1] - 1;
    					$p2 = $p1 + ($p4 - $p3);
    				}
    				else {
    					$p2 = ($wd == 0) ? intval(uniform() * ($this->len[$i1] - $p1)) + $p1 :$p1 + $wd - 1;
    					if ($p2 >= $this->len[$i1])
    						$p2 = $this->len[$i1] - 1;
    					$p4 = $p3 + ($p2 - $p1);
    				}
        					// 実行
        			$p = $p4;
    				for ($i2 = $p2; $i2 >= $p1; $i2--) {
        				$this->ind[$i1][$p] = $this->ind[$i1][$i2];
        				$p--;
    				}
    			}
    		}
    	}
    	
    	/******************************************************/
    	/* 突然変異(摂動.値をある量だけ変化させる)         */
        /*      pr : 突然変異率                               */
        /*      method : =0 : 正規分布(default)               */
        /*               =1 : 一様分布                        */
    	/*      m : 平均または一様分布の下限(default=0.0)     */
    	/*      s : 標準偏差または一様分布の上限(default=1.0) */
    	/******************************************************/
    	function M_per($pr, $method = 0, $m = 0.0, $s = 1.0)
    	{
    		$wd = 0.0;
    	/*
    	     データのチェックと初期設定
    	*/
    		if ($this->dup_a == 0)
    			exit("***error  突然変異方法が不適当 (M_per)\n");
    	
        	if ($method > 0)
        		$wd = $s - $m;
    	/*
             実行
        */
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($this->pi_w[$i1] == 1) {
    				for ($i2 = 0; $i2 < $this->len[$i1]; $i2++) {
    					if (uniform() <= $pr) {
    						if ($method == 0)
    							$w = norm_d($m, $s);
    						else {
        						$w = uniform() * $wd;
        						if (uniform() < 0.5)
        							$w = -$w;
    						}
    						$x1 = (double)$this->ind[$i1][$i2] + $w;
    						if ($x1 > $this->allele_u)
    							$x1 = $this->allele_u;
    						else {
    							if ($x1 < $this->allele_l)
    								$x1 = $this->allele_l;
    						}
    						$this->ind[$i1][$i2] = intval($x1);
    					}
    				}
    			}
    		}
    	}
        
        /**********************************************************************/
    	/* 突然変異(挿入.ある長さの遺伝子を挿入する)                       */
        /*      pr : 突然変異率                                               */
        /*      wd : >0 : 幅を固定                                            */
    	/*           =0 : 幅をランダム(default)                               */
    	/**********************************************************************/
    	function M_ins($pr, $wd = 0)
    	{
    	/*
    	     データのチェック
    	*/
        	if ($this->dup_a == 0 || $this->min_len < 0)
        		exit("***error  突然変異方法が不適当 (M_ins)\n");
    	/*
    	     実行
    	*/
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    						// 挿入位置の決定
    				$p = intval(uniform() * ($this->len[$i1]+1));
    				if ($p > $this->len[$i1])
    					$p = $this->len[$i1];
    						// 挿入する遺伝子長の決定
    				$l = ($wd == 0) ? intval(uniform() * ($this->max_len - $this->len[$i1] + 1)) : $wd;
    				if ($l > $this->max_len-$this->len[$i1])
        				$l = $this->max_len - $this->len[$i1];
        			else {
    					if ($l <= 0)
        					$l = 1;
        			}
    						// 実行
    							// 挿入場所の確保
    				if ($p < $this->len[$i1]) {
    					for ($i2 = $this->len[$i1]+$l-1; $i2 >= $p; $i2--)
    						$this->ind[$i1][$i2] = $this->ind[$i1][$i2-$l];
    				}
    							// 挿入場所の遺伝子の決定
        			for ($i2 = $p; $i2 < $p+$l; $i2++) {
        				$ld = intval(uniform() * ($this->allele_u - $this->allele_l + 1) + $this->allele_l);
        				if ($ld > $this->allele_u)
    						$ld = $this->allele_u;
    					$this->ind[$i1][$i2] = $ld;
    				}
    	
    				$this->len[$i1]  += $l;
    			}
    		}
    	}
    	
    	/**********************************************************************/
    	/* 突然変異(削除.ある長さの遺伝子を削除する)                       */
    	/*      pr : 突然変異率                                               */
    	/*      wd : >0 : 幅を固定                                            */
    	/*           =0 : 幅をランダム(default)                               */
        /**********************************************************************/
        function M_del($pr, $wd = 0)
    	{
        /*
             データのチェック
    	*/
    		if ($this->dup_a == 0 || $this->min_len < 0)
    			exit("***error  突然変異方法が不適当 (M_del)\n");
    			exit(1);
    	/*
    	     実行
        */
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    						// 削除位置の決定
    				$p = intval(uniform() * $this->len[$i1]);
    				if ($p >= $this->len[$i1])
    					$p = $this->len[$i1] - 1;
    						// 削除する遺伝子長の決定
    				$max = ($this->len[$i1]-$this->min_len < $this->len[$i1]-$p) ? $this->len[$i1] - $this->min_len : $this->len[$i1] - $p;
    				$l   = ($wd == 0) ? intval(uniform() * $max + 1) : $wd;
    				if ($l > $max)
    					$l = $max;
    						// 実行
    				for ($i2 = 0; $i2 < $this->len[$i1]-$p-$l; $i2++)
    					$this->ind[$i1][$p+$i2] = $this->ind[$i1][$p+$i2+$l];
    	
        			$this->len[$i1] -= $l;
        		}
    		}
        }
        
    	/*********************************************************************/
    	/* 淘汰(エリート・ルーレット選択)                                  */
    	/*      elite : エリートで残す個体数(default=0)                      */
    	/*      s_method : ルーレット板の作成方法(default=1)                 */
    	/*                   =0 : 適応度をそのまま使用                       */
    	/*                   =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                   =2 : 評価値に順位をつけ,減少率βで線形化       */
        /*      s_bias : α,または,method=2の場合は初期値(default=0)       */
        /*      s_step : β(default=1)                                       */
        /*********************************************************************/
    	function S_roul($elite = 0, $s_method = 1, $s_bias = 0.0, $s_step = 1.0)
    	{
    		$count = 0;
    		$k     = 0;
    		$n     = 0;
    	/*
    	     値のチェックと初期設定
    	*/
    		if ($s_method != 0 && $s_method != 2)
    			$s_method = 1;
    	
    		if ($elite > $this->size)
    			exit("***error  エリートで残す数が多すぎる (S_roul)\n");
        
    		if ($s_method == 2 && $s_step <= 0.0)
        		$s_step = 1.0;
        
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++)
    			$this->s_w[$i1] = 0;
    	/*
    	     重複個体を削除
    	*/
    		if ($this->dup_s == 0) {
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        			if ($this->pi_w[$i1] > 0) {
        				for ($i2 = $i1+1; $i2 < $this->size+$this->max_ch; $i2++) {
        					if ($this->pi_w[$i2] > 0 && $this->len[$i1] == $this->len[$i2]) {
    							$sw = 0;
    							for ($i3 = 0; $i3 < $this->len[$i1] && $sw == 0; $i3++) {
    								if ($this->ind[$i1][$i3] != $this->ind[$i2][$i3])
    									$sw = 1;
    							}
    							if ($sw == 0)
    								$this->pi_w[$i2] = 0;
    						}
    					}
    				}
    			}
    		}
    	
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        		if ($this->pi_w[$i1] > 1)
        			$n++;
    		}
        
        	if ($n < 0 || $this->dup_s == 0 && $n < $this->size)
    			exit("***error  残す個体がない (S_roul)\n");
    	/*
    	     淘汰して残す個体を選ぶ
    	*/
    						// エリートの選択
        	$sw = 0;
        
        	while ($k < $elite && $k < $n && $sw == 0) {
    			$max = -1;
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    				if ($this->pi_w[$i1] > 1 && $this->s_w[$i1] == 0) {
    					if ($max < 0 || $this->pi[$i1] > $this->pi[$max])
    						$max = $i1;
    				}
    			}
    			if ($max < 0)
    				$sw = 1;
    			else {
    				$this->s_w[$max] = 1;
    				$k++;
    			}
    		}
        					// ルーレット選択
        	while ($count < $this->size+$this->max_ch && $k < $this->size) {
    			$p = $this->Select($s_method, $s_bias, $s_step);
        		if ($this->dup_s == 0 && $this->s_w[$p] > 0)
        			$count++;
    			else {
    				$count = 0;
    				$this->s_w[$p]++;
    				$k++;
    			}
    		}
    							// 選択に失敗した場合の処理
        	if ($this->dup_s == 0 && $k < $this->size) {
        		for ($i1 = 0; $i1 < $this->size+$this->max_ch && $k < $this->size; $i1++) {
        			if ($this->pi_w[$i1] > 1 && $this->s_w[$i1] == 0) {
    					$this->s_w[$i1] = 1;
    					$k++;
    				}
    			}
    		}
    							// 複数回選択されたものの処理
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($this->s_w[$i1] == 0)
    				$this->pi_w[$i1] = 0;
    		}
    	
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($this->s_w[$i1] > 0) {
    				if ($this->s_w[$i1] > 1) {
        				for ($i2 = 2; $i2 <= $this->s_w[$i1]; $i2++) {
        					$k              = $this->Position(-1);
    						$this->len[$k]  = $this->len[$i1];
        					$this->pi_w[$k] = 2;
        					$this->pi[$k]   = $this->pi[$i1];
    						for ($i3 = 0; $i3 < $this->len[$i1]; $i3++)
    							$this->ind[$k][$i3] = $this->ind[$i1][$i3];
    					}
    				}
    			}
    		}
    	}
    }
        
    /***********************************/
    /* [0, 1] 区間の一様分布変量の発生 */
    /***********************************/
    function uniform()
    {
    	return mt_rand() / mt_getrandmax();
    }
    
    /***********************************/
    /* 正規分布変量の発生              */
    /*      m : 平均                   */
    /*      s : 標準偏差               */
    /*           return : 正規分布変量 */
    /***********************************/
    function norm_d($m, $s)
    {
      	$x = 0.0;
    
       	for ($i1 = 0; $i1 < 12; $i1++)
       		$x += uniform();
    
    	$x = $s * ($x - 6.0) + $m;
    
    	return $x;
    }
    	
    /*******************/
    /* クラスTSPの定義 */
    /*******************/
    
    class TSP extends Species {
    
    	private $max_gen;   // 最大世代交代数
    	private $kosa_m;   // 交叉方法
                           //   =-1 : 交叉を使用しない
                           //   =0 : 親のコピー
                           //   =1 : 循環交叉
                           //   =2 : 部分的交叉
                           //   =3 : 順序交叉
                           //   =4 : 一様順序交叉
                           //   =5 : 一様位置交叉
                           //   =6 : エッジ組み替え交叉
                           //   =7 : サブツアー交叉
    	private $kosa;   // 交叉確率
    	private $k_point;   // 交差点の数(負の時は,1から-k_point間のランダム)
    	private $k_vr;   // =0 : 両親とも同じ位置で交叉
                         // =1 : 両親が異なる位置で交叉(遺伝子長は可変)
    	private $k_method;   // 交叉の時の親の選択方法
                             //   =-1 : ランダム
    	                     //   =0 : 適応度をそのまま使用
    	                     //   =1 : 最小値からの差(ただし,α以下の場合はα)
    	                     //   =2 : 評価値に順位をつけ,減少率βで線形化
    	private $k_bias;   // α,または,method=2の場合は初期値
    	private $k_step;   // β
    	private $mute_m;   // 突然変異方法
    	                   //   =-1 : 突然変異を使用しない
                           //   =0 : 移動
                           //   =1 : 逆位
                           //   =2 : スクランブル
    	                   //   =3 : 転座
    	private $mute;   // 突然変異率
    	private $wd;   // 突然変異に使用する部分遺伝子長
    	private $m_mean;   // 摂動の平均値
    	private $m_std;   // 摂動の標準偏差
    	private $elite;   // エリート選択で残す数
    	private $s_method;   // ルーレット板の作成方法
    	                     //   =0 : 適応度をそのまま使用
    	                     //   =1 : 最小値からの差(ただし,α以下の場合はα)
    	                     //   =2 : 評価値に順位をつけ,減少率βで線形化
    	private $s_bias;   // α,または,s_method=2の場合は初期値
    	private $s_step;   // β
    	private $out_d;   // 表示間隔
    	private $out_lvl;   // 出力レベル
                            //   =0 : 最終出力だけ
                            //   n>0 : n世代毎に出力(負の時はファイル)
    	private $out_m;   // 出力方法
                          //   =0 : すべてを出力
                          //   =1 : 最大適応度の個体だけを出力
    	private $o_file;   // 出力ファイル名
    	private $city;   //都市の位置データ
    	private $n_city;   // 都市の数
    	private $rg;   // 都市間の距離
    	private $kinbo;   // 近傍探索(0:行わない,1:行う)
    	private $neib;   // 近傍(2 or 3)
    	private $sel;   // エッジの選択方法
                        //   =0 : 最良のものを選択
                        //   =1 : 最初のものを選択
        
    	/***************************************/
    	/* コンストラクタ                      */
    	/*      name1 : Species定義ファイル名  */
    	/*      name2 : TSP定義ファイル名      */
    	/*      seed : 乱数の初期値            */
    	/***************************************/
    	function TSP ($name1, $name2, $seed)
    	{
    		parent::Species($name1, $seed);
    						// 基本データの入力
    		$in = fopen($name2, "r");
    	
    		fscanf($in, "%*s %d %*s %d", $this->out_lvl, $this->out_m);
    		fscanf($in, "%*s %s %*s %d", $this->o_file, $this->out_d);
        	fscanf($in, "%*s %d %*s %lf %*s %d %*s %d %*s %d %*s %lf %*s %lf", $this->kosa_m, $this->kosa, $this->k_point, $this->k_vr, $this->k_method, $this->k_bias, $this->k_step);
    		fscanf($in, "%*s %d %*s %lf %*s %d %*s %lf %*s %lf", $this->mute_m, $this->mute, $this->wd, $this->m_mean, $this->m_stds);
        	fscanf($in, "%*s %d %*s %d %*s %lf %*s %lf", $this->elite, $this->s_method, $this->s_bias, $this->s_step);
    		fscanf($in, "%*s %d %*s %d", $this->n_city, $this->max_gen);
    		fscanf($in, "%*s %d %*s %d", $this->kinbo, $this->neib);
    		fscanf($in, "%*s %d", $this->sel);
    	
    		if ($this->kinbo > 0 && $this->neib != 2 && $this->neib != 3)
    			exit("***error  近傍の値が不適当 \n");
        
    		if ($this->n_city != $this->max_len)
    			exit("***error  都市数が不適当 \n");
    						// 都市の位置データ
    		$this->city = array($this->n_city);
    		for ($i1 = 0; $i1 < $this->n_city; $i1++) {
    			$this->city[$i1] = array(2);
    			fscanf($in, "%d %d", $this->city[$i1][0], $this->city[$i1][1]);
    		}
    						// 距離テーブル
    		$this->rg = array($this->n_city);
    	
    		for ($i1 = 0; $i1 < $this->n_city; $i1++) {
        		$this->rg[$i1] = array($this->n_city);
        		for ($i2 = $i1+1; $i2 < $this->n_city; $i2++) {
    				$x = $this->city[$i2][0] - $this->city[$i1][0];
        			$y = $this->city[$i2][1] - $this->city[$i1][1];
        			$this->rg[$i1][$i2] = round(sqrt($x * $x + $y * $y));
    			}
    		}
    	
    		for ($i1 = 1; $i1 < $this->n_city; $i1++) {
    			for ($i2 = 0; $i2 < $i1; $i2++)
    				$this->rg[$i1][$i2] = $this->rg[$i2][$i1];
    		}
        
        	fclose($in);
        }
    	
    	/**************/
    	/* 全体の制御 */
    	/**************/
    	function Control()
    	{
    		$gen = 1;
    						// 初期集団の発生
    		$this->Init_std();
    						// 評価
    		if ($this->kinbo > 0)
    			$this->Kinbo();
    		else
    			$this->Adap();
        					// 出力
        	printf("***世代 %d 適応度 max %f (%d) mean %f\n", $gen, $this->max, $this->max_n, $this->mean);
        
        	if (abs($this->out_lvl) > 0)
    			$this->Output($gen);
    						// 世代交代
    		for ($gen = 2; $gen <= $this->max_gen; $gen++) {
    							// 交叉
    			switch ($this->kosa_m) {
    				case -1:
    					break;
        			case 0:
        				$this->C_copy();   // 親のコピー
        				break;
    				case 1:
    					$this->C_cycle($this->kosa);   // 循環交叉
    					break;
    				case 2:
    					$this->C_part($this->kosa);   // 部分的交叉
    					break;
    				case 3:
    					$this->C_seq($this->kosa);   // 順序交叉
    					break;
    				case 4:
    					$this->C_useq($this->kosa);   // 一様順序交叉
    					break;
    				case 5:
    					$this->C_upos($this->kosa);   // 一様位置交叉
        				break;
        			case 6:
    					$this->C_edge($this->kosa);   // エッジ組み替え交叉
        				break;
        			case 7:
    					$this->C_sub($this->kosa, $this->k_point);   // サブツアー交叉
    					break;
    				default:
    					break;
    			}
    							// 突然変異
    			switch ($this->mute_m) {
        			case -1:
        				break;
        			case 0:
    					$this->M_move($this->mute);   // 移動
    					break;
    				case 1:
    					$this->M_inv($this->mute);   // 逆位
    					break;
    				case 2:
    					$this->M_scram($this->mute);   // スクランブル
    					break;
    				case 3:
    					$this->M_chg($this->mute);   // 転座
    					break;
    				default:
    					break;
    			}
        						// 適応度
        		if ($this->kinbo > 0)
    				$this->Kinbo();
        		else
        			$this->Adap();
    							// 淘汰
    			$this->S_roul($this->elite);
    							// 出力
    			if ($gen%$this->out_d == 0)
    				printf("***世代 %d 適応度 max %f (%d) mean %f\n", $gen, $this->max, $this->max_n, $this->mean);
    	
        		if (abs($this->out_lvl) > 0) {
        			if ($gen%abs($this->out_lvl) == 0)
        				$this->Output($gen);
    			}
    		}
    	
    		$gen--;
    		$k1 = $this->out_m;
    		$this->out_m = 0;
    		printf("***世代 %d 適応度 max %f (%d) mean %f\n", $gen, $this->max, $this->max_n, $this->mean);
    		$this->Output($gen);
    		$this->out_m = $k1;
    	}
    	
    	/*********************************/
    	/* 距離の計算                    */
        /*      n_c : 都市の数           */
        /*      p : 都市番号             */
    	/*      return : 距離(負)      */
        /*********************************/
        function Kyori($n_c, $p)
    	{
    		$range = 0;
    		$n1    = $p[0];
    	
    		for ($i1 = 1; $i1 < $n_c; $i1++) {
    			$n2     = $p[$i1];
        		$range -= $this->rg[$n1][$n2];
        		$n1     = $n2;
        	}
    	
    		$n2     = $p[0];
    		$range -= $this->rg[$n1][$n2];
    	
    		return $range;
    	}
    	
    	/****************/
    	/* 適応度の計算 */
    	/****************/
    	function Adap()
    	{
    		$k           = 0;
    		$this->mean  = 0.0;
        	$this->max   = 0.0;
        	$this->max_n = -1;
    	
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        		if ($this->pi_w[$i1] == 1) {
    				$this->pi_w[$i1] = 2;
    				$this->pi[$i1]   = $this->Kyori($this->len[$i1], $this->ind[$i1]);
    			}
    			if ($this->pi_w[$i1] > 0) {
    				$k++;
    				$this->mean += $this->pi[$i1];
    				if ($this->max_n < 0 || $this->pi[$i1] > $this->max) {
        				$this->max   = $this->pi[$i1];
        				$this->max_n = $i1;
        			}
    			}
    		}
    	
    		if ($k > 0)
    			$this->mean /= $k;
    	}
    	
    	/**************************************/
    	/* エッジの入れ替え                   */
    	/*      n_city : 都市の数             */
    	/*      seq : 訪問する順番            */
    	/*      r_m : 距離の負値              */
    	/*      return : =0 : 改善がなかった  */
    	/*               =1 : 改善があった    */
        /**************************************/
        function Change($n_city, &$seq, &$r_m)
    	{
        	$ch  = 0;
        	$sw  = 0;
    		$max = $r_m;
    	
    		$n3  = intval(uniform() * ($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;
    	                              // 枝の入れ替え
    				$this->kou1[0] = $seq[$n3];
    				$k             = 1;
    				for ($i3 = $k1; $i3 >= $n3+1; $i3--) {
        				$this->kou1[$k] = $seq[$i3];
        				$k++;
    				}
        
        			$nn = $k2;
    				while ($nn != $n3) {
    					$this->kou1[$k] = $seq[$nn];
    					$k++;
    					$nn++;
    					if ($nn > $n_city-1)
    						$nn = 0;
    				}
                                      // 評価
        			$r = $this->Kyori($n_city, $this->kou1);
        
    				if ($r > $max) {
    					$max = $r;
    					$sw  = 1;
    					for ($i3 = 0; $i3 < $n_city; $i3++)
    						$this->kou2[$i3] = $this->kou1[$i3];
    					if ($this->sel > 0)
    						$ch = 1;
    				}
    			}
    	
    			$n3++;
    			if ($n3 > $n_city-3)
    				$n3 = 0;
    		}
                                 // 3近傍
        	if ($this->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)
    						$this->kou1[0] = $seq[$n3];
    						$k             = 1;
    						for ($i4 = $i2; $i4 >= $n3+1; $i4--) {
    							$this->kou1[$k] = $seq[$i4];
    							$k++;
    						}
    	
    						for ($i4 = $k1; $i4 >= $i2+1; $i4--) {
    							$this->kou1[$k] = $seq[$i4];
    							$k++;
        					}
        
    						$nn = $k2;
        					while ($nn != $n3) {
        						$this->kou1[$k] = $seq[$nn];
    							$k++;
    							$nn++;
    							if ($nn > $n_city-1)
    								$nn = 0;
    						}
    	                                   // 評価(その1)
    						$r = $this->Kyori($n_city, $this->kou1);
        
        					if ($r > $max) {
        						$max = $r;
    							$sw  = 1;
    							for ($i3 = 0; $i3 < $n_city; $i3++)
    								$this->kou2[$i3] = $this->kou1[$i3];
    							if ($this->sel > 0)
    								$ch = 1;
    						}
    	                                   // 入れ替え(その2)
    						$this->kou1[0] = $seq[$n3];
    						$k             = 1;
    						for ($i4 = $k1; $i4 >= $i2+1; $i4--) {
    							$this->kou1[$k] = $seq[$i4];
    							$k++;
    						}
    	
        					for ($i4 = $n3+1; $i4 <= $i2; $i4++) {
        						$this->kou1[$k] = $seq[$i4];
    							$k++;
        					}
        
    						$nn = $k2;
    						while ($nn != $n3) {
    							$this->kou1[$k] = $seq[$nn];
    							$k++;
    							$nn++;
    							if ($nn > $n_city-1)
    								$nn = 0;
        					}
                                           // 評価(その2)
        					$r = $this->Kyori($n_city, $this->kou1);
    	
    						if ($r > $max) {
    							$max = $r;
    							$sw  = 1;
    							for ($i3 = 0; $i3 < $n_city; $i3++)
    								$this->kou2[$i3] = $this->kou1[$i3];
    							if ($this->sel > 0)
    								$ch = 1;
    						}
    	                                   // 入れ替え(その3)
    						$this->kou1[0] = $seq[$n3];
    						$k             = 1;
    						for ($i4 = $i2+1; $i4 <= $k1; $i4++) {
    							$this->kou1[$k] = $seq[$i4];
        						$k++;
        					}
    	
        					for ($i4 = $i2; $i4 >= $n3+1; $i4--) {
        						$this->kou1[$k] = $seq[$i4];
    							$k++;
    						}
    	
    						$nn = $k2;
    						while ($nn != $n3) {
    							$this->kou1[$k] = $seq[$nn];
    							$k++;
        						$nn++;
        						if ($nn > $n_city-1)
        							$nn = 0;
    						}
    	                                   // 評価(その3)
    						$r = $this->Kyori($n_city, $this->kou1);
    	
    						if ($r > $max) {
    							$max = $r;
    							$sw  = 1;
    							for ($i3 = 0; $i3 < $n_city; $i3++)
    								$this->kou2[$i3] = $this->kou1[$i3];
    							if ($this->sel > 0)
    								$ch = 1;
    						}
    	                                   // 入れ替え(その4)
    						$this->kou1[0] = $seq[$n3];
        					$k             = 1;
        					for ($i4 = $i2+1; $i4 <= $k1; $i4++) {
    							$this->kou1[$k] = $seq[$i4];
        						$k++;
        					}
    	
    						for ($i4 = $n3+1; $i4 <= $i2; $i4++) {
    							$this->kou1[$k] = $seq[$i4];
    							$k++;
    						}
    	
    						$nn = $k2;
        					while ($nn != $n3) {
        						$this->kou1[$k] = $seq[$nn];
        						$k++;
    							$nn++;
    							if ($nn > $n_city-1)
    								$nn = 0;
    						}
    	                                   // 評価(その4)
    						$r = $this->Kyori($n_city, $this->kou1);
    	
    						if ($r > $max) {
    							$max = $r;
    							$sw  = 1;
    							for ($i3 = 0; $i3 < $n_city; $i3++)
    								$this->kou2[$i3] = $this->kou1[$i3];
    							if ($this->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] = $this->kou2[$i1];
        	}
    	
    		return $sw;
    	}
    	
    	/**************/
    	/* 近傍の探索 */
    	/**************/
    	function Kinbo()
    	{
    		$k           = 0;
    		$this->max   = 0.0;
    		$this->max_n = -1;
    		$this->mean  = 0.0;
    	
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        		if ($this->pi_w[$i1] == 1) {
    				$this->pi_w[$i1] = 2;
        			$sw              = 1;
        			$r               = $this->Kyori($this->len[$i1], $this->ind[$i1]);
    				while ($sw > 0)
    					$sw = $this->Change($this->len[$i1], $this->ind[$i1], $r);
    				$this->pi[$i1] = $r;
    			}
    			if ($this->pi_w[$i1] > 0) {
    				$k++;
    				$this->mean += $this->pi[$i1];
        			if ($this->max_n < 0 || $this->pi[$i1] > $this->max) {
        				$this->max   = $this->pi[$i1];
        				$this->max_n = $i1;
    				}
    			}
    		}
    	
    		if ($k > 0)
    			$this->mean /= $k;
    	}
    	
    	/*****************************/
    	/* 結果の出力                */
    	/*      gen : 現在の世代番号 */
    	/*****************************/
    	function Output($gen)
    	{
    		$k = 0;
    	
    		if ($this->out_lvl >= 0) {
    			printf("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			fscanf(STDIN, "%d", $pr);
    		}
    		else
    			$pr = -1;
    	
    		if ($pr != 0) {
    					// 出力先の決定と評価値の出力
    			if ($pr > 0) {
    				$out = STDOUT;
    				fgets(STDIN);
    			}
    			else {
    				$x   = getdate();
    				$now = $x["hours"]."時".$x["minutes"]."分".$x["seconds"]."秒";
    				$out = fopen($this->o_file, "ab");
    				fwrite($out, "***世代 ".$gen." 適応度 max ".$this->max." (".$this->max_n.") mean ".$this->mean." 時間 ".$now."\n");
    			}
    					// 巡回順序の出力
    			if ($this->out_m == 0) {
    				for ($i1 = 0; $i1 < $this->len[$this->max_n]; $i1++) {
    					$n = $this->ind[$this->max_n][$i1];
    					fwrite($out, $n." ".$this->city[$n][0]." ".$this->city[$n][1]."\n");
    					if ($pr > 0) {
    						$k++;
    						if ($k == $pr) {
    							fgets(STDIN);
    							$k = 0;
    						}
    					}
    				}
    			}
    
    			if ($pr < 0)
    				fclose($out);
    		}
    	}
    }
    
    /****************/
    /* main program */
    /****************/
    					// 入力ミス
    	if (count($argv) <= 1)
    		exit("***error  ファイル名を入力して下さい\n");
    					// 入力OK
    	else {
    						// ファイルのオープン
    		$in = fopen($argv[1], "rb");
    		if ($in == NULL)
    			exit("***error  ファイル名が不適当です\n");
    						// 入力データファイル名の入力
    		fscanf($in, "%d", $n);   // データの数
    
    		$seed    = array($n);
    		$i_file1 = array($n);
    		$i_file2 = array($n);
    
    		for ($i1 = 0; $i1 < $n; $i1++) {
    			$seed[$i1] = 1000 * $i1 + 1234567;
    			fscanf($in, "%s %s", $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();
    		}
    	}
    
    //----------------ケーススタディデータ(data_ct.txt)------
    /*
    3
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    */
    
    //---------------Species記述データ(data1_t.txt)---------
    /*
    対立遺伝子上限 9 対立遺伝子下限 0
    最大遺伝子長 10 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 0 個体の重複(同じ染色体の個体) 0
    集団サイズ 10 子供 10
    */
    
    //---------------TSP記述データ(data2_t.txt)--------
    /*
    出力レベル(負はファイル) 10 出力方法(0:適応度+順番,1:適応度) 0
    出力ファイル名 out1.txt 表示間隔 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
    */
    
    ?>
    			
    関数の最大値
    <?php
    
    /********************************************************************/
    /* f(x) = sin(3.0*x) + 0.5 * sin(9.0*x) + sin(15.0*x + 50) の最大値 */
    /*      coded by Y.Suganuma                                         */
    /********************************************************************/
    
    /***********************/
    /* クラスSpeciesの定義 */
    /***********************/
    
    class Species {
    
    	protected $max;   // 最大適応度
    	protected $mean;   // 平均適応度
    	protected $pi;   // 適応度
    	protected $ro;   // ルーレット板
    	protected $allele_u;   // 対立遺伝子上限
    	protected $allele_l;   // 対立遺伝子下限
    	protected $size;   // 個体総数
    	protected $max_ch;   // 子供の数の最大値
    	protected $max_len;   // 最大遺伝子長
    	protected $min_len;   // 最小遺伝子長(負の時は,最大遺伝子長で固定)
    	protected $max_n;   // 最大適応度の個体番号
    	protected $dup_a;   // 遺伝子の重複
                            //   =0 : 重複を許さない
                            //   =1 : 重複を許す
    	protected $dup_s;   // 個体の重複(同じ染色体の個体)
                            //   =0 : 重複を許さない
                            //   =1 : 重複を許す
    	protected $ind;   // 集団(個体の集まり)
    	protected $len;   // 各個体の遺伝子長
    	protected $kou1;   // 交叉・突然変異用作業場所1
    	protected $kou2;   // 交叉・突然変異用作業場所2
    	protected $s_w;   // 淘汰用指標(選択された回数)
    	protected $edge;   // エッジ組み替え交叉用ワークエリア
    	protected $pi_w;   // 適応度計算指標
                           //   =0 : 未使用
                           //   =1 : 適応度計算前(突然変異はこの個体だけに適用)
                           //   =2 : 適応度計算済み(交叉時に親とみなす)
    
    	/****************************/
    	/* コンストラクタ           */
    	/*      name : ファイル名   */
    	/*      seed : 乱数の初期値 */
    	/****************************/
    	function Species($name, $seed)
    	{
    	/*
    	     データの入力
    	*/
    		$in = fopen($name, "rb");
    	
    		fscanf($in, "%*s %d %*s %d", $this->allele_u, $this->allele_l);
    		fscanf($in, "%*s %d %*s %d", $this->max_len, $this->min_len);
        	fscanf($in, "%*s %d %*s %d", $this->dup_a, $this->dup_s);
        	fscanf($in, "%*s %d %*s %d", $this->size, $this->max_ch);
    	/*
             データのチェック
        */
    		if ($this->size <= 0)
    			exit("***error  個体総数≦0 (Constructor)\n");
    	
    		if ($this->max_ch < 0)
    			exit("***error  子供の数<0 (Constructor)\n");
        
    		if ($this->max_len <= 0 || $this->min_len == 0)
    			exit("***error  遺伝子長≦0 (Constructor)\n");
    	
    		if ($this->max_len < $this->min_len)
    			exit("***error  最大遺伝子長<最小遺伝子長 (Constructor)\n");
    	
    		if ($this->allele_u <= $this->allele_l)
    			exit("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)\n");
        
        	$kind = $this->allele_u - $this->allele_l + 1;
    		if ($this->dup_a == 0 && $this->max_len > $kind)
        		exit("***error  遺伝子の重複を防ぐことはできない (Constructor)\n");
    	/*
    	     領域の確保
    	*/
    		$num = $this->size + $this->max_ch;
    	
    		$this->ind = array($num);
        	for ($i1 = 0; $i1 < $num; $i1++)
        		$this->ind[$i1] = array($this->max_len);
        
    		$this->edge = array($this->max_len);
    		for ($i1 = 0; $i1 < $this->max_len; $i1++)
    			$this->edge[$i1] = array(5);
    	
    		$this->pi   = array($num);
    		$this->ro   = array($num);
    		$this->len  = array($num);
    		$this->kou1 = array($this->max_len);
    		$this->kou2 = array($this->max_len);
    		$this->s_w  = array($num);
    		$this->pi_w = array($num);
    	/*
    	     乱数の初期設定
    	*/
        	mt_srand($seed);
        }
    	
        /**************************************************/
        /* 場所を探す                                     */
    	/*      n : >=0 : n番目の親を捜す                 */
    	/*          -1 : 空いている場所を探す             */
    	/*      return : 親の場所,または,空いている場所 */
    	/*               (存在しないときは負の値)       */
    	/**************************************************/
    	function Position($n)
    	{
        	$k  = -1;
        	$sw = 0;
        /*
    	     空いている場所を探す
    	*/
    		if ($n < 0) {
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch && $k < 0; $i1++) {
    				if ($this->pi_w[$i1] == 0)
    					$k = $i1;
    			}
    			if ($k < 0)
    				exit("***error  空いている場所がない --Position--\n");
    		}
    	/*
    	     n番目の親($this->pi_w[i]=2)を捜す
        */
        	else {
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch && $sw == 0; $i1++) {
        			if ($this->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 : 個体番号                                          */
    	/*******************************************************************/
    	function Select($method = -1, $bias = 0.0, $step = 1.0)
    	{
        	$sum = 0.0;
        					// ルーレット板の用意
    		switch ($method) {
        						// ランダム
        		case -1:
    				$n = 0;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1)
    						$n++;
    				}
    				$sum = 1.0 / $n;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        				if ($this->pi_w[$i1] > 1)
        					$this->ro[$i1] = $sum;
        			}
    				break;
    							// 評価値をそのまま利用
    			case 0:
    				$n = 0;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1) {
    						$sum += $this->pi[$i1];
    						$n++;
    					}
    				}
    				if (abs($sum) > 1.0e-10) {
    					$sum = 1.0 / abs($sum);
    					for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    						if ($this->pi_w[$i1] > 1)
        						$this->ro[$i1] = $this->pi[$i1] * $sum;
        				}
    				}
        			else {
        				$sum = 1.0 / $n;
    					for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    						if ($this->pi_w[$i1] > 1)
    							$this->ro[$i1] = $sum;
    					}
    				}
    				break;
    							// 最小値からの差
        		case 1:
        			$min = -1;
        			$n   = 0;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1) {
    						$n++;
    						if ($min < 0 || $this->pi[$i1] < $this->pi[$min])
    							$min = $i1;
    					}
    				}
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1) {
    						$this->ro[$i1] = $this->pi[$i1] - $this->pi[$min];
    						if ($this->ro[$i1] < $bias)
    							$this->ro[$i1] = $bias;
    						$sum += $this->ro[$i1];
    					}
        			}
        			if ($sum > 1.0e-10) {
    					$sum = 1.0 / $sum;
        				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        					if ($this->pi_w[$i1] > 1)
    							$this->ro[$i1] *= $sum;
    					}
    				}
    				else {
    					$sum = 1.0 / $n;
    					for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    						if ($this->pi_w[$i1] > 1)
        						$this->ro[$i1] = $sum;
        				}
        			}
    				break;
    							// 線形化
    			case 2:
    				$n = 0;
    				for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1) {
    						$this->ro[$i1] = -1.0;
    						$n++;
    					}
    					else
    						$this->ro[$i1] = 1.0;
    				}
    				$sw  = 0;
    				$sum = $bias;
        			while ($sw == 0) {
        				$min = -1;
    					for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        					if ($this->ro[$i1] < 0.0 && ($min < 0 || $this->pi[$i1] < $this->pi[$min]))
        						$min = $i1;
    					}
    					if ($min < 0)
    						$sw = 1;
    					else {
    						$this->ro[$min]  = $sum;
    						$sum     += $step;
    					}
        			}
        			$sum = 1.0 / (0.5 * (2.0 * $bias + $step * ($n - 1)) * $n);
        			for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    					if ($this->pi_w[$i1] > 1)
    						$this->ro[$i1] *= $sum;
    				}
    				break;
    		}
    	
    		$sum = 0.0;
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($this->pi_w[$i1] > 1) {
    				$sum           += $this->ro[$i1];
    				$this->ro[$i1]  = $sum;
    			}
    		}
    						// 選択
        	$x  = uniform();
        	$sw = 0;
    		$k  = 0;
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch && $sw == 0; $i1++) {
        		if ($this->pi_w[$i1] > 1) {
    				if ($x <= $this->ro[$i1]) {
    					$sw = 1;
    					$k  = $i1;
    				}
    			}
    		}
    	
        	return $k;
        }
        
    	/********************/
    	/* 標準的な初期設定 */
    	/********************/
    	function Init_std()
    	{
    	/*
    	     初期設定
    	*/
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($i1 < $this->size)
    				$this->pi_w[$i1] = 1;   // 適応度の計算前
    			else
    				$this->pi_w[$i1] = 0;   // 未使用
    		}
        /*
             遺伝子の決定
    	*/
        	for ($i1 = 0; $i1 < $this->size; $i1++) {
        
    			$sw1 = 0;
    	
    			while ($sw1 == 0) {
    						// 遺伝子長の決定
    				if ($this->min_len < 0)
    					$length = $this->max_len;
    				else {
        				$length = intval(uniform() * ($this->max_len - $this->min_len + 1) + $this->min_len);
        				if ($length > $this->max_len)
        					$length = $this->max_len;
    				}
    				$this->len[$i1] = $length;
    						// 遺伝子の決定
    				for ($i2 = 0; $i2 < $length; $i2++) {
    					$sw2 = 0;
    					while ($sw2 == 0) {
    						$lid = intval(uniform() * ($this->allele_u - $this->allele_l + 1) + $this->allele_l);
    						if ($lid > $this->allele_u)
    							$lid = $this->allele_u;
    						$this->ind[$i1][$i2] = $lid;
    							// 重複遺伝子のチェック
    						$sw2 = 1;
    						if ($this->dup_a == 0) {
    							for ($i3 = 0; $i3 < $i2 && $sw2 > 0; $i3++) {
        							if ($lid == $this->ind[$i1][$i3])
        								$sw2 = 0;
    							}
        					}
        				}
    				}
    						// 重複個体のチェック
    				$sw1 = 1;
    				if ($this->dup_s == 0) {
    					for ($i2 = 0; $i2 < $i1 && $sw1 > 0; $i2++) {
    						if ($this->len[$i1] == $this->len[$i2]) {
    							$sw2 = 0;
        						for ($i3 = 0; $i3 < $this->len[$i1] && $sw2 == 0; $i3++) {
        							if ($this->ind[$i1][$i3] != $this->ind[$i2][$i3])
        								$sw2 = 1;
    							}
    							if ($sw2 == 0)
    								$sw1 = 0;
    						}
    					}
    				}
    			}
    		}
    	}
    	
    	/****************************************************/
    	/* 標準的な出力                                     */
    	/*      sw : 出力レベル                             */
    	/*             =0 : 最終出力だけ                    */
        /*             n>0 : n世代毎に出力(負はファイル) */
        /*      out_m : 出力方法                            */
    	/*                =0 : すべての個体を出力           */
        /*                =1 : 最大適応度の個体だけを出力   */
        /*      gen : 現在の世代番号                        */
    	/*      name : 出力ファイル名                       */
    	/****************************************************/
    	function Out_std($sw, $out_m, $gen, $name)
    	{
    		$k = 0;
    	
    		if ($sw >= 0) {
        		printf("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
        		fscanf(STDIN, "%d", $pr);
        	}
    		else
    			$pr = -1;
    	
    		if ($pr != 0) {
    						// 出力先の決定と評価値の出力
    			if ($pr > 0) {
    				$out = STDOUT;
    				fgets(STDIN);
    			}
    			else {
    				$x   = getdate();
    				$now = $x["hours"]."時".$x["minutes"]."分".$x["seconds"]."秒";
    				$out = fopen($name, "ab");
    				fwrite($out, "***世代 ".$gen." 適応度 max ".$this->max." (".$this->max_n.") mean ".$this->mean." 時間 ".$now."\n");
        		}
    						// 詳細出力
        		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        			if (($this->pi_w[$i1] > 1) && ($out_m == 0 || $out_m == 1 && $i1 == $this->max_n)) {
    					$str = $i1." allele";
    					for ($i2 = 0; $i2 < $this->len[$i1]; $i2++)
    						$str += " ".$this->ind[$i1][$i2];
    					$str += " value ".$this->pi[$i1];
    					fwrite($out, $str."\n");
    					if ($pr > 0) {
    						$k++;
    						if ($k == $pr) {
        						fgets(STDIN);
        						$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)                                     */
    	/*******************************************************************/
    	function C_copy($method = 2, $pair = 0, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    	/*
             初期設定とデータチェック
        */
        	if ($method != 1)
    			$method = 2;
    	
    		if ($pair <= 0)
    			$pair = ($method==2) ? intval($this->max_ch/2) : $this->max_ch;
    		else {
    			if ($method == 2 && 2*$pair > $this->max_ch || $method == 1 && $pair > $this->max_ch)
    				exit("***error  子供が多すぎる (C_copy)\n");
    		}
    	/*
    	     実行
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
        					// 親の選択
        		$p1 = $this->Select($k_method, $k_bias, $k_step);
    			$sw = 0;
        
        		while ($sw == 0) {
    				$p2 = $this->Select($k_method, $k_bias, $k_step);
    				if ($p1 != $p2)
    					$sw = 1;
    			}
    						// コピー
    			for ($i2 = 0; $i2 < $method; $i2++) {
    				$p       = ($i2 == 0) ? $p1 : $p2;
        			$k       = $this->Position(-1);
        			$this->len[$k]  = $this->len[$p];
        			$this->pi_w[$k] = 1;
    				for ($i3 = 0; $i3 < $this->len[$k]; $i3++)
    					$this->ind[$k][$i3] = $this->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)                                     */
    	/*******************************************************************/
    	function C_point($kosa, $k_point = 1, $k_vr = 0, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    		$mn = 0;
    	/*
    	     初期設定とデータのチェック
        */
        	$pair = $this->max_ch / 2;
        
    		if ($this->dup_a == 0)
    			exit("***error  交叉方法が不適当 (C_point)\n");
    	
    		$abs_p = abs($k_point);
    		if ($abs_p == 0 || $abs_p > $this->max_len-1 || $this->min_len > 0 && $abs_p > $this->min_len-1)
    			exit("***error  交叉点の数が不適当 (C_point)\n");
    	
    		if ($k_vr > 0 && $this->min_len < 0)
    			exit("***error  遺伝子長は可変でなければならない (C_point)\n");
        /*
    	     交叉
        */
        	$num = $k_point;
    	
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
        						// 親の選択
        			$p1 = $this->Select($k_method, $k_bias, $k_step);
        			$sw = 0;
    				while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
    					if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 交叉位置の数の決定
    				if ($k_point < 0) {
    					$num = intval(uniform() * $abs_p + 1);
    					if ($num > $abs_p)
    						$num = $abs_p;
    				}
    							// 交叉位置の決定(点の後ろで交叉)
    				for ($i2 = 0; $i2 < $num; $i2++) {
    								// 親1の交叉位置
        				$sw = 0;
        				while ($sw == 0) {
    						$sw              = 1;
        					$this->kou1[$i2] = intval(uniform() * ($this->len[$p1] - 1));
        					if ($this->kou1[$i2] > $this->len[$p1]-2)
    							$this->kou1[$i2] = $this->len[$p1] - 2;
    						if ($k_vr == 0 && $this->kou1[$i2] > $this->len[$p2]-2)
    							$this->kou1[$i2] = $this->len[$p2] - 2;
    						for ($i3 = 0; $i3 < $i2 && $sw > 0; $i3++) {
    							if ($this->kou1[$i3] == $this->kou1[$i2])
    								$sw = 0;
    						}
        				}
        							// 親2の交叉位置
        				if ($k_vr > 0) {
    						$sw = 0;
    						while ($sw == 0) {
    							$sw              = 1;
    							$this->kou2[$i2] = intval(uniform() * ($this->len[$p2] - 1));
    							if ($this->kou2[$i2] > $this->len[$p2]-2)
    								$this->kou2[$i2] = $this->len[$p2] - 2;
    							for ($i3 = 0; $i3 < $i2 && $sw > 0; $i3++) {
    								if ($this->kou2[$i3] == $this->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              = $this->Position(-1);
        			$this->pi_w[$k1] = 1;
        			$this->len[$k1]  = $this->len[$p1];
        			$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    	
    				for ($i2 = 0; $i2 < $num+1; $i2++ ) {
    								// 次の交叉位置を求める
    					if ($i2 == $num) {            // 最後
    						$t12 = $this->len[$p1];
    						$t22 = $this->len[$p2];
    					}
    					else {
    									// 親1
    						$t12 = $this->max_len;
    						for ($i3 = 0; $i3 < $num; $i3++) {
    							if ($this->kou1[$i3] >= 0 && $this->kou1[$i3] <= $t12) {
        							$t12 = $this->kou1[$i3];
        							$mn  = $i3;
    							}
        					}
        					$this->kou1[$mn] = -1;
    						$t12++;
    									// 親2
    						if ($k_vr == 0)
    							$t22 = $t12;
    						else {
    							$t22 = $this->max_len;
    							for ($i3 = 0; $i3 < $num; $i3++) {
        							if ($this->kou2[$i3] >= 0 && $this->kou2[$i3] <= $t22) {
        								$t22 = $this->kou2[$i3];
        								$mn  = $i3;
    								}
    							}
    							$this->kou2[$mn] = -1;
    							$t22++;
    						}
    					}
    								// 指定箇所のコピー
    					for ($i3 = $t11; $i3 < $t12; $i3++) {
    						if ($i2%2 == 0) {
    							if ($c1 < $this->max_len) {
    								$this->ind[$k1][$c1] = $this->ind[$p1][$i3];
    								$c1++;
    							}
    						}
        					else {
        						if ($c2 < $this->max_len) {
    								$this->ind[$k2][$c2] = $this->ind[$p1][$i3];
        							$c2++;
        						}
    						}
    					}
    	
    					for ($i3 = $t21; $i3 < $t22; $i3++) {
    						if ($i2%2 == 0) {
    							if ($c2 < $this->max_len) {
    								$this->ind[$k2][$c2] = $this->ind[$p2][$i3];
        							$c2++;
        						}
        					}
    						else {
    							if ($c1 < $this->max_len) {
    								$this->ind[$k1][$c1] = $this->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)                                     */
        /*******************************************************************/
        function C_uniform($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
        {
    	/*
    	     初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a == 0)
    			exit("***error  交叉方法が不適当 (C_uniform)\n");
    	
    		if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_uniform)\n");
        /*
             交叉
    	*/
        	for ($i1 = 0; $i1 < $pair; $i1++) {
        					// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
        			while ($sw == 0) {
        				$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
    				$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    							// 交叉
    				for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					if (uniform() > 0.5) {
    						$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    						$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
        				}
        				else {
    						$this->ind[$k1][$i2] = $this->ind[$p2][$i2];
        					$this->ind[$k2][$i2] = $this->ind[$p1][$i2];
        				}
    				}
    			}
    		}
    	}
    	
    	/*******************************************************************/
    	/* 交叉(平均化交叉.2つの親の平均値を受け継ぐ)                  */
        /*      kosa : 交叉確率                                            */
        /*      k_method : 選択方法                                        */
        /*                 =-1 : ランダム(default)                         */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値(default=0)     */
    	/*      k_step : β(default=1)                                     */
    	/*******************************************************************/
    	function C_mean($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    	/*
    	     初期設定とデータのチェック
    	*/
    		if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_mean)\n");
        /*
    	     交叉
        */
        	for ($i1 = 0; $i1 < $this->max_ch; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(1, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
        			$sw = 0;
        			while ($sw == 0) {
        				$p2 = $this->Select($k_method, $k_bias, $k_step);
    					if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 遺伝子長
    				$k             = $this->Position(-1);
    				$this->len[$k]  = $this->len[$p1];
    				$this->pi_w[$k] = 1;
    							// 交叉
    				for ($i2 = 0; $i2 < $this->len[$k]; $i2++)
    					$this->ind[$k][$i2] = ($this->ind[$p1][$i2] + $this->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)                                     */
    	/*******************************************************************/
    	function C_cycle($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    	/*
    	     初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_cycle)\n");
    	
        	if ($this->min_len > 0)
        		exit("***error  遺伝子長は固定長でなければならない (C_cycle)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
        		if (uniform() > $kosa)
        			$this->C_copy(2, 1);
        					// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
    					if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 初期設定
    				for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					$this->kou1[$i2] = 0;
    					$this->kou2[$i2] = 0;
    				}
        						// 遺伝子長
        			$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
        			$this->len[$k1]  = $this->len[$p1];
        			$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    							// 交叉
    				$sw = 0;
    	
    				while ($sw == 0) {
    					$sw = 1;
        				$p  = intval(uniform() * $this->len[$p1]);
        				if ($p >= $this->len[$p1])
        					$p = $this->len[$p1] - 1;
    					if ($this->kou1[$p] == 0 && $this->kou2[$p] == 0) {
    						$this->kou1[$p]     = 1;
    						$this->kou2[$p]     = 1;
    						$this->ind[$k1][$p] = $this->ind[$p1][$p];
    						$this->ind[$k2][$p] = $this->ind[$p2][$p];
    						for ($i2 = 0; $i2 < $this->len[$p1] && $sw > 0; $i2++) {
    							if ($this->ind[$p2][$p] == $this->ind[$p1][$i2]) {
    								$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    								$this->kou1[$i2]     = 1;
    								$sw                  = 0;
    							}
    						}
    						$sw = 1;
    						for ($i2 = 0; $i2 < $this->len[$p2] && $sw > 0; $i2++) {
        						if ($this->ind[$p1][$p] == $this->ind[$p2][$i2]) {
        							$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
    								$this->kou2[$i2]     = 1;
        							$sw                  = 0;
        						}
    						}
    					}
    				}
    	
    				$sw = 0;
    				$i2 = 0;
    				$i3 = 0;
        			while ($sw == 0) {
        				while ($sw == 0 && $i2 < $this->len[$p1]) {
        					if ($this->kou1[$i2] == 0)
    							$sw = 1;
    						else
    							$i2++;
    					}
    					$sw = 0;
    					while ($sw == 0 && $i3 < $this->len[$p2]) {
    						if ($this->kou2[$i3] == 0)
    							$sw = 1;
    						else
    							$i3++;
    					}
    					if ($i2 < $this->len[$p1] && $i3 < $this->len[$p2]) {
    						$this->ind[$k1][$i2] = $this->ind[$p2][$i3];
    						$this->ind[$k2][$i3] = $this->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)                                     */
    	/*******************************************************************/
    	function C_part($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
        {
    	/*
             初期設定とデータのチェック
        */
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_part)\n");
    	
        	if ($this->min_len > 0)
        		exit("***error  遺伝子長は固定長でなければならない (C_part)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
        				$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
    						$sw = 1;
        			}
        						// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
    				$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    							// 交叉
        			$p = intval(uniform() * $this->len[$p1]);
        			if ($p >= $this->len[$p1])
        				$p = $this->len[$p1] - 1;
    	
    				for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    					$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
    				}
    	
    				for ($i2 = $p; $i2 < $this->len[$p1]; $i2++) {
    					$sw = 0;
    					$lv = $this->ind[$k1][$i2];
    					for ($i3 = 0; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    						if ($this->ind[$k2][$i2] == $this->ind[$k1][$i3]) {
    							$this->ind[$k1][$i2] = $this->ind[$k1][$i3];
    							$this->ind[$k1][$i3] = $lv;
    							$sw                  = 1;
        					}
        				}
    					$sw = 0;
        				for ($i3 = 0; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
        					if ($lv == $this->ind[$k2][$i3]) {
    							$this->ind[$k2][$i3] = $this->ind[$k2][$i2];
    							$this->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)                                     */
        /*******************************************************************/
    	function C_seq($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
        {
        /*
    	     初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_seq)\n");
        
        	if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_seq)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
        			$sw = 0;
        			while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
        					$sw = 1;
    				}
    							// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
    				$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
        			$this->len[$k2]  = $this->len[$p2];
        						// 交叉
        			$p = intval(uniform() * ($this->len[$p1] - 1));
    				if ($p >= $this->len[$p1]-1)
    					$p = $this->len[$p1] - 2;
    	
    				for ($i2 = 0; $i2 <= $p; $i2++) {
    					$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    					$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
    				}
    	
    				$pp = 0;
    				for ($i2 = $p+1; $i2 < $this->len[$p1]; $i2++) {
    					$sw = 0;
    					for ($i3 = $pp; $i3 < $this->len[$p2] && $sw == 0; $i3++) {
    						for ($i4 = $p+1; $i4 < $this->len[$p1] && $sw == 0; $i4++) {
    							if ($this->ind[$p2][$i3] == $this->ind[$p1][$i4]) {
        							$sw                  = 1;
        							$pp                  = $i3 + 1;
    								$this->ind[$k1][$i2] = $this->ind[$p1][$i4];
        						}
        					}
    					}
    				}
    				$pp = 0;
    				for ($i2 = $p+1; $i2 < $this->len[$p2]; $i2++) {
    					$sw = 0;
    					for ($i3 = $pp; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    						for ($i4 = $p+1; $i4 < $this->len[$p2] && $sw == 0; $i4++) {
        						if ($this->ind[$p1][$i3] == $this->ind[$p2][$i4]) {
        							$sw                  = 1;
        							$pp                  = $i3 + 1;
    								$this->ind[$k2][$i2] = $this->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)                                     */
    	/*******************************************************************/
    	function C_useq($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
        {
        /*
             初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_useq)\n");
    	
    		if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_useq)\n");
    	/*
    	     交叉
        */
        	for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
        		if (uniform() > $kosa)
        			$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
        					$sw = 1;
        			}
    							// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
    				$k2              = $this->Position(-1);
    				$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
    							// 交叉
    				for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					$this->ind[$k1][$i2] = $this->ind[$p1][$i2];
    					$this->ind[$k2][$i2] = $this->ind[$p2][$i2];
    					$this->kou1[$i2]     = (uniform() < 0.5) ? 0 : 1;
    				}
    	
        			$p = 0;
        			for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					if ($this->kou1[$i2] > 0) {
        					$sw = 0;
        					for ($i3 = $p; $i3 < $this->len[$p2] && $sw == 0; $i3++) {
    							for ($i4 = 0; $i4 < $this->len[$p1] && $sw == 0; $i4++) {
    								if ($this->ind[$p2][$i3] == $this->ind[$p1][$i4] && $this->kou1[$i4] > 0) {
    									$sw                  = 1;
    									$p                   = $i3 + 1;
    									$this->ind[$k1][$i2] = $this->ind[$p1][$i4];
    								}
    							}
        					}
        				}
        			}
    				$p = 0;
    				for ($i2 = 0; $i2 < $this->len[$p2]; $i2++) {
    					if ($this->kou1[$i2] > 0) {
    						$sw = 0;
    						for ($i3 = $p; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    							for ($i4 = 0; $i4 < $this->len[$p2] && $sw == 0; $i4++) {
    								if ($this->ind[$p1][$i3] == $this->ind[$p2][$i4] && $this->kou1[$i4] > 0) {
    									$sw                  = 1;
    									$p                   = $i3 + 1;
    									$this->ind[$k2][$i2] = $this->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)                                     */
    	/*******************************************************************/
    	function C_upos($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
    	/*
    	     初期設定とデータのチェック
    	*/
    		$pair = $this->max_ch / 2;
    	
    		if ($this->dup_a != 0)
        		exit("***error  交叉方法が不適当 (C_upos)\n");
        
        	if ($this->min_len > 0)
    			exit("***error  遺伝子長は固定長でなければならない (C_upos)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
        					// 交叉しない場合
        		if (uniform() > $kosa)
        			$this->C_copy(2, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
    					$p2 = $this->Select($k_method, $k_bias, $k_step);
    					if ($p1 != $p2)
    						$sw = 1;
    				}
    							// 遺伝子長
    				$k1              = $this->Position(-1);
    				$this->pi_w[$k1] = 1;
    				$this->len[$k1]  = $this->len[$p1];
        			$k2              = $this->Position(-1);
        			$this->pi_w[$k2] = 1;
    				$this->len[$k2]  = $this->len[$p2];
        						// 交叉
        			for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
    					$this->kou1[$i2] = (uniform() < 0.5) ? 0 : 1;
    					if ($this->kou1[$i2] > 0) {
    						$this->ind[$k1][$i2] = $this->ind[$p2][$i2];
    						$this->ind[$k2][$i2] = $this->ind[$p1][$i2];
    					}
    				}
    	
        			$p = 0;
        			for ($i2 = 0; $i2 < $this->len[$p1]; $i2++) {
        				$sw = 0;
    					for ($i3 = 0; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    						if ($this->kou1[$i3] > 0 && $this->ind[$p1][$i2] == $this->ind[$k1][$i3])
    							$sw = 1;
    					}
    					if ($sw == 0) {
    						for ($i3 = $p; $i3 < $this->len[$p1] && $sw == 0; $i3++) {
    							if ($this->kou1[$i3] == 0) {
    								$this->ind[$k1][$i3] = $this->ind[$p1][$i2];
    								$p                   = $i3 + 1;
    								$sw                  = 1;
    							}
    						}
    					}
    				}
        			$p = 0;
        			for ($i2 = 0; $i2 < $this->len[$p2]; $i2++) {
    					$sw = 0;
        				for ($i3 = 0; $i3 < $this->len[$p2] && $sw == 0; $i3++) {
        					if ($this->kou1[$i3] > 0 && $this->ind[$p2][$i2] == $this->ind[$k2][$i3])
    							$sw = 1;
    					}
    					if ($sw == 0) {
    						for ($i3 = $p; $i3 < $this->len[$p2] && $sw == 0; $i3++) {
    							if ($this->kou1[$i3] == 0) {
    								$this->ind[$k2][$i3] = $this->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)                                     */
    	/*******************************************************************/
    	function C_edge($kosa, $k_method = -1, $k_bias = 0.0, $k_step = 1.0)
    	{
        	$e  = array(2);
        	$k0 = 0;
    	/*
             初期設定とデータのチェック
        */
    		$pair = $this->max_ch;
    	
    		if ($this->dup_a != 0)
    			exit("***error  交叉方法が不適当 (C_edge)\n");
    	
        	if ($this->min_len > 0)
        		exit("***error  遺伝子長は固定長でなければならない (C_edge)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $pair; $i1++) {
    						// 交叉しない場合
    			if (uniform() > $kosa)
    				$this->C_copy(1, 1);
    						// 交叉する場合
    			else {
    							// 親の選択
    				$p1 = $this->Select($k_method, $k_bias, $k_step);
    				$sw = 0;
    				while ($sw == 0) {
        				$p2 = $this->Select($k_method, $k_bias, $k_step);
        				if ($p1 != $p2)
    						$sw = 1;
        			}
        						// 遺伝子長
    				$k              = $this->Position(-1);
    				$this->pi_w[$k] = 1;
    				$this->len[$k]  = $this->len[$p1];
    							// エッジマップの初期化
    				for ($i2 = 0; $i2 < $this->len[$k]; $i2++) {
    					$this->edge[$i2][0] = 0;
    					for ($i3 = 1; $i3 <= 4; $i3++)
        					$this->edge[$i2][$i3] = -1;
        			}
        						// 交叉
    								// エッジマップの作成
    				for ($i2 = 0; $i2 < $this->len[$k]; $i2++) {
    	
    					$sw = 0;
    					for ($i3 = 0; $i3 < $this->len[$k] && $sw == 0; $i3++) {
    						if ($i2 == $this->ind[$p1][$i3]) {
    							$sw = 1;
    							if ($i3 == 0) {
    								$e[0] = $this->ind[$p1][$this->len[$k]-1];
    								$e[1] = $this->ind[$p1][1];
    							}
    							else {
    								if ($i3 == $this->len[$k]-1) {
    									$e[0] = $this->ind[$p1][$i3-1];
        								$e[1] = $this->ind[$p1][0];
        							}
    								else {
        								$e[0] = $this->ind[$p1][$i3-1];
        								$e[1] = $this->ind[$p1][$i3+1];
    								}
    							}
    							for ($i4 = 0; $i4 < 2; $i4++) {
    								$this->edge[$i2][0]++;
    								$this->edge[$i2][$this->edge[$i2][0]] = $e[$i4];
    							}
    						}
        				}
        
        				$sw = 0;
    					for ($i3 = 0; $i3 < $this->len[$k] && $sw == 0; $i3++) {
    						if ($i2 == $this->ind[$p2][$i3]) {
    							$sw = 1;
    							if ($i3 == 0) {
    								$e[0] = $this->ind[$p2][$this->len[$k]-1];
    								$e[1] = $this->ind[$p2][1];
    							}
    							else {
    								if ($i3 == $this->len[$k]-1) {
    									$e[0] = $this->ind[$p2][$i3-1];
    									$e[1] = $this->ind[$p2][0];
    								}
    								else {
    									$e[0] = $this->ind[$p2][$i3-1];
        								$e[1] = $this->ind[$p2][$i3+1];
        							}
    							}
        						for ($i4 = 0; $i4 < 2; $i4++) {
        							$sw = 1;
    								for ($i5 = 1; $i5 <= $this->edge[$i2][0] && $sw == 1; $i5++) {
    									if ($this->edge[$i2][$i5] == $e[$i4])
    										$sw = 2;
    								}
    								if ($sw == 1) {
    									$this->edge[$i2][0]++;
    									$this->edge[$i2][$this->edge[$i2][0]] = $e[$i4];
        							}
        						}
        					}
    					}
    				}
    								// 交叉の実行
    									// 出発点の決定
    				$k1 = $this->ind[$p1][0];
    				$k2 = $this->ind[$p2][0];
    				if ($this->edge[$k1][0] == $this->edge[$k2][0])
    					$kk = (uniform() > 0.5) ? $k2 : $k1;
    				else
    					$kk = ($this->edge[$k1][0] < $this->edge[$k2][0]) ? $k1 : $k2;
    				$this->ind[$k][0] = $kk;
    				$p                = 1;
    	
    				while ($p < $this->len[$k]) {
        								// ノードの除去
        				for ($i2 = 0; $i2 < $this->len[$k]; $i2++) {
    						$sw = 0;
        					if ($this->edge[$i2][0] > 0) {
        						for ($i3 = 1; $i3 <= 4 && $sw == 0; $i3++) {
    								if ($this->edge[$i2][$i3] == $kk) {
    									$sw                   = 1;
    									$this->edge[$i2][$i3] = -1;
    									$this->edge[$i2][0]--;
    								}
    							}
    						}
        				}
        								// 次の現在ノードの選択
        				$min = 10;
    					$num = 0;
    					for ($i2 = 1; $i2 <= 4; $i2++) {
    						if ($this->edge[$kk][$i2] >= 0) {
    							$k1 = $this->edge[$kk][$i2];
    							if ($this->edge[$k1][0] >= 0 && $this->edge[$k1][0] < $min) {
    								$num = 1;
    								$min = $this->edge[$k1][0];
    								$k0  = $k1;
    							}
    							else {
    								if ($this->edge[$k1][0] == $min)
    									$num++;
    							}
    						}
        				}
        				if ($num > 1) {
    						$k1 = intval(uniform() * $num) + 1;
        					if ($k1 > $num)
        						$k1 = $num;
    						$k2 = 0;
    						$k0 = -1;
    						for ($i2 = 1; $i2 <= 4 && $k0 < 0; $i2++) {
    							if ($this->edge[$kk][$i2] >= 0) {
    								if ($this->edge[$this->edge[$kk][$i2]][0] == $min) {
    									$k2++;
    									if ($k1 == $k2)
        									$k0 = $this->edge[$kk][$i2];
        							}
        						}
    						}
    					}
    					else {
    						if ($num <= 0) {
    							$num = 0;
    							for ($i2 = 0; $i2 < $this->len[$k]; $i2++) {
    								if ($i2 != $kk && $this->edge[$i2][0] >= 0)
    									$num++;
    							}
    							if ($num <= 0)
    								exit("***error  invalid data (C_edge)\n");
    							else {
        							$k1 = intval(uniform() * $num) + 1;
        							if ($k1 > $num)
    									$k1 = $num;
        							$k2 = 0;
        							$k0 = -1;
    								for ($i2 = 0; $i2 < $this->len[$k] && $k0 < 0; $i2++) {
    									if ($i2 != $kk && $this->edge[$i2][0] >= 0) {
    										$k2++;
    										if ($k1 == $k2)
    											$k0 = $i2;
    									}
    								}
        						}
        					}
        				}
    					$this->edge[$kk][0] = -1;
    					$this->ind[$k][$p]  = $k0;
    					$kk                 = $k0;
    					$p++;
    				}
    			}
    		}
    	}
    	
    	/*************************************************************/
    	/* 交叉(サブツアー交叉.2点交叉の拡張である.ただし,相手に*/
    	/*       同じ遺伝子のグループがない限り実行されない.たとえば*/
    	/*         ***abcd**                                         */
    	/*         *cdab****                                         */
        /*       のような両親の時実行され,以下の4つの子供が生成され*/
        /*       る)                                                */
    	/*         ***cdab**                                         */
        /*         *abcd****                                         */
        /*         ***badc**                                         */
    	/*         *dcba****                                         */
    	/*       最大,4*交叉回数*個体総数*(個体総数-1) 個の子 */
    	/*       供が生成される可能性があるので,子供の数としてこの値*/
    	/*       以上のデータを入力しておく必要がある.              */
    	/*      kosa : 交叉確率                                      */
    	/*      count : 1つのペアーに対する交差回数(default=10)     */
    	/*************************************************************/
        function C_sub($kosa, $count = 10)
        {
        	$t22 = 0;
    	/*
    	     初期設定とデータのチェック
    	*/
    		if ((4*$count*$this->size*($this->size-1)) > $this->max_ch)
    			exit("***error  子供が多すぎる (C_sub)\n");
    	/*
    	     交叉
    	*/
    		for ($i1 = 0; $i1 < $this->size-1; $i1++) {
    						// 親1
    			$p1 = $this->Position($i1);
    	
        		if ($p1 >= 0) {
        
    				for ($i2 = $i1; $i2 < $this->size; $i2++) {
        					// 親2
        				$p2 = $this->Position($i2);
    	
    					if ($p2 >= 0) {
    						// 交叉しない場合
    						if (uniform() > $kosa)
    							$this->C_copy(2, 1);
    						// 交叉する場合
    						else {
        						// 交叉回数の制御
        						for ($i3 = 0; $i3 < $count; $i3++) {
        							// 交叉位置の決定(点の後ろで交叉)
    									// 親1の交叉位置
    								$t11 = intval(uniform() * $this->len[$p1]);
    								if ($t11 > ($this->len[$p1]-1))
    									$t11 = $this->len[$p1] - 1;
    								$sw = 0;
    								while ($sw == 0) {
    									$t12 = intval(uniform() * $this->len[$p1]);
    									if ($t12 > ($this->len[$p1]-1))
    										$t12 = $this->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 < $this->len[$p2] && $t21 < 0; $i4++) {
    									for ($i5 = $t11; $i5 <= $t12 && $t21 < 0; $i5++) {
    										if ($this->ind[$p2][$i4] == $this->ind[$p1][$i5])
    											$t21 = $i4;
    									}
    								}
        							if ($t21 >= 0) {
        								$t22 = $t21 + $t12 - $t11;
        								if ($t22 < $this->len[$p2]) {
    										$sw = 1;
    										for ($i4 = $t21+1; $i4 <= $t22 && $sw > 0; $i4++) {
    											$sw = 0;
    											for ($i5 = $t11; $i5 <= $t12 && $sw == 0; $i5++) {
    												if ($this->ind[$p2][$i4] == $this->ind[$p1][$i5])
    													$sw = 1;
    											}
    										}
    									}
    								}
    									// 交叉の実行
    								if ($sw > 0) {
    	
    									$k1              = $this->Position(-1);
        								$this->pi_w[$k1] = 1;
        								$this->len[$k1]  = $this->len[$p1];
    									$k2              = $this->Position(-1);
        								$this->pi_w[$k2] = 1;
        								$this->len[$k2]  = $this->len[$p1];
    									$k3              = $this->Position(-1);
    									$this->pi_w[$k3] = 1;
    									$this->len[$k3]  = $this->len[$p2];
    									$k4              = $this->Position(-1);
    									$this->pi_w[$k4] = 1;
    									$this->len[$k4]  = $this->len[$p2];
    	
        								for ($i4 = 0; $i4 < $t11; $i4++) {
        									$this->ind[$k1][$i4] = $this->ind[$p1][$i4];
        									$this->ind[$k2][$i4] = $this->ind[$p1][$i4];
    									}
    									for ($i4 = $t11; $i4 <= $t12; $i4++) {
    										$this->ind[$k1][$i4] = $this->ind[$p2][$t21+$i4-$t11];
    										$this->ind[$k2][$i4] = $this->ind[$p2][$t22-$i4+$t11];
    									}
    									for ($i4 = $t12+1; $i4 < $this->len[$p1]; $i4++) {
    										$this->ind[$k1][$i4] = $this->ind[$p1][$i4];
    										$this->ind[$k2][$i4] = $this->ind[$p1][$i4];
    									}
    									for ($i4 = 0; $i4 < $t21; $i4++) {
    										$this->ind[$k3][$i4] = $this->ind[$p2][$i4];
    										$this->ind[$k4][$i4] = $this->ind[$p2][$i4];
    									}
    									for ($i4 = $t21; $i4 <= $t22; $i4++) {
        									$this->ind[$k3][$i4] = $this->ind[$p1][$t11+$i4-$t21];
        									$this->ind[$k4][$i4] = $this->ind[$p1][$t12-$i4+$t21];
    									}
        								for ($i4 = $t22+1; $i4 < $this->len[$p2]; $i4++) {
        									$this->ind[$k3][$i4] = $this->ind[$p2][$i4];
    										$this->ind[$k4][$i4] = $this->ind[$p2][$i4];
    									}
    								}
    							}
    						}
    					}
    				}
        		}
        	}
        }
    	
    	/**************************************/
    	/* 突然変異(対立遺伝子との置き換え) */
    	/*      pr : 突然変異率               */
    	/**************************************/
    	function M_alle($pr)
    	{
    	/*
    	     データのチェックと初期設定
    	*/
    		if ($this->dup_a == 0)
    			exit("***error  突然変異方法が不適当 (M_alle)\n");
        /*
             実行
    	*/
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        		if ($this->pi_w[$i1] == 1) {
    				for ($i2 = 0; $i2 < $this->len[$i1]; $i2++) {
    					if (uniform() <= $pr) {
    						$lid = intval(uniform() * ($this->allele_u - $this->allele_l + 1) + $this->allele_l);
    						if ($lid > $this->allele_u)
    							$lid = $this->allele_u;
    						if ($lid != $this->ind[$i1][$i2])
    							$this->ind[$i1][$i2] = $lid;
        				}
        			}
        		}
    		}
    	}
    	
    	/**********************************************************************/
    	/* 突然変異(移動.2点を選択し,2番目の遺伝子を1番目の遺伝子の前に */
    	/*           移動する)                                               */
    	/*      pr : 突然変異率                                               */
    	/**********************************************************************/
    	function M_move($pr)
    	{
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    	/*
             位置の決定
        */
    						// p1
        			$p1 = intval(uniform() * $this->len[$i1]);
        			if ($p1 >= $this->len[$i1])
    					$p1 = $this->len[$i1] - 1;
    						// p2
    				$sw = 0;
    				while ($sw == 0) {
    					$p2 = intval(uniform() * $this->len[$i1]);
    					if ($p2 >= $this->len[$i1])
    						$p2 = $this->len[$i1] - 1;
        				if ($p2 != $p1)
        					$sw = 1;
        			}
    	/*
    	     実行
    	*/
    				if ($p2 > $p1) {
    					$ld = $this->ind[$i1][$p2];
    					for ($i2 = $p2; $i2 > $p1; $i2--)
    						$this->ind[$i1][$i2] = $this->ind[$i1][$i2-1];
    					$this->ind[$i1][$p1] = $ld;
    				}
    				else {
    					$ld = $this->ind[$i1][$p2];
    					for ($i2 = $p2; $i2 < $p1-1; $i2++)
    						$this->ind[$i1][$i2] = $this->ind[$i1][$i2+1];
    					$this->ind[$i1][$p1-1] = $ld;
        			}
        		}
    		}
        }
        
    	/********************************************************/
    	/* 突然変異(逆位.2点間の遺伝子順序を逆に並べ替える) */
    	/*      pr : 突然変異率                                 */
    	/*      wd : >0 : 幅を固定                              */
    	/*           =0 : 幅をランダム(default)                 */
    	/********************************************************/
    	function M_inv($pr, $wd = 0)
        {
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    	/*
    	     区間の決定
    	*/
    				if ($wd == 0) {
    					$p1 = intval(uniform() * $this->len[$i1]);
    					if ($p1 >= $this->len[$i1])
    						$p1 = $this->len[$i1] - 1;
    					$sw = 0;
    					while ($sw == 0) {
    						$p2 = intval(uniform() * $this->len[$i1]);
    						if ($p2 >= $this->len[$i1])
        						$p2 = $this->len[$i1] - 1;
        					if ($p2 != $p1)
    							$sw = 1;
        				}
        				if ($p1 > $p2) {
    						$p  = $p1;
    						$p1 = $p2;
    						$p2 = $p;
    					}
    				}
    	
    				else {
        				$p1 = $this->len[$i1];
        				while ($p1 > $this->len[$i1]-2)
        					$p1 = intval(uniform() * $this->len[$i1]);
    					$p2 = $p1 + $wd - 1;
    					if ($p2 >= $this->len[$i1])
    						$p2 = $this->len[$i1] - 1;
    				}
    	/*
    	     実行
    	*/
    				$sw = 0;
    				while ($sw == 0) {
    					$lid         = $this->ind[$i1][$p1];
    					$this->ind[$i1][$p1] = $this->ind[$i1][$p2];
    					$this->ind[$i1][$p2] = $lid;
    					$p1++;
    					$p2--;
        				if ($p1 >= $p2)
        					$sw = 1;
    				}
        		}
        	}
    	}
    	
    	/**********************************************************************/
    	/* 突然変異(スクランブル.2点間の遺伝子順序をランダムに並べ替える) */
    	/*      pr : 突然変異率                                               */
    	/*      wd : >0 : 幅を固定                                            */
    	/*           =0 : 幅をランダム(default)                               */
        /**********************************************************************/
        function M_scram($pr, $wd = 0)
        {
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    	/*
    	     区間の決定
    	*/
    				if ($wd == 0) {
    					$p1 = intval(uniform() * $this->len[$i1]);
    					if ($p1 >= $this->len[$i1])
    						$p1 = $this->len[$i1] - 1;
    					$sw = 0;
    					while ($sw == 0) {
    						$p2 = intval(uniform() * $this->len[$i1]);
    						if ($p2 >= $this->len[$i1])
        						$p2 = $this->len[$i1] - 1;
        					if ($p2 != $p1)
    							$sw = 1;
        				}
        				if ($p1 > $p2) {
    						$p  = $p1;
    						$p1 = $p2;
    						$p2 = $p;
    					}
    				}
    	
    				else {
        				$p1 = $this->len[$i1];
        				while ($p1 > $this->len[$i1]-2)
        					$p1 = intval(uniform() * $this->len[$i1]);
    					$p2 = $p1 + $wd - 1;
    					if ($p2 >= $this->len[$i1])
    						$p2 = $this->len[$i1] - 1;
    				}
    	/*
    	     実行
    	*/
    				for ($i2 = $p1; $i2 <= $p2; $i2++) {
    					$p = intval(uniform() * ($p2 - $p1 + 1) + $p1);
    					if ($p > $p2)
    						$p = $p2;
    					$ld                  = $this->ind[$i1][$i2];
    					$this->ind[$i1][$i2] = $this->ind[$i1][$p];
    					$this->ind[$i1][$p]  = $ld;
        			}
        		}
    		}
        }
        
    	/**********************************************************************/
    	/* 突然変異(転座.2点間の遺伝子を他の位置のものと置き換える.ただし */
    	/*           重複部分はそのままとする)                               */
    	/*      pr : 突然変異率                                               */
    	/*      wd : >0 : 幅を固定                                            */
    	/*           =0 : 幅をランダム(default)                               */
    	/**********************************************************************/
        function M_chg($pr, $wd = 0)
        {
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    	/*
    	     区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    	*/
    						// p1
    				$p1 = intval(uniform() * $this->len[$i1]);
    				if ($p1 >= $this->len[$i1])
    					$p1 = $this->len[$i1] - 1;
    						// p3
    				$sw = 0;
    				while ($sw == 0) {
    					$p3 = intval(uniform() * $this->len[$i1]);
    					if ($p3 >= $this->len[$i1])
        					$p3 = $this->len[$i1] - 1;
        				if ($p3 != $p1)
    						$sw = 1;
        			}
        					// 小さい方をp1,p2にする
    				if ($p1 > $p3) {
    					$p  = $p1;
    					$p1 = $p3;
    					$p3 = $p;
    				}
    						// p4, p2
    				$p4 = ($wd == 0) ? intval(uniform() * ($this->len[$i1] - $p3)) + $p3 : $p1 + $wd - 1;
        			if ($p4 >= $this->len[$i1])
        				$p4 = $this->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                  = $this->ind[$i1][$i2];
        				$this->ind[$i1][$i2] = $this->ind[$i1][$p];
        				$this->ind[$i1][$p]  = $ld;
    					$p++;
        			}
        		}
    		}
    	}
    	
    	/**********************************************************************/
    	/* 突然変異(重複.2点間の遺伝子を他の位置にコピーする               */
    	/*      pr : 突然変異率                                               */
    	/*      wd : >0 : 幅を固定                                            */
        /*           =0 : 幅をランダム(deafult)                               */
        /**********************************************************************/
        function M_dup($pr, $wd = 0)
    	{
    	/*
    	     データのチェック
    	*/
    		if ($this->dup_a == 0)
    			exit("***error  突然変異方法が不適当 (M_dup)\n");
    	/*
    	     実行
    	*/
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
        					// 区間の決定([p1,p2]を[p3,p4]にコピー)
        						// p1
    				$p1 = intval(uniform() * $this->len[$i1]);
        			if ($p1 >= $this->len[$i1])
        				$p1 = $this->len[$i1] - 1;
    							// p3
    				$sw = 0;
    				while ($sw == 0) {
    					$p3 = intval(uniform() * $this->len[$i1]);
    					if ($p3 >= $this->len[$i1])
    						$p3 = $this->len[$i1] - 1;
    					if ($p3 != $p1)
        					$sw = 1;
        			}
        						// 区間を決める
    				if ($p3 > $p1) {
    					$p4 = ($wd == 0) ? intval(uniform() * ($this->len[$i1] - $p3)) + $p3 : $p3 + $wd - 1;
    					if ($p4 >= $this->len[$i1])
    						$p4 = $this->len[$i1] - 1;
    					$p2 = $p1 + ($p4 - $p3);
    				}
    				else {
    					$p2 = ($wd == 0) ? intval(uniform() * ($this->len[$i1] - $p1)) + $p1 :$p1 + $wd - 1;
    					if ($p2 >= $this->len[$i1])
    						$p2 = $this->len[$i1] - 1;
    					$p4 = $p3 + ($p2 - $p1);
    				}
        					// 実行
        			$p = $p4;
    				for ($i2 = $p2; $i2 >= $p1; $i2--) {
        				$this->ind[$i1][$p] = $this->ind[$i1][$i2];
        				$p--;
    				}
    			}
    		}
    	}
    	
    	/******************************************************/
    	/* 突然変異(摂動.値をある量だけ変化させる)         */
        /*      pr : 突然変異率                               */
        /*      method : =0 : 正規分布(default)               */
        /*               =1 : 一様分布                        */
    	/*      m : 平均または一様分布の下限(default=0.0)     */
    	/*      s : 標準偏差または一様分布の上限(default=1.0) */
    	/******************************************************/
    	function M_per($pr, $method = 0, $m = 0.0, $s = 1.0)
    	{
    		$wd = 0.0;
    	/*
    	     データのチェックと初期設定
    	*/
    		if ($this->dup_a == 0)
    			exit("***error  突然変異方法が不適当 (M_per)\n");
    	
        	if ($method > 0)
        		$wd = $s - $m;
    	/*
             実行
        */
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($this->pi_w[$i1] == 1) {
    				for ($i2 = 0; $i2 < $this->len[$i1]; $i2++) {
    					if (uniform() <= $pr) {
    						if ($method == 0)
    							$w = norm_d($m, $s);
    						else {
        						$w = uniform() * $wd;
        						if (uniform() < 0.5)
        							$w = -$w;
    						}
    						$x1 = (double)$this->ind[$i1][$i2] + $w;
    						if ($x1 > $this->allele_u)
    							$x1 = $this->allele_u;
    						else {
    							if ($x1 < $this->allele_l)
    								$x1 = $this->allele_l;
    						}
    						$this->ind[$i1][$i2] = intval($x1);
    					}
    				}
    			}
    		}
    	}
        
        /**********************************************************************/
    	/* 突然変異(挿入.ある長さの遺伝子を挿入する)                       */
        /*      pr : 突然変異率                                               */
        /*      wd : >0 : 幅を固定                                            */
    	/*           =0 : 幅をランダム(default)                               */
    	/**********************************************************************/
    	function M_ins($pr, $wd = 0)
    	{
    	/*
    	     データのチェック
    	*/
        	if ($this->dup_a == 0 || $this->min_len < 0)
        		exit("***error  突然変異方法が不適当 (M_ins)\n");
    	/*
    	     実行
    	*/
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    	
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    						// 挿入位置の決定
    				$p = intval(uniform() * ($this->len[$i1]+1));
    				if ($p > $this->len[$i1])
    					$p = $this->len[$i1];
    						// 挿入する遺伝子長の決定
    				$l = ($wd == 0) ? intval(uniform() * ($this->max_len - $this->len[$i1] + 1)) : $wd;
    				if ($l > $this->max_len-$this->len[$i1])
        				$l = $this->max_len - $this->len[$i1];
        			else {
    					if ($l <= 0)
        					$l = 1;
        			}
    						// 実行
    							// 挿入場所の確保
    				if ($p < $this->len[$i1]) {
    					for ($i2 = $this->len[$i1]+$l-1; $i2 >= $p; $i2--)
    						$this->ind[$i1][$i2] = $this->ind[$i1][$i2-$l];
    				}
    							// 挿入場所の遺伝子の決定
        			for ($i2 = $p; $i2 < $p+$l; $i2++) {
        				$ld = intval(uniform() * ($this->allele_u - $this->allele_l + 1) + $this->allele_l);
        				if ($ld > $this->allele_u)
    						$ld = $this->allele_u;
    					$this->ind[$i1][$i2] = $ld;
    				}
    	
    				$this->len[$i1]  += $l;
    			}
    		}
    	}
    	
    	/**********************************************************************/
    	/* 突然変異(削除.ある長さの遺伝子を削除する)                       */
    	/*      pr : 突然変異率                                               */
    	/*      wd : >0 : 幅を固定                                            */
    	/*           =0 : 幅をランダム(default)                               */
        /**********************************************************************/
        function M_del($pr, $wd = 0)
    	{
        /*
             データのチェック
    	*/
    		if ($this->dup_a == 0 || $this->min_len < 0)
    			exit("***error  突然変異方法が不適当 (M_del)\n");
    			exit(1);
    	/*
    	     実行
        */
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        
    			if ($this->pi_w[$i1] == 1 && uniform() <= $pr) {
    						// 削除位置の決定
    				$p = intval(uniform() * $this->len[$i1]);
    				if ($p >= $this->len[$i1])
    					$p = $this->len[$i1] - 1;
    						// 削除する遺伝子長の決定
    				$max = ($this->len[$i1]-$this->min_len < $this->len[$i1]-$p) ? $this->len[$i1] - $this->min_len : $this->len[$i1] - $p;
    				$l   = ($wd == 0) ? intval(uniform() * $max + 1) : $wd;
    				if ($l > $max)
    					$l = $max;
    						// 実行
    				for ($i2 = 0; $i2 < $this->len[$i1]-$p-$l; $i2++)
    					$this->ind[$i1][$p+$i2] = $this->ind[$i1][$p+$i2+$l];
    	
        			$this->len[$i1] -= $l;
        		}
    		}
        }
        
    	/*********************************************************************/
    	/* 淘汰(エリート・ルーレット選択)                                  */
    	/*      elite : エリートで残す個体数(default=0)                      */
    	/*      s_method : ルーレット板の作成方法(default=1)                 */
    	/*                   =0 : 適応度をそのまま使用                       */
    	/*                   =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                   =2 : 評価値に順位をつけ,減少率βで線形化       */
        /*      s_bias : α,または,method=2の場合は初期値(default=0)       */
        /*      s_step : β(default=1)                                       */
        /*********************************************************************/
    	function S_roul($elite = 0, $s_method = 1, $s_bias = 0.0, $s_step = 1.0)
    	{
    		$count = 0;
    		$k     = 0;
    		$n     = 0;
    	/*
    	     値のチェックと初期設定
    	*/
    		if ($s_method != 0 && $s_method != 2)
    			$s_method = 1;
    	
    		if ($elite > $this->size)
    			exit("***error  エリートで残す数が多すぎる (S_roul)\n");
        
    		if ($s_method == 2 && $s_step <= 0.0)
        		$s_step = 1.0;
        
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++)
    			$this->s_w[$i1] = 0;
    	/*
    	     重複個体を削除
    	*/
    		if ($this->dup_s == 0) {
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        			if ($this->pi_w[$i1] > 0) {
        				for ($i2 = $i1+1; $i2 < $this->size+$this->max_ch; $i2++) {
        					if ($this->pi_w[$i2] > 0 && $this->len[$i1] == $this->len[$i2]) {
    							$sw = 0;
    							for ($i3 = 0; $i3 < $this->len[$i1] && $sw == 0; $i3++) {
    								if ($this->ind[$i1][$i3] != $this->ind[$i2][$i3])
    									$sw = 1;
    							}
    							if ($sw == 0)
    								$this->pi_w[$i2] = 0;
    						}
    					}
    				}
    			}
    		}
    	
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        		if ($this->pi_w[$i1] > 1)
        			$n++;
    		}
        
        	if ($n < 0 || $this->dup_s == 0 && $n < $this->size)
    			exit("***error  残す個体がない (S_roul)\n");
    	/*
    	     淘汰して残す個体を選ぶ
    	*/
    						// エリートの選択
        	$sw = 0;
        
        	while ($k < $elite && $k < $n && $sw == 0) {
    			$max = -1;
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    				if ($this->pi_w[$i1] > 1 && $this->s_w[$i1] == 0) {
    					if ($max < 0 || $this->pi[$i1] > $this->pi[$max])
    						$max = $i1;
    				}
    			}
    			if ($max < 0)
    				$sw = 1;
    			else {
    				$this->s_w[$max] = 1;
    				$k++;
    			}
    		}
        					// ルーレット選択
        	while ($count < $this->size+$this->max_ch && $k < $this->size) {
    			$p = $this->Select($s_method, $s_bias, $s_step);
        		if ($this->dup_s == 0 && $this->s_w[$p] > 0)
        			$count++;
    			else {
    				$count = 0;
    				$this->s_w[$p]++;
    				$k++;
    			}
    		}
    							// 選択に失敗した場合の処理
        	if ($this->dup_s == 0 && $k < $this->size) {
        		for ($i1 = 0; $i1 < $this->size+$this->max_ch && $k < $this->size; $i1++) {
        			if ($this->pi_w[$i1] > 1 && $this->s_w[$i1] == 0) {
    					$this->s_w[$i1] = 1;
    					$k++;
    				}
    			}
    		}
    							// 複数回選択されたものの処理
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($this->s_w[$i1] == 0)
    				$this->pi_w[$i1] = 0;
    		}
    	
    		for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    			if ($this->s_w[$i1] > 0) {
    				if ($this->s_w[$i1] > 1) {
        				for ($i2 = 2; $i2 <= $this->s_w[$i1]; $i2++) {
        					$k              = $this->Position(-1);
    						$this->len[$k]  = $this->len[$i1];
        					$this->pi_w[$k] = 2;
        					$this->pi[$k]   = $this->pi[$i1];
    						for ($i3 = 0; $i3 < $this->len[$i1]; $i3++)
    							$this->ind[$k][$i3] = $this->ind[$i1][$i3];
    					}
    				}
    			}
    		}
    	}
    }
        
    /***********************************/
    /* [0, 1] 区間の一様分布変量の発生 */
    /***********************************/
    function uniform()
    {
    	return mt_rand() / mt_getrandmax();
    }
    
    /***********************************/
    /* 正規分布変量の発生              */
    /*      m : 平均                   */
    /*      s : 標準偏差               */
    /*           return : 正規分布変量 */
    /***********************************/
    function norm_d($m, $s)
    {
      	$x = 0.0;
    
       	for ($i1 = 0; $i1 < 12; $i1++)
       		$x += uniform();
    
    	$x = $s * ($x - 6.0) + $m;
    
    	return $x;
    }
    	
    /************************/
    /* クラスFunctionの定義 */
    /************************/
    class Func extends Species {
    
    	private $cv;   // 2進数を10進数の変換する係数
    	private $max_gen;   // 最大世代交代数
    	private $kosa_m;   // 交叉方法
                           //   =-1 : 交叉を使用しない
                           //   =0 : 親のコピー
                           //   =1 : 多点交叉
                           //   =2 : 一様交叉
                           //   =3 : 平均化交叉
    	private $kosa;   // 交叉確率
    	private $k_point;   // 交差点の数(負の時は,1から-point間のランダム)
    	private $k_vr;   // =0 : 両親とも同じ位置で交叉
                         // =1 : 両親が異なる位置で交叉(遺伝子長は可変)
    	private $k_method;   // 交叉の時の親の選択方法
                             //   =-1 : ランダム
                             //   =0 : 適応度をそのまま使用
                             //   =1 : 最小値からの差(ただし,α以下の場合はα)
                             //   =2 : 評価値に順位をつけ,減少率βで線形化
    	private $k_bias;   // α,または,method=2の場合は初期値
    	private $k_step;   // β
    	private $mute_m;   // 突然変異方法
                           //   =-1 : 突然変異を使用しない
                           //   =0 : 対立遺伝子への置換
                           //   =1 : 移動
                           //   =2 : 逆位
                           //   =3 : スクランブル
                           //   =4 : 転座
                           //   =5 : 重複
                           //   =6 : 摂動
    	private $mute;   // 突然変異率
    	private $wd;   // 突然変異に使用する部分遺伝子長
    	private $m_mean;   // 摂動の平均値
    	private $m_std;   // 摂動の標準偏差
    	private $elite;   // エリート選択で残す数
    	private $s_method;   // ルーレット板の作成方法
                             //   =0 : 適応度をそのまま使用
                             //   =1 : 最小値からの差(ただし,α以下の場合はα)
                             //   =2 : 評価値に順位をつけ,減少率βで線形化
    	private $s_bias;   // α,または,s_method=2の場合は初期値
    	private $s_step;   // β
    	private $out_d;   // 表示間隔
    	private $out_lvl;   // 出力レベル
                            //   =0 : 最終出力だけ
                            //   n>0 : n世代毎に出力(負の時はファイル)
    	private $out_m;   // 出力方法
                          //   =0 : すべてを出力
                          //   =1 : 最大適応度の個体だけを出力
    	private $o_file;   // 出力ファイル名
    
    	/***************************************/
    	/* コンストラクタ                      */
    	/*      name1 : Species定義ファイル名  */
        /*      name2 : Func定義ファイル名     */
        /*      seed : 乱数の初期値            */
        /***************************************/
        function Func ($name1, $name2, $seed)
        {
    		parent::Species($name1, $seed);
    	
    		$in = fopen($name2, "rb");
        
    		fscanf($in, "%*s %d %*s %d", $this->out_lvl, $this->out_m);
        	fscanf($in, "%*s %s %*s %d", $this->o_file, $this->out_d);
        	fscanf($in, "%*s %d %*s %lf %*s %d %*s %d %*s %d %*s %lf %*s %lf", $this->kosa_m, $this->kosa, $this->k_point, $this->k_vr, $this->k_method, $this->k_bias, $this->k_step);
        	fscanf($in, "%*s %d %*s %lf %*s %d %*s %lf %*s %lf", $this->mute_m, $this->mute, $this->wd, $this->m_mean, $this->m_std);
    		fscanf($in, "%*s %d %*s %d %*s %lf %*s %lf", $this->elite, $this->s_method, $this->s_bias, $this->s_step);
        	fscanf($in, "%*s %d", $this->max_gen);
        
        	$this->cv = 1.0 / (pow(2.0, $this->max_len) - 1.0);
        
        	fclose($in);
        }
        
        /**************/
    	/* 全体の制御 */
    	/**************/
    	function Control()
    	{
    		$gen = 1;
    						// 初期集団の発生
        	$this->Init_std();
        					// 評価
        	$this->Adap();
    						// 出力
    		printf("***世代 %d 適応度 max %f (%d) mean %f\n", $gen, $this->max, $this->max_n, $this->mean);
    	
        	if (abs($this->out_lvl) > 0)
        		$this->Output($gen);
    						// 世代交代
        	for ($gen = 2; $gen <= $this->max_gen; $gen++) {
        						// 交叉
    			switch ($this->kosa_m) {
    				case -1:
    					break;
    				case 0:
        				$this->C_copy();   // 親のコピー
        				break;
        			case 1:
        				$this->C_point($this->kosa, $this->k_point);   // 多点交叉
        				break;
    				case 2:
    					$this->C_uniform($this->kosa);   // 一様交叉
    					break;
        			case 3:
    					$this->C_mean($this->kosa);   // 平均化交叉
        				break;
        			default:
        				break;
        		}
    							// 突然変異
    			switch ($this->mute_m) {
    				case -1:
        				break;
        			case 0:
        				$this->M_alle($this->mute);   // 対立遺伝子への置換
        				break;
        			case 1:
        				$this->M_move($this->mute);   // 移動
        				break;
        			case 2:
    					$this->M_inv($this->mute, $this->wd);   // 逆位
    					break;
    				case 3:
    					$this->M_scram($this->mute, $this->wd);   // スクランブル
    					break;
    				case 4:
        				$this->M_chg($this->mute, $this->wd);   // 転座
        				break;
        			case 5:
    					$this->M_dup($this->mute, $this->wd);   // 重複
    					break;
    				case 6:
    					$this->M_per($this->mute, $this->wd, $this->m_mean, $this->m_std);   // 摂動
        				break;
        			default:
    					break;
        		}
        						// 適応度
    			$this->Adap();
    							// 淘汰
    			$this->S_roul($this->elite);
    							// 出力
        		if ($gen%$this->out_d == 0)
        			printf("***世代 %d 適応度 max %f (%d) mean %f\n", $gen, $this->max, $this->max_n, $this->mean);
        
        		if (abs($this->out_lvl) > 0) {
    				if ($gen%abs($this->out_lvl) == 0)
    					$this->Output($gen);
    			}
        	}
    	
        	$gen--;
        	$k1 = $this->out_m;
        	$this->out_m = 0;
        	printf("***世代 %d 適応度 max %f (%d) mean %f\n", $gen, $this->max, $this->max_n, $this->mean);
    		$this->Output($gen);
    		$this->out_m = $k1;
        }
        
        /****************/
        /* 適応度の計算 */
        /****************/
        function Adap()
        {
    		$n           = 0;
    		$this->max   = 0.0;
    		$this->max_n = -1;
    		$this->mean  = 0.0;
    	
        	for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
        
        		if ($this->pi_w[$i1] == 1) {
    				$x = 0.0;
    				$y = 0.0;
    				for ($i2 = $this->len[$i1]-1; $i2 >= 0; $i2--) {
    					if ($this->ind[$i1][$i2] > 0)
        					$x += pow(2.0, $y);
        				$y += 1.0;
    				}
        			$x               *= $this->cv;
        			$this->pi[$i1]    = sin(3.0*$x) + 0.5 * sin(9.0*$x) + sin(15.0*$x+50.0);
    				$this->pi_w[$i1]  = 2;
    			}
    	
    			if ($this->pi_w[$i1] > 0) {
        			$this->mean += $this->pi[$i1];
        			$n++;
        			if ($this->max_n < 0 || $this->pi[$i1] > $this->max) {
        				$this->max   = $this->pi[$i1];
        				$this->max_n = $i1;
    				}
    			}
    		}
        
    		$this->mean /= $n;
        }
        
        /*****************************/
        /* 結果の出力                */
    	/*      gen : 現在の世代番号 */
    	/*****************************/
    	function Output($gen)
        {
     		$k = 0;
    
        	if ($this->out_lvl >= 0) {
    			printf("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			fscanf(STDIN, "%d", $pr);
    		}
    		else
    			$pr = -1;
    	
        	if ($pr != 0) {
        					// 出力先の決定と評価値の出力
        		if ($pr > 0) {
    				$out = STDOUT;
    				fgets(STDIN);
    			}
    			else {
     				$x   = getdate();
    				$now = $x["hours"]."時".$x["minutes"]."分".$x["seconds"]."秒";
    				$out = fopen($this->o_file, "ab");
    				fwrite($out, "***世代 ".$gen." 適応度 max ".$this->max." (".$this->max_n.") mean ".$this->mean." 時間 ".$now."\n");
    			}
    						// 詳細出力
    			for ($i1 = 0; $i1 < $this->size+$this->max_ch; $i1++) {
    				if (($this->pi_w[$i1] > 1) && ($this->out_m ==0 || $this->out_m == 1 && $i1 == $this->max_n)) {
        				fprintf($out, "%d allele", $i1);
        				for ($i2 = 0; $i2 < $this->len[$i1]; $i2++)
        					fprintf($out, " %d", $this->ind[$i1][$i2]);
        				$x = 0.0;
        				$y = 0.0;
    					for ($i2 = $this->len[$i1]-1; $i2 >= 0; $i2--) {
    						if ($this->ind[$i1][$i2] > 0)
    							$x += pow(2.0, $y);
        					$y += 1.0;
    					}
        				$x *= $this->cv;
        				fprintf($out, " x %f y %f\n", $x, $this->pi[$i1]);
        				if ($pr > 0) {
        					$k++;
    						if ($k == $pr) {
    							fgets(STDIN);
    							$k = 0;
        					}
        				}
        			}
        		}
        
        		if ($pr < 0)
        			fclose($out);
        	}
    	}
    	
    }
    
    /****************/
    /* main program */
    /****************/
       					// 入力ミス
    	if (count($argv) <= 1)
    		exit("***error  ファイル名を入力して下さい\n");
    					// 入力OK
    	else {
    						// ファイルのオープン
    		$in = fopen($argv[1], "rb");
    		if ($in == NULL)
    			exit("***error  ファイル名が不適当です\n");
    						// 入力データファイル名の入力
    		fscanf($in, "%d", $n);   // データの数
    
    		$seed    = array($n);
    		$i_file1 = array($n);
    		$i_file2 = array($n);
    
    		for ($i1 = 0; $i1 < $n; $i1++) {
    			$seed[$i1]    = 1000 * $i1 + 1234567;
    			fscanf($in, "%s %s", $i_file1[$i1], $i_file2[$i1]);
    		}
    
    		fclose($in);
    						// 実行(乱数の初期値を変える)
    		for ($i1 = 0; $i1 < $n; $i1++) {
    
    			printf("\n+++++ケース %d+++++\n", $i1+1);
    
    			$fn = new Func ($i_file1[$i1], $i_file2[$i1], $seed[$i1]);
    
    			$fn->Control();
    		}
    	}
    
    //------------------ケーススタディデータ(data_cf.txt)------
    /*
    3
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    */
    
    //------------------Species記述データ(data1_f.txt)---------
    /*
    対立遺伝子上限 1 対立遺伝子下限 0
    最大遺伝子長 15 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 1 個体の重複(同じ染色体の個体) 0
    集団サイズ 20 子供 20
    */
    
    //------------------Func記述データ(data2_f.txt)--------
    /*
    出力レベル(負はファイル) 20 出力方法(0:すべて,1:最大) 0
    出力ファイル名 out1.txt 表示間隔 1
    交叉方法 1 交叉確率 1.0 点 2 位置 0 方法 1 バイアス 0 ステップ 1
    突然変異方法 0 突然変異率 0.05 幅 1 平均 0.0 標準偏差 1.0
    エリート 2 方法 1 バイアス 0 ステップ 1
    最大世代交代数 200
    */
    
    ?>
    			

  4. Ruby

    TSP
    ####################################
    # 遺伝的アルゴリズムによるTSPの解
    #      coded by Y.Suganuma
    ####################################
    
    ######################
    # クラスSpeciesの定義
    ######################
    
    class Species
    	
    	#########################
    	# コンストラクタ
    	#      name : ファイル名
    	#########################
    
    	def initialize(name)
    	
    				# データの入力
    		inn = open(name, "r")
    	
    		s = inn.gets().split(" ")
    		@_allele_u = Integer(s[1])   # 対立遺伝子上限
    		@_allele_l = Integer(s[3])   # 対立遺伝子下限
    
    		s = inn.gets().split(" ")
    		@_max_len = Integer(s[1])   # 最大遺伝子長
    		@_min_len = Integer(s[3])   # 最小遺伝子長(負の時は,最大遺伝子長で固定)
    
    		s = inn.gets().split(" ")
    		@_dup_a = Integer(s[1])  # 遺伝子の重複
    		                         #   =0 重複を許さない
    		                         #   =1 重複を許す
    		@_dup_s = Integer(s[3])   # 個体の重複(同じ染色体の個体)
    		                          #   =0 重複を許さない
    		                          #   =1 重複を許す
    
    		s = inn.gets().split(" ")
    		@_size   = Integer(s[1])   # 個体総数
    		@_max_ch = Integer(s[3])   # 子供の数の最大値
    				# データのチェック
    		if @_size <= 0
    			print("***error  個体総数≦0 (Constructor)\n")
    		end
    	
    		if @_max_ch < 0
    			print("***error  子供の数<0 (Constructor)\n")
    		end
    	
    		if @_max_len <= 0 or @_min_len == 0
    			print("***error  遺伝子長≦0 (Constructor)\n")
    		end
    	
    		if @_max_len < @_min_len
    			print("***error  最大遺伝子長<最小遺伝子長 (Constructor)\n")
    		end
    	
    		if @_allele_u <= @_allele_l
    			print("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)\n")
    		end
    	
    		kind = @_allele_u - @_allele_l + 1
    		if @_dup_a == 0 and @_max_len > kind
    			print("***error  遺伝子の重複を防ぐことはできない (Constructor)\n")
    		end
    				# 領域の確保
    		num   = @_size + @_max_ch
    		@_ind = Array.new(num)   # 集団(個体の集まり)
    		for i1 in 0 ... num
    			@_ind[i1]  = Array.new(@_max_len)
    		end
    		@_edge = Array.new(@_max_len)   # エッジ組み替え交叉用ワークエリア
    		for i1 in 0 ... @_max_len
    			@_edge[i1] = Array.new(5)
    		end
    		@_pi = Array.new(@_max_len)   # 適応度
    		for i1 in 0 ... @_max_len
    			@_pi[i1]  = Array.new(5)
    		end
    		@_pi   = Array.new(num)   # 適応度
    		@_ro   = Array.new(num)   # ルーレット板
    		@_len  = Array.new(num)   # 各個体の遺伝子長
    		@_kou1 = Array.new(@_max_len)   # 交叉・突然変異用作業場所1
    		@_kou2 = Array.new(@_max_len)   # 交叉・突然変異用作業場所2
    		@_s_w  = Array.new(num)   # 淘汰用指標(選択された回数)
    		@_pi_w = Array.new(num)   # 適応度計算指標
    		                          #   =0 未使用
    		                          #   =1 適応度計算前(突然変異はこの個体だけに適用)
    		                          #   =2 適応度計算済み(交叉時に親とみなす)
    		@_max   = -999999999   # 最大適応度
    		@_mean  = 0.0   # 平均適応度
    		@_max_n = -1   # 最大適応度の個体番号
    	end
    
    	##################################################
    	# 場所を探す
    	#      n >=0 : n番目の親を捜す
    	#        -1 : 空いている場所を探す
    	#      return : 親の場所,または,空いている場所
    	#               (存在しないときは負の値)
    	##################################################
    
    	def Position(n)
    	
    		k  = -1
    		sw = 0
    				# 空いている場所を探す
    		if n < 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] == 0
    					k = i1
    					break
    				end
    			end
    			if k < 0
    				print("***error  空いている場所がない --Position--\n")
    			end
    				# n番目の親(pi_w[i]=2)を捜す
    		else
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] == 2
    					k += 1
    					if k == n
    						sw = 1
    						k  = i1
    						break
    					end
    				end
    			end
    		end
    	
    		return k
    	end
    	
    	###################################################################
    	# 個体の選択
    	#      method : 選択方法
    	#                 =-1 ランダム(default)
    	#                 =0 適応度をそのまま使用
    	#                 =1 最小値からの差(ただし,α以下の場合はα)
    	#                 =2 評価値に順位をつけ,減少率βで線形化
    	#      bias : α,または,method=2の場合は初期値(default=0)
    	#      step : β(default=1)
    	#      return : 個体番号
    	###################################################################
    
    	def Select(method, bias, step)
    	
    		sum = 0.0
    					# ルーレット板の用意
    							# ランダム
    		if method == -1
    			n = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					n += 1
    				end
    			end
    			sum = 1.0 / n
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					@_ro[i1] = sum
    				end
    			end
    							# 評価値をそのまま利用
    		elsif method == 0
    			n = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					sum += @_pi[i1]
    					n   += 1
    				end
    			end
    			if sum.abs() > 1.0e-10
    				sum = 1.0 / sum.abs()
    				for i1 in 0 ... @_size+@_max_ch
    					if @_pi_w[i1] > 1
    						@_ro[i1] = @_pi[i1] * sum
    					end
    				end
    			else
    				sum = 1.0 / n
    				for i1 in 0 ... @_size+@_max_ch
    					if @_pi_w[i1] > 1
    						@_ro[i1] = sum
    					end
    				end
    			end
    							# 最小値からの差
    		elsif method == 1
    			min = -1
    			n   = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					n += 1
    					if min < 0 or @_pi[i1] < @_pi[min]
    						min = i1
    					end
    				end
    			end
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					@_ro[i1] = @_pi[i1] - @_pi[min]
    					if @_ro[i1] < bias
    						@_ro[i1] = bias
    					end
    					sum += @_ro[i1]
    				end
    			end
    			if sum > 1.0e-10
    				sum = 1.0 / sum
    				for i1 in 0 ... @_size+@_max_ch
    					if @_pi_w[i1] > 1
    						@_ro[i1] *= sum
    					end
    				end
    			else
    				sum = 1.0 / n
    				for i1 in 0 ... @_size+@_max_ch
    					if @_pi_w[i1] > 1
    						@_ro[i1] = sum
    					end
    				end
    			end
    							# 線形化
    		elsif method == 2
    			n = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					@_ro[i1] = -1.0
    					n += 1
    				else
    					@_ro[i1] = 1.0
    				end
    			end
    			sw  = 0
    			sum = bias
    			while sw == 0
    				min = -1
    				for i1 in 0 ... @_size+@_max_ch
    					if @_ro[i1] < 0.0 and (min < 0 or @_pi[i1] < @_pi[min])
    						min = i1
    					end
    				end
    				if min < 0
    					sw = 1
    				else
    					@_ro[min]  = sum
    					sum       += @_step
    				end
    			end
    			sum = 1.0 / (0.5 * (2.0 * bias + step * (n - 1)) * n)
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					@_ro[i1] *= sum
    				end
    			end
    		end
    	
    		sum = 0.0
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] > 1
    				sum         += @_ro[i1]
    				@_ro[i1]  = sum
    			end
    		end
    						# 選択
    		x  = rand(0)
    		sw = 0
    		k  = 0
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] > 1
    				if x <= @_ro[i1]
    					sw = 1
    					k  = i1
    					break
    				end
    			end
    		end
    	
    		return k
    	end
    	
    	###################
    	# 標準的な初期設定
    	###################
    
    	def Init_std()
    	
    				# 初期設定
    		for i1 in 0 ... @_size+@_max_ch
    			if i1 < @_size
    				@_pi_w[i1] = 1   # 適応度の計算前
    			else
    				@_pi_w[i1] = 0   # 未使用
    			end
    		end
    				# 遺伝子の決定
    		for i1 in 0 ... @_size
    	
    			sw1    = 0
    			length = 0
    
    			while sw1 == 0
    						# 遺伝子長の決定
    				if @_min_len < 0
    					length = @_max_len
    				else
    					length = Integer(rand(0) * (@_max_len - @_min_len + 1) + @_min_len)
    					if length > @_max_len
    						length = @_max_len
    					end
    				end
    				@_len[i1] = length
    						# 遺伝子の決定
    				for i2 in 0 ... length
    					sw2 = 0
    					while sw2 == 0
    						lid = Integer(rand(0) * (@_allele_u - @_allele_l + 1) + @_allele_l)
    						if lid > @_allele_u
    							lid = @_allele_u
    						end
    						@_ind[i1][i2] = lid
    							# 重複遺伝子のチェック
    						sw2 = 1
    						if @_dup_a == 0
    							for i3 in 0 ... i2
    								if lid == @_ind[i1][i3]
    									sw2 = 0
    									break
    								end
    							end
    						end
    					end
    				end
    						# 重複個体のチェック
    				sw1 = 1
    				if @_dup_s == 0
    					for i2 in 0 ... i1
    						if @_len[i1] == @_len[i2]
    							sw2 = 0
    							for i3 in 0 ... @_len[i1]
    								if @_ind[i1][i3] != @_ind[i2][i3]
    									sw2 = 1
    									break
    								end
    							end
    							if sw2 == 0
    								sw1 = 0
    								break
    							end
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	####################################################
    	# 標準的な出力
    	#      sw : 出力レベル
    	#             =0 : 最終出力だけ
    	#             n>0 : n世代毎に出力(負はファイル)
    	#      out_m : 出力方法
    	#                =0 : すべての個体を出力
    	#                =1 : 最大適応度の個体だけを出力
    	#      gen : 現在の世代番号
    	#      name : 出力ファイル名
    	####################################################
    
    	def Out_std(sw, out_m, gen, name)
    	
    		k  = 0
    		pr = -1
    
    		if sw >= 0
    			print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ")
    			pr = Integer($stdin.gets())
    		end
    	
    		if pr != 0
    						# 出力先の決定と評価値の出力
    			if pr > 0
    				out = $stdout
    				$stdin.gets()
    			else
    				now = String(Time.now)
    				out = open(name, "a")
    				out.print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + " 時間 " + now + "\n")
    						# 詳細出力
    			end
    			for i1 in 0 ... @_size+@_max_ch
    				if (@_pi_w[i1] > 1) and (out_m == 0 or (out_m == 1 and i1 == @_max_n))
    					out.print(String(i1) + " allele")
    					for i2 in 0 ... @_len[i1]
    						out.print(" " + String(@_ind[i1][i2]))
    					end
    					out.print(" value " + String(@_pi[i1]) + "\n")
    					if pr > 0
    						k += 1
    						if k == pr
    							$stdin.gets()
    							k = 0
    						end
    					end
    				end
    			end
    	
    			if pr < 0
    				out.close()
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(親のコピー)
    	#      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)
    	###################################################################
    
    	def C_copy(method = 2, pair = 0, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータチェック
    		if method != 1
    			method = 2
    		end
    	
    		if pair <= 0
    			if method == 2
    				pair = Integer(@_max_ch / 2)
    			else
    				pair = @_max_ch
    			end
    		else
    			if method == 2 and 2*pair > @_max_ch or method == 1 and pair > @_max_ch
    				print("***error  子供が多すぎる (C_copy)\n")
    			end
    		end
    				# 実行
    		for i1 in 0 ... pair
    						# 親の選択
    			p1 = Select(k_method, k_bias, k_step)
    			p2 = p1
    			sw = 0
    	
    			while sw == 0
    				p2 = Select(k_method, k_bias, k_step)
    				if p1 != p2
    					sw = 1
    				end
    			end
    						# コピー
    			for i2 in 0 ... method
    				p = p2
    				if i2 == 0
    					p = p1
    				end
    				k         = Position(-1)
    				@_len[k]  = @_len[p]
    				@_pi_w[k] = 1
    				for i3 in 0 ... @_len[k]
    					@_ind[k][i3] = @_ind[p][i3]
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(多点交叉)
    	#      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)
    	###################################################################
    
    	def C_point(kosa, k_point = 1, k_vr = 0, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    		mn = 0
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a == 0
    			print("***error  交叉方法が不適当 (C_point)\n")
    		end
    	
    		abs_p = k_point.abs()
    		if abs_p == 0 or abs_p > @_max_len-1 or (@_min_len > 0 and abs_p > @_min_len-1)
    			print("***error  交叉点の数が不適当 (C_point)\n")
    		end
    	
    		if k_vr > 0 and @_min_len < 0
    			print("***error  遺伝子長は可変でなければならない (C_point)\n")
    		end
    				# 交叉
    		num = k_point
    	
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 交叉位置の数の決定
    				if k_point < 0
    					num = Integer(rand(0) * abs_p + 1)
    					if num > abs_p
    						num = abs_p
    					end
    				end
    							# 交叉位置の決定(点の後ろで交叉)
    				for i2 in 0 ... num
    								# 親1の交叉位置
    					sw = 0
    					while sw == 0
    						sw            = 1
    						@_kou1[i2] = Integer(rand(0) * (@_len[p1] - 1))
    						if @_kou1[i2] > @_len[p1]-2
    							@_kou1[i2] = @_len[p1] - 2
    						end
    						if k_vr == 0 and @_kou1[i2] > @_len[p2]-2
    							@_kou1[i2] = @_len[p2] - 2
    						end
    						for i3 in 0 ... i2
    							if @_kou1[i3] == @_kou1[i2]
    								sw = 0
    								break
    							end
    						end
    					end
    								# 親2の交叉位置
    					if k_vr > 0
    						sw = 0
    						while sw == 0
    							sw            = 1
    							@_kou2[i2] = Integer(rand(0) * (@_len[p2] - 1))
    							if @_kou2[i2] > @_len[p2]-2
    								@_kou2[i2] = @_len[p2] - 2
    							end
    							for i3 in 0 ... i2
    								if @_kou2[i3] == @_kou2[i2]
    									sw = 0
    									break
    								end
    							end
    						end
    					end
    				end
    							# 交叉の実行
    							#   親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 in 0 ... num+1
    								# 次の交叉位置を求める
    					if i2 == num            # 最後
    						t12 = @_len[p1]
    						t22 = @_len[p2]
    					else
    									# 親1
    						t12 = @_max_len
    						for i3 in 0 ... num
    							if @_kou1[i3] >= 0 and @_kou1[i3] <= t12
    								t12 = @_kou1[i3]
    								mn  = i3
    							end
    						end
    						@_kou1[mn] = -1
    						t12 += 1
    									# 親2
    						if k_vr == 0
    							t22 = t12
    						else
    							t22 = @_max_len
    							for i3 in 0 ... num
    								if @_kou2[i3] >= 0 and @_kou2[i3] <= t22
    									t22 = @_kou2[i3]
    									mn  = i3
    								end
    							end
    							@_kou2[mn] = -1
    							t22 += 1
    						end
    					end
    								# 指定箇所のコピー
    					for i3 in t11 ... t12
    						if i2%2 == 0
    							if c1 < @_max_len
    								@_ind[k1][c1] = @_ind[p1][i3]
    								c1 += 1
    							end
    						else
    							if c2 < @_max_len
    								@_ind[k2][c2] = @_ind[p1][i3]
    								c2 += 1
    							end
    						end
    					end
    	
    					for i3 in t21 ... t22
    						if i2%2 == 0
    							if c2 < @_max_len
    								@_ind[k2][c2] = @_ind[p2][i3]
    								c2 += 1
    							end
    						else
    							if c1 < @_max_len
    								@_ind[k1][c1] = @_ind[p2][i3]
    								c1 += 1
    							end
    						end
    					end
    								# 交叉位置の移動
    					t11 = t12
    					t21 = t22
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(一様交叉.[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)
    	###################################################################
    
    	def C_uniform(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a == 0
    			print("***error  交叉方法が不適当 (C_uniform)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_uniform)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				for i2 in 0 ... @_len[p1]
    					if rand(0) > 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]
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(平均化交叉.2つの親の平均値を受け継ぐ)
    	#      kosa : 交叉確率
    	#      k_method : 選択方法
    	#                 =-1 ランダム(default)
    	#                 =0 適応度をそのまま使用
    	#                 =1 最小値からの差(ただし,α以下の場合はα)
    	#                 =2 評価値に順位をつけ,減少率βで線形化
    	#      k_bias : α,または,method=2の場合は初期値(default=0)
    	#      k_step : β(default=1)
    	###################################################################
    
    	def C_mean(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_mean)\n")
    		end
    				# 交叉
    		for i1 in 0 ... @_max_ch
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(1, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k         = Position(-1)
    				@_len[k]  = @_len[p1]
    				@_pi_w[k] = 1
    							# 交叉
    				for i2 in 0 ... @_len[k]
    					@_ind[k][i2] = Integer((@_ind[p1][i2] + @_ind[p2][i2]) / 2)
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(循環交叉.ランダムに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)
    	###################################################################
    	def C_cycle(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_cycle)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_cycle)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 初期設定
    				for i2 in 0 ... @_len[p1]
    					@_kou1[i2] = 0
    					@_kou2[i2] = 0
    				end
    							# 遺伝子長
    				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  = Integer(rand(0) * @_len[p1])
    					if p >= @_len[p1]
    						p = @_len[p1] - 1
    					end
    					if @_kou1[p] == 0 and @_kou2[p] == 0
    						@_kou1[p]    = 1
    						@_kou2[p]    = 1
    						@_ind[k1][p] = @_ind[p1][p]
    						@_ind[k2][p] = @_ind[p2][p]
    						for i2 in 0 ... @_len[p1]
    							if @_ind[p2][p] == @_ind[p1][i2]
    								@_ind[k1][i2] = @_ind[p1][i2]
    								@_kou1[i2]    = 1
    								sw            = 0
    								break
    							end
    						end
    						sw = 1
    						for i2 in 0 ... @_len[p2]
    							if @_ind[p1][p] == @_ind[p2][i2]
    								@_ind[k2][i2] = @_ind[p2][i2]
    								@_kou2[i2]    = 1
    								sw            = 0
    								break
    							end
    						end
    					end
    				end
    	
    				sw = 0
    				i2 = 0
    				i3 = 0
    				while sw == 0
    					while sw == 0 and i2 < @_len[p1]
    						if @_kou1[i2] == 0
    							sw = 1
    						else
    							i2 += 1
    						end
    					end
    					sw = 0
    					while sw == 0 and i3 < @_len[p2]
    						if @_kou2[i3] == 0
    							sw = 1
    						else
    							i3 += 1
    						end
    					end
    					if i2 < @_len[p1] and i3 < @_len[p2]
    						@_ind[k1][i2] = @_ind[p2][i3]
    						@_ind[k2][i3] = @_ind[p1][i2]
    						sw            = 0
    						i2 += 1
    						i3 += 1
    					else
    						sw = 1
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(部分的交叉.ランダムに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)
    	#******************************************************************/
    	def C_part(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_part)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_part)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				p = Integer(rand(0) * @_len[p1])
    				if p >= @_len[p1]
    					p = @_len[p1] - 1
    				end
    	
    				for i2 in 0 ... @_len[p1]
    					@_ind[k1][i2] = @_ind[p1][i2]
    					@_ind[k2][i2] = @_ind[p2][i2]
    				end
    	
    				for i2 in p ... @_len[p1]
    					sw = 0
    					lv = @_ind[k1][i2]
    					for i3 in 0 ... @_len[p1]
    						if @_ind[k2][i2] == @_ind[k1][i3]
    							@_ind[k1][i2] = @_ind[k1][i3]
    							@_ind[k1][i3] = lv
    							sw            = 1
    							break
    						end
    					end
    					sw = 0
    					for i3 in 0 ... @_len[p1]
    						if lv == @_ind[k2][i3]
    							@_ind[k2][i3] = @_ind[k2][i2]
    							@_ind[k2][i2] = lv
    							sw            = 1
    							break
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(順序交叉.ランダムに切れ目を決定し,子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)
    	###################################################################
    	def C_seq(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_seq)")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_seq)")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				p = Integer(rand(0) * (@_len[p1] - 1))
    				if p >= @_len[p1]-1
    					p = @_len[p1] - 2
    				end
    	
    				for i2 in 0 ... p+1
    					@_ind[k1][i2] = @_ind[p1][i2]
    					@_ind[k2][i2] = @_ind[p2][i2]
    				end
    	
    				pp = 0
    				for i2 in p+1 ... @_len[p1]
    					sw = 0
    					i3 = pp
    					while i3 < @_len[p2] and sw == 0
    						i4 = p + 1
    						while i4 < @_len[p1] and sw == 0
    							if @_ind[p2][i3] == @_ind[p1][i4]
    								sw               = 1
    								pp               = i3 + 1
    								@_ind[k1][i2] = @_ind[p1][i4]
    							end
    							i4 += 1
    						end
    						i3 += 1
    					end
    				end
    				pp = 0
    				for i2 in p+1 ... @_len[p2]
    					sw = 0
    					i3 = pp
    					while i3 < @_len[p1] and sw == 0
    						i4 = p + 1
    						while i4 < @_len[p2] and sw == 0
    							if @_ind[p1][i3] == @_ind[p2][i4]
    								sw               = 1
    								pp               = i3 + 1
    								@_ind[k2][i2] = @_ind[p2][i4]
    							end
    							i4 += 1
    						end
    						i3 += 1
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(一様順序交叉.位置の集合をランダムに選択し,一方の親の選
    	#       択された位置における遺伝子の順序に従って,他の親の遺伝子
    	#       を並べ替える
    	#         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)
    	###################################################################
    	
    	def C_useq(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair =Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_useq)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_useq)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				for i2 in 0 ... @_len[p1]
    					@_ind[k1][i2] = @_ind[p1][i2]
    					@_ind[k2][i2] = @_ind[p2][i2]
    					if rand(0) < 0.5
    						@_kou1[i2] = 0
    					else
    						@_kou1[i2] = 1
    					end
    				end
    	
    				p = 0
    				for i2 in 0 ... @_len[p1]
    					if @_kou1[i2] > 0
    						sw = 0
    						i3 = p
    						while i3 < @_len[p2] and sw == 0
    							i4 = 0
    							while i4 < @_len[p1] and sw == 0
    								if @_ind[p2][i3] == @_ind[p1][i4] and @_kou1[i4] > 0
    									sw            = 1
    									p             = i3 + 1
    									@_ind[k1][i2] = @_ind[p1][i4]
    								end
    								i4 += 1
    							end
    							i3 += 1
    						end
    					end
    				end
    				p = 0
    				for i2 in 0 ... @_len[p3]
    					if @_kou1[i2] > 0
    						sw = 0
    						i3 = p
    						while i3 < @_len[p1] and sw == 0
    							i4 = 0
    							while i4 < @_len[p2] and sw == 0
    								if @_ind[p1][i3] == @_ind[p2][i4] and @_kou1[i4] > 0
    									sw            = 1
    									p             = i3 + 1
    									@_ind[k2][i2] = @_ind[p2][i4]
    								end
    								i4 += 1
    							end
    							i3 += 1
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(一様位置交叉.位置の集合をランダムに選択し,一方の親の選
    	#       択された位置における遺伝子の位置に,他の親の同じ遺伝子を
    	#       配置する.残りの遺伝子は,親と同じ順序に配置する.
    	#         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)
    	###################################################################
    
    	def C_upos(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_upos)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_upos)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				for i2 in 0 ... @_len[p1]
    					@_kou1[i2] = 1
    					if rand(0) < 0.5
    						@_kou1[i2] = 1
    					end
    					if @_kou1[i2] > 0
    						@_ind[k1][i2] = @_ind[p2][i2]
    						@_ind[k2][i2] = @_ind[p1][i2]
    					end
    				end
    	
    				p = 0
    				for i2 in 0 ... @_len[p1]
    					sw = 0
    					for i3 in 0 ... @_len[p1]
    						if @_kou1[i3] > 0 and @_ind[p1][i2] == @_ind[k1][i3]
    							sw = 1
    							break
    						end
    					end
    					if sw == 0
    						for i3 in p ... @_len[p1]
    							if @_kou1[i3] == 0
    								@_ind[k1][i3] = @_ind[p1][i2]
    								p             = i3 + 1
    								sw            = 1
    								break
    							end
    						end
    					end
    				end
    				p = 0
    				for i2 in 0 ... @_len[p2]
    					sw = 0
    					for i3 in 0 ... @_len[p2]
    						if @_kou1[i3] > 0 and @_ind[p2][i2] == @_ind[k2][i3]
    							sw = 1
    							break
    						end
    					end
    					if sw == 0
    						for i3 in p ... @_len[p2]
    							if @_kou1[i3] == 0
    								@_ind[k2][i3] = @_ind[p2][i2]
    								p                = i3 + 1
    								sw               = 1
    								break
    							end
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(エッジ組み替え交叉.以下の手順に従って行う.対立遺伝子は
    	#       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)
    	###################################################################
    
    	def C_edge(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    		e  = Array.new(2)
    		k0 = 0
    				# 初期設定とデータのチェック
    		pair = @_max_ch
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_edge)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_edge)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(1, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k         = Position(-1)
    				@_pi_w[k] = 1
    				@_len[k]  = @_len[p1]
    							# エッジマップの初期化
    				for i2 in 0 ... @_len[k]
    					@_edge[i2][0] = 0
    					for i3 in 1 ... 5
    						@_edge[i2][i3] = -1
    					end
    				end
    							# 交叉
    								# エッジマップの作成
    				for i2 in 0 ... @_len[k]
    	
    					sw = 0
    					for i3 in 0 ... @_len[k]
    						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]
    								end
    							end
    							for i4 in 0 ... 2
    								@_edge[i2][0] += 1
    								@_edge[i2][@_edge[i2][0]] = e[i4]
    							end
    							break
    						end
    					end
    	
    					sw = 0
    					for i3 in 0 ... @_len[k]
    						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]
    								end
    							end
    							for i4 in 0 ... 2
    								sw = 1
    								for i5 in 1 ... @_edge[i2][0]+1
    									if @_edge[i2][i5] == e[i4]
    										sw = 2
    										break
    									end
    								end
    								if sw == 1
    									@_edge[i2][0] += 1
    									@_edge[i2][@_edge[i2][0]] = e[i4]
    								end
    							end
    							break
    						end
    					end
    				end
    								# 交叉の実行
    									# 出発点の決定
    				k1 = @_ind[p1][0]
    				k2 = @_ind[p2][0]
    				if @_edge[k1][0] == @_edge[k2][0]
    					kk = k1
    					if rand(0) > 0.5
    						kk = k2
    					end
    				else
    					kk = k2
    					if @_edge[k1][0] < @_edge[k2][0]
    						kk = k2
    					end
    				end
    				@_ind[k][0] = kk
    				p           = 1
    	
    				while p < @_len[k]
    									# ノードの除去
    					for i2 in 0 ... @_len[k]
    						sw = 0
    						if @_edge[i2][0] > 0
    							for i3 in 1 ... 5
    								if @_edge[i2][i3] == kk
    									sw              = 1
    									@_edge[i2][i3]  = -1
    									@_edge[i2][0]  -= 1
    									break
    								end
    							end
    						end
    					end
    									# 次の現在ノードの選択
    					min = 10
    					num = 0
    					for i2 in 1 ... 5
    						if @_edge[kk][i2] >= 0
    							k1 = @_edge[kk][i2]
    							if @_edge[k1][0] >= 0 and @_edge[k1][0] < min
    								num = 1
    								min = @_edge[k1][0]
    								k0  = k1
    							else
    								if @_edge[k1][0] == min
    									num += 1
    								end
    							end
    						end
    					end
    					if num > 1
    						k1 = Integer(rand(0) * num) + 1
    						if k1 > num
    							k1 = num
    						end
    						k2 = 0
    						k0 = -1
    						i2 = 1
    						while i2 <= 4 and k0 < 0
    							if @_edge[kk][i2] >= 0
    								if @_edge[@_edge[kk][i2]][0] == min
    									k2 += 1
    									if k1 == k2
    										k0 = @_edge[kk][i2]
    									end
    								end
    							end
    							i2 += 1
    						end
    					else
    						if num <= 0
    							num = 0
    							for i2 in 0 ... @_len[k]
    								if i2 != kk and @_edge[i2][0] >= 0
    									num += 1
    								end
    							end
    							if num <= 0
    								print("***error  invalid data (C_edge)\n")
    							else
    								k1 = Integer(rand(0) * num) + 1
    								if k1 > num
    									k1 = num
    								end
    								k2 = 0
    								k0 = -1
    								i2 = 0
    								while i2 < @_len[k] and k0 < 0
    									if i2 != kk and @_edge[i2][0] >= 0
    										k2 += 1
    										if k1 == k2
    											k0 = i2
    										end
    									end
    									i2 += 1
    								end
    							end
    						end
    					end
    					@_edge[kk][0]  = -1
    					@_ind[k][p]    = k0
    					kk                = k0
    					p                += 1
    				end
    			end
    		end
    	end
    	
    	##############################################################
    	# 交叉(サブツアー交叉.2点交叉の拡張である.ただし,相手に
    	#       同じ遺伝子のグループがない限り実行されない.たとえば
    	#         ***abcd**
    	#         *cdab****
    	#       のような両親の時実行され,以下の4つの子供が生成され
    	#       る)
    	#         ***cdab**
    	#         *abcd****
    	#         ***badc**
    	#         *dcba****
    	#       最大,4*交叉回数*個体総数*(個体総数-1) 個の子
    	#       供が生成される可能性があるので,子供の数としてこの値
    	#       以上のデータを入力しておく必要がある.
    	#      kosa : 交叉確率
    	#      count : 1つのペアーに対する交差回数(default=10)
    	##############################################################
    
    	def C_sub(kosa, count = 10)
    	
    		t22 = 0
    				# 初期設定とデータのチェック
    		if (4*count*@_size*(@_size-1)) > @_max_ch
    			print("***error  子供が多すぎる (C_sub)\n")
    		end
    				# 交叉
    		for i1 in 0 ... @_size-1
    						# 親1
    			p1 = Position(i1)
    	
    			if p1 >= 0
    	
    				for i2 in i1 ... @_size
    						# 親2
    					p2 = Position(i2)
    	
    					if p2 >= 0
    						# 交叉しない場合
    						if rand(0) > kosa
    							C_copy(2, 1)
    						# 交叉する場合
    						else
    							# 交叉回数の制御
    							for i3 in 0 ... count
    								# 交叉位置の決定(点の後ろで交叉)
    									# 親1の交叉位置
    								t11 = Integer(rand(0) * @_len[p1])
    								if t11 > (@_len[p1]-1)
    									t11 = @_len[p1] - 1
    								end
    								sw = 0
    								while sw == 0
    									t12 = Integer(rand(0) * @_len[p1])
    									if t12 > (@_len[p1]-1)
    										t12 = @_len[p1] - 1
    									end
    									if t12 != t11
    										sw = 1
    									end
    								end
    								if t11 > t12
    									k1  = t11
    									t11 = t12
    									t12 = k1
    								end
    									# 親2の交叉位置
    								sw  = 0
    								t21 = -1
    								i4  = 0
    								while i4 < @_len[p2] and t21 < 0
    									i5 = t11
    									while i5 <= t12 and t21 < 0
    										if @_ind[p2][i4] == @_ind[p1][i5]
    											t21 = i4
    										end
    										i5 += 1
    									end
    									i4 += 1
    								end
    								if t21 >= 0
    									t22 = t21 + t12 - t11
    									if t22 < @_len[p2]
    										sw = 1
    										i4 = t21 + 1
    										while i4 <= t22 and sw > 0
    											sw = 0
    											i5 = t11
    											while i5 <= t12 and sw == 0
    												if @_ind[p2][i4] == @_ind[p1][i5]
    													sw = 1
    												end
    												i5 += 1
    											end
    											i4 += 1
    										end
    									end
    								end
    									# 交叉の実行
    								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 in 0 ... t11
    										@_ind[k1][i4] = @_ind[p1][i4]
    										@_ind[k2][i4] = @_ind[p1][i4]
    									end
    									for i4 in t11 ... t12+1
    										@_ind[k1][i4] = @_ind[p2][t21+i4-t11]
    										@_ind[k2][i4] = @_ind[p2][t22-i4+t11]
    									end
    									for i4 in t12+1 ... @_len[p1]
    										@_ind[k1][i4] = @_ind[p1][i4]
    										@_ind[k2][i4] = @_ind[p1][i4]
    									end
    									for i4 in 0 ... t21
    										@_ind[k3][i4] = @_ind[p2][i4]
    										@_ind[k4][i4] = @_ind[p2][i4]
    									end
    									for i4 in t21 ... t22+1
    										@_ind[k3][i4] = @_ind[p1][t11+i4-t21]
    										@_ind[k4][i4] = @_ind[p1][t12-i4+t21]
    									end
    									for i4 in t22+1 ... @_len[p2]
    										@_ind[k3][i4] = @_ind[p2][i4]
    										@_ind[k4][i4] = @_ind[p2][i4]
    									end
    								end
    							end
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	#######################################
    	# 突然変異(対立遺伝子との置き換え)
    	#      pr : 突然変異率
    	#######################################
    
    	def M_alle(pr)
    	
    				# データのチェックと初期設定
    		if @_dup_a == 0
    			print("***error  突然変異方法が不適当 (M_alle)\n")
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] == 1
    				for i2 in 0 ... @_len[i1]
    					if rand(0) <= pr
    						lid = Integer(rand(0) * (@_allele_u - @_allele_l + 1) + @_allele_l)
    						if lid > @_allele_u
    							lid = @_allele_u
    						end
    						if lid != @_ind[i1][i2]
    							@_ind[i1][i2] = lid
    						end
    					end
    				end
    			end
    		end
    	end
    
    	######################################################################
    	# 突然変異(移動.2点を選択し,2番目の遺伝子を1番目の遺伝子の前に
    	#           移動する)
    	#      pr : 突然変異率
    	######################################################################
    
    	def M_move(pr)
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    				# 位置の決定
    						# p1
    				p1 = Integer(rand(0) * @_len[i1])
    				if p1 >= @_len[i1]
    					p1 = @_len[i1] - 1
    				end
    						# p2
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Integer(rand(0) * @_len[i1])
    					if p2 >= @_len[i1]
    						p2 = @_len[i1] - 1
    					end
    					if p2 != p1
    						sw = 1
    					end
    				end
    				# 実行
    				if p2 > p1
    					ld = @_ind[i1][p2]
    					i2 = p2
    					while i2 > p1
    						@_ind[i1][i2] = @_ind[i1][i2-1]
    						i2 -= -1
    					end
    					@_ind[i1][p1] = ld
    				else
    					ld = @_ind[i1][p2]
    					for i2 in p2 ... p1-1
    						@_ind[i1][i2] = @_ind[i1][i2+1]
    					end
    					@_ind[i1][p1-1] = ld
    				end
    			end
    		end
    	end
    	
    	########################################################
    	# 突然変異(逆位.2点間の遺伝子順序を逆に並べ替える)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	########################################################
    
    	def M_inv(pr, wd = 0)
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    				# 区間の決定
    				if wd == 0
    					p1 = Integer(rand(0) * @_len[i1])
    					if p1 >= @_len[i1]
    						p1 = @_len[i1] - 1
    					end
    					sw = 0
    					p2 = p1
    					while sw == 0
    						p2 = Integer(rand(0) * @_len[i1])
    						if p2 >= @_len[i1]
    							p2 = @_len[i1] - 1
    						end
    						if p2 != p1
    							sw = 1
    						end
    					end
    					if p1 > p2
    						p  = p1
    						p1 = p2
    						p2 = p
    					end
    	
    				else
    					p1 = @_len[i1]
    					while p1 > @_len[i1]-2
    						p1 = Integer(rand(0) * @_len[i1])
    					end
    					p2 = p1 + wd - 1
    					if p2 >= @_len[i1]
    						p2 = @_len[i1] - 1
    					end
    				end
    				# 実行
    				sw = 0
    				while sw == 0
    					lid           = @_ind[i1][p1]
    					@_ind[i1][p1] = @_ind[i1][p2]
    					@_ind[i1][p2] = lid
    					p1 += 1
    					p2 -= 1
    					if p1 >= p2
    						sw = 1
    					end
    				end
    			end
    		end
    	end
    	
    	######################################################################
    	# 突然変異(スクランブル.2点間の遺伝子順序をランダムに並べ替える)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	######################################################################
    
    	def M_scram(pr, wd = 0)
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    				# 区間の決定
    				if wd == 0
    					p1 = Integer(rand(0) * @_len[i1])
    					if p1 >= @_len[i1]
    						p1 = @_len[i1] - 1
    					end
    					sw = 0
    					p2 = p1
    					while sw == 0
    						p2 = Integer(rand(0) * @_len[i1])
    						if p2 >= @_len[i1]
    							p2 = @_len[i1] - 1
    						end
    						if p2 != p1
    							sw = 1
    						end
    					end
    					if p1 > p2
    						p  = p1
    						p1 = p2
    						p2 = p
    					end
    	
    				else
    					p1 = @_len[i1]
    					while p1 > @_len[i1]-2
    						p1 = Integer(rand(0) * @_len[i1])
    					end
    					p2 = p1 + wd - 1
    					if p2 >= @_len[i1]
    						p2 = @_len[i1] - 1
    					end
    				end
    				# 実行
    				for i2 in p1 ... p2+1
    					p = Integer(rand(0) * (p2 - p1 + 1) + p1)
    					if p > p2
    						p = p2
    					end
    					ld            = @_ind[i1][i2]
    					@_ind[i1][i2] = @_ind[i1][p]
    					@_ind[i1][p]  = ld
    				end
    			end
    		end
    	end
    	
    	######################################################################
    	# 突然変異(転座.2点間の遺伝子を他の位置のものと置き換える.ただし
    	#           重複部分はそのままとする)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	######################################################################
    
    	def M_chg(pr, wd = 0)
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    				# 区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    						# p1
    				p1 = Integer(rand(0) * @_len[i1])
    				if p1 >= @_len[i1]
    					p1 = @_len[i1] - 1
    				end
    						# p3
    				sw = 0
    				p3 = p1
    				while sw == 0
    					p3 = Integer(rand(0) * @_len[i1])
    					if p3 >= @_len[i1]
    						p3 = @_len[i1] - 1
    					end
    					if p3 != p1
    						sw = 1
    					end
    				end
    						# 小さい方をp1,p2にする
    				if p1 > p3
    					p  = p1
    					p1 = p3
    					p3 = p
    				end
    						# p4, p2
    				p4 = p1 + wd - 1
    				if wd == 0
    					p4 = Integer(rand(0) * (@_len[i1] - p3)) + p3
    				end
    				if p4 >= @_len[i1]
    					p4 = @_len[i1] - 1
    				end
    				p2 = p1 + (p4 - p3)
    						# 重複部分のチェック
    				if p2 >= p3
    					p  = p3 - 1
    					p3 = p2 + 1
    					p2 = p
    					p4 = p3 + (p2 - p1)
    				end
    				# 実行
    				p = p3
    				for i2 in p1 ... p2+1
    					ld             = @_ind[i1][i2]
    					@_ind[i1][i2]  = @_ind[i1][p]
    					@_ind[i1][p]   = ld
    					p              += 1
    				end
    			end
    		end
    	end
    	
    	######################################################################
    	# 突然変異(重複.2点間の遺伝子を他の位置にコピーする
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(deafult)
    	######################################################################
    
    	def M_dup(pr, wd = 0)
    	
    				# データのチェック
    		if @_dup_a == 0
    			print("***error  突然変異方法が不適当 (M_dup)\n")
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    						# 区間の決定([p1,p2]を[p3,p4]にコピー)
    							# p1
    				p1 = Integer(rand(0) * @_len[i1])
    				if p1 >= @_len[i1]
    					p1 = @_len[i1] - 1
    				end
    							# p3
    				sw = 0
    				p3 = p1
    				while sw == 0
    					p3 = Integer(rand(0) * @_len[i1])
    					if p3 >= @_len[i1]
    						p3 = @_len[i1] - 1
    					end
    					if p3 != p1
    						sw = 1
    					end
    				end
    							# 区間を決める
    				p2 = p1
    				p4 = p1
    				if p3 > p1
    					p4 = p3 + wd - 1
    					if wd == 0
    						p4 = Integer(rand(0) * (@_len[i1] - p3)) + p3
    					end
    					if p4 >= @_len[i1]
    						p4 = @_len[i1] - 1
    					end
    					p2 = p1 + (p4 - p3)
    				else
    					p2 = p1 + wd - 1
    					if wd == 0
    						p2 = Integer(rand(0) * (@_len[i1] - p1)) + p1
    					end
    					if p2 >= @_len[i1]
    						p2 = @_len[i1] - 1
    					end
    					p4 = p3 + (p2 - p1)
    						# 実行
    				end
    				p  = p4
    				i2 = p2
    				while i2 > p1-1
    					@_ind[i1][p] = @_ind[i1][i2]
    					p  -= 1
    					i2 -= 1
    				end
    			end
    		end
    	end
    	
    	######################################################
    	# 突然変異(摂動.値をある量だけ変化させる)
    	#      pr : 突然変異率
    	#      method : =0 正規分布(default)
    	#               =1 一様分布
    	#      m : 平均または一様分布の下限(default=0.0)
    	#      s : 標準偏差または一様分布の上限(default=1.0)
    	######################################################
    
    	def M_per(pr, method = 0, m = 0.0, s = 1.0)
    	
    		wd = 0.0
    				# データのチェックと初期設定
    		if @_dup_a == 0
    			print("***error  突然変異方法が不適当 (M_per)\n")
    		end
    	
    		if method > 0
    			wd = s - m
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] == 1
    				for i2 in 0 ... @_len[i1]
    					if rand(0) <= pr
    						if method == 0
    							w = normalvariate(m, s)
    						else
    							w = rand(0) * wd
    							if rand(0) < 0.5
    								w = -w
    							end
    						end
    						x1 = float(@_ind[i1][i2]) + w
    						if x1 > @_allele_u
    							x1 = @_allele_u
    						else
    							if x1 < @_allele_l
    								x1 = @_allele_l
    							end
    						end
    						@_ind[i1][i2] = Integer(x1)
    					end
    				end
    			end
    		end
    	end
    	
    	##############################################
    	# 突然変異(挿入.ある長さの遺伝子を挿入する)
    	#      pr : 突然変異率
    	#      wd : >0 幅を固定
    	#           =0 幅をランダム(default)
    	##############################################
    
    	def M_ins(pr, wd = 0)
    	
    				# データのチェック
    		if @_dup_a == 0 or @_min_len < 0
    			print("***error  突然変異方法が不適当 (M_ins)\n")
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    						# 挿入位置の決定
    				p = Integer(rand(0) * (@_len[i1] + 1))
    				if p > @_len[i1]
    					p = @_len[i1]
    				end
    						# 挿入する遺伝子長の決定
    				l = wd
    				if wd == 0
    					l = Integer(rand(0) * (@_max_len - @_len[i1] + 1))
    				end
    				if l > @_max_len-@_len[i1]
    					l = @_max_len - @_len[i1]
    				else
    					if l <= 0
    						l = 1
    					end
    				end
    						# 実行
    							# 挿入場所の確保
    				if p < @_len[i1]
    					i2 = @_len[i1] + l - 1
    					while i2 > p-1
    						@_ind[i1][i2] = @_ind[i1][i2-l]
    						i2 -= 1
    					end
    				end
    							# 挿入場所の遺伝子の決定
    				for i2 in p ... p+l
    					ld = Integer(rand(0) * (@_allele_u - @_allele_l + 1) + @_allele_l)
    					if ld > @_allele_u
    						ld = @_allele_u
    					end
    					@_ind[i1][i2] = ld
    				end
    	
    				@_len[i1]  += l
    			end
    		end
    	end
    	
    	##############################################
    	# 突然変異(削除.ある長さの遺伝子を削除する)
    	#      pr : 突然変異率
    	#      wd : >0 幅を固定
    	#           =0 幅をランダム(default)
    	##############################################
    
    	def M_del(pr, wd = 0)
    	
    				# データのチェック
    		if @_dup_a == 0 or @_min_len < 0
    			print("***error  突然変異方法が不適当 (M_del)\n")
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    						# 削除位置の決定
    				p = Integer(rand(0) * @_len[i1])
    				if p >= @_len[i1]
    					p = @_len[i1] - 1
    				end
    						# 削除する遺伝子長の決定
    				max = @_len[i1] - p
    				if @_len[i1]-@_min_len < @_len[i1]-p
    					max = @_len[i1] - @_min_len
    				end
    				l = wd
    				if wd == 0
    					l = Integer(rand(0) * max + 1)
    				end
    				if l > max
    					l = max
    				end
    						# 実行
    				for i2 in 0 ... @_len[i1]-p-l
    					@_ind[i1][p+i2] = @_ind[i1][p+i2+l]
    				end
    	
    				@_len[i1]  -= l
    			end
    		end
    	end
    	
    	######################################################################
    	# 淘汰(エリート・ルーレット選択)
    	#      elite : エリートで残す個体数(default=0)
    	#      s_method : ルーレット板の作成方法(default=1)
    	#                   =0 適応度をそのまま使用
    	#                   =1 最小値からの差(ただし,α以下の場合はα)
    	#                   =2 評価値に順位をつけ,減少率βで線形化
    	#      s_bias : α,または,method=2の場合は初期値(default=0)
    	#      s_step : β(default=1)
    	######################################################################
    
    	def S_roul(elite = 0, s_method = 1, s_bias = 0.0, s_step = 1.0)
    	
    		count = 0
    		k     = 0
    		n     = 0
    				# 値のチェックと初期設定
    		if s_method != 0 and s_method != 2
    			s_method = 1
    		end
    	
    		if elite > @_size
    			print("***error  エリートで残す数が多すぎる (S_roul)\n")
    		end
    	
    		if s_method == 2 and s_step <= 0.0
    			s_step = 1.0
    		end
    	
    		for i1 in 0 ... @_size+@_max_ch
    			@_s_w[i1] = 0
    		end
    				# 重複個体を削除
    		if @_dup_s == 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 0
    					for i2 in i1+1 ... @_size+@_max_ch
    						if @_pi_w[i2] > 0 and @_len[i1] == @_len[i2]
    							sw = 0
    							for i3 in 0 ... @_len[i1]
    								if @_ind[i1][i3] != @_ind[i2][i3]
    									sw = 1
    									break
    								end
    							end
    							if sw == 0
    								@_pi_w[i2] = 0
    							end
    						end
    					end
    				end
    			end
    		end
    	
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] > 1
    				n += 1
    			end
    		end
    	
    		if n < 0 or @_dup_s == 0 and n < @_size
    			print("***error  残す個体がない (S_roul)\n")
    		end
    				# 淘汰して残す個体を選ぶ
    						# エリートの選択
    		sw = 0
    	
    		while k < elite and k < n and sw == 0
    			max = -1
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1 and @_s_w[i1] == 0
    					if max < 0 or @_pi[i1] > @_pi[max]
    						max = i1
    					end
    				end
    			end
    			if max < 0
    				sw = 1
    			else
    				@_s_w[max]  = 1
    				k          += 1
    			end
    		end
    						# ルーレット選択
    		while count < @_size+@_max_ch and k < @_size
    			p = Select(s_method, s_bias, s_step)
    			if @_dup_s == 0 and @_s_w[p] > 0
    				count += 1
    			else
    				count     = 0
    				@_s_w[p] += 1
    				k        += 1
    			end
    		end
    							# 選択に失敗した場合の処理
    		if @_dup_s == 0 and k < @_size
    			i1 = 0
    			while i1 < @_size+@_max_ch and k < @_size
    				if @_pi_w[i1] > 1 and @_s_w[i1] == 0
    					@_s_w[i1]  = 1
    					k         += 1
    				end
    				i1 += 1
    			end
    		end
    							# 複数回選択されたものの処理
    		for i1 in 0 ... @_size+@_max_ch
    			if @_s_w[i1] == 0
    				@_pi_w[i1] = 0
    			end
    		end
    	
    		for i1 in 0 ... @_size+@_max_ch
    			if @_s_w[i1] > 0
    				if @_s_w[i1] > 1
    					for i2 in 2 ... @_s_w[i1]+1
    						k         = Position(-1)
    						@_len[k]  = @_len[i1]
    						@_pi_w[k] = 2
    						@_pi[k]   = @_pi[i1]
    						for i3 in 0 ... @_len[i1]
    							@_ind[k][i3] = @_ind[i1][i3]
    						end
    					end
    				end
    			end
    		end
    	end
    end
    	
    ####################
    # クラスTSPの定義
    ####################
    
    class TSP < Species
    
    	######################################
    	# コンストラクタ
    	#      name1 : Species定義ファイル名
    	#      name2 : TSP定義ファイル名
    	######################################
    
    	def initialize(name1, name2)
    	
    		super(name1)   # 親のコンストラクタ
    						# 基本データの入力
    		inn = open(name2, "r")
    	
    		s = inn.gets().split(" ")
    		@_out_lvl = Integer(s[1])   # 出力レベル
    		                            #   =0 最終出力だけ
    		                            #   n>0 n世代毎に出力(負の時はファイル)
    		@_out_m   = Integer(s[3])  # 出力方法
    		                           #   =0 すべてを出力
    		                           #   =1 最大適応度の個体だけを出力
    		s = inn.gets().split(" ")
    		@_o_file = s[1]   # 出力ファイル名
    		@_out_d  = Integer(s[3])   # 表示間隔
    
    		s = inn.gets().split(" ")
    		@_kosa_m   = Integer(s[1])   # 交叉方法
    		                             #   =-1 交叉を使用しない
    		                             #   =0 親のコピー
    		                             #   =1 循環交叉
    		                             #   =2 部分的交叉
    		                             #   =3 順序交叉
    		                             #   =4 一様順序交叉
    		                             #   =5 一様位置交叉
    		                             #   =6 エッジ組み替え交叉
    		                             #   =7 サブツアー交叉
    		@_kosa     = Float(s[3])   # 交叉確率
    		@_k_point  = Integer(s[5])   # 交差点の数(負の時は,1から-k_point間のランダム)
    		@_k_vr     = Integer(s[7])   # =0 両親とも同じ位置で交叉
    		                       # =1 両親が異なる位置で交叉(遺伝子長は可変)
    		@_k_method = Integer(s[9])   # 交叉の時の親の選択方法
    		                             #   =-1 ランダム
    		                             #   =0 適応度をそのまま使用
    		                             #   =1 最小値からの差(ただし,α以下の場合はα)
    		                             #   =2 評価値に順位をつけ,減少率βで線形化
    		@_k_bias   = Float(s[11])   # α,または,method=2の場合は初期値
    		@_k_step   = Float(s[13])   # β
    
    		s = inn.gets().split(" ")
    		@_mute_m = Integer(s[1])   # 突然変異方法
    		                           #   =-1 突然変異を使用しない
    		                           #   =0 移動
    		                           #   =1 逆位
    		                           #   =2 スクランブル
    		                           #   =3 転座
    		@_mute   = Float(s[3])   # 突然変異率
    		@_wd     = Integer(s[5])   # 突然変異に使用する部分遺伝子長
    		@_m_mean = Float(s[7])   # 摂動の平均値
    		@_m_std  = Float(s[9])   # 摂動の標準偏差
    
    		s = inn.gets().split(" ")
    		@_elite    = Integer(s[1])   # エリート選択で残す数
    		@_s_method = Integer(s[3])   # ルーレット板の作成方法
    		                             #   =0 適応度をそのまま使用
    		                             #   =1 最小値からの差(ただし,α以下の場合はα)
    		                             #   =2 評価値に順位をつけ,減少率βで線形化
    		@_s_bias   = Float(s[5])   # α,または,s_method=2の場合は初期値
    		@_s_step   = Float(s[7])   # β
    
    		s = inn.gets().split(" ")
    		@_n_city  = Integer(s[1])   # 都市の数
    		@_max_gen = Integer(s[3])   # 最大世代交代数
    
    		s = inn.gets().split(" ")
    		@_kinbo    = Integer(s[1])   # 近傍探索(0:行わない,1:行う)
    		@_neib     = Integer(s[3])   # 近傍(2 or 3)
    
    		s = inn.gets().split(" ")
    		@_sel = Integer(s[1])   # エッジの選択方法
    		                        #   =0 最良のものを選択
    		                        #   =1 最初のものを選択
    	
    		if @_kinbo > 0 and @_neib != 2 and @_neib != 3
    			print("***error  近傍の値が不適当\n")
    		end
    	
    		if @_n_city != @_max_len
    			print("***error  都市数が不適当\n")
    		end
    						# 都市の位置データ
    		@_city = Array.new(@_n_city)
    		for i1 in 0 ... @_n_city
    			@_city[i1] = Array.new(2)
    			s = inn.gets().split(" ")
    			@_city[i1][0] = Integer(s[0])
    			@_city[i1][1] = Integer(s[1])
    		end
    						# 距離テーブル
    		@_rg = Array.new(@_n_city)
    		for i1 in 0 ... @_max_len
    			@_rg[i1] = Array.new(@_n_city)
    		end
    	
    		for i1 in 0 ... @_n_city
    			for i2 in i1+1 ... @_n_city
    				x            = @_city[i2][0] - @_city[i1][0]
    				y            = @_city[i2][1] - @_city[i1][1]
    				@_rg[i1][i2] = Math.sqrt(x * x + y * y).round()
    			end
    		end
    	
    		for i1 in 1 ... @_n_city
    			for i2 in 0 ... i1
    				@_rg[i1][i2] = @_rg[i2][i1]
    			end
    		end
    	
    		inn.close()
    	end
    	
    	###############
    	# 全体の制御
    	###############
    
    	def Control()
    	
    		gen = 1
    						# 初期集団の発生
    		Init_std()
    						# 評価
    		if @_kinbo > 0
    			Kinbo()
    		else
    			Adap()
    		end
    						# 出力
    		print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + "\n")
    	
    		if @_out_lvl.abs() > 0
    			Output(gen)
    		end
    						# 世代交代
    		for gen in 2 ... @_max_gen+1
    							# 交叉
    			if @_kosa_m == 0
    				C_copy()   # 親のコピー
    			elsif @_kosa_m == 1
    				C_cycle(@_kosa)   # 循環交叉
    			elsif @_kosa_m == 2
    				C_part(@_kosa)   # 部分的交叉
    			elsif @_kosa_m == 3
    				C_seq(@_kosa)   # 順序交叉
    			elsif @_kosa_m == 4
    				C_useq(@_kosa)   # 一様順序交叉
    			elsif @_kosa_m == 5
    				C_upos(@_kosa)   # 一様位置交叉
    			elsif @_kosa_m == 6
    				C_edge(@_kosa)   # エッジ組み替え交叉
    			elsif @_kosa_m == 7
    				C_sub(@_kosa, @_k_point)   # サブツアー交叉
    			end
    							# 突然変異
    			if @_mute_m == 0
    				M_move(@_mute)   # 移動
    			elsif @_mute_m == 1
    				M_inv(@_mute)   # 逆位
    			elsif @_mute_m == 2
    				M_scram(@_mute)   # スクランブル
    			elsif @_mute_m == 3
    				M_chg(@_mute)   # 転座
    			end
    							# 適応度
    			if @_kinbo > 0
    				Kinbo()
    			else
    				Adap()
    			end
    							# 淘汰
    			S_roul(@_elite)
    							# 出力
    			if gen%@_out_d == 0
    				print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + "\n")
    			end
    	
    			if @_out_lvl.abs() > 0
    				if gen%@_out_lvl.abs() == 0
    					Output(gen)
    				end
    			end
    		end
    	
    		gen     -= 1
    		k1       = @_out_m
    		@_out_m  = 0
    		print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + "\n")
    		Output(gen)
    		@_out_m = k1
    	end
    	
    	##########################
    	# 距離の計算
    	#      n_c : 都市の数
    	#      p : 都市番号
    	#      return : 距離(負)
    	##########################
    
    	def Kyori(n_c, p)
    	
    		r  = 0
    		n1 = p[0]
    	
    		for i1 in 1 ... n_c
    			n2  = p[i1]
    			r  -= @_rg[n1][n2]
    			n1  = n2
    		end
    
    		n2  = p[0]
    		r  -= @_rg[n1][n2]
    
    		return r
    	end
    
    	################
    	# 適応度の計算
    	################
    
    	def Adap()
    	
    		k       = 0
    		@_mean  = 0.0
    		@_max   = 0.0
    		@_max_n = -1
    	
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] == 1
    				@_pi_w[i1] = 2
    				@_pi[i1]   = Kyori(@_len[i1], @_ind[i1])
    			end
    			if @_pi_w[i1] > 0
    				k      += 1
    				@_mean += @_pi[i1]
    				if @_max_n < 0 or @_pi[i1] > @_max
    					@_max   = @_pi[i1]
    					@_max_n = i1
    				end
    			end
    		end
    	
    		if k > 0
    			@_mean /= k
    		end
    	end
    
    	######################################
    	# エッジの入れ替え
    	#      n_city : 都市の数
    	#      seq : 訪問する順番
    	#      r_m : 距離の負値
    	#      return : =0 改善がなかった
    	#               =1 改善があった
    	######################################
    
    	def Change(n_city, seq, r_m)
    	
    		ch  = 0
    		sw  = 0
    		max = r_m[0]
    	
    		n3  = Integer(rand(0) * (n_city - 2))
    		if n3 > n_city-3
    			n3 = n_city - 3
    		end
    	                         # 2近傍
    		i1 = 0
    		while i1 <= n_city-3 and ch == 0
    	
    			if n3 == 0
    				n1 = n_city - 2
    			else
    				n1 = n_city - 1
    			end
    	
    			i2 = n3 + 2
    			while i2 <= n1 and ch == 0
    	                              # 枝の場所((n3,n3+1), (k1,k2))
    				k1 = i2
    				if i2 == n_city-1
    					k2 = 0
    				else
    					k2 = i2 + 1
    				end
    	                              # 枝の入れ替え
    				@_kou1[0] = seq[n3]
    				k         = 1
    				i3        = k1
    				while i3 > n3
    					@_kou1[k]  = seq[i3]
    					k         += 1
    					i3        -= 1
    				end
    	
    				nn = k2
    				while nn != n3
    					@_kou1[k] = seq[nn]
    					k  += 1
    					nn += 1
    					if nn > n_city-1
    						nn = 0
    					end
    				end
    	                              # 評価
    				r = Kyori(n_city, @_kou1)
    	
    				if r > max
    					max = r
    					sw  = 1
    					for i3 in 0 ... n_city
    						@_kou2[i3] = @_kou1[i3]
    					end
    					if @_sel > 0
    						ch = 1
    					end
    				end
    				i2 += 1
    			end
    	
    			n3 += 1
    			if n3 > n_city-3
    				n3 = 0
    			end
    			i1 += 1
    		end
    	                         # 3近傍
    		if @_neib == 3 and ch == 0
    	
    			i1 = 0
    			while i1 <= n_city-3 and ch == 0
    	
    				n1 = n_city - 2
    				n2 = n_city - 1
    	
    				i2 = n3 + 1
    				while i2 <= n1 and ch == 0
    	
    					i3 = i2 + 1
    					while i3 <= n2 and ch == 0
    	                              # 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
    						k1 = i3
    						k2 = k1
    						if i3 == n_city-1
    							k2 = 0
    						else
    							k2 = i3 + 1
    						end
    	                              # 枝の入れ替えと評価
    	                                   # 入れ替え(その1)
    						@_kou1[0] = seq[n3]
    						k         = 1
    						i4        = i2
    						while i4 > n3
    							@_kou1[k]  = seq[i4]
    							k         += 1
    							i4        -= 1
    						end
    	
    						i4 = k1
    						while i4 > i2
    							@_kou1[k]  = seq[i4]
    							k         += 1
    							i4        -= 1
    						end
    	
    						nn = k2
    						while nn != n3
    							@_kou1[k] = seq[nn]
    							k  += 1
    							nn += 1
    							if nn > n_city-1
    								nn = 0
    							end
    						end
    	                                   # 評価(その1)
    						r = Kyori(n_city, @_kou1)
    	
    						if r > max
    							max = r
    							sw  = 1
    							for i3 in 0 ... n_city
    								@_kou2[i3] = @_kou1[i3]
    							end
    							if @_sel > 0
    								ch = 1
    							end
    						end
    	                                   # 入れ替え(その2)
    						@_kou1[0] = seq[n3]
    						k         = 1
    						i4        = k1
    						while i4 > i2
    							@_kou1[k]  = seq[i4]
    							k         += 1
    							i4        -= 1
    						end
    	
    						for i4 in n3+1 ... i2+1
    							@_kou1[k]  = seq[i4]
    							k            += 1
    						end
    	
    						nn = k2
    						while nn != n3
    							@_kou1[k] = seq[nn]
    							k  += 1
    							nn += 1
    							if nn > n_city-1
    								nn = 0
    							end
    						end
    	                                   # 評価(その2)
    						r = Kyori(n_city, @_kou1)
    	
    						if r > max
    							max = r
    							sw  = 1
    							for i3 in 0 ... n_city
    								@_kou2[i3] = @_kou1[i3]
    							end
    							if @_sel > 0
    								ch = 1
    							end
    						end
    	                                   # 入れ替え(その3)
    						@_kou1[0] = seq[n3]
    						k         = 1
    						for i4 in i2+1 ... k1+1
    							@_kou1[k]  = seq[i4]
    							k         += 1
    						end
    	
    						i4 = i2
    						while i4 > n3
    							@_kou1[k]  = seq[i4]
    							k         += 1
    							i4        -= 1
    						end
    	
    						nn = k2
    						while nn != n3
    							@_kou1[k] = seq[nn]
    							k  += 1
    							nn += 1
    							if nn > n_city-1
    								nn = 0
    							end
    						end
    	                                   # 評価(その3)
    						r = Kyori(n_city, @_kou1)
    	
    						if r > max
    							max = r
    							sw  = 1
    							for i3 in 0 ... n_city
    								@_kou2[i3] = @_kou1[i3]
    							end
    							if @_sel > 0
    								ch = 1
    							end
    						end
    	                                   # 入れ替え(その4)
    						@_kou1[0] = seq[n3]
    						k         = 1
    						for i4 in i2+1 ... k1+1
    							@_kou1[k]  = seq[i4]
    							k         += 1
    						end
    	
    						for i4 in n3+1 ... i2+1
    							@_kou1[k]  = seq[i4]
    							k         += 1
    						end
    	
    						nn = k2
    						while nn != n3
    							@_kou1[k] = seq[nn]
    							k  += 1
    							nn += 1
    							if nn > n_city-1
    								nn = 0
    							end
    						end
    	                                   # 評価(その4)
    						r = Kyori(n_city, @_kou1)
    	
    						if r > max
    							max = r
    							sw  = 1
    							for i3 in 0 ... n_city
    								@_kou2[i3] = @_kou1[i3]
    							end
    							if @_sel > 0
    								ch = 1
    							end
    						end
    						i3 += 1
    					end
    					i2 += 1
    				end
    	
    				n3 += 1
    				if n3 > n_city-3
    					n3 = 0
    				end
    				i1 += 1
    			end
    		end
    	                         # 設定
    		if sw > 0
    			r_m[0] = max
    			for i1 in 0 ... n_city
    				seq[i1] = @_kou2[i1]
    			end
    		end
    	
    		return sw
    	end
    	
    	##############
    	# 近傍の探索
    	##############
    
    	def Kinbo()
    	
    		k       = 0
    		@_max   = 0.0
    		@_max_n = -1
    		@_mean  = 0.0
    	
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] == 1
    				@_pi_w[i1] = 2
    				sw         = 1
    				r          = Kyori(@_len[i1], @_ind[i1])
    				while sw > 0
    					r  = Array.new(1)
    					sw = Change(@_len[i1], @_ind[i1], r)
    				end
    				@_pi[i1] = r[0]
    			end
    			if @_pi_w[i1] > 0
    				k      += 1
    				@_mean += @_pi[i1]
    				if @_max_n < 0 or @_pi[i1] > @_max
    					@_max   = @_pi[i1]
    					@_max_n = i1
    				end
    			end
    		end
    	
    		if k > 0
    			@_mean /= k
    		end
    	end
    	
    	#############################
    	# 結果の出力
    	#      gen : 現在の世代番号
    	#############################
    
    	def Output(gen)
    	
    		k  = 0
    		pr = -1
    
    		if @_out_lvl >= 0
    			print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ")
    			pr = Integer($stdin.gets())
    		end
    	
    		if pr != 0
    						# 出力先の決定と評価値の出力
    			if pr > 0
    				out = $stdout
    				$stdin.gets()
    			else
    				now = String(Time.now)
    				out = open(@_o_file, "a")
    				out.print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + " 時間 " + now + "\n")
    			end
    						# 巡回順序の出力
    			if @_out_m == 0
    				for i1 in 0 ... @_len[@_max_n]
    					n = @_ind[@_max_n][i1]
    					out.print(String(n) + " " + String(@_city[n][0]) + " " + String(@_city[n][1]) + "\n")
    					if pr > 0
    						k += 1
    						if k == pr
    							$stdin.gets()
    							k = 0
    						end
    					end
    				end
    			end
    	
    			if pr < 0
    				out.close()
    			end
    		end
    	end
    end
    
    				# 入力ミス
    if ARGV[0] == nil
    	print("***error  ファイル名を入力して下さい\n")
    				# 入力OK
    else
    					# データの数と入力データファイル名の入力
    	line   = gets()
    	n      = Integer(line)   # データの数
    	i_file1 = Array.new(n)
    	i_file2 = Array.new(n)
    
    	for i1 in 0 ... n
    		line        = gets()
    		a           = line.split(" ")
    		i_file1[i1] = a[0]
    		i_file2[i1] = a[1]
    	end
    					# 実行(乱数の初期値を変える)
    	for i1 in 0 ... n
    
    		print("\n+++++ケース " + String(i1+1) + "+++++\n")
    		srand(1000 * i1 + 1234567);
    
    		tsp = TSP.new(i_file1[i1], i_file2[i1])
    
    		tsp.Control()
    	end
    end
    
    =begin
    ----------------ケーススタディデータ(data_ct.txt)------
    3
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    
    ---------------Species記述データ(data1_t.txt)---------
    対立遺伝子上限 9 対立遺伝子下限 0
    最大遺伝子長 10 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 0 個体の重複(同じ染色体の個体) 0
    集団サイズ 10 子供 10
    
    ---------------TSP記述データ(data2_t.txt)--------
    出力レベル(負はファイル) 10 出力方法(0:適応度+順番,1:適応度) 0
    出力ファイル名 out1.txt 表示間隔 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
    =end
    			
    関数の最大値
    /********************************************************************/
    /* f(x) = sin(3.0*x) + 0.5 * sin(9.0*x) + sin(15.0*x + 50) の最大値 */
    /*      coded by Y.Suganuma                                         */
    /********************************************************************/
    
    ######################
    # クラスSpeciesの定義
    ######################
    
    class Species
    	
    	#########################
    	# コンストラクタ
    	#      name : ファイル名
    	#########################
    
    	def initialize(name)
    	
    				# データの入力
    		inn = open(name, "r")
    	
    		s = inn.gets().split(" ")
    		@_allele_u = Integer(s[1])   # 対立遺伝子上限
    		@_allele_l = Integer(s[3])   # 対立遺伝子下限
    
    		s = inn.gets().split(" ")
    		@_max_len = Integer(s[1])   # 最大遺伝子長
    		@_min_len = Integer(s[3])   # 最小遺伝子長(負の時は,最大遺伝子長で固定)
    
    		s = inn.gets().split(" ")
    		@_dup_a = Integer(s[1])  # 遺伝子の重複
    		                         #   =0 重複を許さない
    		                         #   =1 重複を許す
    		@_dup_s = Integer(s[3])   # 個体の重複(同じ染色体の個体)
    		                          #   =0 重複を許さない
    		                          #   =1 重複を許す
    
    		s = inn.gets().split(" ")
    		@_size   = Integer(s[1])   # 個体総数
    		@_max_ch = Integer(s[3])   # 子供の数の最大値
    				# データのチェック
    		if @_size <= 0
    			print("***error  個体総数≦0 (Constructor)\n")
    		end
    	
    		if @_max_ch < 0
    			print("***error  子供の数<0 (Constructor)\n")
    		end
    	
    		if @_max_len <= 0 or @_min_len == 0
    			print("***error  遺伝子長≦0 (Constructor)\n")
    		end
    	
    		if @_max_len < @_min_len
    			print("***error  最大遺伝子長<最小遺伝子長 (Constructor)\n")
    		end
    	
    		if @_allele_u <= @_allele_l
    			print("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)\n")
    		end
    	
    		kind = @_allele_u - @_allele_l + 1
    		if @_dup_a == 0 and @_max_len > kind
    			print("***error  遺伝子の重複を防ぐことはできない (Constructor)\n")
    		end
    				# 領域の確保
    		num   = @_size + @_max_ch
    		@_ind = Array.new(num)   # 集団(個体の集まり)
    		for i1 in 0 ... num
    			@_ind[i1]  = Array.new(@_max_len)
    		end
    		@_edge = Array.new(@_max_len)   # エッジ組み替え交叉用ワークエリア
    		for i1 in 0 ... @_max_len
    			@_edge[i1] = Array.new(5)
    		end
    		@_pi = Array.new(@_max_len)   # 適応度
    		for i1 in 0 ... @_max_len
    			@_pi[i1]  = Array.new(5)
    		end
    		@_pi   = Array.new(num)   # 適応度
    		@_ro   = Array.new(num)   # ルーレット板
    		@_len  = Array.new(num)   # 各個体の遺伝子長
    		@_kou1 = Array.new(@_max_len)   # 交叉・突然変異用作業場所1
    		@_kou2 = Array.new(@_max_len)   # 交叉・突然変異用作業場所2
    		@_s_w  = Array.new(num)   # 淘汰用指標(選択された回数)
    		@_pi_w = Array.new(num)   # 適応度計算指標
    		                          #   =0 未使用
    		                          #   =1 適応度計算前(突然変異はこの個体だけに適用)
    		                          #   =2 適応度計算済み(交叉時に親とみなす)
    		@_max   = -999999999   # 最大適応度
    		@_mean  = 0.0   # 平均適応度
    		@_max_n = -1   # 最大適応度の個体番号
    	end
    
    	##################################################
    	# 場所を探す
    	#      n >=0 : n番目の親を捜す
    	#        -1 : 空いている場所を探す
    	#      return : 親の場所,または,空いている場所
    	#               (存在しないときは負の値)
    	##################################################
    
    	def Position(n)
    	
    		k  = -1
    		sw = 0
    				# 空いている場所を探す
    		if n < 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] == 0
    					k = i1
    					break
    				end
    			end
    			if k < 0
    				print("***error  空いている場所がない --Position--\n")
    			end
    				# n番目の親(pi_w[i]=2)を捜す
    		else
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] == 2
    					k += 1
    					if k == n
    						sw = 1
    						k  = i1
    						break
    					end
    				end
    			end
    		end
    	
    		return k
    	end
    	
    	###################################################################
    	# 個体の選択
    	#      method : 選択方法
    	#                 =-1 ランダム(default)
    	#                 =0 適応度をそのまま使用
    	#                 =1 最小値からの差(ただし,α以下の場合はα)
    	#                 =2 評価値に順位をつけ,減少率βで線形化
    	#      bias : α,または,method=2の場合は初期値(default=0)
    	#      step : β(default=1)
    	#      return : 個体番号
    	###################################################################
    
    	def Select(method, bias, step)
    	
    		sum = 0.0
    					# ルーレット板の用意
    							# ランダム
    		if method == -1
    			n = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					n += 1
    				end
    			end
    			sum = 1.0 / n
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					@_ro[i1] = sum
    				end
    			end
    							# 評価値をそのまま利用
    		elsif method == 0
    			n = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					sum += @_pi[i1]
    					n   += 1
    				end
    			end
    			if sum.abs() > 1.0e-10
    				sum = 1.0 / sum.abs()
    				for i1 in 0 ... @_size+@_max_ch
    					if @_pi_w[i1] > 1
    						@_ro[i1] = @_pi[i1] * sum
    					end
    				end
    			else
    				sum = 1.0 / n
    				for i1 in 0 ... @_size+@_max_ch
    					if @_pi_w[i1] > 1
    						@_ro[i1] = sum
    					end
    				end
    			end
    							# 最小値からの差
    		elsif method == 1
    			min = -1
    			n   = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					n += 1
    					if min < 0 or @_pi[i1] < @_pi[min]
    						min = i1
    					end
    				end
    			end
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					@_ro[i1] = @_pi[i1] - @_pi[min]
    					if @_ro[i1] < bias
    						@_ro[i1] = bias
    					end
    					sum += @_ro[i1]
    				end
    			end
    			if sum > 1.0e-10
    				sum = 1.0 / sum
    				for i1 in 0 ... @_size+@_max_ch
    					if @_pi_w[i1] > 1
    						@_ro[i1] *= sum
    					end
    				end
    			else
    				sum = 1.0 / n
    				for i1 in 0 ... @_size+@_max_ch
    					if @_pi_w[i1] > 1
    						@_ro[i1] = sum
    					end
    				end
    			end
    							# 線形化
    		elsif method == 2
    			n = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					@_ro[i1] = -1.0
    					n += 1
    				else
    					@_ro[i1] = 1.0
    				end
    			end
    			sw  = 0
    			sum = bias
    			while sw == 0
    				min = -1
    				for i1 in 0 ... @_size+@_max_ch
    					if @_ro[i1] < 0.0 and (min < 0 or @_pi[i1] < @_pi[min])
    						min = i1
    					end
    				end
    				if min < 0
    					sw = 1
    				else
    					@_ro[min]  = sum
    					sum       += @_step
    				end
    			end
    			sum = 1.0 / (0.5 * (2.0 * bias + step * (n - 1)) * n)
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1
    					@_ro[i1] *= sum
    				end
    			end
    		end
    	
    		sum = 0.0
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] > 1
    				sum         += @_ro[i1]
    				@_ro[i1]  = sum
    			end
    		end
    						# 選択
    		x  = rand(0)
    		sw = 0
    		k  = 0
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] > 1
    				if x <= @_ro[i1]
    					sw = 1
    					k  = i1
    					break
    				end
    			end
    		end
    	
    		return k
    	end
    	
    	###################
    	# 標準的な初期設定
    	###################
    
    	def Init_std()
    	
    				# 初期設定
    		for i1 in 0 ... @_size+@_max_ch
    			if i1 < @_size
    				@_pi_w[i1] = 1   # 適応度の計算前
    			else
    				@_pi_w[i1] = 0   # 未使用
    			end
    		end
    				# 遺伝子の決定
    		for i1 in 0 ... @_size
    	
    			sw1    = 0
    			length = 0
    
    			while sw1 == 0
    						# 遺伝子長の決定
    				if @_min_len < 0
    					length = @_max_len
    				else
    					length = Integer(rand(0) * (@_max_len - @_min_len + 1) + @_min_len)
    					if length > @_max_len
    						length = @_max_len
    					end
    				end
    				@_len[i1] = length
    						# 遺伝子の決定
    				for i2 in 0 ... length
    					sw2 = 0
    					while sw2 == 0
    						lid = Integer(rand(0) * (@_allele_u - @_allele_l + 1) + @_allele_l)
    						if lid > @_allele_u
    							lid = @_allele_u
    						end
    						@_ind[i1][i2] = lid
    							# 重複遺伝子のチェック
    						sw2 = 1
    						if @_dup_a == 0
    							for i3 in 0 ... i2
    								if lid == @_ind[i1][i3]
    									sw2 = 0
    									break
    								end
    							end
    						end
    					end
    				end
    						# 重複個体のチェック
    				sw1 = 1
    				if @_dup_s == 0
    					for i2 in 0 ... i1
    						if @_len[i1] == @_len[i2]
    							sw2 = 0
    							for i3 in 0 ... @_len[i1]
    								if @_ind[i1][i3] != @_ind[i2][i3]
    									sw2 = 1
    									break
    								end
    							end
    							if sw2 == 0
    								sw1 = 0
    								break
    							end
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	####################################################
    	# 標準的な出力
    	#      sw : 出力レベル
    	#             =0 : 最終出力だけ
    	#             n>0 : n世代毎に出力(負はファイル)
    	#      out_m : 出力方法
    	#                =0 : すべての個体を出力
    	#                =1 : 最大適応度の個体だけを出力
    	#      gen : 現在の世代番号
    	#      name : 出力ファイル名
    	####################################################
    
    	def Out_std(sw, out_m, gen, name)
    	
    		k  = 0
    		pr = -1
    
    		if sw >= 0
    			print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ")
    			pr = Integer($stdin.gets())
    		end
    	
    		if pr != 0
    						# 出力先の決定と評価値の出力
    			if pr > 0
    				out = $stdout
    				$stdin.gets()
    			else
    				now = String(Time.now)
    				out = open(name, "a")
    				out.print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + " 時間 " + now + "\n")
    						# 詳細出力
    			end
    			for i1 in 0 ... @_size+@_max_ch
    				if (@_pi_w[i1] > 1) and (out_m == 0 or (out_m == 1 and i1 == @_max_n))
    					out.print(String(i1) + " allele")
    					for i2 in 0 ... @_len[i1]
    						out.print(" " + String(@_ind[i1][i2]))
    					end
    					out.print(" value " + String(@_pi[i1]) + "\n")
    					if pr > 0
    						k += 1
    						if k == pr
    							$stdin.gets()
    							k = 0
    						end
    					end
    				end
    			end
    	
    			if pr < 0
    				out.close()
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(親のコピー)
    	#      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)
    	###################################################################
    
    	def C_copy(method = 2, pair = 0, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータチェック
    		if method != 1
    			method = 2
    		end
    	
    		if pair <= 0
    			if method == 2
    				pair = Integer(@_max_ch / 2)
    			else
    				pair = @_max_ch
    			end
    		else
    			if (method == 2 and 2*pair > @_max_ch) or (method == 1 and pair > @_max_ch)
    				print("***error  子供が多すぎる (C_copy)\n")
    			end
    		end
    				# 実行
    		for i1 in 0 ... pair
    						# 親の選択
    			p1 = Select(k_method, k_bias, k_step)
    			p2 = p1
    			sw = 0
    	
    			while sw == 0
    				p2 = Select(k_method, k_bias, k_step)
    				if p1 != p2
    					sw = 1
    				end
    			end
    						# コピー
    			for i2 in 0 ... method
    				p = p2
    				if i2 == 0
    					p = p1
    				end
    				k         = Position(-1)
    				@_len[k]  = @_len[p]
    				@_pi_w[k] = 1
    				for i3 in 0 ... @_len[k]
    					@_ind[k][i3] = @_ind[p][i3]
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(多点交叉)
    	#      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)
    	###################################################################
    
    	def C_point(kosa, k_point = 1, k_vr = 0, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    		mn = 0
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a == 0
    			print("***error  交叉方法が不適当 (C_point)\n")
    		end
    	
    		abs_p = k_point.abs()
    		if abs_p == 0 or abs_p > @_max_len-1 or (@_min_len > 0 and abs_p > @_min_len-1)
    			print("***error  交叉点の数が不適当 (C_point)\n")
    		end
    	
    		if k_vr > 0 and @_min_len < 0
    			print("***error  遺伝子長は可変でなければならない (C_point)\n")
    		end
    				# 交叉
    		num = k_point
    	
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 交叉位置の数の決定
    				if k_point < 0
    					num = Integer(rand(0) * abs_p + 1)
    					if num > abs_p
    						num = abs_p
    					end
    				end
    							# 交叉位置の決定(点の後ろで交叉)
    				for i2 in 0 ... num
    								# 親1の交叉位置
    					sw = 0
    					while sw == 0
    						sw            = 1
    						@_kou1[i2] = Integer(rand(0) * (@_len[p1] - 1))
    						if @_kou1[i2] > @_len[p1]-2
    							@_kou1[i2] = @_len[p1] - 2
    						end
    						if k_vr == 0 and @_kou1[i2] > @_len[p2]-2
    							@_kou1[i2] = @_len[p2] - 2
    						end
    						for i3 in 0 ... i2
    							if @_kou1[i3] == @_kou1[i2]
    								sw = 0
    								break
    							end
    						end
    					end
    								# 親2の交叉位置
    					if k_vr > 0
    						sw = 0
    						while sw == 0
    							sw            = 1
    							@_kou2[i2] = Integer(rand(0) * (@_len[p2] - 1))
    							if @_kou2[i2] > @_len[p2]-2
    								@_kou2[i2] = @_len[p2] - 2
    							end
    							for i3 in 0 ... i2
    								if @_kou2[i3] == @_kou2[i2]
    									sw = 0
    									break
    								end
    							end
    						end
    					end
    				end
    							# 交叉の実行
    							#   親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 in 0 ... num+1
    								# 次の交叉位置を求める
    					if i2 == num            # 最後
    						t12 = @_len[p1]
    						t22 = @_len[p2]
    					else
    									# 親1
    						t12 = @_max_len
    						for i3 in 0 ... num
    							if @_kou1[i3] >= 0 and @_kou1[i3] <= t12
    								t12 = @_kou1[i3]
    								mn  = i3
    							end
    						end
    						@_kou1[mn] = -1
    						t12 += 1
    									# 親2
    						if k_vr == 0
    							t22 = t12
    						else
    							t22 = @_max_len
    							for i3 in 0 ... num
    								if @_kou2[i3] >= 0 and @_kou2[i3] <= t22
    									t22 = @_kou2[i3]
    									mn  = i3
    								end
    							end
    							@_kou2[mn] = -1
    							t22 += 1
    						end
    					end
    								# 指定箇所のコピー
    					for i3 in t11 ... t12
    						if i2%2 == 0
    							if c1 < @_max_len
    								@_ind[k1][c1] = @_ind[p1][i3]
    								c1 += 1
    							end
    						else
    							if c2 < @_max_len
    								@_ind[k2][c2] = @_ind[p1][i3]
    								c2 += 1
    							end
    						end
    					end
    	
    					for i3 in t21 ... t22
    						if i2%2 == 0
    							if c2 < @_max_len
    								@_ind[k2][c2] = @_ind[p2][i3]
    								c2 += 1
    							end
    						else
    							if c1 < @_max_len
    								@_ind[k1][c1] = @_ind[p2][i3]
    								c1 += 1
    							end
    						end
    					end
    								# 交叉位置の移動
    					t11 = t12
    					t21 = t22
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(一様交叉.[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)
    	###################################################################
    
    	def C_uniform(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a == 0
    			print("***error  交叉方法が不適当 (C_uniform)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_uniform)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				for i2 in 0 ... @_len[p1]
    					if rand(0) > 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]
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(平均化交叉.2つの親の平均値を受け継ぐ)
    	#      kosa : 交叉確率
    	#      k_method : 選択方法
    	#                 =-1 ランダム(default)
    	#                 =0 適応度をそのまま使用
    	#                 =1 最小値からの差(ただし,α以下の場合はα)
    	#                 =2 評価値に順位をつけ,減少率βで線形化
    	#      k_bias : α,または,method=2の場合は初期値(default=0)
    	#      k_step : β(default=1)
    	###################################################################
    
    	def C_mean(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_mean)\n")
    		end
    				# 交叉
    		for i1 in 0 ... @_max_ch
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(1, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k         = Position(-1)
    				@_len[k]  = @_len[p1]
    				@_pi_w[k] = 1
    							# 交叉
    				for i2 in 0 ... @_len[k]
    					@_ind[k][i2] = Integer((@_ind[p1][i2] + @_ind[p2][i2]) / 2)
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(循環交叉.ランダムに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)
    	###################################################################
    	def C_cycle(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_cycle)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_cycle)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 初期設定
    				for i2 in 0 ... @_len[p1]
    					@_kou1[i2] = 0
    					@_kou2[i2] = 0
    				end
    							# 遺伝子長
    				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  = Integer(rand(0) * @_len[p1])
    					if p >= @_len[p1]
    						p = @_len[p1] - 1
    					end
    					if @_kou1[p] == 0 and @_kou2[p] == 0
    						@_kou1[p]    = 1
    						@_kou2[p]    = 1
    						@_ind[k1][p] = @_ind[p1][p]
    						@_ind[k2][p] = @_ind[p2][p]
    						for i2 in 0 ... @_len[p1]
    							if @_ind[p2][p] == @_ind[p1][i2]
    								@_ind[k1][i2] = @_ind[p1][i2]
    								@_kou1[i2]    = 1
    								sw            = 0
    								break
    							end
    						end
    						sw = 1
    						for i2 in 0 ... @_len[p2]
    							if @_ind[p1][p] == @_ind[p2][i2]
    								@_ind[k2][i2] = @_ind[p2][i2]
    								@_kou2[i2]    = 1
    								sw            = 0
    								break
    							end
    						end
    					end
    				end
    	
    				sw = 0
    				i2 = 0
    				i3 = 0
    				while sw == 0
    					while sw == 0 and i2 < @_len[p1]
    						if @_kou1[i2] == 0
    							sw = 1
    						else
    							i2 += 1
    						end
    					end
    					sw = 0
    					while sw == 0 and i3 < @_len[p2]
    						if @_kou2[i3] == 0
    							sw = 1
    						else
    							i3 += 1
    						end
    					end
    					if i2 < @_len[p1] and i3 < @_len[p2]
    						@_ind[k1][i2] = @_ind[p2][i3]
    						@_ind[k2][i3] = @_ind[p1][i2]
    						sw            = 0
    						i2 += 1
    						i3 += 1
    					else
    						sw = 1
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(部分的交叉.ランダムに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)
    	#******************************************************************/
    	def C_part(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_part)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_part)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				p = Integer(rand(0) * @_len[p1])
    				if p >= @_len[p1]
    					p = @_len[p1] - 1
    				end
    	
    				for i2 in 0 ... @_len[p1]
    					@_ind[k1][i2] = @_ind[p1][i2]
    					@_ind[k2][i2] = @_ind[p2][i2]
    				end
    	
    				for i2 in p ... @_len[p1]
    					sw = 0
    					lv = @_ind[k1][i2]
    					for i3 in 0 ... @_len[p1]
    						if @_ind[k2][i2] == @_ind[k1][i3]
    							@_ind[k1][i2] = @_ind[k1][i3]
    							@_ind[k1][i3] = lv
    							sw            = 1
    							break
    						end
    					end
    					sw = 0
    					for i3 in 0 ... @_len[p1]
    						if lv == @_ind[k2][i3]
    							@_ind[k2][i3] = @_ind[k2][i2]
    							@_ind[k2][i2] = lv
    							sw            = 1
    							break
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(順序交叉.ランダムに切れ目を決定し,子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)
    	###################################################################
    	def C_seq(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_seq)")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_seq)")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				p = Integer(rand(0) * (@_len[p1] - 1))
    				if p >= @_len[p1]-1
    					p = @_len[p1] - 2
    				end
    	
    				for i2 in 0 ... p+1
    					@_ind[k1][i2] = @_ind[p1][i2]
    					@_ind[k2][i2] = @_ind[p2][i2]
    				end
    	
    				pp = 0
    				for i2 in p+1 ... @_len[p1]
    					sw = 0
    					i3 = pp
    					while i3 < @_len[p2] and sw == 0
    						i4 = p + 1
    						while i4 < @_len[p1] and sw == 0
    							if @_ind[p2][i3] == @_ind[p1][i4]
    								sw               = 1
    								pp               = i3 + 1
    								@_ind[k1][i2] = @_ind[p1][i4]
    							end
    							i4 += 1
    						end
    						i3 += 1
    					end
    				end
    				pp = 0
    				for i2 in p+1 ... @_len[p2]
    					sw = 0
    					i3 = pp
    					while i3 < @_len[p1] and sw == 0
    						i4 = p + 1
    						while i4 < @_len[p2] and sw == 0
    							if @_ind[p1][i3] == @_ind[p2][i4]
    								sw               = 1
    								pp               = i3 + 1
    								@_ind[k2][i2] = @_ind[p2][i4]
    							end
    							i4 += 1
    						end
    						i3 += 1
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(一様順序交叉.位置の集合をランダムに選択し,一方の親の選
    	#       択された位置における遺伝子の順序に従って,他の親の遺伝子
    	#       を並べ替える
    	#         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)
    	###################################################################
    	
    	def C_useq(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair =Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_useq)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_useq)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				for i2 in 0 ... @_len[p1]
    					@_ind[k1][i2] = @_ind[p1][i2]
    					@_ind[k2][i2] = @_ind[p2][i2]
    					if rand(0) < 0.5
    						@_kou1[i2] = 0
    					else
    						@_kou1[i2] = 1
    					end
    				end
    	
    				p = 0
    				for i2 in 0 ... @_len[p1]
    					if @_kou1[i2] > 0
    						sw = 0
    						i3 = p
    						while i3 < @_len[p2] and sw == 0
    							i4 = 0
    							while i4 < @_len[p1] and sw == 0
    								if @_ind[p2][i3] == @_ind[p1][i4] and @_kou1[i4] > 0
    									sw            = 1
    									p             = i3 + 1
    									@_ind[k1][i2] = @_ind[p1][i4]
    								end
    								i4 += 1
    							end
    							i3 += 1
    						end
    					end
    				end
    				p = 0
    				for i2 in 0 ... @_len[p3]
    					if @_kou1[i2] > 0
    						sw = 0
    						i3 = p
    						while i3 < @_len[p1] and sw == 0
    							i4 = 0
    							while i4 < @_len[p2] and sw == 0
    								if @_ind[p1][i3] == @_ind[p2][i4] and @_kou1[i4] > 0
    									sw            = 1
    									p             = i3 + 1
    									@_ind[k2][i2] = @_ind[p2][i4]
    								end
    								i4 += 1
    							end
    							i3 += 1
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(一様位置交叉.位置の集合をランダムに選択し,一方の親の選
    	#       択された位置における遺伝子の位置に,他の親の同じ遺伝子を
    	#       配置する.残りの遺伝子は,親と同じ順序に配置する.
    	#         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)
    	###################################################################
    
    	def C_upos(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    				# 初期設定とデータのチェック
    		pair = Integer(@_max_ch / 2)
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_upos)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_upos)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(2, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k1         = Position(-1)
    				@_pi_w[k1] = 1
    				@_len[k1]  = @_len[p1]
    				k2         = Position(-1)
    				@_pi_w[k2] = 1
    				@_len[k2]  = @_len[p2]
    							# 交叉
    				for i2 in 0 ... @_len[p1]
    					@_kou1[i2] = 1
    					if rand(0) < 0.5
    						@_kou1[i2] = 1
    					end
    					if @_kou1[i2] > 0
    						@_ind[k1][i2] = @_ind[p2][i2]
    						@_ind[k2][i2] = @_ind[p1][i2]
    					end
    				end
    	
    				p = 0
    				for i2 in 0 ... @_len[p1]
    					sw = 0
    					for i3 in 0 ... @_len[p1]
    						if @_kou1[i3] > 0 and @_ind[p1][i2] == @_ind[k1][i3]
    							sw = 1
    							break
    						end
    					end
    					if sw == 0
    						for i3 in p ... @_len[p1]
    							if @_kou1[i3] == 0
    								@_ind[k1][i3] = @_ind[p1][i2]
    								p             = i3 + 1
    								sw            = 1
    								break
    							end
    						end
    					end
    				end
    				p = 0
    				for i2 in 0 ... @_len[p2]
    					sw = 0
    					for i3 in 0 ... @_len[p2]
    						if @_kou1[i3] > 0 and @_ind[p2][i2] == @_ind[k2][i3]
    							sw = 1
    							break
    						end
    					end
    					if sw == 0
    						for i3 in p ... @_len[p2]
    							if @_kou1[i3] == 0
    								@_ind[k2][i3] = @_ind[p2][i2]
    								p                = i3 + 1
    								sw               = 1
    								break
    							end
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	###################################################################
    	# 交叉(エッジ組み替え交叉.以下の手順に従って行う.対立遺伝子は
    	#       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)
    	###################################################################
    
    	def C_edge(kosa, k_method = -1, k_bias = 0.0, k_step = 1.0)
    	
    		e  = Array.new(2)
    		k0 = 0
    				# 初期設定とデータのチェック
    		pair = @_max_ch
    	
    		if @_dup_a != 0
    			print("***error  交叉方法が不適当 (C_edge)\n")
    		end
    	
    		if @_min_len > 0
    			print("***error  遺伝子長は固定長でなければならない (C_edge)\n")
    		end
    				# 交叉
    		for i1 in 0 ... pair
    						# 交叉しない場合
    			if rand(0) > kosa
    				C_copy(1, 1)
    						# 交叉する場合
    			else
    							# 親の選択
    				p1 = Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Select(k_method, k_bias, k_step)
    					if p1 != p2
    						sw = 1
    					end
    				end
    							# 遺伝子長
    				k         = Position(-1)
    				@_pi_w[k] = 1
    				@_len[k]  = @_len[p1]
    							# エッジマップの初期化
    				for i2 in 0 ... @_len[k]
    					@_edge[i2][0] = 0
    					for i3 in 1 ... 5
    						@_edge[i2][i3] = -1
    					end
    				end
    							# 交叉
    								# エッジマップの作成
    				for i2 in 0 ... @_len[k]
    	
    					sw = 0
    					for i3 in 0 ... @_len[k]
    						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]
    								end
    							end
    							for i4 in 0 ... 2
    								@_edge[i2][0] += 1
    								@_edge[i2][@_edge[i2][0]] = e[i4]
    							end
    							break
    						end
    					end
    	
    					sw = 0
    					for i3 in 0 ... @_len[k]
    						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]
    								end
    							end
    							for i4 in 0 ... 2
    								sw = 1
    								for i5 in 1 ... @_edge[i2][0]+1
    									if @_edge[i2][i5] == e[i4]
    										sw = 2
    										break
    									end
    								end
    								if sw == 1
    									@_edge[i2][0] += 1
    									@_edge[i2][@_edge[i2][0]] = e[i4]
    								end
    							end
    							break
    						end
    					end
    				end
    								# 交叉の実行
    									# 出発点の決定
    				k1 = @_ind[p1][0]
    				k2 = @_ind[p2][0]
    				if @_edge[k1][0] == @_edge[k2][0]
    					kk = k1
    					if rand(0) > 0.5
    						kk = k2
    					end
    				else
    					kk = k2
    					if @_edge[k1][0] < @_edge[k2][0]
    						kk = k2
    					end
    				end
    				@_ind[k][0] = kk
    				p           = 1
    	
    				while p < @_len[k]
    									# ノードの除去
    					for i2 in 0 ... @_len[k]
    						sw = 0
    						if @_edge[i2][0] > 0
    							for i3 in 1 ... 5
    								if @_edge[i2][i3] == kk
    									sw              = 1
    									@_edge[i2][i3]  = -1
    									@_edge[i2][0]  -= 1
    									break
    								end
    							end
    						end
    					end
    									# 次の現在ノードの選択
    					min = 10
    					num = 0
    					for i2 in 1 ... 5
    						if @_edge[kk][i2] >= 0
    							k1 = @_edge[kk][i2]
    							if @_edge[k1][0] >= 0 and @_edge[k1][0] < min
    								num = 1
    								min = @_edge[k1][0]
    								k0  = k1
    							else
    								if @_edge[k1][0] == min
    									num += 1
    								end
    							end
    						end
    					end
    					if num > 1
    						k1 = Integer(rand(0) * num) + 1
    						if k1 > num
    							k1 = num
    						end
    						k2 = 0
    						k0 = -1
    						i2 = 1
    						while i2 <= 4 and k0 < 0
    							if @_edge[kk][i2] >= 0
    								if @_edge[@_edge[kk][i2]][0] == min
    									k2 += 1
    									if k1 == k2
    										k0 = @_edge[kk][i2]
    									end
    								end
    							end
    							i2 += 1
    						end
    					else
    						if num <= 0
    							num = 0
    							for i2 in 0 ... @_len[k]
    								if i2 != kk and @_edge[i2][0] >= 0
    									num += 1
    								end
    							end
    							if num <= 0
    								print("***error  invalid data (C_edge)\n")
    							else
    								k1 = Integer(rand(0) * num) + 1
    								if k1 > num
    									k1 = num
    								end
    								k2 = 0
    								k0 = -1
    								i2 = 0
    								while i2 < @_len[k] and k0 < 0
    									if i2 != kk and @_edge[i2][0] >= 0
    										k2 += 1
    										if k1 == k2
    											k0 = i2
    										end
    									end
    									i2 += 1
    								end
    							end
    						end
    					end
    					@_edge[kk][0]  = -1
    					@_ind[k][p]    = k0
    					kk                = k0
    					p                += 1
    				end
    			end
    		end
    	end
    	
    	##############################################################
    	# 交叉(サブツアー交叉.2点交叉の拡張である.ただし,相手に
    	#       同じ遺伝子のグループがない限り実行されない.たとえば
    	#         ***abcd**
    	#         *cdab****
    	#       のような両親の時実行され,以下の4つの子供が生成され
    	#       る)
    	#         ***cdab**
    	#         *abcd****
    	#         ***badc**
    	#         *dcba****
    	#       最大,4*交叉回数*個体総数*(個体総数-1) 個の子
    	#       供が生成される可能性があるので,子供の数としてこの値
    	#       以上のデータを入力しておく必要がある.
    	#      kosa : 交叉確率
    	#      count : 1つのペアーに対する交差回数(default=10)
    	##############################################################
    
    	def C_sub(kosa, count = 10)
    	
    		t22 = 0
    				# 初期設定とデータのチェック
    		if (4*count*@_size*(@_size-1)) > @_max_ch
    			print("***error  子供が多すぎる (C_sub)\n")
    		end
    				# 交叉
    		for i1 in 0 ... @_size-1
    						# 親1
    			p1 = Position(i1)
    	
    			if p1 >= 0
    	
    				for i2 in i1 ... @_size
    						# 親2
    					p2 = Position(i2)
    	
    					if p2 >= 0
    						# 交叉しない場合
    						if rand(0) > kosa
    							C_copy(2, 1)
    						# 交叉する場合
    						else
    							# 交叉回数の制御
    							for i3 in 0 ... count
    								# 交叉位置の決定(点の後ろで交叉)
    									# 親1の交叉位置
    								t11 = Integer(rand(0) * @_len[p1])
    								if t11 > (@_len[p1]-1)
    									t11 = @_len[p1] - 1
    								end
    								sw = 0
    								while sw == 0
    									t12 = Integer(rand(0) * @_len[p1])
    									if t12 > (@_len[p1]-1)
    										t12 = @_len[p1] - 1
    									end
    									if t12 != t11
    										sw = 1
    									end
    								end
    								if t11 > t12
    									k1  = t11
    									t11 = t12
    									t12 = k1
    								end
    									# 親2の交叉位置
    								sw  = 0
    								t21 = -1
    								i4  = 0
    								while i4 < @_len[p2] and t21 < 0
    									i5 = t11
    									while i5 <= t12 and t21 < 0
    										if @_ind[p2][i4] == @_ind[p1][i5]
    											t21 = i4
    										end
    										i5 += 1
    									end
    									i4 += 1
    								end
    								if t21 >= 0
    									t22 = t21 + t12 - t11
    									if t22 < @_len[p2]
    										sw = 1
    										i4 = t21 + 1
    										while i4 <= t22 and sw > 0
    											sw = 0
    											i5 = t11
    											while i5 <= t12 and sw == 0
    												if @_ind[p2][i4] == @_ind[p1][i5]
    													sw = 1
    												end
    												i5 += 1
    											end
    											i4 += 1
    										end
    									end
    								end
    									# 交叉の実行
    								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 in 0 ... t11
    										@_ind[k1][i4] = @_ind[p1][i4]
    										@_ind[k2][i4] = @_ind[p1][i4]
    									end
    									for i4 in t11 ... t12+1
    										@_ind[k1][i4] = @_ind[p2][t21+i4-t11]
    										@_ind[k2][i4] = @_ind[p2][t22-i4+t11]
    									end
    									for i4 in t12+1 ... @_len[p1]
    										@_ind[k1][i4] = @_ind[p1][i4]
    										@_ind[k2][i4] = @_ind[p1][i4]
    									end
    									for i4 in 0 ... t21
    										@_ind[k3][i4] = @_ind[p2][i4]
    										@_ind[k4][i4] = @_ind[p2][i4]
    									end
    									for i4 in t21 ... t22+1
    										@_ind[k3][i4] = @_ind[p1][t11+i4-t21]
    										@_ind[k4][i4] = @_ind[p1][t12-i4+t21]
    									end
    									for i4 in t22+1 ... @_len[p2]
    										@_ind[k3][i4] = @_ind[p2][i4]
    										@_ind[k4][i4] = @_ind[p2][i4]
    									end
    								end
    							end
    						end
    					end
    				end
    			end
    		end
    	end
    	
    	#######################################
    	# 突然変異(対立遺伝子との置き換え)
    	#      pr : 突然変異率
    	#######################################
    
    	def M_alle(pr)
    	
    				# データのチェックと初期設定
    		if @_dup_a == 0
    			print("***error  突然変異方法が不適当 (M_alle)\n")
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] == 1
    				for i2 in 0 ... @_len[i1]
    					if rand(0) <= pr
    						lid = Integer(rand(0) * (@_allele_u - @_allele_l + 1) + @_allele_l)
    						if lid > @_allele_u
    							lid = @_allele_u
    						end
    						if lid != @_ind[i1][i2]
    							@_ind[i1][i2] = lid
    						end
    					end
    				end
    			end
    		end
    	end
    
    	######################################################################
    	# 突然変異(移動.2点を選択し,2番目の遺伝子を1番目の遺伝子の前に
    	#           移動する)
    	#      pr : 突然変異率
    	######################################################################
    
    	def M_move(pr)
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    				# 位置の決定
    						# p1
    				p1 = Integer(rand(0) * @_len[i1])
    				if p1 >= @_len[i1]
    					p1 = @_len[i1] - 1
    				end
    						# p2
    				p2 = p1
    				sw = 0
    				while sw == 0
    					p2 = Integer(rand(0) * @_len[i1])
    					if p2 >= @_len[i1]
    						p2 = @_len[i1] - 1
    					end
    					if p2 != p1
    						sw = 1
    					end
    				end
    				# 実行
    				if p2 > p1
    					ld = @_ind[i1][p2]
    					i2 = p2
    					while i2 > p1
    						@_ind[i1][i2] = @_ind[i1][i2-1]
    						i2 -= -1
    					end
    					@_ind[i1][p1] = ld
    				else
    					ld = @_ind[i1][p2]
    					for i2 in p2 ... p1-1
    						@_ind[i1][i2] = @_ind[i1][i2+1]
    					end
    					@_ind[i1][p1-1] = ld
    				end
    			end
    		end
    	end
    	
    	########################################################
    	# 突然変異(逆位.2点間の遺伝子順序を逆に並べ替える)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	########################################################
    
    	def M_inv(pr, wd = 0)
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    				# 区間の決定
    				if wd == 0
    					p1 = Integer(rand(0) * @_len[i1])
    					if p1 >= @_len[i1]
    						p1 = @_len[i1] - 1
    					end
    					sw = 0
    					p2 = p1
    					while sw == 0
    						p2 = Integer(rand(0) * @_len[i1])
    						if p2 >= @_len[i1]
    							p2 = @_len[i1] - 1
    						end
    						if p2 != p1
    							sw = 1
    						end
    					end
    					if p1 > p2
    						p  = p1
    						p1 = p2
    						p2 = p
    					end
    	
    				else
    					p1 = @_len[i1]
    					while p1 > @_len[i1]-2
    						p1 = Integer(rand(0) * @_len[i1])
    					end
    					p2 = p1 + wd - 1
    					if p2 >= @_len[i1]
    						p2 = @_len[i1] - 1
    					end
    				end
    				# 実行
    				sw = 0
    				while sw == 0
    					lid           = @_ind[i1][p1]
    					@_ind[i1][p1] = @_ind[i1][p2]
    					@_ind[i1][p2] = lid
    					p1 += 1
    					p2 -= 1
    					if p1 >= p2
    						sw = 1
    					end
    				end
    			end
    		end
    	end
    	
    	######################################################################
    	# 突然変異(スクランブル.2点間の遺伝子順序をランダムに並べ替える)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	######################################################################
    
    	def M_scram(pr, wd = 0)
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    				# 区間の決定
    				if wd == 0
    					p1 = Integer(rand(0) * @_len[i1])
    					if p1 >= @_len[i1]
    						p1 = @_len[i1] - 1
    					end
    					sw = 0
    					p2 = p1
    					while sw == 0
    						p2 = Integer(rand(0) * @_len[i1])
    						if p2 >= @_len[i1]
    							p2 = @_len[i1] - 1
    						end
    						if p2 != p1
    							sw = 1
    						end
    					end
    					if p1 > p2
    						p  = p1
    						p1 = p2
    						p2 = p
    					end
    	
    				else
    					p1 = @_len[i1]
    					while p1 > @_len[i1]-2
    						p1 = Integer(rand(0) * @_len[i1])
    					end
    					p2 = p1 + wd - 1
    					if p2 >= @_len[i1]
    						p2 = @_len[i1] - 1
    					end
    				end
    				# 実行
    				for i2 in p1 ... p2+1
    					p = Integer(rand(0) * (p2 - p1 + 1) + p1)
    					if p > p2
    						p = p2
    					end
    					ld            = @_ind[i1][i2]
    					@_ind[i1][i2] = @_ind[i1][p]
    					@_ind[i1][p]  = ld
    				end
    			end
    		end
    	end
    	
    	######################################################################
    	# 突然変異(転座.2点間の遺伝子を他の位置のものと置き換える.ただし
    	#           重複部分はそのままとする)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	######################################################################
    
    	def M_chg(pr, wd = 0)
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    				# 区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    						# p1
    				p1 = Integer(rand(0) * @_len[i1])
    				if p1 >= @_len[i1]
    					p1 = @_len[i1] - 1
    				end
    						# p3
    				sw = 0
    				p3 = p1
    				while sw == 0
    					p3 = Integer(rand(0) * @_len[i1])
    					if p3 >= @_len[i1]
    						p3 = @_len[i1] - 1
    					end
    					if p3 != p1
    						sw = 1
    					end
    				end
    						# 小さい方をp1,p2にする
    				if p1 > p3
    					p  = p1
    					p1 = p3
    					p3 = p
    				end
    						# p4, p2
    				p4 = p1 + wd - 1
    				if wd == 0
    					p4 = Integer(rand(0) * (@_len[i1] - p3)) + p3
    				end
    				if p4 >= @_len[i1]
    					p4 = @_len[i1] - 1
    				end
    				p2 = p1 + (p4 - p3)
    						# 重複部分のチェック
    				if p2 >= p3
    					p  = p3 - 1
    					p3 = p2 + 1
    					p2 = p
    					p4 = p3 + (p2 - p1)
    				end
    				# 実行
    				p = p3
    				for i2 in p1 ... p2+1
    					ld             = @_ind[i1][i2]
    					@_ind[i1][i2]  = @_ind[i1][p]
    					@_ind[i1][p]   = ld
    					p              += 1
    				end
    			end
    		end
    	end
    	
    	######################################################################
    	# 突然変異(重複.2点間の遺伝子を他の位置にコピーする
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(deafult)
    	######################################################################
    
    	def M_dup(pr, wd = 0)
    	
    				# データのチェック
    		if @_dup_a == 0
    			print("***error  突然変異方法が不適当 (M_dup)\n")
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    						# 区間の決定([p1,p2]を[p3,p4]にコピー)
    							# p1
    				p1 = Integer(rand(0) * @_len[i1])
    				if p1 >= @_len[i1]
    					p1 = @_len[i1] - 1
    				end
    							# p3
    				sw = 0
    				p3 = p1
    				while sw == 0
    					p3 = Integer(rand(0) * @_len[i1])
    					if p3 >= @_len[i1]
    						p3 = @_len[i1] - 1
    					end
    					if p3 != p1
    						sw = 1
    					end
    				end
    							# 区間を決める
    				p2 = p1
    				p4 = p1
    				if p3 > p1
    					p4 = p3 + wd - 1
    					if wd == 0
    						p4 = Integer(rand(0) * (@_len[i1] - p3)) + p3
    					end
    					if p4 >= @_len[i1]
    						p4 = @_len[i1] - 1
    					end
    					p2 = p1 + (p4 - p3)
    				else
    					p2 = p1 + wd - 1
    					if wd == 0
    						p2 = Integer(rand(0) * (@_len[i1] - p1)) + p1
    					end
    					if p2 >= @_len[i1]
    						p2 = @_len[i1] - 1
    					end
    					p4 = p3 + (p2 - p1)
    						# 実行
    				end
    				p  = p4
    				i2 = p2
    				while i2 > p1-1
    					@_ind[i1][p] = @_ind[i1][i2]
    					p  -= 1
    					i2 -= 1
    				end
    			end
    		end
    	end
    	
    	######################################################
    	# 突然変異(摂動.値をある量だけ変化させる)
    	#      pr : 突然変異率
    	#      method : =0 正規分布(default)
    	#               =1 一様分布
    	#      m : 平均または一様分布の下限(default=0.0)
    	#      s : 標準偏差または一様分布の上限(default=1.0)
    	######################################################
    
    	def M_per(pr, method = 0, m = 0.0, s = 1.0)
    	
    		wd = 0.0
    				# データのチェックと初期設定
    		if @_dup_a == 0
    			print("***error  突然変異方法が不適当 (M_per)\n")
    		end
    	
    		if method > 0
    			wd = s - m
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] == 1
    				for i2 in 0 ... @_len[i1]
    					if rand(0) <= pr
    						if method == 0
    							w = normalvariate(m, s)
    						else
    							w = rand(0) * wd
    							if rand(0) < 0.5
    								w = -w
    							end
    						end
    						x1 = float(@_ind[i1][i2]) + w
    						if x1 > @_allele_u
    							x1 = @_allele_u
    						else
    							if x1 < @_allele_l
    								x1 = @_allele_l
    							end
    						end
    						@_ind[i1][i2] = Integer(x1)
    					end
    				end
    			end
    		end
    	end
    	
    	##############################################
    	# 突然変異(挿入.ある長さの遺伝子を挿入する)
    	#      pr : 突然変異率
    	#      wd : >0 幅を固定
    	#           =0 幅をランダム(default)
    	##############################################
    
    	def M_ins(pr, wd = 0)
    	
    				# データのチェック
    		if @_dup_a == 0 or @_min_len < 0
    			print("***error  突然変異方法が不適当 (M_ins)\n")
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    						# 挿入位置の決定
    				p = Integer(rand(0) * (@_len[i1] + 1))
    				if p > @_len[i1]
    					p = @_len[i1]
    				end
    						# 挿入する遺伝子長の決定
    				l = wd
    				if wd == 0
    					l = Integer(rand(0) * (@_max_len - @_len[i1] + 1))
    				end
    				if l > @_max_len-@_len[i1]
    					l = @_max_len - @_len[i1]
    				else
    					if l <= 0
    						l = 1
    					end
    				end
    						# 実行
    							# 挿入場所の確保
    				if p < @_len[i1]
    					i2 = @_len[i1] + l - 1
    					while i2 > p-1
    						@_ind[i1][i2] = @_ind[i1][i2-l]
    						i2 -= 1
    					end
    				end
    							# 挿入場所の遺伝子の決定
    				for i2 in p ... p+l
    					ld = Integer(rand(0) * (@_allele_u - @_allele_l + 1) + @_allele_l)
    					if ld > @_allele_u
    						ld = @_allele_u
    					end
    					@_ind[i1][i2] = ld
    				end
    	
    				@_len[i1]  += l
    			end
    		end
    	end
    	
    	##############################################
    	# 突然変異(削除.ある長さの遺伝子を削除する)
    	#      pr : 突然変異率
    	#      wd : >0 幅を固定
    	#           =0 幅をランダム(default)
    	##############################################
    
    	def M_del(pr, wd = 0)
    	
    				# データのチェック
    		if @_dup_a == 0 or @_min_len < 0
    			print("***error  突然変異方法が不適当 (M_del)\n")
    		end
    				# 実行
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1 and rand(0) <= pr
    						# 削除位置の決定
    				p = Integer(rand(0) * @_len[i1])
    				if p >= @_len[i1]
    					p = @_len[i1] - 1
    				end
    						# 削除する遺伝子長の決定
    				max = @_len[i1] - p
    				if @_len[i1]-@_min_len < @_len[i1]-p
    					max = @_len[i1] - @_min_len
    				end
    				l = wd
    				if wd == 0
    					l = Integer(rand(0) * max + 1)
    				end
    				if l > max
    					l = max
    				end
    						# 実行
    				for i2 in 0 ... @_len[i1]-p-l
    					@_ind[i1][p+i2] = @_ind[i1][p+i2+l]
    				end
    	
    				@_len[i1]  -= l
    			end
    		end
    	end
    	
    	######################################################################
    	# 淘汰(エリート・ルーレット選択)
    	#      elite : エリートで残す個体数(default=0)
    	#      s_method : ルーレット板の作成方法(default=1)
    	#                   =0 適応度をそのまま使用
    	#                   =1 最小値からの差(ただし,α以下の場合はα)
    	#                   =2 評価値に順位をつけ,減少率βで線形化
    	#      s_bias : α,または,method=2の場合は初期値(default=0)
    	#      s_step : β(default=1)
    	######################################################################
    
    	def S_roul(elite = 0, s_method = 1, s_bias = 0.0, s_step = 1.0)
    	
    		count = 0
    		k     = 0
    		n     = 0
    				# 値のチェックと初期設定
    		if s_method != 0 and s_method != 2
    			s_method = 1
    		end
    	
    		if elite > @_size
    			print("***error  エリートで残す数が多すぎる (S_roul)\n")
    		end
    	
    		if s_method == 2 and s_step <= 0.0
    			s_step = 1.0
    		end
    	
    		for i1 in 0 ... @_size+@_max_ch
    			@_s_w[i1] = 0
    		end
    				# 重複個体を削除
    		if @_dup_s == 0
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 0
    					for i2 in i1+1 ... @_size+@_max_ch
    						if @_pi_w[i2] > 0 and @_len[i1] == @_len[i2]
    							sw = 0
    							for i3 in 0 ... @_len[i1]
    								if @_ind[i1][i3] != @_ind[i2][i3]
    									sw = 1
    									break
    								end
    							end
    							if sw == 0
    								@_pi_w[i2] = 0
    							end
    						end
    					end
    				end
    			end
    		end
    	
    		for i1 in 0 ... @_size+@_max_ch
    			if @_pi_w[i1] > 1
    				n += 1
    			end
    		end
    	
    		if n < 0 or (@_dup_s == 0 and n < @_size)
    			print("***error  残す個体がない (S_roul)\n")
    		end
    				# 淘汰して残す個体を選ぶ
    						# エリートの選択
    		sw = 0
    	
    		while k < elite and k < n and sw == 0
    			max = -1
    			for i1 in 0 ... @_size+@_max_ch
    				if @_pi_w[i1] > 1 and @_s_w[i1] == 0
    					if max < 0 or @_pi[i1] > @_pi[max]
    						max = i1
    					end
    				end
    			end
    			if max < 0
    				sw = 1
    			else
    				@_s_w[max]  = 1
    				k          += 1
    			end
    		end
    						# ルーレット選択
    		while count < @_size+@_max_ch and k < @_size
    			p = Select(s_method, s_bias, s_step)
    			if @_dup_s == 0 and @_s_w[p] > 0
    				count += 1
    			else
    				count     = 0
    				@_s_w[p] += 1
    				k        += 1
    			end
    		end
    							# 選択に失敗した場合の処理
    		if @_dup_s == 0 and k < @_size
    			i1 = 0
    			while i1 < @_size+@_max_ch and k < @_size
    				if @_pi_w[i1] > 1 and @_s_w[i1] == 0
    					@_s_w[i1]  = 1
    					k         += 1
    				end
    				i1 += 1
    			end
    		end
    							# 複数回選択されたものの処理
    		for i1 in 0 ... @_size+@_max_ch
    			if @_s_w[i1] == 0
    				@_pi_w[i1] = 0
    			end
    		end
    	
    		for i1 in 0 ... @_size+@_max_ch
    			if @_s_w[i1] > 0
    				if @_s_w[i1] > 1
    					for i2 in 2 ... @_s_w[i1]+1
    						k         = Position(-1)
    						@_len[k]  = @_len[i1]
    						@_pi_w[k] = 2
    						@_pi[k]   = @_pi[i1]
    						for i3 in 0 ... @_len[i1]
    							@_ind[k][i3] = @_ind[i1][i3]
    						end
    					end
    				end
    			end
    		end
    	end
    end
    	
    #######################
    # クラスFunctionの定義
    #######################
    
    class Function < Species
    
    	######################################
    	# コンストラクタ
    	#      name1 : Species定義ファイル名
    	#      name2 : Function定義ファイル名
    	######################################
    
    	def initialize(name1, name2)
    	
    		super(name1)   # 親のコンストラクタ
    						# 基本データの入力
    		inn = open(name2, "r")
    	
    		s = inn.gets().split(" ")
    		@_out_lvl = Integer(s[1])   # 出力レベル
    		                            #   =0 : 最終出力だけ
    		                            #   n>0 : n世代毎に出力(負の時はファイル)
    		@_out_m   = Integer(s[3])  # 出力方法
    		                           #   =0 : すべてを出力
    		                           #   =1 : 最大適応度の個体だけを出力
    
    		s = inn.gets().split(" ")
    		@_o_file = s[1]   # 出力ファイル名
    		@_out_d  = Integer(s[3])   # 表示間隔
    
    		s = inn.gets().split(" ")
    		@_kosa_m   = Integer(s[1])   # 交叉方法
    		                             #   =-1 : 交叉を使用しない
    		                             #   =0 : 親のコピー
    		                             #   =1 : 多点交叉
    		                             #   =2 : 一様交叉
    		                             #   =3 : 平均化交叉
    		@_kosa     = Float(s[3])   # 交叉確率
    		@_k_point  = Integer(s[5])   # 交差点の数(負の時は,1から-k_point間のランダム)
    		@_k_vr     = Integer(s[7])   # =0 : 両親とも同じ位置で交叉
    		                             # =1 : 両親が異なる位置で交叉(遺伝子長は可変)
    		@_k_method = Integer(s[9])   # 交叉の時の親の選択方法
    		                             #   =-1 : ランダム
    		                             #   =0 : 適応度をそのまま使用
    		                             #   =1 : 最小値からの差(ただし,α以下の場合はα)
    		                             #   =2 : 評価値に順位をつけ,減少率βで線形化
    		@_k_bias   = Float(s[11])   # α,または,method=2の場合は初期値
    		@_k_step   = Float(s[13])   # β
    
    		s = inn.gets().split(" ")
    		@_mute_m = Integer(s[1])   # 突然変異方法
    		                           #   =-1 : 突然変異を使用しない
    		                           #   =0 : 対立遺伝子への置換
    		                           #   =1 : 移動
    		                           #   =2 : 逆位
    		                           #   =3 : スクランブル
    		                           #   =4 : 転座
    		                           #   =5 : 重複
    		                           #   =6 : 摂動
    		@_mute   = Float(s[3])   # 突然変異率
    		@_wd     = Integer(s[5])   # 突然変異に使用する部分遺伝子長
    		@_m_mean = Float(s[7])   # 摂動の平均値
    		@_m_std  = Float(s[9])   # 摂動の標準偏差
    
    		s = inn.gets().split(" ")
    		@_elite    = Integer(s[1])   # エリート選択で残す数
    		@_s_method = Integer(s[3])   # ルーレット板の作成方法
    		                             #   =0 : 適応度をそのまま使用
    		                             #   =1 : 最小値からの差(ただし,α以下の場合はα)
    		                             #   =2 : 評価値に順位をつけ,減少率βで線形化
    		@_s_bias   = Float(s[5])   # α,または,s_method=2の場合は初期値
    		@_s_step   = Float(s[7])   # β
    
    		s = inn.gets().split(" ")
    		@_max_gen = Integer(s[1])   # 最大世代交代数
    	
    		@_cv = 1.0 / (2.0 ** Float(@_max_len) - 1.0)   # 2進数を10進数の変換する係数
    	
    		inn.close()
    	end
    	
    	###############
    	# 全体の制御
    	###############
    
    	def Control()
    	
    		gen = 1
    						# 初期集団の発生
    		Init_std()
    						# 評価
    		Adap()
    						# 出力
    		print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + "\n")
    	
    		if @_out_lvl.abs() > 0
    			Output(gen)
    		end
    						# 世代交代
    		for gen in 2 ... @_max_gen+1
    							# 交叉
    			if @_kosa_m == 0
    				C_copy()   # 親のコピー
    			elsif @_kosa_m == 1
    				C_point(@_kosa, @_k_point)   # 多点交叉
    			elsif @_kosa_m == 2
    				C_uniform(@_kosa)   # 一様交叉
    			elsif @_kosa_m == 3
    				C_mean(@_kosa)   # 平均化交叉
    			end
    							# 突然変異
    			if @_mute_m == 0
    				M_alle(@_mute)   # 対立遺伝子への置換
    			elsif @_mute_m == 1
    				M_move(@_mute)   # 移動
    			elsif @_mute_m == 2
    				M_inv(@_mute, @_wd)   # 逆位
    			elsif @_mute_m == 3
    				M_scram(@_mute, @_wd)   # スクランブル
    			elsif @_mute_m == 4
    				M_chg(@_mute, @_wd)   # 転座
    			elsif @_mute_m == 5
    				M_dup(@_mute, @_wd)   # 重複
    			elsif @_mute_m == 6
    				M_per(@_mute, @_wd, @_m_mean, @_m_std)   # 摂動
    			end
    							# 適応度
    			Adap()
    							# 淘汰
    			S_roul(@_elite)
    							# 出力
    			if gen%@_out_d == 0
    				print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + "\n")
    			end
    	
    			if @_out_lvl.abs() > 0
    				if gen%@_out_lvl.abs() == 0
    					Output(gen)
    				end
    			end
    		end
    	
    		gen     -= 1
    		k1       = @_out_m
    		@_out_m  = 0
    		print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + "\n")
    		Output(gen)
    		@_out_m = k1
    	end
    
    	################
    	# 適応度の計算
    	################
    
    	def Adap()
    	
    		n          = 0
    		@_max   = 0.0
    		@_max_n = -1
    		@_mean  = 0.0
    	
    		for i1 in 0 ... @_size+@_max_ch
    	
    			if @_pi_w[i1] == 1
    				x  = 0.0
    				y  = 0.0
    				i2 = @_len[i1] - 1
    				while i2 > -1
    					if @_ind[i1][i2] > 0
    						x += 2.0 ** y
    					end
    					y  += 1.0
    					i2 -= 1
    				end
    				x          *= @_cv
    				@_pi[i1]    = Math.sin(3.0*x) + 0.5 * Math.sin(9.0*x) + Math.sin(15.0*x+50.0)
    				@_pi_w[i1]  = 2
    			end
    	
    			if @_pi_w[i1] > 0
    				@_mean += @_pi[i1]
    				n      += 1
    				if @_max_n < 0 or @_pi[i1] > @_max
    					@_max   = @_pi[i1]
    					@_max_n = i1
    				end
    			end
    		end
    	
    		@_mean /= n
    	end
    	
    	#############################
    	# 結果の出力
    	#      gen : 現在の世代番号
    	#############################
    
    	def Output(gen)
    	
    		k  = 0
    		pr = -1
    
    		if @_out_lvl >= 0
    			print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ")
    			pr = Integer($stdin.gets())
    		end
    	
    		if pr != 0
    						# 出力先の決定と評価値の出力
    			if pr > 0
    				out = $stdout
    				$stdin.gets()
    			else
    				now = String(Time.now)
    				out = open(@_o_file, "a")
    				out.print("***世代 " + String(gen) + " 適応度 max " + String(@_max) + " (" + String(@_max_n) + ") mean " + String(@_mean) + " 時間 " + now + "\n")
    			end
    						# 詳細出力
    			sw = 0
    			for i1 in 0 ... @_size+@_max_ch
    				if (@_pi_w[i1] > 1) and (@_out_m == 0 or (@_out_m == 1 and i1 == @_max_n))
    					out.print(String(i1) + " allele")
    					for i2 in 0 ... @_len[i1]
    						out.print(" " + String(@_ind[i1][i2]))
    					end
    					x  = 0.0
    					y  = 0.0
    					i2 = @_len[i1] - 1
    					while i2 > -1
    						if @_ind[i1][i2] > 0
    							x += 2.0 ** y
    						end
    						y  += 1.0
    						i2 -= 1
    					end
    					x *= @_cv
    					out.print(" x " + String(x) + " y " + String(@_pi[i1]) + "\n")
    					if pr > 0
    						k += 1
    						if k == pr
    							$stdin.gets()
    							k = 0
    						end
    					end
    				end
    			end
    	
    			if pr < 0
    				out.close()
    			end
    		end
    	end
    end
    
    				# 入力ミス
    if ARGV[0] == nil
    	print("***error  ファイル名を入力して下さい\n")
    				# 入力OK
    else
    					# データの数と入力データファイル名の入力
    	line    = gets()
    	n       = Integer(line)   # データの数
    	i_file1 = Array.new(n)
    	i_file2 = Array.new(n)
    
    	for i1 in 0 ... n
    		line        = gets()
    		a           = line.split(" ")
    		i_file1[i1] = a[0]
    		i_file2[i1] = a[1]
    	end
    					# 実行(乱数の初期値を変える)
    	for i1 in 0 ... n
    
    		print("\n+++++ケース " + String(i1+1) + "+++++\n")
    		srand(1000 * i1 + 1234567);
    
    		fn = Function.new(i_file1[i1], i_file2[i1])
    
    		fn.Control()
    	end
    end
    
    =begin
    ------------------ケーススタディデータ(data_cf.txt)------
    3
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    
    ------------------Species記述データ(data1_f.txt)---------
    対立遺伝子上限 1 対立遺伝子下限 0
    最大遺伝子長 15 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 1 個体の重複(同じ染色体の個体) 0
    集団サイズ 20 子供 20
    
    ------------------Function記述データ(data2_f.txt)--------
    出力レベル(負はファイル) 20 出力方法(0:すべて,1:最大) 0
    出力ファイル名 out1.txt 表示間隔 1
    交叉方法 1 交叉確率 1.0 点 2 位置 0 方法 1 バイアス 0 ステップ 1
    突然変異方法 0 突然変異率 0.05 幅 1 平均 0.0 標準偏差 1.0
    エリート 2 方法 1 バイアス 0 ステップ 1
    最大世代交代数 200
    =end
    			

  5. Python

    TSP
    # -*- coding: UTF-8 -*-
    import numpy as np
    import sys
    from math import *
    from random import *
    from datetime import *
    
    /***********************************/
    /* 遺伝的アルゴリズムによるTSPの解 */
    /*      coded by Y.Suganuma        */
    /***********************************/
    
    ######################
    # クラスSpeciesの定義
    ######################
    
    class Species :
    	
    	#########################
    	# コンストラクタ
    	#      name : ファイル名
    	#########################
    
    	def __init__(self, name) :
    	
    				# データの入力
    		inn = open(name, "r")
    	
    		s = inn.readline().split()
    		self.allele_u = int(s[1])   # 対立遺伝子上限
    		self.allele_l = int(s[3])   # 対立遺伝子下限
    
    		s = inn.readline().split()
    		self.max_len = int(s[1])   # 最大遺伝子長
    		self.min_len = int(s[3])   # 最小遺伝子長(負の時は,最大遺伝子長で固定)
    
    		s = inn.readline().split()
    		self.dup_a = int(s[1])  # 遺伝子の重複
    		                        #   =0 : 重複を許さない
    		                        #   =1 : 重複を許す
    		self.dup_s = int(s[3])   # 個体の重複(同じ染色体の個体)
    		                         #   =0 : 重複を許さない
    		                         #   =1 : 重複を許す
    
    		s = inn.readline().split()
    		self.size   = int(s[1])   # 個体総数
    		self.max_ch = int(s[3])   # 子供の数の最大値
    				# データのチェック
    		if self.size <= 0 :
    			print("***error  個体総数≦0 (Constructor)")
    	
    		if self.max_ch < 0 :
    			print("***error  子供の数<0 (Constructor)")
    	
    		if self.max_len <= 0 or self.min_len == 0 :
    			print("***error  遺伝子長≦0 (Constructor)")
    	
    		if self.max_len < self.min_len :
    			print("***error  最大遺伝子長<最小遺伝子長 (Constructor)")
    	
    		if self.allele_u <= self.allele_l :
    			print("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)")
    	
    		kind = self.allele_u - self.allele_l + 1
    		if self.dup_a == 0 and self.max_len > kind :
    			print("***error  遺伝子の重複を防ぐことはできない (Constructor)")
    				# 領域の確保
    		num       = self.size + self.max_ch
    		self.ind  = np.empty((num, self.max_len), np.int)   # 集団(個体の集まり)
    		self.edge = np.empty((self.max_len, 5), np.int)   # エッジ組み替え交叉用ワークエリア
    		self.pi   = np.empty(num, np.float)   # 適応度
    		self.ro   = np.empty(num, np.float)   # ルーレット板
    		self.len  = np.empty(num, np.int)   # 各個体の遺伝子長
    		self.kou1 = np.empty(self.max_len, np.int)   # 交叉・突然変異用作業場所1
    		self.kou2 = np.empty(self.max_len, np.int)   # 交叉・突然変異用作業場所2
    		self.s_w  = np.empty(num, np.int)   # 淘汰用指標(選択された回数)
    		self.pi_w = np.empty(num, np.int)   # 適応度計算指標
    		                                    #   =0 : 未使用
    		                                    #   =1 : 適応度計算前(突然変異はこの個体だけに適用)
    		                                    #   =2 : 適応度計算済み(交叉時に親とみなす)
    		self.max   = -inf   # 最大適応度
    		self.mean  = 0.0   # 平均適応度
    		self.max_n = -1   # 最大適応度の個体番号
    
    	##################################################
    	# 場所を探す
    	#      n : >=0 : n番目の親を捜す
    	#          -1 : 空いている場所を探す
    	#      return : 親の場所,または,空いている場所
    	#               (存在しないときは負の値)
    	##################################################
    
    	def Position(self, n) :
    	
    		k  = -1
    		sw = 0
    				# 空いている場所を探す
    		if n < 0 :
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] == 0 :
    					k = i1
    					break
    			if k < 0 :
    				print("***error  空いている場所がない --Position--")
    				# n番目の親(pi_w[i]=2)を捜す
    		else :
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] == 2 :
    					k += 1
    					if k == n :
    						sw = 1
    						k  = i1
    						break
    	
    		return k
    	
    	###################################################################
    	# 個体の選択
    	#      method : 選択方法
    	#                 =-1 : ランダム(default)
    	#                 =0 : 適応度をそのまま使用
    	#                 =1 : 最小値からの差(ただし,α以下の場合はα)
    	#                 =2 : 評価値に順位をつけ,減少率βで線形化
    	#      bias : α,または,method=2の場合は初期値(default=0)
    	#      step : β(default=1)
    	#      return : 個体番号
    	###################################################################
    
    	def Select(self, method, bias, step) :
    	
    		sum = 0.0
    					# ルーレット板の用意
    							# ランダム
    		if method == -1 :
    			n = 0
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					n += 1
    			sum = 1.0 / n
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					self.ro[i1] = sum
    							# 評価値をそのまま利用
    		elif method == 0 :
    			n = 0
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					sum += self.pi[i1]
    					n   += 1
    			if fabs(sum) > 1.0e-10 :
    				sum = 1.0 / fabs(sum)
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.pi_w[i1] > 1 :
    						self.ro[i1] = self.pi[i1] * sum
    			else :
    				sum = 1.0 / n
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.pi_w[i1] > 1 :
    						self.ro[i1] = sum
    							# 最小値からの差
    		elif method == 1 :
    			min = -1
    			n   = 0
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					n += 1
    					if min < 0 or self.pi[i1] < self.pi[min] :
    						min = i1
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					self.ro[i1] = self.pi[i1] - self.pi[min]
    					if self.ro[i1] < bias :
    						self.ro[i1] = bias
    					sum += self.ro[i1]
    			if sum > 1.0e-10 :
    				sum = 1.0 / sum
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.pi_w[i1] > 1 :
    						self.ro[i1] *= sum
    			else :
    				sum = 1.0 / n
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.pi_w[i1] > 1 :
    						self.ro[i1] = sum
    							# 線形化
    		elif method == 2 :
    			n = 0
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					self.ro[i1] = -1.0
    					n += 1
    				else :
    					self.ro[i1] = 1.0
    			sw  = 0
    			sum = bias
    			while sw == 0 :
    				min = -1
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.ro[i1] < 0.0 and (min < 0 or self.pi[i1] < self.pi[min]) :
    						min = i1
    				if min < 0 :
    					sw = 1
    				else :
    					self.ro[min]  = sum
    					sum          += self.step
    			sum = 1.0 / (0.5 * (2.0 * bias + step * (n - 1)) * n)
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					self.ro[i1] *= sum
    	
    		sum = 0.0
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] > 1 :
    				sum         += self.ro[i1]
    				self.ro[i1]  = sum
    						# 選択
    		x  = random()
    		sw = 0
    		k  = 0
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] > 1 :
    				if x <= self.ro[i1] :
    					sw = 1
    					k  = i1
    					break
    	
    		return k
    	
    	###################
    	# 標準的な初期設定
    	###################
    
    	def Init_std(self) :
    	
    				# 初期設定
    		for i1 in range(0, self.size+self.max_ch) :
    			if i1 < self.size :
    				self.pi_w[i1] = 1   # 適応度の計算前
    			else :
    				self.pi_w[i1] = 0   # 未使用
    				# 遺伝子の決定
    		for i1 in range(0, self.size) :
    	
    			sw1    = 0
    			length = 0
    
    			while sw1 == 0 :
    						# 遺伝子長の決定
    				if self.min_len < 0 :
    					length = self.max_len
    				else :
    					length = int(random() * (self.max_len - self.min_len + 1) + self.min_len)
    					if length > self.max_len :
    						length = self.max_len
    				self.len[i1] = length
    						# 遺伝子の決定
    				for i2 in range(0, length) :
    					sw2 = 0
    					while sw2 == 0 :
    						lid = int(random() * (self.allele_u - self.allele_l + 1) + self.allele_l)
    						if lid > self.allele_u :
    							lid = self.allele_u
    						self.ind[i1][i2] = lid
    							# 重複遺伝子のチェック
    						sw2 = 1
    						if self.dup_a == 0 :
    							for i3 in range(0, i2) :
    								if lid == self.ind[i1][i3] :
    									sw2 = 0
    									break
    						# 重複個体のチェック
    				sw1 = 1
    				if self.dup_s == 0 :
    					for i2 in range(0, i1) :
    						if self.len[i1] == self.len[i2] :
    							sw2 = 0
    							for i3 in range(0, self.len[i1]) :
    								if self.ind[i1][i3] != self.ind[i2][i3] :
    									sw2 = 1
    									break
    							if sw2 == 0 :
    								sw1 = 0
    								break
    	
    	####################################################
    	# 標準的な出力
    	#      sw : 出力レベル
    	#             =0 : 最終出力だけ
    	#             n>0 : n世代毎に出力(負はファイル)
    	#      out_m : 出力方法
    	#                =0 : すべての個体を出力
    	#                =1 : 最大適応度の個体だけを出力
    	#      gen : 現在の世代番号
    	#      name : 出力ファイル名
    	####################################################
    
    	def Out_std(self, sw, out_m, gen, name) :
    	
    		k  = 0
    		pr = -1
    
    		if sw >= 0 :
    			pr = int(input("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? "))
    	
    		if pr != 0 :
    						# 出力先の決定と評価値の出力
    			if pr > 0 :
    				out = sys.stdout
    				input("")
    			else :
    				now = datetime.today().time().isoformat()
    				out = open(name, "a")
    				out.write("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean) + " 時間 " + now + "\n")
    						# 詳細出力
    			for i1 in range(0, self.size+self.max_ch) :
    				if (self.pi_w[i1] > 1) and (out_m == 0 or (out_m == 1 and i1 == self.max_n)) :
    					out.write(str(i1) + " allele")
    					for i2 in range(0, self.len[i1]) :
    						out.write(" " + str(self.ind[i1][i2]))
    					out.write(" value " + str(self.pi[i1]) + "\n")
    					if pr > 0 :
    						k += 1
    						if k == pr :
    							input("")
    							k = 0
    	
    			if pr < 0 :
    				out.close()
    	
    	###################################################################
    	# 交叉(親のコピー)
    	#      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)
    	###################################################################
    
    	def C_copy(self, method = 2, pair = 0, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータチェック
    		if method != 1 :
    			method = 2
    	
    		if pair <= 0 :
    			if method == 2 :
    				pair = int(self.max_ch / 2)
    			else :
    				pair = self.max_ch
    		else :
    			if method == 2 and 2*pair > self.max_ch or method == 1 and pair > self.max_ch :
    				print("***error  子供が多すぎる (C_copy)")
    				# 実行
    		for i1 in range(0, pair) :
    						# 親の選択
    			p1 = self.Select(k_method, k_bias, k_step)
    			p2 = p1
    			sw = 0
    	
    			while sw == 0 :
    				p2 = self.Select(k_method, k_bias, k_step)
    				if p1 != p2 :
    					sw = 1
    						# コピー
    			for i2 in range(0, method) :
    				p = p2
    				if i2 == 0 :
    					p = p1
    				k            = self.Position(-1)
    				self.len[k]  = self.len[p]
    				self.pi_w[k] = 1
    				for i3 in range(0, self.len[k]) :
    					self.ind[k][i3] = self.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)
    	###################################################################
    
    	def C_point(self, kosa, k_point = 1, k_vr = 0, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    		mn = 0
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a == 0 :
    			print("***error  交叉方法が不適当 (C_point)")
    	
    		abs_p = abs(k_point)
    		if abs_p == 0 or abs_p > self.max_len-1 or self.min_len > 0 and abs_p > self.min_len-1 :
    			print("***error  交叉点の数が不適当 (C_point)")
    	
    		if k_vr > 0 and self.min_len < 0 :
    			print("***error  遺伝子長は可変でなければならない (C_point)")
    				# 交叉
    		num = k_point
    	
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 交叉位置の数の決定
    				if k_point < 0 :
    					num = int(random() * abs_p + 1)
    					if num > abs_p :
    						num = abs_p
    							# 交叉位置の決定(点の後ろで交叉)
    				for i2 in range(0, num) :
    								# 親1の交叉位置
    					sw = 0
    					while sw == 0 :
    						sw            = 1
    						self.kou1[i2] = int(random() * (self.len[p1] - 1))
    						if self.kou1[i2] > self.len[p1]-2 :
    							self.kou1[i2] = self.len[p1] - 2
    						if k_vr == 0 and self.kou1[i2] > self.len[p2]-2 :
    							self.kou1[i2] = self.len[p2] - 2
    						for i3 in range(0, i2) :
    							if self.kou1[i3] == self.kou1[i2] :
    								sw = 0
    								break
    								# 親2の交叉位置
    					if k_vr > 0 :
    						sw = 0
    						while sw == 0 :
    							sw            = 1
    							self.kou2[i2] = int(random() * (self.len[p2] - 1))
    							if self.kou2[i2] > self.len[p2]-2 :
    								self.kou2[i2] = self.len[p2] - 2
    							for i3 in range(0, i2) :
    								if self.kou2[i3] == self.kou2[i2] :
    									sw = 0
    									break
    							# 交叉の実行
    							#   親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            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    	
    				for i2 in range(0, num+1) :
    								# 次の交叉位置を求める
    					if i2 == num :            # 最後
    						t12 = self.len[p1]
    						t22 = self.len[p2]
    					else :
    									# 親1
    						t12 = self.max_len
    						for i3 in range(0, num) :
    							if self.kou1[i3] >= 0 and self.kou1[i3] <= t12 :
    								t12 = self.kou1[i3]
    								mn  = i3
    						self.kou1[mn] = -1
    						t12 += 1
    									# 親2
    						if k_vr == 0 :
    							t22 = t12
    						else :
    							t22 = self.max_len
    							for i3 in range(0, num) :
    								if self.kou2[i3] >= 0 and self.kou2[i3] <= t22 :
    									t22 = self.kou2[i3]
    									mn  = i3
    							self.kou2[mn] = -1
    							t22 += 1
    								# 指定箇所のコピー
    					for i3 in range(t11, t12) :
    						if i2%2 == 0 :
    							if c1 < self.max_len :
    								self.ind[k1][c1] = self.ind[p1][i3]
    								c1 += 1
    						else :
    							if c2 < self.max_len :
    								self.ind[k2][c2] = self.ind[p1][i3]
    								c2 += 1
    	
    					for i3 in range(t21, t22) :
    						if i2%2 == 0 :
    							if c2 < self.max_len :
    								self.ind[k2][c2] = self.ind[p2][i3]
    								c2 += 1
    						else :
    							if c1 < self.max_len :
    								self.ind[k1][c1] = self.ind[p2][i3]
    								c1 += 1
    								# 交叉位置の移動
    					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)
    	###################################################################
    
    	def C_uniform(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a == 0 :
    			print("***error  交叉方法が不適当 (C_uniform)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_uniform)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				for i2 in range(0, self.len[p1]) :
    					if random() > 0.5 :
    						self.ind[k1][i2] = self.ind[p1][i2]
    						self.ind[k2][i2] = self.ind[p2][i2]
    					else :
    						self.ind[k1][i2] = self.ind[p2][i2]
    						self.ind[k2][i2] = self.ind[p1][i2]
    	
    	###################################################################
    	# 交叉(平均化交叉.2つの親の平均値を受け継ぐ)
    	#      kosa : 交叉確率
    	#      k_method : 選択方法
    	#                 =-1 : ランダム(default)
    	#                 =0 : 適応度をそのまま使用
    	#                 =1 : 最小値からの差(ただし,α以下の場合はα)
    	#                 =2 : 評価値に順位をつけ,減少率βで線形化
    	#      k_bias : α,または,method=2の場合は初期値(default=0)
    	#      k_step : β(default=1)
    	###################################################################
    
    	def C_mean(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_mean)")
    				# 交叉
    		for i1 in range(0, self.max_ch) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(1, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k            = self.Position(-1)
    				self.len[k]  = self.len[p1]
    				self.pi_w[k] = 1
    							# 交叉
    				for i2 in range(0, self.len[k]) :
    					self.ind[k][i2] = int((self.ind[p1][i2] + self.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)
    	###################################################################
    	def C_cycle(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_cycle)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_cycle)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 初期設定
    				for i2 in range(0, self.len[p1]) :
    					self.kou1[i2] = 0
    					self.kou2[i2] = 0
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				sw = 0
    	
    				while sw == 0 :
    					sw = 1
    					p  = int(random() * self.len[p1])
    					if p >= self.len[p1] :
    						p = self.len[p1] - 1
    					if self.kou1[p] == 0 and self.kou2[p] == 0 :
    						self.kou1[p]    = 1
    						self.kou2[p]    = 1
    						self.ind[k1][p] = self.ind[p1][p]
    						self.ind[k2][p] = self.ind[p2][p]
    						for i2 in range(0, self.len[p1]) :
    							if self.ind[p2][p] == self.ind[p1][i2] :
    								self.ind[k1][i2] = self.ind[p1][i2]
    								self.kou1[i2]    = 1
    								sw               = 0
    								break
    						sw = 1
    						for i2 in range(0, self.len[p2]) :
    							if self.ind[p1][p] == self.ind[p2][i2] :
    								self.ind[k2][i2] = self.ind[p2][i2]
    								self.kou2[i2]    = 1
    								sw               = 0
    								break
    	
    				sw = 0
    				i2 = 0
    				i3 = 0
    				while sw == 0 :
    					while sw == 0 and i2 < self.len[p1] :
    						if self.kou1[i2] == 0 :
    							sw = 1
    						else :
    							i2 += 1
    					sw = 0
    					while sw == 0 and i3 < self.len[p2] :
    						if self.kou2[i3] == 0 :
    							sw = 1
    						else :
    							i3 += 1
    					if i2 < self.len[p1] and i3 < self.len[p2] :
    						self.ind[k1][i2] = self.ind[p2][i3]
    						self.ind[k2][i3] = self.ind[p1][i2]
    						sw          = 0
    						i2 += 1
    						i3 += 1
    					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)
    	#******************************************************************/
    	def C_part(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_part)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_part)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				p = int(random() * self.len[p1])
    				if p >= self.len[p1] :
    					p = self.len[p1] - 1
    	
    				for i2 in range(0, self.len[p1]) :
    					self.ind[k1][i2] = self.ind[p1][i2]
    					self.ind[k2][i2] = self.ind[p2][i2]
    	
    				for i2 in range(p, self.len[p1]) :
    					sw = 0
    					lv = self.ind[k1][i2]
    					for i3 in range(0, self.len[p1]) :
    						if self.ind[k2][i2] == self.ind[k1][i3] :
    							self.ind[k1][i2] = self.ind[k1][i3]
    							self.ind[k1][i3] = lv
    							sw               = 1
    							break
    					sw = 0
    					for i3 in range(0, self.len[p1]) :
    						if lv == self.ind[k2][i3] :
    							self.ind[k2][i3] = self.ind[k2][i2]
    							self.ind[k2][i2] = lv
    							sw               = 1
    							break
    	
    	###################################################################
    	# 交叉(順序交叉.ランダムに切れ目を決定し,子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)
    	###################################################################
    	def C_seq(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_seq)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_seq)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				p = int(random() * (self.len[p1] - 1))
    				if p >= self.len[p1]-1 :
    					p = self.len[p1] - 2
    	
    				for i2 in range(0, p+1) :
    					self.ind[k1][i2] = self.ind[p1][i2]
    					self.ind[k2][i2] = self.ind[p2][i2]
    	
    				pp = 0
    				for i2 in range(p+1, self.len[p1]) :
    					sw = 0
    					i3 = pp
    					while i3 < self.len[p2] and sw == 0 :
    						i4 = p + 1
    						while i4 < self.len[p1] and sw == 0 :
    							if self.ind[p2][i3] == self.ind[p1][i4] :
    								sw               = 1
    								pp               = i3 + 1
    								self.ind[k1][i2] = self.ind[p1][i4]
    							i4 += 1
    						i3 += 1
    				pp = 0
    				for i2 in range(p+1, self.len[p2]) :
    					sw = 0
    					i3 = pp
    					while i3 < self.len[p1] and sw == 0 :
    						i4 = p + 1
    						while i4 < self.len[p2] and sw == 0 :
    							if self.ind[p1][i3] == self.ind[p2][i4] :
    								sw               = 1
    								pp               = i3 + 1
    								self.ind[k2][i2] = self.ind[p2][i4]
    							i4 += 1
    						i3 += 1
    	
    	###################################################################
    	# 交叉(一様順序交叉.位置の集合をランダムに選択し,一方の親の選
    	#       択された位置における遺伝子の順序に従って,他の親の遺伝子
    	#       を並べ替える
    	#         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)
    	###################################################################
    	
    	def C_useq(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair =int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_useq)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_useq)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				for i2 in range(0, self.len[p1]) :
    					self.ind[k1][i2] = self.ind[p1][i2]
    					self.ind[k2][i2] = self.ind[p2][i2]
    					if random() < 0.5 :
    						self.kou1[i2] = 0
    					else :
    						self.kou1[i2] = 1
    	
    				p = 0
    				for i2 in range(0, self.len[p1]) :
    					if self.kou1[i2] > 0 :
    						sw = 0
    						i3 = p
    						while i3 < self.len[p2] and sw == 0 :
    							i4 = 0
    							while i4 < self.len[p1] and sw == 0 :
    								if self.ind[p2][i3] == self.ind[p1][i4] and self.kou1[i4] > 0 :
    									sw               = 1
    									p                = i3 + 1
    									self.ind[k1][i2] = self.ind[p1][i4]
    								i4 += 1
    							i3 += 1
    				p = 0
    				for i2 in range(0, self.len[p3]) :
    					if self.kou1[i2] > 0 :
    						sw = 0
    						i3 = p
    						while i3 < self.len[p1] and sw == 0 :
    							i4 = 0
    							while i4 < self.len[p2] and sw == 0 :
    								if self.ind[p1][i3] == self.ind[p2][i4] and self.kou1[i4] > 0 :
    									sw               = 1
    									p                = i3 + 1
    									self.ind[k2][i2] = self.ind[p2][i4]
    								i4 += 1
    							i3 += 1
    	
    	###################################################################
    	# 交叉(一様位置交叉.位置の集合をランダムに選択し,一方の親の選
    	#       択された位置における遺伝子の位置に,他の親の同じ遺伝子を
    	#       配置する.残りの遺伝子は,親と同じ順序に配置する.
    	#         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)
    	###################################################################
    
    	def C_upos(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_upos)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_upos)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				for i2 in range(0, self.len[p1]) :
    					self.kou1[i2] = 1
    					if random() < 0.5 :
    						self.kou1[i2] = 1
    					if self.kou1[i2] > 0 :
    						self.ind[k1][i2] = self.ind[p2][i2]
    						self.ind[k2][i2] = self.ind[p1][i2]
    	
    				p = 0
    				for i2 in range(0, self.len[p1]) :
    					sw = 0
    					for i3 in range(0, self.len[p1]) :
    						if self.kou1[i3] > 0 and self.ind[p1][i2] == self.ind[k1][i3] :
    							sw = 1
    							break
    					if sw == 0 :
    						for i3 in range(p, self.len[p1]) :
    							if self.kou1[i3] == 0 :
    								self.ind[k1][i3] = self.ind[p1][i2]
    								p                = i3 + 1
    								sw               = 1
    								break
    				p = 0
    				for i2 in range(0, self.len[p2]) :
    					sw = 0
    					for i3 in range(0, self.len[p2]) :
    						if self.kou1[i3] > 0 and self.ind[p2][i2] == self.ind[k2][i3] :
    							sw = 1
    							break
    					if sw == 0 :
    						for i3 in range(p, self.len[p2]) :
    							if self.kou1[i3] == 0 :
    								self.ind[k2][i3] = self.ind[p2][i2]
    								p                = i3 + 1
    								sw               = 1
    								break
    	
    	###################################################################
    	# 交叉(エッジ組み替え交叉.以下の手順に従って行う.対立遺伝子は
    	#       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)
    	###################################################################
    
    	def C_edge(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    		e  = np.empty(2, np.int)
    		k0 = 0
    				# 初期設定とデータのチェック
    		pair = self.max_ch
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_edge)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_edge)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(1, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k            = self.Position(-1)
    				self.pi_w[k] = 1
    				self.len[k]  = self.len[p1]
    							# エッジマップの初期化
    				for i2 in range(0, self.len[k]) :
    					self.edge[i2][0] = 0
    					for i3 in range(1, 5) :
    						self.edge[i2][i3] = -1
    							# 交叉
    								# エッジマップの作成
    				for i2 in range(0, self.len[k]) :
    	
    					sw = 0
    					for i3 in range(0, self.len[k]) :
    						if i2 == self.ind[p1][i3] :
    							sw = 1
    							if i3 == 0 :
    								e[0] = self.ind[p1][self.len[k]-1]
    								e[1] = self.ind[p1][1]
    							else :
    								if i3 == self.len[k]-1 :
    									e[0] = self.ind[p1][i3-1]
    									e[1] = self.ind[p1][0]
    								else :
    									e[0] = self.ind[p1][i3-1]
    									e[1] = self.ind[p1][i3+1]
    							for i4 in range(0, 2) :
    								self.edge[i2][0] += 1
    								self.edge[i2][self.edge[i2][0]] = e[i4]
    							break
    	
    					sw = 0
    					for i3 in range(0, self.len[k]) :
    						if i2 == self.ind[p2][i3] :
    							sw = 1
    							if i3 == 0 :
    								e[0] = self.ind[p2][self.len[k]-1]
    								e[1] = self.ind[p2][1]
    							else :
    								if i3 == self.len[k]-1 :
    									e[0] = self.ind[p2][i3-1]
    									e[1] = self.ind[p2][0]
    								else :
    									e[0] = self.ind[p2][i3-1]
    									e[1] = self.ind[p2][i3+1]
    							for i4 in range(0, 2) :
    								sw = 1
    								for i5 in range(1, self.edge[i2][0]+1) :
    									if self.edge[i2][i5] == e[i4] :
    										sw = 2
    										break
    								if sw == 1 :
    									self.edge[i2][0] += 1
    									self.edge[i2][self.edge[i2][0]] = e[i4]
    							break
    								# 交叉の実行
    									# 出発点の決定
    				k1 = self.ind[p1][0]
    				k2 = self.ind[p2][0]
    				if self.edge[k1][0] == self.edge[k2][0] :
    					kk = k1
    					if random() > 0.5 :
    						kk = k2
    				else :
    					kk = k2
    					if self.edge[k1][0] < self.edge[k2][0] :
    						kk = k2
    				self.ind[k][0] = kk
    				p              = 1
    	
    				while p < self.len[k] :
    									# ノードの除去
    					for i2 in range(0, self.len[k]) :
    						sw = 0
    						if self.edge[i2][0] > 0 :
    							for i3 in range(1, 5) :
    								if self.edge[i2][i3] == kk :
    									sw                 = 1
    									self.edge[i2][i3]  = -1
    									self.edge[i2][0]  -= 1
    									break
    									# 次の現在ノードの選択
    					min = 10
    					num = 0
    					for i2 in range(1, 5) :
    						if self.edge[kk][i2] >= 0 :
    							k1 = self.edge[kk][i2]
    							if self.edge[k1][0] >= 0 and self.edge[k1][0] < min :
    								num = 1
    								min = self.edge[k1][0]
    								k0  = k1
    							else :
    								if self.edge[k1][0] == min :
    									num += 1
    					if num > 1 :
    						k1 = int(random() * num) + 1
    						if k1 > num :
    							k1 = num
    						k2 = 0
    						k0 = -1
    						i2 = 1
    						while i2 <= 4 and k0 < 0 :
    							if self.edge[kk][i2] >= 0 :
    								if self.edge[self.edge[kk][i2]][0] == min :
    									k2 += 1
    									if k1 == k2 :
    										k0 = self.edge[kk][i2]
    							i2 += 1
    					else :
    						if num <= 0 :
    							num = 0
    							for i2 in range(0, self.len[k]) :
    								if i2 != kk and self.edge[i2][0] >= 0 :
    									num += 1
    							if num <= 0 :
    								print("***error  invalid data (C_edge)")
    							else :
    								k1 = int(random() * num) + 1
    								if k1 > num :
    									k1 = num
    								k2 = 0
    								k0 = -1
    								i2 = 0
    								while i2 < self.len[k] and k0 < 0 :
    									if i2 != kk and self.edge[i2][0] >= 0 :
    										k2 += 1
    										if k1 == k2 :
    											k0 = i2
    									i2 += 1
    					self.edge[kk][0]  = -1
    					self.ind[k][p]    = k0
    					kk                = k0
    					p                += 1
    	
    	##############################################################
    	# 交叉(サブツアー交叉.2点交叉の拡張である.ただし,相手に
    	#       同じ遺伝子のグループがない限り実行されない.たとえば
    	#         ***abcd**
    	#         *cdab****
    	#       のような両親の時実行され,以下の4つの子供が生成され
    	#       る)
    	#         ***cdab**
    	#         *abcd****
    	#         ***badc**
    	#         *dcba****
    	#       最大,4*交叉回数*個体総数*(個体総数-1) 個の子
    	#       供が生成される可能性があるので,子供の数としてこの値
    	#       以上のデータを入力しておく必要がある.
    	#      kosa : 交叉確率
    	#      count : 1つのペアーに対する交差回数(default=10)
    	##############################################################
    
    	def C_sub(self, kosa, count = 10) :
    	
    		t22 = 0
    				# 初期設定とデータのチェック
    		if (4*count*self.size*(self.size-1)) > self.max_ch :
    			print("***error  子供が多すぎる (C_sub)")
    				# 交叉
    		for i1 in range(0, self.size-1) :
    						# 親1
    			p1 = self.Position(i1)
    	
    			if p1 >= 0 :
    	
    				for i2 in range(i1, self.size) :
    						# 親2
    					p2 = self.Position(i2)
    	
    					if p2 >= 0 :
    						# 交叉しない場合
    						if random() > kosa :
    							self.C_copy(2, 1)
    						# 交叉する場合
    						else :
    							# 交叉回数の制御
    							for i3 in range(0, count) :
    								# 交叉位置の決定(点の後ろで交叉)
    									# 親1の交叉位置
    								t11 = int(random() * self.len[p1])
    								if t11 > (self.len[p1]-1) :
    									t11 = self.len[p1] - 1
    								sw = 0
    								while sw == 0 :
    									t12 = int(random() * self.len[p1])
    									if t12 > (self.len[p1]-1) :
    										t12 = self.len[p1] - 1
    									if t12 != t11 :
    										sw = 1
    								if t11 > t12 :
    									k1  = t11
    									t11 = t12
    									t12 = k1
    									# 親2の交叉位置
    								sw  = 0
    								t21 = -1
    								i4  = 0
    								while i4 < self.len[p2] and t21 < 0 :
    									i5 = t11
    									while i5 <= t12 and t21 < 0 :
    										if self.ind[p2][i4] == self.ind[p1][i5] :
    											t21 = i4
    										i5 += 1
    									i4 += 1
    								if t21 >= 0 :
    									t22 = t21 + t12 - t11
    									if t22 < self.len[p2] :
    										sw = 1
    										i4 = t21 + 1
    										while i4 <= t22 and sw > 0 :
    											sw = 0
    											i5 = t11
    											while i5 <= t12 and sw == 0 :
    												if self.ind[p2][i4] == self.ind[p1][i5] :
    													sw = 1
    												i5 += 1
    											i4 += 1
    									# 交叉の実行
    								if sw > 0 :
    	
    									k1            = self.Position(-1)
    									self.pi_w[k1] = 1
    									self.len[k1]  = self.len[p1]
    									k2            = self.Position(-1)
    									self.pi_w[k2] = 1
    									self.len[k2]  = self.len[p1]
    									k3            = self.Position(-1)
    									self.pi_w[k3] = 1
    									self.len[k3]  = self.len[p2]
    									k4            = self.Position(-1)
    									self.pi_w[k4] = 1
    									self.len[k4]  = self.len[p2]
    	
    									for i4 in range(0, t11) :
    										self.ind[k1][i4] = self.ind[p1][i4]
    										self.ind[k2][i4] = self.ind[p1][i4]
    									for i4 in range(t11, t12+1) :
    										self.ind[k1][i4] = self.ind[p2][t21+i4-t11]
    										self.ind[k2][i4] = self.ind[p2][t22-i4+t11]
    									for i4 in range(t12+1, self.len[p1]) :
    										self.ind[k1][i4] = self.ind[p1][i4]
    										self.ind[k2][i4] = self.ind[p1][i4]
    									for i4 in range(0, t21) :
    										self.ind[k3][i4] = self.ind[p2][i4]
    										self.ind[k4][i4] = self.ind[p2][i4]
    									for i4 in range(t21, t22+1) :
    										self.ind[k3][i4] = self.ind[p1][t11+i4-t21]
    										self.ind[k4][i4] = self.ind[p1][t12-i4+t21]
    									for i4 in range(t22+1, self.len[p2]) :
    										self.ind[k3][i4] = self.ind[p2][i4]
    										self.ind[k4][i4] = self.ind[p2][i4]
    	
    	#######################################
    	# 突然変異(対立遺伝子との置き換え)
    	#      pr : 突然変異率
    	#######################################
    
    	def M_alle(self, pr) :
    	
    				# データのチェックと初期設定
    		if self.dup_a == 0 :
    			print("***error  突然変異方法が不適当 (M_alle)")
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] == 1 :
    				for i2 in range(0, self.len[i1]) :
    					if random() <= pr :
    						lid = int(random() * (self.allele_u - self.allele_l + 1) + self.allele_l)
    						if lid > self.allele_u :
    							lid = self.allele_u
    						if lid != self.ind[i1][i2] :
    							self.ind[i1][i2] = lid
    
    	######################################################################
    	# 突然変異(移動.2点を選択し,2番目の遺伝子を1番目の遺伝子の前に
    	#           移動する)
    	#      pr : 突然変異率
    	######################################################################
    
    	def M_move(self, pr) :
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    				# 位置の決定
    						# p1
    				p1 = int(random() * self.len[i1])
    				if p1 >= self.len[i1] :
    					p1 = self.len[i1] - 1
    						# p2
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = int(random() * self.len[i1])
    					if p2 >= self.len[i1] :
    						p2 = self.len[i1] - 1
    					if p2 != p1 :
    						sw = 1
    				# 実行
    				if p2 > p1 :
    					ld = self.ind[i1][p2]
    					for i2 in range(p2, p1, -1) :
    						self.ind[i1][i2] = self.ind[i1][i2-1]
    					self.ind[i1][p1] = ld
    				else :
    					ld = self.ind[i1][p2]
    					for i2 in range(p2, p1-1) :
    						self.ind[i1][i2] = self.ind[i1][i2+1]
    					self.ind[i1][p1-1] = ld
    	
    	########################################################
    	# 突然変異(逆位.2点間の遺伝子順序を逆に並べ替える)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	########################################################
    
    	def M_inv(self, pr, wd = 0) :
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    				# 区間の決定
    				if wd == 0 :
    					p1 = int(random() * self.len[i1])
    					if p1 >= self.len[i1] :
    						p1 = self.len[i1] - 1
    					sw = 0
    					p2 = p1
    					while sw == 0 :
    						p2 = int(random() * self.len[i1])
    						if p2 >= self.len[i1] :
    							p2 = self.len[i1] - 1
    						if p2 != p1 :
    							sw = 1
    					if p1 > p2 :
    						p  = p1
    						p1 = p2
    						p2 = p
    	
    				else :
    					p1 = self.len[i1]
    					while p1 > self.len[i1]-2 :
    						p1 = int(random() * self.len[i1])
    					p2 = p1 + wd - 1
    					if p2 >= self.len[i1] :
    						p2 = self.len[i1] - 1
    				# 実行
    				sw = 0
    				while sw == 0 :
    					lid              = self.ind[i1][p1]
    					self.ind[i1][p1] = self.ind[i1][p2]
    					self.ind[i1][p2] = lid
    					p1 += 1
    					p2 -= 1
    					if p1 >= p2 :
    						sw = 1
    	
    	######################################################################
    	# 突然変異(スクランブル.2点間の遺伝子順序をランダムに並べ替える)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	######################################################################
    
    	def M_scram(self, pr, wd = 0) :
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    				# 区間の決定
    				if wd == 0 :
    					p1 = int(random() * self.len[i1])
    					if p1 >= self.len[i1] :
    						p1 = self.len[i1] - 1
    					sw = 0
    					p2 = p1
    					while sw == 0 :
    						p2 = int(random() * self.len[i1])
    						if p2 >= self.len[i1] :
    							p2 = self.len[i1] - 1
    						if p2 != p1 :
    							sw = 1
    					if p1 > p2 :
    						p  = p1
    						p1 = p2
    						p2 = p
    	
    				else :
    					p1 = self.len[i1]
    					while p1 > self.len[i1]-2 :
    						p1 = int(random() * self.len[i1])
    					p2 = p1 + wd - 1
    					if p2 >= self.len[i1] :
    						p2 = self.len[i1] - 1
    				# 実行
    				for i2 in range(p1, p2+1) :
    					p = int(random() * (p2 - p1 + 1) + p1)
    					if p > p2 :
    						p = p2
    					ld               = self.ind[i1][i2]
    					self.ind[i1][i2] = self.ind[i1][p]
    					self.ind[i1][p]  = ld
    	
    	######################################################################
    	# 突然変異(転座.2点間の遺伝子を他の位置のものと置き換える.ただし
    	#           重複部分はそのままとする)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	######################################################################
    
    	def M_chg(self, pr, wd = 0) :
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    				# 区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    						# p1
    				p1 = int(random() * self.len[i1])
    				if p1 >= self.len[i1] :
    					p1 = self.len[i1] - 1
    						# p3
    				sw = 0
    				p3 = p1
    				while sw == 0 :
    					p3 = int(random() * self.len[i1])
    					if p3 >= self.len[i1] :
    						p3 = self.len[i1] - 1
    					if p3 != p1 :
    						sw = 1
    						# 小さい方をp1,p2にする
    				if p1 > p3 :
    					p  = p1
    					p1 = p3
    					p3 = p
    						# p4, p2
    				p4 = p1 + wd - 1
    				if wd == 0 :
    					p4 = int(random() * (self.len[i1] - p3)) + p3
    				if p4 >= self.len[i1] :
    					p4 = self.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 in range(p1, p2+1) :
    					ld                = self.ind[i1][i2]
    					self.ind[i1][i2]  = self.ind[i1][p]
    					self.ind[i1][p]   = ld
    					p                += 1
    	
    	######################################################################
    	# 突然変異(重複.2点間の遺伝子を他の位置にコピーする
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(deafult)
    	######################################################################
    
    	def M_dup(self, pr, wd = 0) :
    	
    				# データのチェック
    		if self.dup_a == 0 :
    			print("***error  突然変異方法が不適当 (M_dup)")
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    						# 区間の決定([p1,p2]を[p3,p4]にコピー)
    							# p1
    				p1 = int(random() * self.len[i1])
    				if p1 >= self.len[i1] :
    					p1 = self.len[i1] - 1
    							# p3
    				sw = 0
    				p3 = p1
    				while sw == 0 :
    					p3 = int(random() * self.len[i1])
    					if p3 >= self.len[i1] :
    						p3 = self.len[i1] - 1
    					if p3 != p1 :
    						sw = 1
    							# 区間を決める
    				p2 = p1
    				p4 = p1
    				if p3 > p1 :
    					p4 = p3 + wd - 1
    					if wd == 0 :
    						p4 = int(random() * (self.len[i1] - p3)) + p3
    					if p4 >= self.len[i1] :
    						p4 = self.len[i1] - 1
    					p2 = p1 + (p4 - p3)
    				else :
    					p2 = p1 + wd - 1
    					if wd == 0 :
    						p2 = int(random() * (self.len[i1] - p1)) + p1
    					if p2 >= self.len[i1] :
    						p2 = self.len[i1] - 1
    					p4 = p3 + (p2 - p1)
    						# 実行
    				p = p4
    				for i2 in range(p2, p1-1, -1) :
    					self.ind[i1][p] = self.ind[i1][i2]
    					p -= 1
    	
    	######################################################
    	# 突然変異(摂動.値をある量だけ変化させる)
    	#      pr : 突然変異率
    	#      method : =0 : 正規分布(default)
    	#               =1 : 一様分布
    	#      m : 平均または一様分布の下限(default=0.0)
    	#      s : 標準偏差または一様分布の上限(default=1.0)
    	######################################################
    
    	def M_per(self, pr, method = 0, m = 0.0, s = 1.0) :
    	
    		wd = 0.0
    				# データのチェックと初期設定
    		if self.dup_a == 0 :
    			print("***error  突然変異方法が不適当 (M_per)")
    	
    		if method > 0 :
    			wd = s - m
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] == 1 :
    				for i2 in range(0, self.len[i1]) :
    					if random() <= pr :
    						if method == 0 :
    							w = normalvariate(m, s)
    						else :
    							w = random() * wd
    							if random() < 0.5 :
    								w = -w
    						x1 = float(self.ind[i1][i2]) + w
    						if x1 > self.allele_u :
    							x1 = self.allele_u
    						else :
    							if x1 < self.allele_l :
    								x1 = self.allele_l
    						self.ind[i1][i2] = int(x1)
    	
    	##############################################
    	# 突然変異(挿入.ある長さの遺伝子を挿入する)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	##############################################
    
    	def M_ins(self, pr, wd = 0) :
    	
    				# データのチェック
    		if self.dup_a == 0 or self.min_len < 0 :
    			print("***error  突然変異方法が不適当 (M_ins)")
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    						# 挿入位置の決定
    				p = int(random() * (self.len[i1] + 1))
    				if p > self.len[i1] :
    					p = self.len[i1]
    						# 挿入する遺伝子長の決定
    				l = wd
    				if wd == 0 :
    					l = int(random() * (self.max_len - self.len[i1] + 1))
    				if l > self.max_len-self.len[i1] :
    					l = self.max_len - self.len[i1]
    				else :
    					if l <= 0 :
    						l = 1
    						# 実行
    							# 挿入場所の確保
    				if p < self.len[i1] :
    					for i2 in range(self.len[i1]+l-1, p-1, -1) :
    						self.ind[i1][i2] = self.ind[i1][i2-l]
    							# 挿入場所の遺伝子の決定
    				for i2 in range(p, p+l) :
    					ld = int(random() * (self.allele_u - self.allele_l + 1) + self.allele_l)
    					if ld > self.allele_u :
    						ld = self.allele_u
    					self.ind[i1][i2] = ld
    	
    				self.len[i1]  += l
    	
    	##############################################
    	# 突然変異(削除.ある長さの遺伝子を削除する)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	##############################################
    
    	def M_del(self, pr, wd = 0) :
    	
    				# データのチェック
    		if self.dup_a == 0 or self.min_len < 0 :
    			print("***error  突然変異方法が不適当 (M_del)")
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    						# 削除位置の決定
    				p = int(random() * self.len[i1])
    				if p >= self.len[i1] :
    					p = self.len[i1] - 1
    						# 削除する遺伝子長の決定
    				max = self.len[i1] - p
    				if self.len[i1]-self.min_len < self.len[i1]-p :
    					max = self.len[i1] - self.min_len
    				l = wd
    				if wd == 0 :
    					l = int(random() * max + 1)
    				if l > max :
    					l = max
    						# 実行
    				for i2 in range(0, self.len[i1]-p-l) :
    					self.ind[i1][p+i2] = self.ind[i1][p+i2+l]
    	
    				self.len[i1]  -= l
    	
    	######################################################################
    	# 淘汰(エリート・ルーレット選択)
    	#      elite : エリートで残す個体数(default=0)
    	#      s_method : ルーレット板の作成方法(default=1)
    	#                   =0 : 適応度をそのまま使用
    	#                   =1 : 最小値からの差(ただし,α以下の場合はα)
    	#                   =2 : 評価値に順位をつけ,減少率βで線形化
    	#      s_bias : α,または,method=2の場合は初期値(default=0)
    	#      s_step : β(default=1)
    	######################################################################
    
    	def S_roul(self, elite = 0, s_method = 1, s_bias = 0.0, s_step = 1.0) :
    	
    		count = 0
    		k     = 0
    		n     = 0
    				# 値のチェックと初期設定
    		if s_method != 0 and s_method != 2 :
    			s_method = 1
    	
    		if elite > self.size :
    			print("***error  エリートで残す数が多すぎる (S_roul)")
    	
    		if s_method == 2 and s_step <= 0.0 :
    			s_step = 1.0
    	
    		for i1 in range(0, self.size+self.max_ch) :
    			self.s_w[i1] = 0
    				# 重複個体を削除
    		if self.dup_s == 0 :
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 0 :
    					for i2 in range(i1+1, self.size+self.max_ch) :
    						if self.pi_w[i2] > 0 and self.len[i1] == self.len[i2] :
    							sw = 0
    							for i3 in range(0, self.len[i1]) :
    								if self.ind[i1][i3] != self.ind[i2][i3] :
    									sw = 1
    									break
    							if sw == 0 :
    								self.pi_w[i2] = 0
    	
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] > 1 :
    				n += 1
    	
    		if n < 0 or self.dup_s == 0 and n < self.size :
    			print("***error  残す個体がない (S_roul)")
    				# 淘汰して残す個体を選ぶ
    						# エリートの選択
    		sw = 0
    	
    		while k < elite and k < n and sw == 0 :
    			max = -1
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 and self.s_w[i1] == 0 :
    					if max < 0 or self.pi[i1] > self.pi[max] :
    						max = i1
    			if max < 0 :
    				sw = 1
    			else :
    				self.s_w[max]  = 1
    				k             += 1
    						# ルーレット選択
    		while count < self.size+self.max_ch and k < self.size :
    			p = self.Select(s_method, s_bias, s_step)
    			if self.dup_s == 0 and self.s_w[p] > 0 :
    				count += 1
    			else :
    				count        = 0
    				self.s_w[p] += 1
    				k           += 1
    							# 選択に失敗した場合の処理
    		if self.dup_s == 0 and k < self.size :
    			i1 = 0
    			while i1 < self.size+self.max_ch and k < self.size :
    				if self.pi_w[i1] > 1 and self.s_w[i1] == 0 :
    					self.s_w[i1]  = 1
    					k            += 1
    				i1 += 1
    							# 複数回選択されたものの処理
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.s_w[i1] == 0 :
    				self.pi_w[i1] = 0
    	
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.s_w[i1] > 0 :
    				if self.s_w[i1] > 1 :
    					for i2 in range(2, self.s_w[i1]+1) :
    						k            = self.Position(-1)
    						self.len[k]  = self.len[i1]
    						self.pi_w[k] = 2
    						self.pi[k]   = self.pi[i1]
    						for i3 in range(0, self.len[i1]) :
    							self.ind[k][i3] = self.ind[i1][i3]
    	
    ####################
    # クラスTSPの定義
    ####################
    
    class TSP ( Species ) :
    
    	######################################
    	# コンストラクタ
    	#      name1 : Species定義ファイル名
    	#      name2 : TSP定義ファイル名
    	######################################
    
    	def __init__(self, name1, name2) :
    	
    		Species.__init__(self, name1)   # 親のコンストラクタ
    						# 基本データの入力
    		inn = open(name2, "r")
    	
    		s = inn.readline().split()
    		self.out_lvl = int(s[1])   # 出力レベル
    		                       #   =0 : 最終出力だけ
    		                       #   n>0 : n世代毎に出力(負の時はファイル)
    		self.out_m   = int(s[3])  # 出力方法
    		                      #   =0 : すべてを出力
    		                      #   =1 : 最大適応度の個体だけを出力
    
    		s = inn.readline().split()
    		self.o_file = s[1]   # 出力ファイル名
    		self.out_d  = int(s[3])   # 表示間隔
    
    		s = inn.readline().split()
    		self.kosa_m   = int(s[1])   # 交叉方法
    		                       #   =-1 : 交叉を使用しない
    		                       #   =0 : 親のコピー
    		                       #   =1 : 循環交叉
    		                       #   =2 : 部分的交叉
    		                       #   =3 : 順序交叉
    		                       #   =4 : 一様順序交叉
    		                       #   =5 : 一様位置交叉
    		                       #   =6 : エッジ組み替え交叉
    		                       #   =7 : サブツアー交叉
    		self.kosa     = float(s[3])   # 交叉確率
    		self.k_point  = int(s[5])   # 交差点の数(負の時は,1から-k_point間のランダム)
    		self.k_vr     = int(s[7])   # =0 : 両親とも同じ位置で交叉
    		                       # =1 : 両親が異なる位置で交叉(遺伝子長は可変)
    		self.k_method = int(s[9])   # 交叉の時の親の選択方法
    		                       #   =-1 : ランダム
    		                       #   =0 : 適応度をそのまま使用
    		                       #   =1 : 最小値からの差(ただし,α以下の場合はα)
    		                       #   =2 : 評価値に順位をつけ,減少率βで線形化
    		self.k_bias   = float(s[11])   # α,または,method=2の場合は初期値
    		self.k_step   = float(s[13])   # β
    
    		s = inn.readline().split()
    		self.mute_m = int(s[1])   # 突然変異方法
    		                       #   =-1 : 突然変異を使用しない
    		                       #   =0 : 移動
    		                       #   =1 : 逆位
    		                       #   =2 : スクランブル
    		                       #   =3 : 転座
    		self.mute   = float(s[3])   # 突然変異率
    		self.wd     = int(s[5])   # 突然変異に使用する部分遺伝子長
    		self.m_mean = float(s[7])   # 摂動の平均値
    		self.m_std  = float(s[9])   # 摂動の標準偏差
    
    		s = inn.readline().split()
    		self.elite    = int(s[1])   # エリート選択で残す数
    		self.s_method = int(s[3])   # ルーレット板の作成方法
    		                       #   =0 : 適応度をそのまま使用
    		                       #   =1 : 最小値からの差(ただし,α以下の場合はα)
    		                       #   =2 : 評価値に順位をつけ,減少率βで線形化
    		self.s_bias   = float(s[5])   # α,または,s_method=2の場合は初期値
    		self.s_step   = float(s[7])   # β
    
    		s = inn.readline().split()
    		self.n_city  = int(s[1])   # 都市の数
    		self.max_gen = int(s[3])   # 最大世代交代数
    
    		s = inn.readline().split()
    		self.kinbo    = int(s[1])   # 近傍探索(0:行わない,1:行う)
    		self.neib     = int(s[3])   # 近傍(2 or 3)
    
    		s = inn.readline().split()
    		self.sel = int(s[1])   # エッジの選択方法
    		                       #   =0 : 最良のものを選択
    		                       #   =1 : 最初のものを選択
    	
    		if self.kinbo > 0 and self.neib != 2 and self.neib != 3 :
    			print("***error  近傍の値が不適当")
    	
    		if self.n_city != self.max_len :
    			print("***error  都市数が不適当")
    						# 都市の位置データ
    		self.city = np.empty((self.n_city, 2), np.int)
    		for i1 in range(0, self.n_city) :
    			s = inn.readline().split()
    			self.city[i1][0] = int(s[0])
    			self.city[i1][1] = int(s[1])
    						# 距離テーブル
    		self.rg = np.empty((self.n_city, self.n_city), np.int)
    	
    		for i1 in range(0, self.n_city) :
    			for i2 in range(i1+1, self.n_city) :
    				x               = self.city[i2][0] - self.city[i1][0]
    				y               = self.city[i2][1] - self.city[i1][1]
    				self.rg[i1][i2] = int(sqrt(x * x + y * y) + 0.5)
    	
    		for i1 in range(1, self.n_city) :
    			for i2 in range(0, i1) :
    				self.rg[i1][i2] = self.rg[i2][i1]
    	
    		inn.close()
    	
    	###############
    	# 全体の制御
    	###############
    
    	def Control(self) :
    	
    		gen = 1
    						# 初期集団の発生
    		self.Init_std()
    						# 評価
    		if self.kinbo > 0 :
    			self.Kinbo()
    		else :
    			self.Adap()
    						# 出力
    		print("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean))
    	
    		if abs(self.out_lvl) > 0 :
    			self.Output(gen)
    						# 世代交代
    		for gen in range(2, self.max_gen+1) :
    							# 交叉
    			if self.kosa_m == 0 :
    				C_copy()   # 親のコピー
    			elif self.kosa_m == 1 :
    				self.C_cycle(self.kosa)   # 循環交叉
    			elif self.kosa_m == 2 :
    				self.C_part(self.kosa)   # 部分的交叉
    			elif self.kosa_m == 3 :
    				self.C_seq(self.kosa)   # 順序交叉
    			elif self.kosa_m == 4 :
    				self.C_useq(self.kosa)   # 一様順序交叉
    			elif self.kosa_m == 5 :
    				self.C_upos(self.kosa)   # 一様位置交叉
    			elif self.kosa_m == 6 :
    				self.C_edge(self.kosa)   # エッジ組み替え交叉
    			elif self.kosa_m == 7 :
    				self.C_sub(self.kosa, self.k_point)   # サブツアー交叉
    							# 突然変異
    			if self.mute_m == 0 :
    				self.M_move(self.mute)   # 移動
    			elif self.mute_m == 1 :
    				self.M_inv(self.mute)   # 逆位
    			elif self.mute_m == 2 :
    				self.M_scram(self.mute)   # スクランブル
    			elif self.mute_m == 3 :
    				self.M_chg(self.mute)   # 転座
    							# 適応度
    			if self.kinbo > 0 :
    				self.Kinbo()
    			else :
    				self.Adap()
    							# 淘汰
    			self.S_roul(self.elite)
    							# 出力
    			if gen%self.out_d == 0 :
    				print("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean))
    	
    			if abs(self.out_lvl) > 0 :
    				if gen%abs(self.out_lvl) == 0 :
    					self.Output(gen)
    	
    		gen        -= 1
    		k1          = self.out_m
    		self.out_m  = 0
    		print("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean))
    		self.Output(gen)
    		self.out_m = k1
    	
    	##########################
    	# 距離の計算
    	#      n_c : 都市の数
    	#      p : 都市番号
    	#      return : 距離(負)
    	##########################
    
    	def Kyori(self, n_c, p) :
    	
    		r  = 0
    		n1 = p[0]
    	
    		for i1 in range(1, n_c) :
    			n2  = p[i1]
    			r  -= self.rg[n1][n2]
    			n1  = n2
    
    		n2  = p[0]
    		r  -= self.rg[n1][n2]
    
    		return r
    
    	################
    	# 適応度の計算
    	################
    
    	def Adap(self) :
    	
    		k          = 0
    		self.mean  = 0.0
    		self.max   = 0.0
    		self.max_n = -1
    	
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] == 1 :
    				self.pi_w[i1] = 2
    				self.pi[i1]   = self.Kyori(self.len[i1], self.ind[i1])
    			if self.pi_w[i1] > 0 :
    				k         += 1
    				self.mean += self.pi[i1]
    				if self.max_n < 0 or self.pi[i1] > self.max :
    					self.max   = self.pi[i1]
    					self.max_n = i1
    	
    		if k > 0 :
    			self.mean /= k
    
    	######################################
    	# エッジの入れ替え
    	#      n_city : 都市の数
    	#      seq : 訪問する順番
    	#      r_m : 距離の負値
    	#      return : =0 : 改善がなかった
    	#               =1 : 改善があった
    	######################################
    
    	def Change(self, n_city, seq, r_m) :
    	
    		ch  = 0
    		sw  = 0
    		max = r_m[0]
    	
    		n3  = int(random() * (n_city - 2))
    		if n3 > n_city-3 :
    			n3 = n_city - 3
    	                         # 2近傍
    		i1 = 0
    		while i1 <= n_city-3 and ch == 0 :
    	
    			if n3 == 0 :
    				n1 = n_city - 2
    			else :
    				n1 = n_city - 1
    	
    			i2 = n3 + 2
    			while i2 <= n1 and ch == 0 :
    	                              # 枝の場所((n3,n3+1), (k1,k2))
    				k1 = i2
    				if i2 == n_city-1 :
    					k2 = 0
    				else :
    					k2 = i2 + 1
    	                              # 枝の入れ替え
    				self.kou1[0] = seq[n3]
    				k            = 1
    				for i3 in range(k1, n3, -1) :
    					self.kou1[k]  = seq[i3]
    					k            += 1
    	
    				nn = k2
    				while nn != n3 :
    					self.kou1[k] = seq[nn]
    					k  += 1
    					nn += 1
    					if nn > n_city-1 :
    						nn = 0
    	                              # 評価
    				r = self.Kyori(n_city, self.kou1)
    	
    				if r > max :
    					max = r
    					sw  = 1
    					for i3 in range(0, n_city) :
    						self.kou2[i3] = self.kou1[i3]
    					if self.sel > 0 :
    						ch = 1
    				i2 += 1
    	
    			n3 += 1
    			if n3 > n_city-3 :
    				n3 = 0
    			i1 += 1
    	                         # 3近傍
    		if self.neib == 3 and ch == 0 :
    	
    			i1 = 0
    			while i1 <= n_city-3 and ch == 0 :
    	
    				n1 = n_city - 2
    				n2 = n_city - 1
    	
    				i2 = n3 + 1
    				while i2 <= n1 and ch == 0 :
    	
    					i3 = i2 + 1
    					while i3 <= n2 and ch == 0 :
    	                              # 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
    						k1 = i3
    						k2 = k1
    						if i3 == n_city-1 :
    							k2 = 0
    						else :
    							k2 = i3 + 1
    	                              # 枝の入れ替えと評価
    	                                   # 入れ替え(その1)
    						self.kou1[0] = seq[n3]
    						k            = 1
    						for i4 in range(i2, n3, -1) :
    							self.kou1[k]  = seq[i4]
    							k            += 1
    	
    						for i4 in range(k1, i2, -1) :
    							self.kou1[k]  = seq[i4]
    							k            += 1
    	
    						nn = k2
    						while nn != n3 :
    							self.kou1[k] = seq[nn]
    							k  += 1
    							nn += 1
    							if nn > n_city-1 :
    								nn = 0
    	                                   # 評価(その1)
    						r = self.Kyori(n_city, self.kou1)
    	
    						if r > max :
    							max = r
    							sw  = 1
    							for i3 in range(0, n_city) :
    								self.kou2[i3] = self.kou1[i3]
    							if self.sel > 0 :
    								ch = 1
    	                                   # 入れ替え(その2)
    						self.kou1[0] = seq[n3]
    						k            = 1
    						for i4 in range(k1, i2, -1) :
    							self.kou1[k]  = seq[i4]
    							k            += 1
    	
    						for i4 in range(n3+1, i2+1) :
    							self.kou1[k]  = seq[i4]
    							k            += 1
    	
    						nn = k2
    						while nn != n3 :
    							self.kou1[k] = seq[nn]
    							k  += 1
    							nn += 1
    							if nn > n_city-1 :
    								nn = 0
    	                                   # 評価(その2)
    						r = self.Kyori(n_city, self.kou1)
    	
    						if r > max :
    							max = r
    							sw  = 1
    							for i3 in range(0, n_city) :
    								self.kou2[i3] = self.kou1[i3]
    							if self.sel > 0 :
    								ch = 1
    	                                   # 入れ替え(その3)
    						self.kou1[0] = seq[n3]
    						k            = 1
    						for i4 in range(i2+1, k1+1) :
    							self.kou1[k]  = seq[i4]
    							k            += 1
    	
    						for i4 in range(i2, n3, -1) :
    							self.kou1[k]  = seq[i4]
    							k            += 1
    	
    						nn = k2
    						while nn != n3 :
    							self.kou1[k] = seq[nn]
    							k  += 1
    							nn += 1
    							if nn > n_city-1 :
    								nn = 0
    	                                   # 評価(その3)
    						r = self.Kyori(n_city, self.kou1)
    	
    						if r > max :
    							max = r
    							sw  = 1
    							for i3 in range(0, n_city) :
    								self.kou2[i3] = self.kou1[i3]
    							if self.sel > 0 :
    								ch = 1
    	                                   # 入れ替え(その4)
    						self.kou1[0] = seq[n3]
    						k            = 1
    						for i4 in range(i2+1, k1+1) :
    							self.kou1[k]  = seq[i4]
    							k            += 1
    	
    						for i4 in range(n3+1, i2+1) :
    							self.kou1[k]  = seq[i4]
    							k            += 1
    	
    						nn = k2
    						while nn != n3 :
    							self.kou1[k] = seq[nn]
    							k  += 1
    							nn += 1
    							if nn > n_city-1 :
    								nn = 0
    	                                   # 評価(その4)
    						r = self.Kyori(n_city, self.kou1)
    	
    						if r > max :
    							max = r
    							sw  = 1
    							for i3 in range(0, n_city) :
    								self.kou2[i3] = self.kou1[i3]
    							if self.sel > 0 :
    								ch = 1
    						i3 += 1
    					i2 += 1
    	
    				n3 += 1
    				if n3 > n_city-3 :
    					n3 = 0
    				i1 += 1
    	                         # 設定
    		if sw > 0 :
    			r_m[0] = max
    			for i1 in range(0, n_city) :
    				seq[i1] = self.kou2[i1]
    	
    		return sw
    	
    	##############
    	# 近傍の探索
    	##############
    
    	def Kinbo(self) :
    	
    		k          = 0
    		self.max   = 0.0
    		self.max_n = -1
    		self.mean  = 0.0
    	
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] == 1 :
    				self.pi_w[i1] = 2
    				sw            = 1
    				r             = self.Kyori(self.len[i1], self.ind[i1])
    				while sw > 0 :
    					r  = np.empty(1, np.int)
    					sw = self.Change(self.len[i1], self.ind[i1], r)
    				self.pi[i1] = r[0]
    			if self.pi_w[i1] > 0 :
    				k         += 1
    				self.mean += self.pi[i1]
    				if self.max_n < 0 or self.pi[i1] > self.max :
    					self.max   = self.pi[i1]
    					self.max_n = i1
    	
    		if k > 0 :
    			self.mean /= k
    	
    	#############################
    	# 結果の出力
    	#      gen : 現在の世代番号
    	#############################
    
    	def Output(self, gen) :
    	
    		k  = 0
    		pr = -1
    
    		if self.out_lvl >= 0 :
    			print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ", end=" ")
    			pr = int(input())
    	
    		if pr != 0 :
    						# 出力先の決定と評価値の出力
    			if pr > 0 :
    				out = sys.stdout
    				input("")
    			else :
    				now = datetime.today().time().isoformat()
    				out = open(self.o_file, "a")
    				out.write("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean) + " 時間 " + now + "\n")
    						# 巡回順序の出力
    			if self.out_m == 0 :
    				for i1 in range(0, self.len[self.max_n]) :
    					n = self.ind[self.max_n][i1]
    					out.write(str(n) + " " + str(self.city[n][0]) + " " + str(self.city[n][1]) + "\n")
    					if pr > 0 :
    						k += 1
    						if k == pr :
    							input("")
    							k = 0
    	
    			if pr < 0 :
    				out.close()
    
    				# 入力ミス
    if len(sys.argv) <= 1 :
    	print("***error  ファイル名を入力して下さい")
    				# 入力OK
    else :
    					# データの数と入力データファイル名の入力
    	inn     = open(sys.argv[1], "r")
    
    	ss      = inn.readline()
    	n       = int(ss)   # データの数
    	i_file1 = []
    	i_file2 = []
    
    	for i1 in range(0, n) :
    		s = inn.readline().split()
    		i_file1.append(s[0])
    		i_file2.append(s[1])
    
    	inn.close()
    					# 実行(乱数の初期値を変える)
    	for i1 in range(0, n) :
    
    		print("\n+++++ケース " + str(i1+1) + "+++++")
    		seed(1000 * i1 + 1234567);
    
    		tsp = TSP(i_file1[i1], i_file2[i1])
    
    		tsp.Control()
    
    """
    ----------------ケーススタディデータ(data_ct.txt)------
    3
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    
    ---------------Species記述データ(data1_t.txt)---------
    対立遺伝子上限 9 対立遺伝子下限 0
    最大遺伝子長 10 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 0 個体の重複(同じ染色体の個体) 0
    集団サイズ 10 子供 10
    
    ---------------TSP記述データ(data2_t.txt)--------
    出力レベル(負はファイル) 10 出力方法(0:適応度+順番,1:適応度) 0
    出力ファイル名 out1.txt 表示間隔 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
    """
    			
    関数の最大値
    # -*- coding: UTF-8 -*-
    import numpy as np
    import sys
    from math import *
    from random import *
    from datetime import *
    
    ###################################################################
    # f(x) = sin(3.0*x) + 0.5 * sin(9.0*x) + sin(15.0*x + 50) の最大値
    #      coded by Y.Suganuma
    ###################################################################
    
    
    ######################
    # クラスSpeciesの定義
    ######################
    
    class Species :
    	
    	#########################
    	# コンストラクタ
    	#      name : ファイル名
    	#########################
    
    	def __init__(self, name) :
    	
    				# データの入力
    		inn = open(name, "r")
    	
    		s             = inn.readline().split()
    		self.allele_u = int(s[1])   # 対立遺伝子上限
    		self.allele_l = int(s[3])   # 対立遺伝子下限
    		s             = inn.readline().split()
    		self.max_len  = int(s[1])   # 最大遺伝子長
    		self.min_len  = int(s[3])   # 最小遺伝子長(負の時は,最大遺伝子長で固定)
    		s             = inn.readline().split()
    		self.dup_a    = int(s[1])  # 遺伝子の重複
    		                           #   =0 : 重複を許さない
    		                           #   =1 : 重複を許す
    		self.dup_s    = int(s[3])   # 個体の重複(同じ染色体の個体)
    		                            #   =0 : 重複を許さない
    		                            #   =1 : 重複を許す
    		s             = inn.readline().split()
    		self.size     = int(s[1])   # 個体総数
    		self.max_ch   = int(s[3])   # 子供の数の最大値
    				# データのチェック
    		if self.size <= 0 :
    			print("***error  個体総数≦0 (Constructor)")
    	
    		if self.max_ch < 0 :
    			print("***error  子供の数<0 (Constructor)")
    	
    		if self.max_len <= 0 or self.min_len == 0 :
    			print("***error  遺伝子長≦0 (Constructor)")
    	
    		if self.max_len < self.min_len :
    			print("***error  最大遺伝子長<最小遺伝子長 (Constructor)")
    	
    		if self.allele_u <= self.allele_l :
    			print("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)")
    	
    		kind = self.allele_u - self.allele_l + 1
    		if self.dup_a == 0 and self.max_len > kind :
    			print("***error  遺伝子の重複を防ぐことはできない (Constructor)")
    				# 領域の確保
    		num       = self.size + self.max_ch
    		self.ind  = np.empty((num, self.max_len), np.int)   # 集団(個体の集まり)
    		self.edge = np.empty((self.max_len, 5), np.int)   # エッジ組み替え交叉用ワークエリア
    		self.pi   = np.empty(num, np.float)   # 適応度
    		self.ro   = np.empty(num, np.float)   # ルーレット板
    		self.len  = np.empty(num, np.int)   # 各個体の遺伝子長
    		self.kou1 = np.empty(self.max_len, np.int)   # 交叉・突然変異用作業場所1
    		self.kou2 = np.empty(self.max_len, np.int)   # 交叉・突然変異用作業場所2
    		self.s_w  = np.empty(num, np.int)   # 淘汰用指標(選択された回数)
    		self.pi_w = np.empty(num, np.int)   # 適応度計算指標
    		                                    #   =0 : 未使用
    		                                    #   =1 : 適応度計算前(突然変異はこの個体だけに適用)
    		                                    #   =2 : 適応度計算済み(交叉時に親とみなす)
    		self.max   = -inf   # 最大適応度
    		self.mean  = 0.0   # 平均適応度
    		self.max_n = -1   # 最大適応度の個体番号
    
    	##################################################
    	# 場所を探す
    	#      n : >=0 : n番目の親を捜す
    	#          -1 : 空いている場所を探す
    	#      return : 親の場所,または,空いている場所
    	#               (存在しないときは負の値)
    	##################################################
    
    	def Position(self, n) :
    	
    		k  = -1
    		sw = 0
    				# 空いている場所を探す
    		if n < 0 :
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] == 0 :
    					k = i1
    					break
    			if k < 0 :
    				print("***error  空いている場所がない --Position--")
    				# n番目の親(pi_w[i]=2)を捜す
    		else :
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] == 2 :
    					k += 1
    					if k == n :
    						sw = 1
    						k  = i1
    						break
    	
    		return k
    	
    	###################################################################
    	# 個体の選択
    	#      method : 選択方法
    	#                 =-1 : ランダム(default)
    	#                 =0 : 適応度をそのまま使用
    	#                 =1 : 最小値からの差(ただし,α以下の場合はα)
    	#                 =2 : 評価値に順位をつけ,減少率βで線形化
    	#      bias : α,または,method=2の場合は初期値(default=0)
    	#      step : β(default=1)
    	#      return : 個体番号
    	###################################################################
    
    	def Select(self, method, bias, step) :
    	
    		sum = 0.0
    					# ルーレット板の用意
    							# ランダム
    		if method == -1 :
    			n = 0
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					n += 1
    			sum = 1.0 / n
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					self.ro[i1] = sum
    							# 評価値をそのまま利用
    		elif method == 0 :
    			n = 0
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					sum += self.pi[i1]
    					n   += 1
    			if fabs(sum) > 1.0e-10 :
    				sum = 1.0 / fabs(sum)
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.pi_w[i1] > 1 :
    						self.ro[i1] = self.pi[i1] * sum
    			else :
    				sum = 1.0 / n
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.pi_w[i1] > 1 :
    						self.ro[i1] = sum
    							# 最小値からの差
    		elif method == 1 :
    			min = -1
    			n   = 0
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					n += 1
    					if min < 0 or self.pi[i1] < self.pi[min] :
    						min = i1
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					self.ro[i1] = self.pi[i1] - self.pi[min]
    					if self.ro[i1] < bias :
    						self.ro[i1] = bias
    					sum += self.ro[i1]
    			if sum > 1.0e-10 :
    				sum = 1.0 / sum
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.pi_w[i1] > 1 :
    						self.ro[i1] *= sum
    			else :
    				sum = 1.0 / n
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.pi_w[i1] > 1 :
    						self.ro[i1] = sum
    							# 線形化
    		elif method == 2 :
    			n = 0
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					self.ro[i1] = -1.0
    					n += 1
    				else :
    					self.ro[i1] = 1.0
    			sw  = 0
    			sum = bias
    			while sw == 0 :
    				min = -1
    				for i1 in range(0, self.size+self.max_ch) :
    					if self.ro[i1] < 0.0 and (min < 0 or self.pi[i1] < self.pi[min]) :
    						min = i1
    				if min < 0 :
    					sw = 1
    				else :
    					self.ro[min]  = sum
    					sum          += self.step
    			sum = 1.0 / (0.5 * (2.0 * bias + step * (n - 1)) * n)
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 :
    					self.ro[i1] *= sum
    	
    		sum = 0.0
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] > 1 :
    				sum         += self.ro[i1]
    				self.ro[i1]  = sum
    						# 選択
    		x  = random()
    		sw = 0
    		k  = 0
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] > 1 :
    				if x <= self.ro[i1] :
    					sw = 1
    					k  = i1
    					break
    	
    		return k
    	
    	###################
    	# 標準的な初期設定
    	###################
    
    	def Init_std(self) :
    	
    				# 初期設定
    		for i1 in range(0, self.size+self.max_ch) :
    			if i1 < self.size :
    				self.pi_w[i1] = 1   # 適応度の計算前
    			else :
    				self.pi_w[i1] = 0   # 未使用
    				# 遺伝子の決定
    		for i1 in range(0, self.size) :
    	
    			sw1    = 0
    			length = 0
    
    			while sw1 == 0 :
    						# 遺伝子長の決定
    				if self.min_len < 0 :
    					length = self.max_len
    				else :
    					length = int(random() * (self.max_len - self.min_len + 1) + self.min_len)
    					if length > self.max_len :
    						length = self.max_len
    				self.len[i1] = length
    						# 遺伝子の決定
    				for i2 in range(0, length) :
    					sw2 = 0
    					while sw2 == 0 :
    						lid = int(random() * (self.allele_u - self.allele_l + 1) + self.allele_l)
    						if lid > self.allele_u :
    							lid = self.allele_u
    						self.ind[i1][i2] = lid
    							# 重複遺伝子のチェック
    						sw2 = 1
    						if self.dup_a == 0 :
    							for i3 in range(0, i2) :
    								if lid == self.ind[i1][i3] :
    									sw2 = 0
    									break
    						# 重複個体のチェック
    				sw1 = 1
    				if self.dup_s == 0 :
    					for i2 in range(0, i1) :
    						if self.len[i1] == self.len[i2] :
    							sw2 = 0
    							for i3 in range(0, self.len[i1]) :
    								if self.ind[i1][i3] != self.ind[i2][i3] :
    									sw2 = 1
    									break
    							if sw2 == 0 :
    								sw1 = 0
    								break
    	
    	####################################################
    	# 標準的な出力
    	#      sw : 出力レベル
    	#             =0 : 最終出力だけ
    	#             n>0 : n世代毎に出力(負はファイル)
    	#      out_m : 出力方法
    	#                =0 : すべての個体を出力
    	#                =1 : 最大適応度の個体だけを出力
    	#      gen : 現在の世代番号
    	#      name : 出力ファイル名
    	####################################################
    
    	def Out_std(self, sw, out_m, gen, name) :
    	
    		k  = 0
    		pr = -1
    
    		if sw >= 0 :
    			pr = int(input("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? "))
    	
    		if pr != 0 :
    						# 出力先の決定と評価値の出力
    			if pr > 0 :
    				out = sys.stdout
    				input("")
    			else :
    				now = datetime.today().time().isoformat()
    				out = open(name, "a")
    				out.write("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean) + " 時間 " + now + "\n")
    						# 詳細出力
    			for i1 in range(0, self.size+self.max_ch) :
    				if (self.pi_w[i1] > 1) and (out_m == 0 or (out_m == 1 and i1 == self.max_n)) :
    					out.write(str(i1) + " allele")
    					for i2 in range(0, self.len[i1]) :
    						out.write(" " + str(self.ind[i1][i2]))
    					out.write(" value " + str(self.pi[i1]) + "\n")
    					if pr > 0 :
    						k += 1
    						if k == pr :
    							input("")
    							k = 0
    	
    			if pr < 0 :
    				out.close()
    	
    	###################################################################
    	# 交叉(親のコピー)
    	#      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)
    	###################################################################
    
    	def C_copy(self, method = 2, pair = 0, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータチェック
    		if method != 1 :
    			method = 2
    	
    		if pair <= 0 :
    			if method == 2 :
    				pair = int(self.max_ch / 2)
    			else :
    				pair = self.max_ch
    		else :
    			if method == 2 and 2*pair > self.max_ch or method == 1 and pair > self.max_ch :
    				print("***error  子供が多すぎる (C_copy)")
    				# 実行
    		for i1 in range(0, pair) :
    						# 親の選択
    			p1 = self.Select(k_method, k_bias, k_step)
    			p2 = p1
    			sw = 0
    	
    			while sw == 0 :
    				p2 = self.Select(k_method, k_bias, k_step)
    				if p1 != p2 :
    					sw = 1
    						# コピー
    			for i2 in range(0, method) :
    				p = p2
    				if i2 == 0 :
    					p = p1
    				k            = self.Position(-1)
    				self.len[k]  = self.len[p]
    				self.pi_w[k] = 1
    				for i3 in range(0, self.len[k]) :
    					self.ind[k][i3] = self.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)
    	###################################################################
    
    	def C_point(self, kosa, k_point = 1, k_vr = 0, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    		mn = 0
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a == 0 :
    			print("***error  交叉方法が不適当 (C_point)")
    	
    		abs_p = abs(k_point)
    		if abs_p == 0 or abs_p > self.max_len-1 or self.min_len > 0 and abs_p > self.min_len-1 :
    			print("***error  交叉点の数が不適当 (C_point)")
    	
    		if k_vr > 0 and self.min_len < 0 :
    			print("***error  遺伝子長は可変でなければならない (C_point)")
    				# 交叉
    		num = k_point
    	
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 交叉位置の数の決定
    				if k_point < 0 :
    					num = int(random() * abs_p + 1)
    					if num > abs_p :
    						num = abs_p
    							# 交叉位置の決定(点の後ろで交叉)
    				for i2 in range(0, num) :
    								# 親1の交叉位置
    					sw = 0
    					while sw == 0 :
    						sw            = 1
    						self.kou1[i2] = int(random() * (self.len[p1] - 1))
    						if self.kou1[i2] > self.len[p1]-2 :
    							self.kou1[i2] = self.len[p1] - 2
    						if k_vr == 0 and self.kou1[i2] > self.len[p2]-2 :
    							self.kou1[i2] = self.len[p2] - 2
    						for i3 in range(0, i2) :
    							if self.kou1[i3] == self.kou1[i2] :
    								sw = 0
    								break
    								# 親2の交叉位置
    					if k_vr > 0 :
    						sw = 0
    						while sw == 0 :
    							sw            = 1
    							self.kou2[i2] = int(random() * (self.len[p2] - 1))
    							if self.kou2[i2] > self.len[p2]-2 :
    								self.kou2[i2] = self.len[p2] - 2
    							for i3 in range(0, i2) :
    								if self.kou2[i3] == self.kou2[i2] :
    									sw = 0
    									break
    							# 交叉の実行
    							#   親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            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    	
    				for i2 in range(0, num+1) :
    								# 次の交叉位置を求める
    					if i2 == num :            # 最後
    						t12 = self.len[p1]
    						t22 = self.len[p2]
    					else :
    									# 親1
    						t12 = self.max_len
    						for i3 in range(0, num) :
    							if self.kou1[i3] >= 0 and self.kou1[i3] <= t12 :
    								t12 = self.kou1[i3]
    								mn  = i3
    						self.kou1[mn] = -1
    						t12 += 1
    									# 親2
    						if k_vr == 0 :
    							t22 = t12
    						else :
    							t22 = self.max_len
    							for i3 in range(0, num) :
    								if self.kou2[i3] >= 0 and self.kou2[i3] <= t22 :
    									t22 = self.kou2[i3]
    									mn  = i3
    							self.kou2[mn] = -1
    							t22 += 1
    								# 指定箇所のコピー
    					for i3 in range(t11, t12) :
    						if i2%2 == 0 :
    							if c1 < self.max_len :
    								self.ind[k1][c1] = self.ind[p1][i3]
    								c1 += 1
    						else :
    							if c2 < self.max_len :
    								self.ind[k2][c2] = self.ind[p1][i3]
    								c2 += 1
    	
    					for i3 in range(t21, t22) :
    						if i2%2 == 0 :
    							if c2 < self.max_len :
    								self.ind[k2][c2] = self.ind[p2][i3]
    								c2 += 1
    						else :
    							if c1 < self.max_len :
    								self.ind[k1][c1] = self.ind[p2][i3]
    								c1 += 1
    								# 交叉位置の移動
    					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)
    	###################################################################
    
    	def C_uniform(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a == 0 :
    			print("***error  交叉方法が不適当 (C_uniform)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_uniform)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				for i2 in range(0, self.len[p1]) :
    					if random() > 0.5 :
    						self.ind[k1][i2] = self.ind[p1][i2]
    						self.ind[k2][i2] = self.ind[p2][i2]
    					else :
    						self.ind[k1][i2] = self.ind[p2][i2]
    						self.ind[k2][i2] = self.ind[p1][i2]
    	
    	###################################################################
    	# 交叉(平均化交叉.2つの親の平均値を受け継ぐ)
    	#      kosa : 交叉確率
    	#      k_method : 選択方法
    	#                 =-1 : ランダム(default)
    	#                 =0 : 適応度をそのまま使用
    	#                 =1 : 最小値からの差(ただし,α以下の場合はα)
    	#                 =2 : 評価値に順位をつけ,減少率βで線形化
    	#      k_bias : α,または,method=2の場合は初期値(default=0)
    	#      k_step : β(default=1)
    	###################################################################
    
    	def C_mean(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_mean)")
    				# 交叉
    		for i1 in range(0, self.max_ch) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(1, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k            = self.Position(-1)
    				self.len[k]  = self.len[p1]
    				self.pi_w[k] = 1
    							# 交叉
    				for i2 in range(0, self.len[k]) :
    					self.ind[k][i2] = int((self.ind[p1][i2] + self.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)
    	###################################################################
    	def C_cycle(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_cycle)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_cycle)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 初期設定
    				for i2 in range(0, self.len[p1]) :
    					self.kou1[i2] = 0
    					self.kou2[i2] = 0
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				sw = 0
    	
    				while sw == 0 :
    					sw = 1
    					p  = int(random() * self.len[p1])
    					if p >= self.len[p1] :
    						p = self.len[p1] - 1
    					if self.kou1[p] == 0 and self.kou2[p] == 0 :
    						self.kou1[p]    = 1
    						self.kou2[p]    = 1
    						self.ind[k1][p] = self.ind[p1][p]
    						self.ind[k2][p] = self.ind[p2][p]
    						for i2 in range(0, self.len[p1]) :
    							if self.ind[p2][p] == self.ind[p1][i2] :
    								self.ind[k1][i2] = self.ind[p1][i2]
    								self.kou1[i2]    = 1
    								sw               = 0
    								break
    						sw = 1
    						for i2 in range(0, self.len[p2]) :
    							if self.ind[p1][p] == self.ind[p2][i2] :
    								self.ind[k2][i2] = self.ind[p2][i2]
    								self.kou2[i2]    = 1
    								sw               = 0
    								break
    	
    				sw = 0
    				i2 = 0
    				i3 = 0
    				while sw == 0 :
    					while sw == 0 and i2 < self.len[p1] :
    						if self.kou1[i2] == 0 :
    							sw = 1
    						else :
    							i2 += 1
    					sw = 0
    					while sw == 0 and i3 < self.len[p2] :
    						if self.kou2[i3] == 0 :
    							sw = 1
    						else :
    							i3 += 1
    					if i2 < self.len[p1] and i3 < self.len[p2] :
    						self.ind[k1][i2] = self.ind[p2][i3]
    						self.ind[k2][i3] = self.ind[p1][i2]
    						sw          = 0
    						i2 += 1
    						i3 += 1
    					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)
    	#******************************************************************/
    	def C_part(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_part)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_part)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				p = int(random() * self.len[p1])
    				if p >= self.len[p1] :
    					p = self.len[p1] - 1
    	
    				for i2 in range(0, self.len[p1]) :
    					self.ind[k1][i2] = self.ind[p1][i2]
    					self.ind[k2][i2] = self.ind[p2][i2]
    	
    				for i2 in range(p, self.len[p1]) :
    					sw = 0
    					lv = self.ind[k1][i2]
    					for i3 in range(0, self.len[p1]) :
    						if self.ind[k2][i2] == self.ind[k1][i3] :
    							self.ind[k1][i2] = self.ind[k1][i3]
    							self.ind[k1][i3] = lv
    							sw               = 1
    							break
    					sw = 0
    					for i3 in range(0, self.len[p1]) :
    						if lv == self.ind[k2][i3] :
    							self.ind[k2][i3] = self.ind[k2][i2]
    							self.ind[k2][i2] = lv
    							sw               = 1
    							break
    	
    	###################################################################
    	# 交叉(順序交叉.ランダムに切れ目を決定し,子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)
    	###################################################################
    	def C_seq(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_seq)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_seq)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				p = int(random() * (self.len[p1] - 1))
    				if p >= self.len[p1]-1 :
    					p = self.len[p1] - 2
    	
    				for i2 in range(0, p+1) :
    					self.ind[k1][i2] = self.ind[p1][i2]
    					self.ind[k2][i2] = self.ind[p2][i2]
    	
    				pp = 0
    				for i2 in range(p+1, self.len[p1]) :
    					sw = 0
    					i3 = pp
    					while i3 < self.len[p2] and sw == 0 :
    						i4 = p + 1
    						while i4 < self.len[p1] and sw == 0 :
    							if self.ind[p2][i3] == self.ind[p1][i4] :
    								sw               = 1
    								pp               = i3 + 1
    								self.ind[k1][i2] = self.ind[p1][i4]
    							i4 += 1
    						i3 += 1
    				pp = 0
    				for i2 in range(p+1, self.len[p2]) :
    					sw = 0
    					i3 = pp
    					while i3 < self.len[p1] and sw == 0 :
    						i4 = p + 1
    						while i4 < self.len[p2] and sw == 0 :
    							if self.ind[p1][i3] == self.ind[p2][i4] :
    								sw               = 1
    								pp               = i3 + 1
    								self.ind[k2][i2] = self.ind[p2][i4]
    							i4 += 1
    						i3 += 1
    	
    	###################################################################
    	# 交叉(一様順序交叉.位置の集合をランダムに選択し,一方の親の選
    	#       択された位置における遺伝子の順序に従って,他の親の遺伝子
    	#       を並べ替える
    	#         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)
    	###################################################################
    	
    	def C_useq(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair =int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_useq)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_useq)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				for i2 in range(0, self.len[p1]) :
    					self.ind[k1][i2] = self.ind[p1][i2]
    					self.ind[k2][i2] = self.ind[p2][i2]
    					if random() < 0.5 :
    						self.kou1[i2] = 0
    					else :
    						self.kou1[i2] = 1
    	
    				p = 0
    				for i2 in range(0, self.len[p1]) :
    					if self.kou1[i2] > 0 :
    						sw = 0
    						i3 = p
    						while i3 < self.len[p2] and sw == 0 :
    							i4 = 0
    							while i4 < self.len[p1] and sw == 0 :
    								if self.ind[p2][i3] == self.ind[p1][i4] and self.kou1[i4] > 0 :
    									sw               = 1
    									p                = i3 + 1
    									self.ind[k1][i2] = self.ind[p1][i4]
    								i4 += 1
    							i3 += 1
    				p = 0
    				for i2 in range(0, self.len[p3]) :
    					if self.kou1[i2] > 0 :
    						sw = 0
    						i3 = p
    						while i3 < self.len[p1] and sw == 0 :
    							i4 = 0
    							while i4 < self.len[p2] and sw == 0 :
    								if self.ind[p1][i3] == self.ind[p2][i4] and self.kou1[i4] > 0 :
    									sw               = 1
    									p                = i3 + 1
    									self.ind[k2][i2] = self.ind[p2][i4]
    								i4 += 1
    							i3 += 1
    	
    	###################################################################
    	# 交叉(一様位置交叉.位置の集合をランダムに選択し,一方の親の選
    	#       択された位置における遺伝子の位置に,他の親の同じ遺伝子を
    	#       配置する.残りの遺伝子は,親と同じ順序に配置する.
    	#         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)
    	###################################################################
    
    	def C_upos(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    				# 初期設定とデータのチェック
    		pair = int(self.max_ch / 2)
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_upos)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_upos)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(2, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k1            = self.Position(-1)
    				self.pi_w[k1] = 1
    				self.len[k1]  = self.len[p1]
    				k2            = self.Position(-1)
    				self.pi_w[k2] = 1
    				self.len[k2]  = self.len[p2]
    							# 交叉
    				for i2 in range(0, self.len[p1]) :
    					self.kou1[i2] = 1
    					if random() < 0.5 :
    						self.kou1[i2] = 1
    					if self.kou1[i2] > 0 :
    						self.ind[k1][i2] = self.ind[p2][i2]
    						self.ind[k2][i2] = self.ind[p1][i2]
    	
    				p = 0
    				for i2 in range(0, self.len[p1]) :
    					sw = 0
    					for i3 in range(0, self.len[p1]) :
    						if self.kou1[i3] > 0 and self.ind[p1][i2] == self.ind[k1][i3] :
    							sw = 1
    							break
    					if sw == 0 :
    						for i3 in range(p, self.len[p1]) :
    							if self.kou1[i3] == 0 :
    								self.ind[k1][i3] = self.ind[p1][i2]
    								p                = i3 + 1
    								sw               = 1
    								break
    				p = 0
    				for i2 in range(0, self.len[p2]) :
    					sw = 0
    					for i3 in range(0, self.len[p2]) :
    						if self.kou1[i3] > 0 and self.ind[p2][i2] == self.ind[k2][i3] :
    							sw = 1
    							break
    					if sw == 0 :
    						for i3 in range(p, self.len[p2]) :
    							if self.kou1[i3] == 0 :
    								self.ind[k2][i3] = self.ind[p2][i2]
    								p                = i3 + 1
    								sw               = 1
    								break
    	
    	###################################################################
    	# 交叉(エッジ組み替え交叉.以下の手順に従って行う.対立遺伝子は
    	#       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)
    	###################################################################
    
    	def C_edge(self, kosa, k_method = -1, k_bias = 0.0, k_step = 1.0) :
    	
    		e  = np.empty(2, np.int)
    		k0 = 0
    				# 初期設定とデータのチェック
    		pair = self.max_ch
    	
    		if self.dup_a != 0 :
    			print("***error  交叉方法が不適当 (C_edge)")
    	
    		if self.min_len > 0 :
    			print("***error  遺伝子長は固定長でなければならない (C_edge)")
    				# 交叉
    		for i1 in range(0, pair) :
    						# 交叉しない場合
    			if random() > kosa :
    				self.C_copy(1, 1)
    						# 交叉する場合
    			else :
    							# 親の選択
    				p1 = self.Select(k_method, k_bias, k_step)
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = self.Select(k_method, k_bias, k_step)
    					if p1 != p2 :
    						sw = 1
    							# 遺伝子長
    				k            = self.Position(-1)
    				self.pi_w[k] = 1
    				self.len[k]  = self.len[p1]
    							# エッジマップの初期化
    				for i2 in range(0, self.len[k]) :
    					self.edge[i2][0] = 0
    					for i3 in range(1, 5) :
    						self.edge[i2][i3] = -1
    							# 交叉
    								# エッジマップの作成
    				for i2 in range(0, self.len[k]) :
    	
    					sw = 0
    					for i3 in range(0, self.len[k]) :
    						if i2 == self.ind[p1][i3] :
    							sw = 1
    							if i3 == 0 :
    								e[0] = self.ind[p1][self.len[k]-1]
    								e[1] = self.ind[p1][1]
    							else :
    								if i3 == self.len[k]-1 :
    									e[0] = self.ind[p1][i3-1]
    									e[1] = self.ind[p1][0]
    								else :
    									e[0] = self.ind[p1][i3-1]
    									e[1] = self.ind[p1][i3+1]
    							for i4 in range(0, 2) :
    								self.edge[i2][0] += 1
    								self.edge[i2][self.edge[i2][0]] = e[i4]
    							break
    	
    					sw = 0
    					for i3 in range(0, self.len[k]) :
    						if i2 == self.ind[p2][i3] :
    							sw = 1
    							if i3 == 0 :
    								e[0] = self.ind[p2][self.len[k]-1]
    								e[1] = self.ind[p2][1]
    							else :
    								if i3 == self.len[k]-1 :
    									e[0] = self.ind[p2][i3-1]
    									e[1] = self.ind[p2][0]
    								else :
    									e[0] = self.ind[p2][i3-1]
    									e[1] = self.ind[p2][i3+1]
    							for i4 in range(0, 2) :
    								sw = 1
    								for i5 in range(1, self.edge[i2][0]+1) :
    									if self.edge[i2][i5] == e[i4] :
    										sw = 2
    										break
    								if sw == 1 :
    									self.edge[i2][0] += 1
    									self.edge[i2][self.edge[i2][0]] = e[i4]
    							break
    								# 交叉の実行
    									# 出発点の決定
    				k1 = self.ind[p1][0]
    				k2 = self.ind[p2][0]
    				if self.edge[k1][0] == self.edge[k2][0] :
    					kk = k1
    					if random() > 0.5 :
    						kk = k2
    				else :
    					kk = k2
    					if self.edge[k1][0] < self.edge[k2][0] :
    						kk = k2
    				self.ind[k][0] = kk
    				p              = 1
    	
    				while p < self.len[k] :
    									# ノードの除去
    					for i2 in range(0, self.len[k]) :
    						sw = 0
    						if self.edge[i2][0] > 0 :
    							for i3 in range(1, 5) :
    								if self.edge[i2][i3] == kk :
    									sw                 = 1
    									self.edge[i2][i3]  = -1
    									self.edge[i2][0]  -= 1
    									break
    									# 次の現在ノードの選択
    					min = 10
    					num = 0
    					for i2 in range(1, 5) :
    						if self.edge[kk][i2] >= 0 :
    							k1 = self.edge[kk][i2]
    							if self.edge[k1][0] >= 0 and self.edge[k1][0] < min :
    								num = 1
    								min = self.edge[k1][0]
    								k0  = k1
    							else :
    								if self.edge[k1][0] == min :
    									num += 1
    					if num > 1 :
    						k1 = int(random() * num) + 1
    						if k1 > num :
    							k1 = num
    						k2 = 0
    						k0 = -1
    						i2 = 1
    						while i2 <= 4 and k0 < 0 :
    							if self.edge[kk][i2] >= 0 :
    								if self.edge[self.edge[kk][i2]][0] == min :
    									k2 += 1
    									if k1 == k2 :
    										k0 = self.edge[kk][i2]
    							i2 += 1
    					else :
    						if num <= 0 :
    							num = 0
    							for i2 in range(0, self.len[k]) :
    								if i2 != kk and self.edge[i2][0] >= 0 :
    									num += 1
    							if num <= 0 :
    								print("***error  invalid data (C_edge)")
    							else :
    								k1 = int(random() * num) + 1
    								if k1 > num :
    									k1 = num
    								k2 = 0
    								k0 = -1
    								i2 = 0
    								while i2 < self.len[k] and k0 < 0 :
    									if i2 != kk and self.edge[i2][0] >= 0 :
    										k2 += 1
    										if k1 == k2 :
    											k0 = i2
    									i2 += 1
    					self.edge[kk][0]  = -1
    					self.ind[k][p]    = k0
    					kk                = k0
    					p                += 1
    	
    	##############################################################
    	# 交叉(サブツアー交叉.2点交叉の拡張である.ただし,相手に
    	#       同じ遺伝子のグループがない限り実行されない.たとえば
    	#         ***abcd**
    	#         *cdab****
    	#       のような両親の時実行され,以下の4つの子供が生成され
    	#       る)
    	#         ***cdab**
    	#         *abcd****
    	#         ***badc**
    	#         *dcba****
    	#       最大,4*交叉回数*個体総数*(個体総数-1) 個の子
    	#       供が生成される可能性があるので,子供の数としてこの値
    	#       以上のデータを入力しておく必要がある.
    	#      kosa : 交叉確率
    	#      count : 1つのペアーに対する交差回数(default=10)
    	##############################################################
    
    	def C_sub(self, kosa, count = 10) :
    	
    		t22 = 0
    				# 初期設定とデータのチェック
    		if (4*count*self.size*(self.size-1)) > self.max_ch :
    			print("***error  子供が多すぎる (C_sub)")
    				# 交叉
    		for i1 in range(0, self.size-1) :
    						# 親1
    			p1 = self.Position(i1)
    	
    			if p1 >= 0 :
    	
    				for i2 in range(i1, self.size) :
    						# 親2
    					p2 = self.Position(i2)
    	
    					if p2 >= 0 :
    						# 交叉しない場合
    						if random() > kosa :
    							self.C_copy(2, 1)
    						# 交叉する場合
    						else :
    							# 交叉回数の制御
    							for i3 in range(0, count) :
    								# 交叉位置の決定(点の後ろで交叉)
    									# 親1の交叉位置
    								t11 = int(random() * self.len[p1])
    								if t11 > (self.len[p1]-1) :
    									t11 = self.len[p1] - 1
    								sw = 0
    								while sw == 0 :
    									t12 = int(random() * self.len[p1])
    									if t12 > (self.len[p1]-1) :
    										t12 = self.len[p1] - 1
    									if t12 != t11 :
    										sw = 1
    								if t11 > t12 :
    									k1  = t11
    									t11 = t12
    									t12 = k1
    									# 親2の交叉位置
    								sw  = 0
    								t21 = -1
    								i4  = 0
    								while i4 < self.len[p2] and t21 < 0 :
    									i5 = t11
    									while i5 <= t12 and t21 < 0 :
    										if self.ind[p2][i4] == self.ind[p1][i5] :
    											t21 = i4
    										i5 += 1
    									i4 += 1
    								if t21 >= 0 :
    									t22 = t21 + t12 - t11
    									if t22 < self.len[p2] :
    										sw = 1
    										i4 = t21 + 1
    										while i4 <= t22 and sw > 0 :
    											sw = 0
    											i5 = t11
    											while i5 <= t12 and sw == 0 :
    												if self.ind[p2][i4] == self.ind[p1][i5] :
    													sw = 1
    												i5 += 1
    											i4 += 1
    									# 交叉の実行
    								if sw > 0 :
    	
    									k1            = self.Position(-1)
    									self.pi_w[k1] = 1
    									self.len[k1]  = self.len[p1]
    									k2            = self.Position(-1)
    									self.pi_w[k2] = 1
    									self.len[k2]  = self.len[p1]
    									k3            = self.Position(-1)
    									self.pi_w[k3] = 1
    									self.len[k3]  = self.len[p2]
    									k4            = self.Position(-1)
    									self.pi_w[k4] = 1
    									self.len[k4]  = self.len[p2]
    	
    									for i4 in range(0, t11) :
    										self.ind[k1][i4] = self.ind[p1][i4]
    										self.ind[k2][i4] = self.ind[p1][i4]
    									for i4 in range(t11, t12+1) :
    										self.ind[k1][i4] = self.ind[p2][t21+i4-t11]
    										self.ind[k2][i4] = self.ind[p2][t22-i4+t11]
    									for i4 in range(t12+1, self.len[p1]) :
    										self.ind[k1][i4] = self.ind[p1][i4]
    										self.ind[k2][i4] = self.ind[p1][i4]
    									for i4 in range(0, t21) :
    										self.ind[k3][i4] = self.ind[p2][i4]
    										self.ind[k4][i4] = self.ind[p2][i4]
    									for i4 in range(t21, t22+1) :
    										self.ind[k3][i4] = self.ind[p1][t11+i4-t21]
    										self.ind[k4][i4] = self.ind[p1][t12-i4+t21]
    									for i4 in range(t22+1, self.len[p2]) :
    										self.ind[k3][i4] = self.ind[p2][i4]
    										self.ind[k4][i4] = self.ind[p2][i4]
    	
    	#######################################
    	# 突然変異(対立遺伝子との置き換え)
    	#      pr : 突然変異率
    	#######################################
    
    	def M_alle(self, pr) :
    	
    				# データのチェックと初期設定
    		if self.dup_a == 0 :
    			print("***error  突然変異方法が不適当 (M_alle)")
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] == 1 :
    				for i2 in range(0, self.len[i1]) :
    					if random() <= pr :
    						lid = int(random() * (self.allele_u - self.allele_l + 1) + self.allele_l)
    						if lid > self.allele_u :
    							lid = self.allele_u
    						if lid != self.ind[i1][i2] :
    							self.ind[i1][i2] = lid
    
    	######################################################################
    	# 突然変異(移動.2点を選択し,2番目の遺伝子を1番目の遺伝子の前に
    	#           移動する)
    	#      pr : 突然変異率
    	######################################################################
    
    	def M_move(self, pr) :
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    				# 位置の決定
    						# p1
    				p1 = int(random() * self.len[i1])
    				if p1 >= self.len[i1] :
    					p1 = self.len[i1] - 1
    						# p2
    				p2 = p1
    				sw = 0
    				while sw == 0 :
    					p2 = int(random() * self.len[i1])
    					if p2 >= self.len[i1] :
    						p2 = self.len[i1] - 1
    					if p2 != p1 :
    						sw = 1
    				# 実行
    				if p2 > p1 :
    					ld = self.ind[i1][p2]
    					for i2 in range(p2, p1, -1) :
    						self.ind[i1][i2] = self.ind[i1][i2-1]
    					self.ind[i1][p1] = ld
    				else :
    					ld = self.ind[i1][p2]
    					for i2 in range(p2, p1-1) :
    						self.ind[i1][i2] = self.ind[i1][i2+1]
    					self.ind[i1][p1-1] = ld
    	
    	########################################################
    	# 突然変異(逆位.2点間の遺伝子順序を逆に並べ替える)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	########################################################
    
    	def M_inv(self, pr, wd = 0) :
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    				# 区間の決定
    				if wd == 0 :
    					p1 = int(random() * self.len[i1])
    					if p1 >= self.len[i1] :
    						p1 = self.len[i1] - 1
    					sw = 0
    					p2 = p1
    					while sw == 0 :
    						p2 = int(random() * self.len[i1])
    						if p2 >= self.len[i1] :
    							p2 = self.len[i1] - 1
    						if p2 != p1 :
    							sw = 1
    					if p1 > p2 :
    						p  = p1
    						p1 = p2
    						p2 = p
    	
    				else :
    					p1 = self.len[i1]
    					while p1 > self.len[i1]-2 :
    						p1 = int(random() * self.len[i1])
    					p2 = p1 + wd - 1
    					if p2 >= self.len[i1] :
    						p2 = self.len[i1] - 1
    				# 実行
    				sw = 0
    				while sw == 0 :
    					lid              = self.ind[i1][p1]
    					self.ind[i1][p1] = self.ind[i1][p2]
    					self.ind[i1][p2] = lid
    					p1 += 1
    					p2 -= 1
    					if p1 >= p2 :
    						sw = 1
    	
    	######################################################################
    	# 突然変異(スクランブル.2点間の遺伝子順序をランダムに並べ替える)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	######################################################################
    
    	def M_scram(self, pr, wd = 0) :
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    				# 区間の決定
    				if wd == 0 :
    					p1 = int(random() * self.len[i1])
    					if p1 >= self.len[i1] :
    						p1 = self.len[i1] - 1
    					sw = 0
    					p2 = p1
    					while sw == 0 :
    						p2 = int(random() * self.len[i1])
    						if p2 >= self.len[i1] :
    							p2 = self.len[i1] - 1
    						if p2 != p1 :
    							sw = 1
    					if p1 > p2 :
    						p  = p1
    						p1 = p2
    						p2 = p
    	
    				else :
    					p1 = self.len[i1]
    					while p1 > self.len[i1]-2 :
    						p1 = int(random() * self.len[i1])
    					p2 = p1 + wd - 1
    					if p2 >= self.len[i1] :
    						p2 = self.len[i1] - 1
    				# 実行
    				for i2 in range(p1, p2+1) :
    					p = int(random() * (p2 - p1 + 1) + p1)
    					if p > p2 :
    						p = p2
    					ld               = self.ind[i1][i2]
    					self.ind[i1][i2] = self.ind[i1][p]
    					self.ind[i1][p]  = ld
    	
    	######################################################################
    	# 突然変異(転座.2点間の遺伝子を他の位置のものと置き換える.ただし
    	#           重複部分はそのままとする)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	######################################################################
    
    	def M_chg(self, pr, wd = 0) :
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    				# 区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    						# p1
    				p1 = int(random() * self.len[i1])
    				if p1 >= self.len[i1] :
    					p1 = self.len[i1] - 1
    						# p3
    				sw = 0
    				p3 = p1
    				while sw == 0 :
    					p3 = int(random() * self.len[i1])
    					if p3 >= self.len[i1] :
    						p3 = self.len[i1] - 1
    					if p3 != p1 :
    						sw = 1
    						# 小さい方をp1,p2にする
    				if p1 > p3 :
    					p  = p1
    					p1 = p3
    					p3 = p
    						# p4, p2
    				p4 = p1 + wd - 1
    				if wd == 0 :
    					p4 = int(random() * (self.len[i1] - p3)) + p3
    				if p4 >= self.len[i1] :
    					p4 = self.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 in range(p1, p2+1) :
    					ld                = self.ind[i1][i2]
    					self.ind[i1][i2]  = self.ind[i1][p]
    					self.ind[i1][p]   = ld
    					p                += 1
    	
    	######################################################################
    	# 突然変異(重複.2点間の遺伝子を他の位置にコピーする
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(deafult)
    	######################################################################
    
    	def M_dup(self, pr, wd = 0) :
    	
    				# データのチェック
    		if self.dup_a == 0 :
    			print("***error  突然変異方法が不適当 (M_dup)")
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    						# 区間の決定([p1,p2]を[p3,p4]にコピー)
    							# p1
    				p1 = int(random() * self.len[i1])
    				if p1 >= self.len[i1] :
    					p1 = self.len[i1] - 1
    							# p3
    				sw = 0
    				p3 = p1
    				while sw == 0 :
    					p3 = int(random() * self.len[i1])
    					if p3 >= self.len[i1] :
    						p3 = self.len[i1] - 1
    					if p3 != p1 :
    						sw = 1
    							# 区間を決める
    				p2 = p1
    				p4 = p1
    				if p3 > p1 :
    					p4 = p3 + wd - 1
    					if wd == 0 :
    						p4 = int(random() * (self.len[i1] - p3)) + p3
    					if p4 >= self.len[i1] :
    						p4 = self.len[i1] - 1
    					p2 = p1 + (p4 - p3)
    				else :
    					p2 = p1 + wd - 1
    					if wd == 0 :
    						p2 = int(random() * (self.len[i1] - p1)) + p1
    					if p2 >= self.len[i1] :
    						p2 = self.len[i1] - 1
    					p4 = p3 + (p2 - p1)
    						# 実行
    				p = p4
    				for i2 in range(p2, p1-1, -1) :
    					self.ind[i1][p] = self.ind[i1][i2]
    					p -= 1
    	
    	######################################################
    	# 突然変異(摂動.値をある量だけ変化させる)
    	#      pr : 突然変異率
    	#      method : =0 : 正規分布(default)
    	#               =1 : 一様分布
    	#      m : 平均または一様分布の下限(default=0.0)
    	#      s : 標準偏差または一様分布の上限(default=1.0)
    	######################################################
    
    	def M_per(self, pr, method = 0, m = 0.0, s = 1.0) :
    	
    		wd = 0.0
    				# データのチェックと初期設定
    		if self.dup_a == 0 :
    			print("***error  突然変異方法が不適当 (M_per)")
    	
    		if method > 0 :
    			wd = s - m
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] == 1 :
    				for i2 in range(0, self.len[i1]) :
    					if random() <= pr :
    						if method == 0 :
    							w = normalvariate(m, s)
    						else :
    							w = random() * wd
    							if random() < 0.5 :
    								w = -w
    						x1 = float(self.ind[i1][i2]) + w
    						if x1 > self.allele_u :
    							x1 = self.allele_u
    						else :
    							if x1 < self.allele_l :
    								x1 = self.allele_l
    						self.ind[i1][i2] = int(x1)
    	
    	##############################################
    	# 突然変異(挿入.ある長さの遺伝子を挿入する)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	##############################################
    
    	def M_ins(self, pr, wd = 0) :
    	
    				# データのチェック
    		if self.dup_a == 0 or self.min_len < 0 :
    			print("***error  突然変異方法が不適当 (M_ins)")
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    						# 挿入位置の決定
    				p = int(random() * (self.len[i1] + 1))
    				if p > self.len[i1] :
    					p = self.len[i1]
    						# 挿入する遺伝子長の決定
    				l = wd
    				if wd == 0 :
    					l = int(random() * (self.max_len - self.len[i1] + 1))
    				if l > self.max_len-self.len[i1] :
    					l = self.max_len - self.len[i1]
    				else :
    					if l <= 0 :
    						l = 1
    						# 実行
    							# 挿入場所の確保
    				if p < self.len[i1] :
    					for i2 in range(self.len[i1]+l-1, p-1, -1) :
    						self.ind[i1][i2] = self.ind[i1][i2-l]
    							# 挿入場所の遺伝子の決定
    				for i2 in range(p, p+l) :
    					ld = int(random() * (self.allele_u - self.allele_l + 1) + self.allele_l)
    					if ld > self.allele_u :
    						ld = self.allele_u
    					self.ind[i1][i2] = ld
    	
    				self.len[i1]  += l
    	
    	##############################################
    	# 突然変異(削除.ある長さの遺伝子を削除する)
    	#      pr : 突然変異率
    	#      wd : >0 : 幅を固定
    	#           =0 : 幅をランダム(default)
    	##############################################
    
    	def M_del(self, pr, wd = 0) :
    	
    				# データのチェック
    		if self.dup_a == 0 or self.min_len < 0 :
    			print("***error  突然変異方法が不適当 (M_del)")
    				# 実行
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 and random() <= pr :
    						# 削除位置の決定
    				p = int(random() * self.len[i1])
    				if p >= self.len[i1] :
    					p = self.len[i1] - 1
    						# 削除する遺伝子長の決定
    				max = self.len[i1] - p
    				if self.len[i1]-self.min_len < self.len[i1]-p :
    					max = self.len[i1] - self.min_len
    				l = wd
    				if wd == 0 :
    					l = int(random() * max + 1)
    				if l > max :
    					l = max
    						# 実行
    				for i2 in range(0, self.len[i1]-p-l) :
    					self.ind[i1][p+i2] = self.ind[i1][p+i2+l]
    	
    				self.len[i1]  -= l
    	
    	######################################################################
    	# 淘汰(エリート・ルーレット選択)
    	#      elite : エリートで残す個体数(default=0)
    	#      s_method : ルーレット板の作成方法(default=1)
    	#                   =0 : 適応度をそのまま使用
    	#                   =1 : 最小値からの差(ただし,α以下の場合はα)
    	#                   =2 : 評価値に順位をつけ,減少率βで線形化
    	#      s_bias : α,または,method=2の場合は初期値(default=0)
    	#      s_step : β(default=1)
    	######################################################################
    
    	def S_roul(self, elite = 0, s_method = 1, s_bias = 0.0, s_step = 1.0) :
    	
    		count = 0
    		k     = 0
    		n     = 0
    				# 値のチェックと初期設定
    		if s_method != 0 and s_method != 2 :
    			s_method = 1
    	
    		if elite > self.size :
    			print("***error  エリートで残す数が多すぎる (S_roul)")
    	
    		if s_method == 2 and s_step <= 0.0 :
    			s_step = 1.0
    	
    		for i1 in range(0, self.size+self.max_ch) :
    			self.s_w[i1] = 0
    				# 重複個体を削除
    		if self.dup_s == 0 :
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 0 :
    					for i2 in range(i1+1, self.size+self.max_ch) :
    						if self.pi_w[i2] > 0 and self.len[i1] == self.len[i2] :
    							sw = 0
    							for i3 in range(0, self.len[i1]) :
    								if self.ind[i1][i3] != self.ind[i2][i3] :
    									sw = 1
    									break
    							if sw == 0 :
    								self.pi_w[i2] = 0
    	
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.pi_w[i1] > 1 :
    				n += 1
    	
    		if n < 0 or self.dup_s == 0 and n < self.size :
    			print("***error  残す個体がない (S_roul)")
    				# 淘汰して残す個体を選ぶ
    						# エリートの選択
    		sw = 0
    	
    		while k < elite and k < n and sw == 0 :
    			max = -1
    			for i1 in range(0, self.size+self.max_ch) :
    				if self.pi_w[i1] > 1 and self.s_w[i1] == 0 :
    					if max < 0 or self.pi[i1] > self.pi[max] :
    						max = i1
    			if max < 0 :
    				sw = 1
    			else :
    				self.s_w[max]  = 1
    				k             += 1
    						# ルーレット選択
    		while count < self.size+self.max_ch and k < self.size :
    			p = self.Select(s_method, s_bias, s_step)
    			if self.dup_s == 0 and self.s_w[p] > 0 :
    				count += 1
    			else :
    				count        = 0
    				self.s_w[p] += 1
    				k           += 1
    							# 選択に失敗した場合の処理
    		if self.dup_s == 0 and k < self.size :
    			i1 = 0
    			while i1 < self.size+self.max_ch and k < self.size :
    				if self.pi_w[i1] > 1 and self.s_w[i1] == 0 :
    					self.s_w[i1]  = 1
    					k            += 1
    				i1 += 1
    							# 複数回選択されたものの処理
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.s_w[i1] == 0 :
    				self.pi_w[i1] = 0
    	
    		for i1 in range(0, self.size+self.max_ch) :
    			if self.s_w[i1] > 0 :
    				if self.s_w[i1] > 1 :
    					for i2 in range(2, self.s_w[i1]+1) :
    						k            = self.Position(-1)
    						self.len[k]  = self.len[i1]
    						self.pi_w[k] = 2
    						self.pi[k]   = self.pi[i1]
    						for i3 in range(0, self.len[i1]) :
    							self.ind[k][i3] = self.ind[i1][i3]
    	
    #######################
    # クラスFunctionの定義
    #######################
    
    class Function ( Species ) :
    
    	######################################
    	# コンストラクタ
    	#      name1 : Species定義ファイル名
    	#      name2 : Function定義ファイル名
    	######################################
    
    	def __init__(self, name1, name2) :
    	
    		Species.__init__(self, name1)   # 親のコンストラクタ
    						# 基本データの入力
    		inn = open(name2, "r")
    	
    		s = inn.readline().split()
    		self.out_lvl = int(s[1])   # 出力レベル
    		                       #   =0 : 最終出力だけ
    		                       #   n>0 : n世代毎に出力(負の時はファイル)
    		self.out_m   = int(s[3])  # 出力方法
    		                      #   =0 : すべてを出力
    		                      #   =1 : 最大適応度の個体だけを出力
    
    		s = inn.readline().split()
    		self.o_file = s[1]   # 出力ファイル名
    		self.out_d  = int(s[3])   # 表示間隔
    
    		s = inn.readline().split()
    		self.kosa_m   = int(s[1])   # 交叉方法
    		                       #   =-1 : 交叉を使用しない
    		                       #   =0 : 親のコピー
    		                       #   =1 : 多点交叉
    		                       #   =2 : 一様交叉
    		                       #   =3 : 平均化交叉
    		self.kosa     = float(s[3])   # 交叉確率
    		self.k_point  = int(s[5])   # 交差点の数(負の時は,1から-k_point間のランダム)
    		self.k_vr     = int(s[7])   # =0 : 両親とも同じ位置で交叉
    		                       # =1 : 両親が異なる位置で交叉(遺伝子長は可変)
    		self.k_method = int(s[9])   # 交叉の時の親の選択方法
    		                       #   =-1 : ランダム
    		                       #   =0 : 適応度をそのまま使用
    		                       #   =1 : 最小値からの差(ただし,α以下の場合はα)
    		                       #   =2 : 評価値に順位をつけ,減少率βで線形化
    		self.k_bias   = float(s[11])   # α,または,method=2の場合は初期値
    		self.k_step   = float(s[13])   # β
    
    		s = inn.readline().split()
    		self.mute_m = int(s[1])   # 突然変異方法
    		                       #   =-1 : 突然変異を使用しない
    		                       #   =0 : 対立遺伝子への置換
    		                       #   =1 : 移動
    		                       #   =2 : 逆位
    		                       #   =3 : スクランブル
    		                       #   =4 : 転座
    		                       #   =5 : 重複
    		                       #   =6 : 摂動
    		self.mute   = float(s[3])   # 突然変異率
    		self.wd     = int(s[5])   # 突然変異に使用する部分遺伝子長
    		self.m_mean = float(s[7])   # 摂動の平均値
    		self.m_std  = float(s[9])   # 摂動の標準偏差
    
    		s = inn.readline().split()
    		self.elite    = int(s[1])   # エリート選択で残す数
    		self.s_method = int(s[3])   # ルーレット板の作成方法
    		                       #   =0 : 適応度をそのまま使用
    		                       #   =1 : 最小値からの差(ただし,α以下の場合はα)
    		                       #   =2 : 評価値に順位をつけ,減少率βで線形化
    		self.s_bias   = float(s[5])   # α,または,s_method=2の場合は初期値
    		self.s_step   = float(s[7])   # β
    
    		s = inn.readline().split()
    		self.max_gen = int(s[1])   # 最大世代交代数
    	
    		self.cv = 1.0 / (pow(2.0, float(self.max_len)) - 1.0)   # 2進数を10進数の変換する係数
    	
    		inn.close()
    	
    	###############
    	# 全体の制御
    	###############
    
    	def Control(self) :
    	
    		gen = 1
    						# 初期集団の発生
    		self.Init_std()
    						# 評価
    		self.Adap()
    						# 出力
    		print("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean))
    	
    		if abs(self.out_lvl) > 0 :
    			self.Output(gen)
    						# 世代交代
    		for gen in range(2, self.max_gen+1) :
    							# 交叉
    			if self.kosa_m == 0 :
    				C_copy()   # 親のコピー
    			elif self.kosa_m == 1 :
    				self.C_point(self.kosa, self.k_point)   # 多点交叉
    			elif self.kosa_m == 2 :
    				self.C_uniform(self.kosa)   # 一様交叉
    			elif self.kosa_m == 3 :
    				self.C_mean(self.kosa)   # 平均化交叉
    							# 突然変異
    			if self.mute_m == 0 :
    				self.M_alle(self.mute)   # 対立遺伝子への置換
    			elif self.mute_m == 1 :
    				self.M_move(self.mute)   # 移動
    			elif self.mute_m == 2 :
    				self.M_inv(self.mute, self.wd)   # 逆位
    			elif self.mute_m == 3 :
    				self.M_scram(self.mute, self.wd)   # スクランブル
    			elif self.mute_m == 4 :
    				self.M_chg(self.mute, self.wd)   # 転座
    			elif self.mute_m == 5 :
    				self.M_dup(self.mute, self.wd)   # 重複
    			elif self.mute_m == 6 :
    				self.M_per(self.mute, self.wd, self.m_mean, self.m_std)   # 摂動
    							# 適応度
    			self.Adap()
    							# 淘汰
    			self.S_roul(self.elite)
    							# 出力
    			if gen%self.out_d == 0 :
    				print("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean))
    	
    			if abs(self.out_lvl) > 0 :
    				if gen%abs(self.out_lvl) == 0 :
    					self.Output(gen)
    	
    		gen        -= 1
    		k1          = self.out_m
    		self.out_m  = 0
    		print("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean))
    		self.Output(gen)
    		self.out_m = k1
    
    	################
    	# 適応度の計算
    	################
    
    	def Adap(self) :
    	
    		n          = 0
    		self.max   = 0.0
    		self.max_n = -1
    		self.mean  = 0.0
    	
    		for i1 in range(0, self.size+self.max_ch) :
    	
    			if self.pi_w[i1] == 1 :
    				x = 0.0
    				y = 0.0
    				for i2 in range(self.len[i1]-1, -1, -1) :
    					if self.ind[i1][i2] > 0 :
    						x += pow(2.0, y)
    					y += 1.0
    				x             *= self.cv
    				self.pi[i1]    = sin(3.0*x) + 0.5 * sin(9.0*x) + sin(15.0*x+50.0)
    				self.pi_w[i1]  = 2
    	
    			if self.pi_w[i1] > 0 :
    				self.mean += self.pi[i1]
    				n += 1
    				if self.max_n < 0 or self.pi[i1] > self.max :
    					self.max   = self.pi[i1]
    					self.max_n = i1
    	
    		self.mean /= n
    	
    	#############################
    	# 結果の出力
    	#      gen : 現在の世代番号
    	#############################
    
    	def Output(self, gen) :
    	
    		k  = 0
    		pr = -1
    
    		if self.out_lvl >= 0 :
    			print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ", end=" ")
    			pr = int(input())
    	
    		if pr != 0 :
    						# 出力先の決定と評価値の出力
    			if pr > 0 :
    				out = sys.stdout
    				input("")
    			else :
    				now = datetime.today().time().isoformat()
    				out = open(self.o_file, "a")
    				out.write("***世代 " + str(gen) + " 適応度 max " + str(self.max) + " (" + str(self.max_n) + ") mean " + str(self.mean) + " 時間 " + now + "\n")
    						# 詳細出力
    			for i1 in range(0, self.size+self.max_ch) :
    				if (self.pi_w[i1] > 1) and (self.out_m == 0 or (self.out_m == 1 and i1 == self.max_n)) :
    					out.write(str(i1) + " allele")
    					for i2 in range(0, self.len[i1]) :
    						out.write(" " + str(self.ind[i1][i2]))
    					x = 0.0
    					y = 0.0
    					for i2 in range(self.len[i1]-1, -1, -1) :
    						if self.ind[i1][i2] > 0 :
    							x += pow(2.0, y)
    						y += 1.0
    					x *= self.cv
    					out.write(" x " + str(x) + " y " + str(self.pi[i1]) + "\n")
    					if pr > 0 :
    						k += 1
    						if k == pr :
    							input("")
    							k = 0
    	
    			if pr < 0 :
    				out.close()
    
    				# 入力ミス
    if len(sys.argv) <= 1 :
    	print("***error  ファイル名を入力して下さい")
    				# 入力OK
    else :
    					# データの数と入力データファイル名の入力
    	inn     = open(sys.argv[1], "r")
    
    	ss      = inn.readline()
    	n       = int(ss)   # データの数
    	i_file1 = []
    	i_file2 = []
    
    	for i1 in range(0, n) :
    		s = inn.readline().split()
    		i_file1.append(s[0])
    		i_file2.append(s[1])
    
    	inn.close()
    					# 実行(乱数の初期値を変える)
    	for i1 in range(0, n) :
    
    		print("\n+++++ケース " + str(i1+1) + "+++++")
    		seed(1000 * i1 + 1234567);
    
    		fn = Function(i_file1[i1], i_file2[i1])
    
    		fn.Control()
    
    """
    ------------------ケーススタディデータ(data_cf.txt)------
    3
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    
    ------------------Species記述データ(data1_f.txt)---------
    対立遺伝子上限 1 対立遺伝子下限 0
    最大遺伝子長 15 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 1 個体の重複(同じ染色体の個体) 0
    集団サイズ 20 子供 20
    
    ------------------Function記述データ(data2_f.txt)--------
    出力レベル(負はファイル) 20 出力方法(0:すべて,1:最大) 0
    出力ファイル名 out1.txt 表示間隔 1
    交叉方法 1 交叉確率 1.0 点 2 位置 0 方法 1 バイアス 0 ステップ 1
    突然変異方法 0 突然変異率 0.05 幅 1 平均 0.0 標準偏差 1.0
    エリート 2 方法 1 バイアス 0 ステップ 1
    最大世代交代数 200
    """
    			

  6. C#

    TSP
    /***********************************/
    /* 遺伝的アルゴリズムによるTSPの解 */
    /*      coded by Y.Suganuma        */
    /***********************************/
    using System;
    using System.IO;
    
    /***********************/
    /* クラスSpeciesの定義 */
    /***********************/
    class Species {
    
    	protected double max;   // 最大適応度
    	protected double mean;   // 平均適応度
    	protected double [] pi;   // 適応度
    	protected double [] ro;   // ルーレット板
    	protected int allele_u;   // 対立遺伝子上限
    	protected int allele_l;   // 対立遺伝子下限
    	protected int size;   // 個体総数
    	protected int max_ch;   // 子供の数の最大値
    	protected int max_len;   // 最大遺伝子長
    	protected int min_len;   // 最小遺伝子長(負の時は,最大遺伝子長で固定)
    	protected int max_n;   // 最大適応度の個体番号
    	protected int dup_a;   // 遺伝子の重複
                               //   =0 : 重複を許さない
                               //   =1 : 重複を許す
    	protected int dup_s;   // 個体の重複(同じ染色体の個体)
                               //   =0 : 重複を許さない
                               //   =1 : 重複を許す
    	protected int [][] ind;   // 集団(個体の集まり)
    	protected int [] len;   // 各個体の遺伝子長
    	protected int [] kou1;   // 交叉・突然変異用作業場所1
    	protected int [] kou2;   // 交叉・突然変異用作業場所2
    	protected int [] s_w;   // 淘汰用指標(選択された回数)
    	protected int [][] edge;   // エッジ組み替え交叉用ワークエリア
    	protected byte [] pi_w;   // 適応度計算指標
                                  //   =0 : 未使用
                                  //   =1 : 適応度計算前(突然変異はこの個体だけに適用)
                                  //   =2 : 適応度計算済み(交叉時に親とみなす)
    	protected Random rn;   // 乱数
    
    	/***********************************/
    	/* 正規分布変量の発生              */
    	/*      m : 平均                   */
    	/*      s : 標準偏差               */
    	/*           return : 正規分布変量 */
    	/***********************************/
    	double norm_d(double m, double s)
    	{
    		double x = 0.0;
    		for (int i1 = 0; i1 < 12; i1++)
    			x += rn.NextDouble();
    
    		x = s * (x - 6.0) + m;
    
    		return x;
    	}
    
    	/**************************************************/
    	/* 場所を探す                                     */
    	/*      n : >=0 : n番目の親を捜す                 */
    	/*          -1 : 空いている場所を探す             */
    	/*      return : 親の場所,または,空いている場所 */
    	/*               (存在しないときは負の値)       */
    	/**************************************************/
    	int 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) {
    				Console.WriteLine("***error  空いている場所がない --Position--");
    				Environment.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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      bias : α,または,method=2の場合は初期値                  */
    	/*      step : β                                                  */
    	/*      return : 個体番号                                          */
    	/*******************************************************************/
    	int 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 (Math.Abs(sum) > 1.0e-10) {
    					sum = 1.0 / Math.Abs(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  = rn.NextDouble();
    		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;
    	}
    
    	/****************************/
    	/* コンストラクタ           */
    	/*      name : ファイル名   */
    	/*      seed : 乱数の初期値 */
    	/****************************/
    	public Species (String name, int seed)
    	{
    		string[] lines = File.ReadAllLines(name);
    		char[] charSep = new char[] {' '};
    				//
    				// データの入力
    				//
    						// 1行目
    		string[] str = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		allele_u     = int.Parse(str[1]);
    		allele_l     = int.Parse(str[3]);
    						// 2行目
    		str     = lines[1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		max_len = int.Parse(str[1]);
    		min_len = int.Parse(str[3]);
    						// 3行目
    		str   = lines[2].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		dup_a = int.Parse(str[1]);
    		dup_s = int.Parse(str[3]);
    						// 4行目
    		str    = lines[3].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		size   = int.Parse(str[1]);
    		max_ch = int.Parse(str[3]);
    				//
    				// データのチェック
    				//
    		if (size <= 0) {
    			Console.WriteLine("***error  個体総数≦0 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		if (max_ch < 0) {
    			Console.WriteLine("***error  子供の数<0 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		if (max_len <= 0 || min_len == 0) {
    			Console.WriteLine("***error  遺伝子長≦0 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		if (max_len < min_len) {
    			Console.WriteLine("***error  最大遺伝子長<最小遺伝子長 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		if (allele_u <= allele_l) {
    			Console.WriteLine("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		int kind = allele_u - allele_l + 1;
    		if (dup_a == 0 && max_len > kind) {
    			Console.WriteLine("***error  遺伝子の重複を防ぐことはできない (Constructor)");
    			Environment.Exit(1);
    		}
    				//
    				// 領域の確保
    				//
    		int num  = size + max_ch;
    
    		ind  = new int [num][];
    		for (int i1 = 0; i1 < num; i1++)
    			ind[i1]  = new int [max_len];
    		edge = new int [max_len][];
    		for (int 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 byte [num];
    				//
    				// 乱数の初期設定
    				//
    		rn = new Random(seed);
    	}
    
    	/********************/
    	/* 標準的な初期設定 */
    	/********************/
    	protected void 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)(rn.NextDouble() * (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)(rn.NextDouble() * (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 Out_std(int sw, int out_m, int gen, String name)
    	{
    		int pr = -1;
    		if (sw >= 0) {
    			Console.Write("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = int.Parse(Console.ReadLine());
    		}
    
    		if (pr != 0) {
    
    			StreamWriter OUT = new StreamWriter(name, true);
    						// 出力先の決定と評価値の出力
    			if (pr < 0) {
    				DateTime now = DateTime.Now;   // 現在時刻の獲得
    				OUT.WriteLine("***世代 " + gen + " 適応度 max " + max +
                                  " (" + max_n + ") mean " + mean + " 時間 " + now);
    			}
    						// 詳細出力
    			int k = 0;
    			for (int i1 = 0; i1 < size+max_ch; i1++) {
    				if ((pi_w[i1] > 1) && (out_m ==0 || out_m == 1 && i1 == max_n)) {
    					if (pr < 0) {
    						OUT.Write(i1 + " allele");
    						for (int i2 = 0; i2 < len[i1]; i2++)
    							OUT.Write(" " + ind[i1][i2]);
    						OUT.WriteLine(" value " + pi[i1]);
    					}
    					else {
    						Console.Write(i1 + " allele");
    						for (int i2 = 0; i2 < len[i1]; i2++)
    							Console.Write(" " + ind[i1][i2]);
    						Console.WriteLine(" value " + pi[i1]);
    					}
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							Console.ReadLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			OUT.Close();
    		}
    	}
    
    	/*******************************************************************/
    	/* 交叉(親のコピー)                                              */
    	/*      method : =2 : 有性(2つの親から2つの子供)               */
    	/*               =1 : 1つの親から1つの子供                       */
    	/*      pair : method=2 の時は親のペア数                           */
    	/*             method=1 の時は親の数(=子供の数)                 */
    	/*      k_method : 選択方法                                        */
    	/*                 =-1 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_copy(int method, int pair, int k_method, double k_bias,
                    double k_step)
    	{
    	   int i1, i2, i3, k, p, p1, p2 = 0, 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) {
    				Console.WriteLine("***error  子供が多すぎる (C_copy)");
    				Environment.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 : 交叉点の数                                       */
    	/*                (負の時は,1から-k_point間のランダム)          */
    	/*      k_vr : =0 : 両親とも同じ位置で交叉                         */
    	/*             =1 : 両親が異なる位置で交叉(遺伝子長は可変)       */
    	/*      k_method : 選択方法                                        */
    	/*                 =-1 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void 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 = 0,
                pair, sw, t11, t12, t21, t22;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    
    		if (dup_a == 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_point)");
    			Environment.Exit(1);
    		}
    
    		abs_p = Math.Abs(k_point);
    		if (abs_p == 0 || abs_p > max_len-1 || min_len > 0 && abs_p > min_len-1) {
    			Console.WriteLine("***error  交叉点の数が不適当 (C_point)");
    			Environment.Exit(1);
    		}
    
    		if (k_vr > 0 && min_len < 0) {
    			Console.WriteLine("***error  遺伝子長は可変でなければならない (C_point)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		num = k_point;
    
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.NextDouble() * 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)(rn.NextDouble() * (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)(rn.NextDouble() * (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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_uniform(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, k1, k2, p1, p2 = 0, pair, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    
    		if (dup_a == 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_uniform)");
    			Environment.Exit(1);
    		}
    
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_uniform)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 (rn.NextDouble() > 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_mean(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, k, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_mean)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < max_ch; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(1, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_cycle(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_cycle)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_cycle)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.NextDouble() * 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_part(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, i3, k1, k2, lv, p, pair, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_part)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_part)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.NextDouble() * 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void 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 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_seq)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_seq)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.NextDouble() * (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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_useq(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, i4, k1, k2, p, pair, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_useq)\n");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_useq)\n");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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]    = (rn.NextDouble() < 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_upos(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_upos)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_upos)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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] = (rn.NextDouble() < 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_edge(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, i3, i4, i5, k, kk, k0 = 0, k1, k2, min, num,
    	        p, pair, p1, p2 = 0, sw;
    		int[] e = new int [2];
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_edge)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_edge)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(1, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 = (rn.NextDouble() > 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)(rn.NextDouble() * 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) {
    								Console.WriteLine("***error  invalid data (C_edge)");
    								Environment.Exit(1);
    							}
    							else {
    								k1 = (int)(rn.NextDouble() * 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つのペアーに対する交差回数                 */
    	/*************************************************************/
    	protected void C_sub(double kosa, int count)
    	{
    		int i1, i2, i3, i4, i5, k1, k2, k3, k4, p1, p2,
    	        t11, t12 = 0, t21, t22 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		if ((4*count*size*(size-1)) > max_ch) {
    			Console.WriteLine("***error  子供が多すぎる (C_sub)");
    			Environment.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 (rn.NextDouble() > kosa)
    							C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    						else {
    							// 交叉回数の制御
    							for (i3 = 0; i3 < count; i3++) {
    								// 交叉位置の決定(点の後ろで交叉)
    									// 親1の交叉位置
    								t11 = (int)(rn.NextDouble() * len[p1]);
    								if (t11 > (len[p1]-1))
    									t11 = len[p1] - 1;
    								sw = 0;
    								while (sw == 0) {
    									t12 = (int)(rn.NextDouble() * 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 : 突然変異率               */
    	/**************************************/
    	protected void M_alle(double pr)
    	{
    		int i1, i2, lid;
    				//
    				// データのチェックと初期設定
    				//
    		if (dup_a == 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_alle)");
    			Environment.Exit(1);
    		}
    				//
    				// 実行
    				//
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    			if (pi_w[i1] == 1) {
    				for (i2 = 0; i2 < len[i1]; i2++) {
    					if (rn.NextDouble() <= pr) {
    						lid = (int)(rn.NextDouble() * (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 : 突然変異率                                               */
    	/**********************************************************************/
    	protected void M_move(double pr)
    	{
    		int i1, i2, ld, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    				//
    				// 位置の決定
    				//
    						// p1
    				p1 = (int)(rn.NextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    						// p2
    				sw = 0;
    				while (sw == 0) {
    					p2 = (int)(rn.NextDouble() * 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 : 幅をランダム                          */
    	/********************************************************/
    	protected void M_inv(double pr, int wd)
    	{
    		int i1, lid, p, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    				//
    				// 区間の決定
    				//
    				if (wd == 0) {
    					p1 = (int)(rn.NextDouble() * len[i1]);
    					if (p1 >= len[i1])
    						p1 = len[i1] - 1;
    					sw = 0;
    					while (sw == 0) {
    						p2 = (int)(rn.NextDouble() * 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)(rn.NextDouble() * 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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_scram(double pr, int wd)
    	{
    		int i1, i2, ld, p, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    				//
    				// 区間の決定
    				//
    				if (wd == 0) {
    					p1 = (int)(rn.NextDouble() * len[i1]);
    					if (p1 >= len[i1])
    						p1 = len[i1] - 1;
    					sw = 0;
    					while (sw == 0) {
    						p2 = (int)(rn.NextDouble() * 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)(rn.NextDouble() * len[i1]);
    					p2 = p1 + wd - 1;
    					if (p2 >= len[i1])
    						p2 = len[i1] - 1;
    				}
    				//
    				// 実行
    				//
    				for (i2 = p1; i2 <= p2; i2++) {
    					p = (int)(rn.NextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_chg(double pr, int wd)
    	{
    		int i1, i2, ld, p, p1, p2, p3 = 0, p4, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    				// 
    				// 区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    				//
    						// p1
    				p1 = (int)(rn.NextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    						// p3
    				sw = 0;
    				while (sw == 0) {
    					p3 = (int)(rn.NextDouble() * 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)(rn.NextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_dup(double pr, int wd)
    	{
    		int i1, i2, p, p1, p2, p3 = 0, p4, sw;
    				//
    				// データのチェック
    				//
    		if (dup_a == 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_dup)");
    			Environment.Exit(1);
    		}
    				//
    				// 実行
    				//
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    						// 区間の決定([p1,p2]を[p3,p4]にコピー)
    							// p1
    				p1 = (int)(rn.NextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    							// p3
    				sw = 0;
    				while (sw == 0) {
    					p3 = (int)(rn.NextDouble() * len[i1]);
    					if (p3 >= len[i1])
    						p3 = len[i1] - 1;
    					if (p3 != p1)
    						sw = 1;
    				}
    							// 区間を決める
    				if (p3 > p1) {
    					p4 = (wd == 0) ? (int)(rn.NextDouble() * (len[i1] - p3)) + p3 :
                                         p3 + wd - 1;
    					if (p4 >= len[i1])
    						p4 = len[i1] - 1;
    					p2 = p1 + (p4 - p3);
    				}
    				else {
    					p2 = (wd == 0) ? (int)(rn.NextDouble() * (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 : 正規分布                        */
    	/*               =1 : 一様分布                        */
    	/*      m : 平均または一様分布の下限                  */
    	/*      s : 標準偏差または一様分布の上限              */
    	/******************************************************/
    	protected void M_per(double pr, int method, double m, double s)
    	{
    		double w, wd = 0.0, x1;
    		int i1, i2;
    				//
    				// データのチェックと初期設定
    				//
    		if (dup_a == 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_per)");
    			Environment.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 (rn.NextDouble() <= pr) {
    						if (method == 0)
    							w = norm_d(m, s);
    						else {
    							w = rn.NextDouble() * wd;
    							if (rn.NextDouble() < 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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_ins(double pr, int wd)
    	{
    		int i1, i2, l, ld, p;
    				//
    				// データのチェック
    				//
    		if (dup_a == 0 || min_len < 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_ins)");
    			Environment.Exit(1);
    		}
    				//
    				// 実行
    				//
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    						// 挿入位置の決定
    				p = (int)(rn.NextDouble() * (len[i1]+1));
    				if (p > len[i1])
    					p = len[i1];
    						// 挿入する遺伝子長の決定
    				l = (wd == 0) ? (int)(rn.NextDouble() * (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)(rn.NextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_del(double pr, int wd)
    	{
    		int i1, i2, l, max, p;
    				//
    				// データのチェック
    				//
    		if (dup_a == 0 || min_len < 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_del)");
    			Environment.Exit(1);
    		}
    				//
    				// 実行
    				//
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    						// 削除位置の決定
    				p = (int)(rn.NextDouble() * 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)(rn.NextDouble() * 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)                                       */
    	/*********************************************************************/
    	protected void 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) {
    			Console.WriteLine("***error  エリートで残す数が多すぎる (S_roul)");
    			Environment.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) {
    			Console.WriteLine("***error  残す個体がない (S_roul)");
    			Environment.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];
    					}
    				}
    			}
    		}
    	}
    }
    
    /*******************/
    /* クラスTSPの定義 */
    /*******************/
    class TSP : Species {
    
    	int max_gen;   // 最大世代交代数
    	int kosa_m;   // 交叉方法
                      //   =-1 : 交叉を使用しない
                      //   =0 : 親のコピー
                      //   =1 : 循環交叉
                      //   =2 : 部分的交叉
                      //   =3 : 順序交叉
                      //   =4 : 一様順序交叉
                      //   =5 : 一様位置交叉
                      //   =6 : エッジ組み替え交叉
                      //   =7 : サブツアー交叉
    	double kosa;   // 交叉確率
    	int k_point;   // 交差点の数(負の時は,1から-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 : 最大適応度の個体だけを出力
    	String o_file;   // 出力ファイル名
    	int n_city;   // 都市の数
    	int [][] rg;   // 都市間の距離
    	int kinbo;   // 近傍探索(0:行わない,1:行う)
    	int neib;   // 近傍(2 or 3)
    	int sel;   // エッジの選択方法
                   //   =0 : 最良のものを選択
                   //   =1 : 最初のものを選択
    
    	int [][] city;   //都市の位置データ
    
    	/***************************************/
    	/* コンストラクタ                      */
    	/*      name1 : Species定義ファイル名  */
    	/*      name2 : TSP定義ファイル名      */
    	/*      seed : 乱数の初期値            */
    	/***************************************/
    	public TSP (String name1, String name2, int seed) : base(name1, seed)
    	{
    		string[] lines = File.ReadAllLines(name2);
    		char[] charSep = new char[] {' '};
    					// 基本データの入力
    						// 1行目
    		string[] str = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		out_lvl      = int.Parse(str[1]);
    		out_m        = int.Parse(str[3]);
    						// 2行目
    		str    = lines[1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		o_file = str[1];
    		out_d  = int.Parse(str[3]);
    						// 3行目
    		str      = lines[2].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		kosa_m   = int.Parse(str[1]);
    		kosa     = double.Parse(str[3]);
    		k_point  = int.Parse(str[5]);
    		k_vr     = int.Parse(str[7]);
    		k_method = int.Parse(str[9]);
    		k_bias   = double.Parse(str[11]);
    		k_step   = double.Parse(str[13]);
    						// 4行目
    		str    = lines[3].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		mute_m = int.Parse(str[1]);
    		mute   = double.Parse(str[3]);
    		wd     = int.Parse(str[5]);
    		m_mean = double.Parse(str[7]);
    		m_std  = double.Parse(str[9]);
    						// 5行目
    		str      = lines[4].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		elite    = int.Parse(str[1]);
    		s_method = int.Parse(str[3]);
    		s_bias   = double.Parse(str[5]);
    		s_step   = double.Parse(str[7]);
    						// 6行目
    		str     = lines[5].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		n_city  = int.Parse(str[1]);
    		max_gen = int.Parse(str[3]);
    						// 7行目
    		str   = lines[6].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		kinbo = int.Parse(str[1]);
    		neib  = int.Parse(str[3]);
    						// 8行目
    		str = lines[7].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		sel = int.Parse(str[1]);
    
    		if (kinbo > 0 && neib != 2 && neib != 3) {
    			Console.WriteLine("***error  近傍の値が不適当");
    			Environment.Exit(1);
    		}
    
    		if (n_city != max_len) {
    			Console.WriteLine("***error  都市数が不適当");
    			Environment.Exit(1);
    		}
    					// 都市の位置データ
    		city = new int [n_city][];
    		for (int i1 = 0; i1 < n_city; i1++) {
    			city[i1]    = new int [2];
    			str         = lines[i1+8].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    			city[i1][0] = int.Parse(str[0]);
    			city[i1][1] = int.Parse(str[1]);
    		}
    					// 距離テーブル
    		rg = new int [n_city][];
    
    		for (int i1 = 0; i1 < n_city; i1++) {
    			rg[i1] = new int [n_city];
    			for (int i2 = i1+1; i2 < n_city; i2++) {
    				double x   = city[i2][0] - city[i1][0];
    				double y   = city[i2][1] - city[i1][1];
    				rg[i1][i2] = (int)(Math.Sqrt(x * x + y * y) + 0.5);
    			}
    		}
    
    		for (int i1 = 1; i1 < n_city; i1++) {
    			for (int i2 = 0; i2 < i1; i2++)
    				rg[i1][i2] = rg[i2][i1];
    		}
    	}
    
    	/**************/
    	/* 全体の制御 */
    	/**************/
    	public void Control()
    	{
    		int gen = 1;
    						// 初期集団の発生
    		Init_std();
    						// 評価
    		if (kinbo > 0)
    			Kinbo();
    		else
    			Adap();
    						// 画面表示
    		Console.WriteLine("***世代 " + gen + " 適応度 max " + max +
                              " (" + max_n + ") mean " + mean);
    						// 出力
    		if (Math.Abs(out_lvl) > 0)
    			Output(gen);
    						// 世代交代
    		for (gen = 2; gen <= max_gen; gen++) {
    							// 交叉
    			switch (kosa_m) {
    				case -1:
    					break;
    				case 0:
    					C_copy(2, max_ch/2, k_method, k_bias, k_step);   // 親のコピー
    					break;
    				case 1:
    					C_cycle(kosa, k_method, k_bias, k_step);   // 循環交叉
    					break;
    				case 2:
    					C_part(kosa, k_method, k_bias, k_step);   // 部分的交叉
    					break;
    				case 3:
    					C_seq(kosa, k_method, k_bias, k_step);   // 順序交叉
    					break;
    				case 4:
    					C_useq(kosa, k_method, k_bias, k_step);   // 一様順序交叉
    					break;
    				case 5:
    					C_upos(kosa, k_method, k_bias, k_step);   // 一様位置交叉
    					break;
    				case 6:
    					C_edge(kosa, k_method, k_bias, k_step);   // エッジ組み替え交叉
    					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, wd);   // 逆位
    					break;
    				case 2:
    					M_scram(mute, wd);   // スクランブル
    					break;
    				case 3:
    					M_chg(mute, wd);   // 転座
    					break;
    				default:
    					break;
    			}
    							// 適応度
    			if (kinbo > 0)
    				Kinbo();
    			else
    				Adap();
    							// 淘汰
    			S_roul(elite, s_method, s_bias, s_step);
    							// 表示
    			if (gen%out_d == 0)
    				Console.WriteLine("***世代 " + gen + " 適応度 max " + max +
                                      " (" + max_n + ") mean " + mean);
    			if (Math.Abs(out_lvl) > 0) {
    				if (gen%Math.Abs(out_lvl) == 0)
    					Output(gen);
    			}
    		}
    
    		gen--;
    		int k1 = out_m;
    		out_m  = 0;
    		Console.WriteLine("***世代 " + gen + " 適応度 max " + max +
                              " (" + max_n + ") mean " + mean);
    		Output(gen);
    		out_m = k1;
    	}
    
    	/*********************************/
    	/* 距離の計算                    */
    	/*      n_c : 都市の数           */
    	/*      p : 都市番号             */
    	/*      return : 距離(負)      */
    	/*********************************/
    	int Kyori(int n_c, int [] p)
    	{
    		int range = 0;
    		int n1    = p[0];
    		int n2;
    
    		for (int 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 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 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[0];
    	
    		n3  = (int)(rn.NextDouble() * (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[0] = max;
    			for (i1 = 0; i1 < n_city; i1++)
    				seq[i1] = kou2[i1];
    		}
    	
    		return sw;
    	}
    	
    	/**************/
    	/* 近傍の探索 */
    	/**************/
    	void Kinbo()
    	{
    		int i1, k = 0, sw;
    		int[] r = new int [1];
    		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[0]     = Kyori(len[i1], ind[i1]);
    				while (sw > 0)
    					sw = Change(len[i1], ind[i1], r);
    				pi[i1] = r[0];
    			}
    			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 Output(int gen)
    	{
    		int pr = -1;
    		if (out_lvl >= 0) {
    			Console.Write("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = int.Parse(Console.ReadLine());
    		}
    
    		if (pr != 0) {
    
    			StreamWriter OUT = new StreamWriter(o_file, true);
    						// 出力先の決定と評価値の出力
    			if (pr < 0) {
    				DateTime now = DateTime.Now;   // 現在時刻の獲得
    				OUT.WriteLine("***世代 " + gen + " 適応度 max " + max +
                                  " (" + max_n + ") mean " + mean + " 時間 " + now);
    			}
    					// 巡回順序の出力
    			if (out_m == 0) {
    				int k = 0;
    				for (int i1 = 0; i1 < len[max_n]; i1++) {
    					int n = ind[max_n][i1];
    					if (pr < 0)
    						OUT.WriteLine(n + " " + city[n][0] + " " + city[n][1]);
    					else
    						Console.WriteLine(n + " " + city[n][0] + " " + city[n][1]);
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							Console.ReadLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			OUT.Close();
    		}
    	}
    }
    
    /****************/
    /* main program */
    /****************/
    class Program
    {
    	static void Main(String[] args)
    	{
    						// 入力ミス
    		if (args.Length == 0)
    			Console.WriteLine("***error  ケーススタディファイル名を入力して下さい\n");
    						// 入力OK
    		else {
    							// 入力データファイル名の入力
    			String[] lines   = File.ReadAllLines(args[0]);
    			int n            = int.Parse(lines[0]);   // 問題の数
    			String[] i_file1 = new String [n];
    			String[] i_file2 = new String [n];
    
    			char[] charSep = new char[] {' '};
    			for (int i1 = 0; i1 < n; i1++) {
    				string[] str = lines[i1+1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    				i_file1[i1] = str[0];
    				i_file2[i1] = str[1];
    			}
    							// 実行(乱数の初期値を変える)
    			for (int i1 = 0; i1 < n; i1++) {
    				Console.WriteLine();
    				Console.WriteLine("+++++ケース " + (i1+1) + "+++++\n");
    								// 入力と初期設定
    				TSP tsp = new TSP (i_file1[i1], i_file2[i1], 1000 * i1 + 1234567);
    								// 最適化
    				tsp.Control();
    			}
    		}
    	}
    }
    
    //----------------ケーススタディデータ(data_ct.txt)------
    /*
    3
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    data1_t.txt data2_t.txt
    */
    
    //---------------Species記述データ(data1_t.txt)---------
    /*
    対立遺伝子上限 9 対立遺伝子下限 0
    最大遺伝子長 10 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 0 個体の重複(同じ染色体の個体) 0
    集団サイズ 10 子供 10
    */
    
    //---------------TSP記述データ(data2_t.txt)--------
    /*
    出力レベル(負はファイル) 10 出力方法(0:適応度+順番,1:適応度) 0
    出力ファイル名 out1.txt 表示間隔 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
    */
    			
    関数の最大値
    /********************************************************************/
    /* f(x) = sin(3.0*x) + 0.5 * sin(9.0*x) + sin(15.0*x + 50) の最大値 */
    /*      coded by Y.Suganuma                                         */
    /********************************************************************/
    using System;
    using System.IO;
    
    /***********************/
    /* クラスSpeciesの定義 */
    /***********************/
    class Species {
    
    	protected double max;   // 最大適応度
    	protected double mean;   // 平均適応度
    	protected double [] pi;   // 適応度
    	protected double [] ro;   // ルーレット板
    	protected int allele_u;   // 対立遺伝子上限
    	protected int allele_l;   // 対立遺伝子下限
    	protected int size;   // 個体総数
    	protected int max_ch;   // 子供の数の最大値
    	protected int max_len;   // 最大遺伝子長
    	protected int min_len;   // 最小遺伝子長(負の時は,最大遺伝子長で固定)
    	protected int max_n;   // 最大適応度の個体番号
    	protected int dup_a;   // 遺伝子の重複
                               //   =0 : 重複を許さない
                               //   =1 : 重複を許す
    	protected int dup_s;   // 個体の重複(同じ染色体の個体)
                               //   =0 : 重複を許さない
                               //   =1 : 重複を許す
    	protected int [][] ind;   // 集団(個体の集まり)
    	protected int [] len;   // 各個体の遺伝子長
    	protected int [] kou1;   // 交叉・突然変異用作業場所1
    	protected int [] kou2;   // 交叉・突然変異用作業場所2
    	protected int [] s_w;   // 淘汰用指標(選択された回数)
    	protected int [][] edge;   // エッジ組み替え交叉用ワークエリア
    	protected byte [] pi_w;   // 適応度計算指標
                                  //   =0 : 未使用
                                  //   =1 : 適応度計算前(突然変異はこの個体だけに適用)
                                  //   =2 : 適応度計算済み(交叉時に親とみなす)
    	protected Random rn;   // 乱数
    
    	/***********************************/
    	/* 正規分布変量の発生              */
    	/*      m : 平均                   */
    	/*      s : 標準偏差               */
    	/*           return : 正規分布変量 */
    	/***********************************/
    	double norm_d(double m, double s)
    	{
    		double x = 0.0;
    		for (int i1 = 0; i1 < 12; i1++)
    			x += rn.NextDouble();
    
    		x = s * (x - 6.0) + m;
    
    		return x;
    	}
    
    	/**************************************************/
    	/* 場所を探す                                     */
    	/*      n : >=0 : n番目の親を捜す                 */
    	/*          -1 : 空いている場所を探す             */
    	/*      return : 親の場所,または,空いている場所 */
    	/*               (存在しないときは負の値)       */
    	/**************************************************/
    	int 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) {
    				Console.WriteLine("***error  空いている場所がない --Position--");
    				Environment.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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      bias : α,または,method=2の場合は初期値                  */
    	/*      step : β                                                  */
    	/*      return : 個体番号                                          */
    	/*******************************************************************/
    	int 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 (Math.Abs(sum) > 1.0e-10) {
    					sum = 1.0 / Math.Abs(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  = rn.NextDouble();
    		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;
    	}
    
    	/****************************/
    	/* コンストラクタ           */
    	/*      name : ファイル名   */
    	/*      seed : 乱数の初期値 */
    	/****************************/
    	public Species (String name, int seed)
    	{
    		string[] lines = File.ReadAllLines(name);
    		char[] charSep = new char[] {' '};
    				//
    				// データの入力
    				//
    						// 1行目
    		string[] str = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		allele_u     = int.Parse(str[1]);
    		allele_l     = int.Parse(str[3]);
    						// 2行目
    		str     = lines[1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		max_len = int.Parse(str[1]);
    		min_len = int.Parse(str[3]);
    						// 3行目
    		str   = lines[2].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		dup_a = int.Parse(str[1]);
    		dup_s = int.Parse(str[3]);
    						// 4行目
    		str    = lines[3].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		size   = int.Parse(str[1]);
    		max_ch = int.Parse(str[3]);
    				//
    				// データのチェック
    				//
    		if (size <= 0) {
    			Console.WriteLine("***error  個体総数≦0 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		if (max_ch < 0) {
    			Console.WriteLine("***error  子供の数<0 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		if (max_len <= 0 || min_len == 0) {
    			Console.WriteLine("***error  遺伝子長≦0 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		if (max_len < min_len) {
    			Console.WriteLine("***error  最大遺伝子長<最小遺伝子長 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		if (allele_u <= allele_l) {
    			Console.WriteLine("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)");
    			Environment.Exit(1);
    		}
    
    		int kind = allele_u - allele_l + 1;
    		if (dup_a == 0 && max_len > kind) {
    			Console.WriteLine("***error  遺伝子の重複を防ぐことはできない (Constructor)");
    			Environment.Exit(1);
    		}
    				//
    				// 領域の確保
    				//
    		int num  = size + max_ch;
    
    		ind  = new int [num][];
    		for (int i1 = 0; i1 < num; i1++)
    			ind[i1]  = new int [max_len];
    		edge = new int [max_len][];
    		for (int 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 byte [num];
    				//
    				// 乱数の初期設定
    				//
    		rn = new Random(seed);
    	}
    
    	/********************/
    	/* 標準的な初期設定 */
    	/********************/
    	protected void 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)(rn.NextDouble() * (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)(rn.NextDouble() * (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 Out_std(int sw, int out_m, int gen, String name)
    	{
    		int pr = -1;
    		if (sw >= 0) {
    			Console.Write("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = int.Parse(Console.ReadLine());
    		}
    
    		if (pr != 0) {
    
    			StreamWriter OUT = new StreamWriter(name, true);
    						// 出力先の決定と評価値の出力
    			if (pr < 0) {
    				DateTime now = DateTime.Now;   // 現在時刻の獲得
    				OUT.WriteLine("***世代 " + gen + " 適応度 max " + max +
                                  " (" + max_n + ") mean " + mean + " 時間 " + now);
    			}
    						// 詳細出力
    			int k = 0;
    			for (int i1 = 0; i1 < size+max_ch; i1++) {
    				if ((pi_w[i1] > 1) && (out_m ==0 || out_m == 1 && i1 == max_n)) {
    					if (pr < 0) {
    						OUT.Write(i1 + " allele");
    						for (int i2 = 0; i2 < len[i1]; i2++)
    							OUT.Write(" " + ind[i1][i2]);
    						OUT.WriteLine(" value " + pi[i1]);
    					}
    					else {
    						Console.Write(i1 + " allele");
    						for (int i2 = 0; i2 < len[i1]; i2++)
    							Console.Write(" " + ind[i1][i2]);
    						Console.WriteLine(" value " + pi[i1]);
    					}
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							Console.ReadLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			OUT.Close();
    		}
    	}
    
    	/*******************************************************************/
    	/* 交叉(親のコピー)                                              */
    	/*      method : =2 : 有性(2つの親から2つの子供)               */
    	/*               =1 : 1つの親から1つの子供                       */
    	/*      pair : method=2 の時は親のペア数                           */
    	/*             method=1 の時は親の数(=子供の数)                 */
    	/*      k_method : 選択方法                                        */
    	/*                 =-1 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_copy(int method, int pair, int k_method, double k_bias,
                    double k_step)
    	{
    	   int i1, i2, i3, k, p, p1, p2 = 0, 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) {
    				Console.WriteLine("***error  子供が多すぎる (C_copy)");
    				Environment.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 : 交叉点の数                                       */
    	/*                (負の時は,1から-k_point間のランダム)          */
    	/*      k_vr : =0 : 両親とも同じ位置で交叉                         */
    	/*             =1 : 両親が異なる位置で交叉(遺伝子長は可変)       */
    	/*      k_method : 選択方法                                        */
    	/*                 =-1 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void 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 = 0,
                pair, sw, t11, t12, t21, t22;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    
    		if (dup_a == 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_point)");
    			Environment.Exit(1);
    		}
    
    		abs_p = Math.Abs(k_point);
    		if (abs_p == 0 || abs_p > max_len-1 || min_len > 0 && abs_p > min_len-1) {
    			Console.WriteLine("***error  交叉点の数が不適当 (C_point)");
    			Environment.Exit(1);
    		}
    
    		if (k_vr > 0 && min_len < 0) {
    			Console.WriteLine("***error  遺伝子長は可変でなければならない (C_point)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		num = k_point;
    
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.NextDouble() * 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)(rn.NextDouble() * (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)(rn.NextDouble() * (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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_uniform(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, k1, k2, p1, p2 = 0, pair, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    
    		if (dup_a == 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_uniform)");
    			Environment.Exit(1);
    		}
    
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_uniform)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 (rn.NextDouble() > 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_mean(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, k, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_mean)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < max_ch; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(1, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_cycle(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_cycle)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_cycle)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.NextDouble() * 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_part(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, i3, k1, k2, lv, p, pair, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_part)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_part)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.NextDouble() * 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void 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 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_seq)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_seq)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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)(rn.NextDouble() * (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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_useq(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, i4, k1, k2, p, pair, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_useq)\n");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_useq)\n");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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]    = (rn.NextDouble() < 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_upos(double kosa, int k_method, double k_bias, double k_step)
    	{
    	   int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch / 2;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_upos)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_upos)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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] = (rn.NextDouble() < 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 : ランダム                                  */
    	/*                 =0 : 適応度をそのまま使用                       */
    	/*                 =1 : 最小値からの差(ただし,α以下の場合はα) */
    	/*                 =2 : 評価値に順位をつけ,減少率βで線形化       */
    	/*      k_bias : α,または,method=2の場合は初期値                */
    	/*      k_step : β                                                */
    	/*******************************************************************/
    	protected void C_edge(double kosa, int k_method, double k_bias, double k_step)
    	{
    		int i1, i2, i3, i4, i5, k, kk, k0 = 0, k1, k2, min, num,
    	        p, pair, p1, p2 = 0, sw;
    		int[] e = new int [2];
    				//
    				// 初期設定とデータのチェック
    				//
    		pair = max_ch;
    	
    		if (dup_a != 0) {
    			Console.WriteLine("***error  交叉方法が不適当 (C_edge)");
    			Environment.Exit(1);
    		}
    	
    		if (min_len > 0) {
    			Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_edge)");
    			Environment.Exit(1);
    		}
    				//
    				// 交叉
    				//
    		for (i1 = 0; i1 < pair; i1++) {
    						// 交叉しない場合
    			if (rn.NextDouble() > kosa)
    				C_copy(1, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    			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 = (rn.NextDouble() > 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)(rn.NextDouble() * 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) {
    								Console.WriteLine("***error  invalid data (C_edge)");
    								Environment.Exit(1);
    							}
    							else {
    								k1 = (int)(rn.NextDouble() * 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つのペアーに対する交差回数                 */
    	/*************************************************************/
    	protected void C_sub(double kosa, int count)
    	{
    		int i1, i2, i3, i4, i5, k1, k2, k3, k4, p1, p2,
    	        t11, t12 = 0, t21, t22 = 0, sw;
    				//
    				// 初期設定とデータのチェック
    				//
    		if ((4*count*size*(size-1)) > max_ch) {
    			Console.WriteLine("***error  子供が多すぎる (C_sub)");
    			Environment.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 (rn.NextDouble() > kosa)
    							C_copy(2, 1, -1, 0.0, 0.0);
    						// 交叉する場合
    						else {
    							// 交叉回数の制御
    							for (i3 = 0; i3 < count; i3++) {
    								// 交叉位置の決定(点の後ろで交叉)
    									// 親1の交叉位置
    								t11 = (int)(rn.NextDouble() * len[p1]);
    								if (t11 > (len[p1]-1))
    									t11 = len[p1] - 1;
    								sw = 0;
    								while (sw == 0) {
    									t12 = (int)(rn.NextDouble() * 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 : 突然変異率               */
    	/**************************************/
    	protected void M_alle(double pr)
    	{
    		int i1, i2, lid;
    				//
    				// データのチェックと初期設定
    				//
    		if (dup_a == 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_alle)");
    			Environment.Exit(1);
    		}
    				//
    				// 実行
    				//
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    			if (pi_w[i1] == 1) {
    				for (i2 = 0; i2 < len[i1]; i2++) {
    					if (rn.NextDouble() <= pr) {
    						lid = (int)(rn.NextDouble() * (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 : 突然変異率                                               */
    	/**********************************************************************/
    	protected void M_move(double pr)
    	{
    		int i1, i2, ld, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    				//
    				// 位置の決定
    				//
    						// p1
    				p1 = (int)(rn.NextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    						// p2
    				sw = 0;
    				while (sw == 0) {
    					p2 = (int)(rn.NextDouble() * 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 : 幅をランダム                          */
    	/********************************************************/
    	protected void M_inv(double pr, int wd)
    	{
    		int i1, lid, p, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    				//
    				// 区間の決定
    				//
    				if (wd == 0) {
    					p1 = (int)(rn.NextDouble() * len[i1]);
    					if (p1 >= len[i1])
    						p1 = len[i1] - 1;
    					sw = 0;
    					while (sw == 0) {
    						p2 = (int)(rn.NextDouble() * 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)(rn.NextDouble() * 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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_scram(double pr, int wd)
    	{
    		int i1, i2, ld, p, p1, p2 = 0, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    				//
    				// 区間の決定
    				//
    				if (wd == 0) {
    					p1 = (int)(rn.NextDouble() * len[i1]);
    					if (p1 >= len[i1])
    						p1 = len[i1] - 1;
    					sw = 0;
    					while (sw == 0) {
    						p2 = (int)(rn.NextDouble() * 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)(rn.NextDouble() * len[i1]);
    					p2 = p1 + wd - 1;
    					if (p2 >= len[i1])
    						p2 = len[i1] - 1;
    				}
    				//
    				// 実行
    				//
    				for (i2 = p1; i2 <= p2; i2++) {
    					p = (int)(rn.NextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_chg(double pr, int wd)
    	{
    		int i1, i2, ld, p, p1, p2, p3 = 0, p4, sw;
    
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    				// 
    				// 区間等の決定([p1,p2]と[p3,p4]の入れ替え)
    				//
    						// p1
    				p1 = (int)(rn.NextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    						// p3
    				sw = 0;
    				while (sw == 0) {
    					p3 = (int)(rn.NextDouble() * 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)(rn.NextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_dup(double pr, int wd)
    	{
    		int i1, i2, p, p1, p2, p3 = 0, p4, sw;
    				//
    				// データのチェック
    				//
    		if (dup_a == 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_dup)");
    			Environment.Exit(1);
    		}
    				//
    				// 実行
    				//
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    						// 区間の決定([p1,p2]を[p3,p4]にコピー)
    							// p1
    				p1 = (int)(rn.NextDouble() * len[i1]);
    				if (p1 >= len[i1])
    					p1 = len[i1] - 1;
    							// p3
    				sw = 0;
    				while (sw == 0) {
    					p3 = (int)(rn.NextDouble() * len[i1]);
    					if (p3 >= len[i1])
    						p3 = len[i1] - 1;
    					if (p3 != p1)
    						sw = 1;
    				}
    							// 区間を決める
    				if (p3 > p1) {
    					p4 = (wd == 0) ? (int)(rn.NextDouble() * (len[i1] - p3)) + p3 :
                                         p3 + wd - 1;
    					if (p4 >= len[i1])
    						p4 = len[i1] - 1;
    					p2 = p1 + (p4 - p3);
    				}
    				else {
    					p2 = (wd == 0) ? (int)(rn.NextDouble() * (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 : 正規分布                        */
    	/*               =1 : 一様分布                        */
    	/*      m : 平均または一様分布の下限                  */
    	/*      s : 標準偏差または一様分布の上限              */
    	/******************************************************/
    	protected void M_per(double pr, int method, double m, double s)
    	{
    		double w, wd = 0.0, x1;
    		int i1, i2;
    				//
    				// データのチェックと初期設定
    				//
    		if (dup_a == 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_per)");
    			Environment.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 (rn.NextDouble() <= pr) {
    						if (method == 0)
    							w = norm_d(m, s);
    						else {
    							w = rn.NextDouble() * wd;
    							if (rn.NextDouble() < 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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_ins(double pr, int wd)
    	{
    		int i1, i2, l, ld, p;
    				//
    				// データのチェック
    				//
    		if (dup_a == 0 || min_len < 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_ins)");
    			Environment.Exit(1);
    		}
    				//
    				// 実行
    				//
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    						// 挿入位置の決定
    				p = (int)(rn.NextDouble() * (len[i1]+1));
    				if (p > len[i1])
    					p = len[i1];
    						// 挿入する遺伝子長の決定
    				l = (wd == 0) ? (int)(rn.NextDouble() * (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)(rn.NextDouble() * (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 : 幅をランダム                                        */
    	/**********************************************************************/
    	protected void M_del(double pr, int wd)
    	{
    		int i1, i2, l, max, p;
    				//
    				// データのチェック
    				//
    		if (dup_a == 0 || min_len < 0) {
    			Console.WriteLine("***error  突然変異方法が不適当 (M_del)");
    			Environment.Exit(1);
    		}
    				//
    				// 実行
    				//
    		for (i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1 && rn.NextDouble() <= pr) {
    						// 削除位置の決定
    				p = (int)(rn.NextDouble() * 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)(rn.NextDouble() * 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)                                       */
    	/*********************************************************************/
    	protected void 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) {
    			Console.WriteLine("***error  エリートで残す数が多すぎる (S_roul)");
    			Environment.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) {
    			Console.WriteLine("***error  残す個体がない (S_roul)");
    			Environment.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];
    					}
    				}
    			}
    		}
    	}
    }
    
    /************************/
    /* クラスFunctionの定義 */
    /************************/
    class Function : Species {
    
    	double cv;   // 2進数を10進数の変換する係数
    	int max_gen;   // 最大世代交代数
    	int kosa_m;   // 交叉方法
                      //   =-1 : 交叉を使用しない
                      //   =0 : 親のコピー
                      //   =1 : 多点交叉
                      //   =2 : 一様交叉
                      //   =3 : 平均化交叉
    	double kosa;   // 交叉確率
    	int k_point;   // 交差点の数(負の時は,1から-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 : スクランブル
                      //   =4 : 転座
                      //   =5 : 重複
                      //   =6 : 摂動
    	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 : 最大適応度の個体だけを出力
    	String o_file;   // 出力ファイル名
    
    	/***************************************/
    	/* コンストラクタ                      */
    	/*      name1 : Species定義ファイル名  */
    	/*      name2 : Function定義ファイル名 */
    	/*      seed : 乱数の初期値            */
    	/***************************************/
    	public Function (String name1, String name2, int seed) : base(name1, seed)
    	{
    		string[] lines = File.ReadAllLines(name2);
    		char[] charSep = new char[] {' '};
    					// 基本データの入力
    						// 1行目
    		string[] str = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		out_lvl      = int.Parse(str[1]);
    		out_m        = int.Parse(str[3]);
    						// 2行目
    		str    = lines[1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		o_file = str[1];
    		out_d  = int.Parse(str[3]);
    						// 3行目
    		str      = lines[2].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		kosa_m   = int.Parse(str[1]);
    		kosa     = double.Parse(str[3]);
    		k_point  = int.Parse(str[5]);
    		k_vr     = int.Parse(str[7]);
    		k_method = int.Parse(str[9]);
    		k_bias   = double.Parse(str[11]);
    		k_step   = double.Parse(str[13]);
    						// 4行目
    		str    = lines[3].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		mute_m = int.Parse(str[1]);
    		mute   = double.Parse(str[3]);
    		wd     = int.Parse(str[5]);
    		m_mean = double.Parse(str[7]);
    		m_std  = double.Parse(str[9]);
    						// 5行目
    		str      = lines[4].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		elite    = int.Parse(str[1]);
    		s_method = int.Parse(str[3]);
    		s_bias   = double.Parse(str[5]);
    		s_step   = double.Parse(str[7]);
    						// 6行目
    		str     = lines[5].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		max_gen = int.Parse(str[1]);
    
    		cv = 1.0 / (Math.Pow(2.0, (double)max_len) - 1.0);
    	}
    
    	/**************/
    	/* 全体の制御 */
    	/**************/
    	public void Control()
    	{
    		int gen = 1;
    						// 初期集団の発生
    		Init_std();
    						// 評価
    		Adap();
    						// 出力
    		Console.WriteLine("***世代 " + gen + " 適応度 max " + max +
                              " (" + max_n + ") mean " + mean);
    
    		if (Math.Abs(out_lvl) > 0)
    			Output(gen);
    						// 世代交代
    		for (gen = 2; gen <= max_gen; gen++) {
    							// 交叉
    			switch (kosa_m) {
    				case -1:
    					break;
    				case 0:
    					C_copy(2, max_ch/2, k_method, k_bias, k_step);   // 親のコピー
    					break;
    				case 1:
    					C_point(kosa, k_point, k_vr, k_method, k_bias, k_step);   // 多点交叉
    					break;
    				case 2:
    					C_uniform(kosa, k_method, k_bias, k_step);   // 一様交叉
    					break;
    				case 3:
    					C_mean(kosa, k_method, k_bias, k_step);   // 平均化交叉
    					break;
    				default:
    					break;
    			}
    							// 突然変異
    			switch (mute_m) {
    				case -1:
    					break;
    				case 0:
    					M_alle(mute);   // 対立遺伝子への置換
    					break;
    				case 1:
    					M_move(mute);   // 移動
    					break;
    				case 2:
    					M_inv(mute, wd);   // 逆位
    					break;
    				case 3:
    					M_scram(mute, wd);   // スクランブル
    					break;
    				case 4:
    					M_chg(mute, wd);   // 転座
    					break;
    				case 5:
    					M_dup(mute, wd);   // 重複
    					break;
    				case 6:
    					M_per(mute, wd, m_mean, m_std);   // 摂動
    					break;
    				default:
    					break;
    			}
    							// 適応度
    			Adap();
    							// 淘汰
    			S_roul(elite, s_method, s_bias, s_step);
    							// 出力
    			if (gen%out_d == 0)
    				Console.WriteLine("***世代 " + gen + " 適応度 max " + max +
                                      " (" + max_n + ") mean " + mean);
    
    			if (Math.Abs(out_lvl) > 0) {
    				if (gen%Math.Abs(out_lvl) == 0)
    					Output(gen);
    			}
    		}
    
    		gen--;
    		int k1 = out_m;
    		out_m  = 0;
    		Console.WriteLine("***世代 " + gen + " 適応度 max " + max +
                              " (" + max_n + ") mean " + mean);
    		Output(gen);
    		out_m = k1;
    	}
    
    	/****************/
    	/* 適応度の計算 */
    	/****************/
    	void Adap()
    	{
    		max   = 0.0;
    		max_n = -1;
    		mean  = 0.0;
    		int n = 0;
    
    		for (int i1 = 0; i1 < size+max_ch; i1++) {
    
    			if (pi_w[i1] == 1) {
    				double x = 0.0;
    				double y = 0.0;
    				for (int i2 = len[i1]-1; i2 >= 0; i2--) {
    					if (ind[i1][i2] > 0)
    						x += Math.Pow(2.0, y);
    					y += 1.0;
    				}
    				x        *= cv;
    				pi[i1]    = Math.Sin(3.0*x) + 0.5 * Math.Sin(9.0*x) +
                                Math.Sin(15.0*x+50.0);
    				pi_w[i1]  = 2;
    			}
    
    			if (pi_w[i1] > 0) {
    				mean += pi[i1];
    				n++;
    				if (max_n < 0 || pi[i1] > max) {
    					max   = pi[i1];
    					max_n = i1;
    				}
    			}
    		}
    
    		mean /= n;
    	}
    
    	/*****************************/
    	/* 結果の出力                */
    	/*      gen : 現在の世代番号 */
    	/*****************************/
    	void Output(int gen)
    	{
    		int pr = -1;
    		if (out_lvl >= 0) {
    			Console.Write("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = int.Parse(Console.ReadLine());
    		}
    
    		if (pr != 0) {
    
    			StreamWriter OUT = new StreamWriter(o_file, true);
    						// 出力先の決定と評価値の出力
    			if (pr < 0) {
    				DateTime now = DateTime.Now;   // 現在時刻の獲得
    				OUT.WriteLine("***世代 " + gen + " 適応度 max " + max +
                                  " (" + max_n + ") mean " + mean + " 時間 " + now);
    			}
    						// 詳細出力
    			int k = 0;
    			for (int i1 = 0; i1 < size+max_ch; i1++) {
    				if ((pi_w[i1] > 1) && (out_m ==0 || out_m == 1 && i1 == max_n)) {
    					if (pr < 0) {
    						OUT.Write(i1 + " allele");
    						for (int i2 = 0; i2 < len[i1]; i2++)
    							OUT.Write(" " + ind[i1][i2]);
    						double x = 0.0;
    						double y = 0.0;
    						for (int i2 = len[i1]-1; i2 >= 0; i2--) {
    							if (ind[i1][i2] > 0)
    								x += Math.Pow(2.0, y);
    							y += 1.0;
    						}
    						x *= cv;
    						OUT.WriteLine(" x " + x + " y " + pi[i1]);
    					}
    					else {
    						Console.Write(i1 + " allele");
    						for (int i2 = 0; i2 < len[i1]; i2++)
    							Console.Write(" " + ind[i1][i2]);
    						double x = 0.0;
    						double y = 0.0;
    						for (int i2 = len[i1]-1; i2 >= 0; i2--) {
    							if (ind[i1][i2] > 0)
    								x += Math.Pow(2.0, y);
    							y += 1.0;
    						}
    						x *= cv;
    						Console.WriteLine(" x " + x + " y " + pi[i1]);
    					}
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							Console.ReadLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			OUT.Close();
    		}
    	}
    }
    
    /****************/
    /* main program */
    /****************/
    class Program
    {
    	static void Main(String[] args)
    	{
    						// 入力ミス
    		if (args.Length == 0)
    			Console.WriteLine("***error  ケーススタディファイル名を入力して下さい\n");
    						// 入力OK
    		else {
    							// 入力データファイル名の入力
    			String[] lines   = File.ReadAllLines(args[0]);
    			int n            = int.Parse(lines[0]);   // 問題の数
    			String[] i_file1 = new String [n];
    			String[] i_file2 = new String [n];
    
    			char[] charSep = new char[] {' '};
    			for (int i1 = 0; i1 < n; i1++) {
    				string[] str = lines[i1+1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    				i_file1[i1] = str[0];
    				i_file2[i1] = str[1];
    			}
    							// 実行(乱数の初期値を変える)
    			for (int i1 = 0; i1 < n; i1++) {
    				Console.WriteLine();
    				Console.WriteLine("+++++ケース " + (i1+1) + "+++++\n");
    								// 入力と初期設定
    				Function fn = new Function (i_file1[i1], i_file2[i1], 1000 * i1 + 1234567);
    								// 最適化
    				fn.Control();
    			}
    		}
    	}
    }
    
    //------------------ケーススタディデータ(data_cf.txt)------
    /*
    3
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    data1_f.txt data2_f.txt
    */
    
    //------------------Species記述データ(data1_f.txt)---------
    /*
    対立遺伝子上限 1 対立遺伝子下限 0
    最大遺伝子長 15 最小遺伝子長(負の時は,最大遺伝子長で固定) -1
    遺伝子の重複 1 個体の重複(同じ染色体の個体) 0
    集団サイズ 20 子供 20
    */
    
    //------------------Function記述データ(data2_f.txt)--------
    /*
    出力レベル(負はファイル) 20 出力方法(0:すべて,1:最大) 0
    出力ファイル名 out1.txt 表示間隔 1
    交叉方法 1 交叉確率 1.0 点 2 位置 0 方法 1 バイアス 0 ステップ 1
    突然変異方法 0 突然変異率 0.05 幅 1 平均 0.0 標準偏差 1.0
    エリート 2 方法 1 バイアス 0 ステップ 1
    最大世代交代数 200
    */
    			

  7. VB

    TSP
    '*********************************'
    ' 遺伝的アルゴリズムによるTSPの解 '
    '      coded by Y.Suganuma        '
    '*********************************'
    Imports System.IO
    Imports System.Text.RegularExpressions
    
    Module Test
    
    	Sub Main(args() As String)
    						' 入力ミス
    		If args.Length = 0
    			Console.WriteLine("***error  ケーススタディファイル名を入力して下さい")
    						' 入力OK
    		Else
    							' 入力データファイル名の入力
    			Dim inp As StreamReader = New StreamReader(args(0))
    			Dim MS As Regex         = New Regex("\s+") 
    			Dim n As Integer        = Integer.Parse(inp.ReadLine().Trim())   ' 問題の数
    			Dim i_file1(n) As String
    			Dim i_file2(n) As String
    
    			For i1 As Integer = 0 To n-1
    				Dim str() As String = MS.Split(inp.ReadLine().Trim())
    				i_file1(i1) = str(0)
    				i_file2(i1) = str(1)
    			Next
    			inp.Close()
    							' 実行(乱数の初期値を変える)
    			For i1 As Integer = 0 To n-1
    				Console.WriteLine()
    				Console.WriteLine("+++++ケース " & (i1+1) & "+++++")
    								' 入力と初期設定
    				Dim tsp As TSP = new TSP (i_file1(i1), i_file2(i1), 1000 * i1 + 1234567)
    								' 最適化
    				tsp.Control()
    			Next
    		End If
    
    	End Sub
    
    	'*********************'
    	' クラスSpeciesの定義 '
    	'*********************'
    	Class Species
    	
    		protected max As Double   ' 最大適応度
    		protected mean As Double   ' 平均適応度
    		protected pi() As Double   ' 適応度
    		protected ro() As Double   ' ルーレット板
    		protected allele_u As Integer   ' 対立遺伝子上限
    		protected allele_l As Integer   ' 対立遺伝子下限
    		protected size As Integer   ' 個体総数
    		protected max_ch As Integer   ' 子供の数の最大値
    		protected max_len As Integer   ' 最大遺伝子長
    		protected min_len As Integer   ' 最小遺伝子長(負の時は,最大遺伝子長で固定)
    		protected max_n As Integer   ' 最大適応度の個体番号
    		protected dup_a As Integer   ' 遺伝子の重複
    	                                 '   =0 : 重複を許さない
    	                                 '   =1 : 重複を許す
    		protected dup_s As Integer   ' 個体の重複(同じ染色体の個体)
    	                                 '   =0 : 重複を許さない
    	                                 '   =1 : 重複を許す
    		protected ind(,) As Integer   ' 集団(個体の集まり)
    		protected len() As Integer   ' 各個体の遺伝子長
    		protected kou1() As Integer   ' 交叉・突然変異用作業場所1
    		protected kou2() As Integer   ' 交叉・突然変異用作業場所2
    		protected s_w() As Integer   ' 淘汰用指標(選択された回数)
    		protected edge(,) As Integer   ' エッジ組み替え交叉用ワークエリア
    		protected pi_w() As Integer   ' 適応度計算指標
    	                                  '   =0 : 未使用
    	                                  '   =1 : 適応度計算前(突然変異はこの個体だけに適用)
    	                                  '   =2 : 適応度計算済み(交叉時に親とみなす)
    		protected rn As Random   ' 乱数
    	
    		'**************************'
    		' コンストラクタ           '
    		'      name : ファイル名   '
    		'      seed : 乱数の初期値 '
    		'**************************'
    		Public Sub New (name As String, seed As Integer)
    
    			Dim MS As Regex         = New Regex("\s+") 
    			Dim inp As StreamReader = New StreamReader(name)
    					'
    					' データの入力
    					'
    							' 1行目
    			Dim str() As String = MS.Split(inp.ReadLine().Trim())
    			allele_u            = Integer.Parse(str(1))
    			allele_l            = Integer.Parse(str(3))
    							' 2行目
    			str     = MS.Split(inp.ReadLine().Trim())
    			max_len = Integer.Parse(str(1))
    			min_len = Integer.Parse(str(3))
    							' 3行目
    			str   = MS.Split(inp.ReadLine().Trim())
    			dup_a = Integer.Parse(str(1))
    			dup_s = Integer.Parse(str(3))
    							' 4行目
    			str    = MS.Split(inp.ReadLine().Trim())
    			size   = Integer.Parse(str(1))
    			max_ch = Integer.Parse(str(3))
    
    			inp.Close()
    					'
    					' データのチェック
    					'
    			If size <= 0
    				Console.WriteLine("***error  個体総数≦0 (Constructor)")
    				Environment.Exit(1)
    			End If
    	
    			If max_ch < 0
    				Console.WriteLine("***error  子供の数<0 (Constructor)")
    				Environment.Exit(1)
    			End If
    	
    			If max_len <= 0 or min_len = 0
    				Console.WriteLine("***error  遺伝子長≦0 (Constructor)")
    				Environment.Exit(1)
    			End If
    	
    			If max_len < min_len
    				Console.WriteLine("***error  最大遺伝子長<最小遺伝子長 (Constructor)")
    				Environment.Exit(1)
    			End If
    	
    			If allele_u <= allele_l
    				Console.WriteLine("***error  対立遺伝子上限≦対立遺伝子下限 (Constructor)")
    				Environment.Exit(1)
    			End If
    	
    			Dim kind As Integer = allele_u - allele_l + 1
    			If dup_a = 0 and max_len > kind
    				Console.WriteLine("***error  遺伝子の重複を防ぐことはできない (Constructor)")
    				Environment.Exit(1)
    			End If
    					'
    					' 領域の確保
    					'
    			Dim num As Integer  = size + max_ch
    	
    			ReDim ind(num, max_len)
    			ReDim edge(max_len, 5)
    			ReDim pi(num)
    			ReDim ro(num)
    			ReDim len(num)
    			ReDim kou1(max_len)
    			ReDim kou2(max_len)
    			ReDim s_w(num)
    			ReDim pi_w(num)
    					'
    					' 乱数の初期設定
    					'
    			rn = new Random(seed)
    	
    		End Sub
    
    		'*********************************'
    		' 正規分布変量の発生              '
    		'      m : 平均                   '
    		'      s : 標準偏差               '
    		'           return : 正規分布変量 '
    		'*********************************'
    		Function norm_d(m As Double, s As Double)
    
    			Dim x As Double = 0.0
    			For i1 As Integer = 0 To 11
    				x += rn.NextDouble()
    			Next
    
    			x = s * (x - 6.0) + m
    
    			Return x
    
    		End Function
    
    		'************************************************'
    		' 場所を探す                                     '
    		'      n : >=0 : n番目の親を捜す                 '
    		'          -1 : 空いている場所を探す             '
    		'      return : 親の場所,または,空いている場所 '
    		'               (存在しないときは負の値)       '
    		'************************************************'
    		Function Position(n As Integer)
    
    			Dim i1 As Integer
    			Dim k As Integer  = -1
    			Dim sw As Integer = 0
    					'
    					'  空いている場所を探す
    					'
    			If n < 0
    				i1 = 0
    				Do While i1 < size+max_ch and k < 0
    					If pi_w(i1) = 0
    						k = i1
    					End If
    					i1 += 1
    				Loop
    				If k < 0
    					Console.WriteLine("***error  空いている場所がない --Position--")
    					Environment.Exit(1)
    				End If
    					'
    					' n番目の親(pi_w(i)=2)を捜す
    					'
    			Else
    				i1 = 0
    				Do While i1 < size+max_ch and sw = 0
    					If pi_w(i1) = 2
    						k += 1
    						If k = n
    							sw = 1
    							k  = i1
    						End If
    					End If
    					i1 += 1
    				Loop
    			End If
    	
    			Return k
    
    		End Function
    
    		'*****************************************************************'
    		' 個体の選択                                                      '
    		'      method : 選択方法                                          '
    		'                 =-1 : ランダム                                  '
    		'                 =0 : 適応度をそのまま使用                       '
    		'                 =1 : 最小値からの差(ただし,α以下の場合はα) '
    		'                 =2 : 評価値に順位をつけ,減少率βで線形化       '
    		'      bias : α,または,method=2の場合は初期値                  '
    		'      sttp : β                                                  '
    		'      return : 個体番号                                          '
    		'*****************************************************************'
    		Function Select_f(method As Integer, bias As Double, sttp As Double)
    
    			Dim sum As Double = 0.0
    			Dim x As Double
    			Dim i1 As Integer
    			Dim k As Integer
    			Dim min As Integer
    			Dim n As Integer
    			Dim sw As Integer
    							' ルーレット板の用意
    			Select Case method
    								' ランダム
    				Case -1
    					n = 0
    					For i1 = 0 To size+max_ch-1
    						If pi_w(i1) > 1
    							n += 1
    						End If
    					Next
    					sum = 1.0 / n
    					For i1 = 0 To size+max_ch-1
    						If pi_w(i1) > 1
    							ro(i1) = sum
    						End If
    					Next
    								' 評価値をそのまま利用
    				Case 0
    					n = 0
    					For i1 = 0 To size+max_ch-1
    						If pi_w(i1) > 1
    							sum += pi(i1)
    							n   += 1
    						End If
    					Next
    					If Math.Abs(sum) > 1.0e-10
    						sum = 1.0 / Math.Abs(sum)
    						For i1 = 0 To size+max_ch-1
    							If pi_w(i1) > 1
    								ro(i1) = pi(i1) * sum
    							End If
    						Next
    					Else
    						sum = 1.0 / n
    						For i1 = 0 To size+max_ch-1
    							If pi_w(i1) > 1
    								ro(i1) = sum
    							End If
    						Next
    					End If
    								' 最小値からの差
    				Case 1
    					min = -1
    					n   = 0
    					For i1 = 0 To size+max_ch-1
    						If pi_w(i1) > 1
    							n += 1
    							If min < 0
    								min = i1
    							ElseIf pi(i1) < pi(min)
    								min = i1
    							End If
    						End If
    					Next
    					For i1 = 0 To size+max_ch-1
    						If pi_w(i1) > 1
    							ro(i1) = pi(i1) - pi(min)
    							If ro(i1) < bias
    								ro(i1) = bias
    							End If
    							sum += ro(i1)
    						End If
    					Next
    					If sum > 1.0e-10
    						sum = 1.0 / sum
    						For i1 = 0 To size+max_ch-1
    							If pi_w(i1) > 1
    								ro(i1) *= sum
    							End If
    						Next
    					Else
    						sum = 1.0 / n
    						For i1 = 0 To size+max_ch-1
    							If pi_w(i1) > 1
    								ro(i1) = sum
    							End If
    						Next
    					End If
    								' 線形化
    				Case 2
    					n = 0
    					For i1 = 0 To size+max_ch-1
    						If pi_w(i1) > 1
    							ro(i1) = -1.0
    							n     += 1
    						Else
    							ro(i1) = 1.0
    						End If
    					Next
    					sw  = 0
    					sum = bias
    					Do while sw = 0
    						min = -1
    						For i1 = 0 To size+max_ch-1
    							If ro(i1) < 0.0
    								If min < 0
    									min = i1
    								ElseIf pi(i1) < pi(min)
    									min = i1
    								End If
    							End If
    						Next
    						If min < 0
    							sw = 1
    						Else
    							ro(min)  = sum
    							sum     += sttp
    						End If
    					Loop
    					sum = 1.0 / (0.5 * (2.0 * bias + sttp * (n - 1)) * n)
    					For i1 = 0 To size+max_ch-1
    						If pi_w(i1) > 1
    							ro(i1) *= sum
    						End If
    					Next
    			End Select
    	
    			sum = 0.0
    			For i1 = 0 To size+max_ch-1
    				If pi_w(i1) > 1
    					sum    += ro(i1)
    					ro(i1)  = sum
    				End If
    			Next
    							' 選択
    			x  = rn.NextDouble()
    			sw = 0
    			k  = 0
    			i1 = 0
    			Do While i1 < size+max_ch and sw = 0
    				If pi_w(i1) > 1
    					If x <= ro(i1)
    						sw = 1
    						k  = i1
    					End If
    				End If
    				i1 += 1
    			Loop
    
    			Return k
    
    		End Function
    
    		'******************'
    		' 標準的な初期設定 '
    		'******************'
    		Sub Init_std()
    
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim i3 As Integer
    			Dim length As Integer
    			Dim lid As Integer
    			Dim sw1 As Integer
    			Dim sw2 As Integer
    					'
    					' 初期設定
    					'
    			For i1 = 0 To size+max_ch-1
    				If i1 < size
    					pi_w(i1) = 1   ' 適応度の計算前
    				Else
    					pi_w(i1) = 0   ' 未使用
    				End If
    			Next
    					'
    					' 遺伝子の決定
    					'
    			For i1 = 0 To size-1
    	
    				sw1 = 0
    	
    				Do While sw1 = 0
    							' 遺伝子長の決定
    					If min_len < 0
    						length = max_len
    					Else
    						length = Math.Floor(rn.NextDouble() * (max_len - min_len + 1) + min_len)
    						If length > max_len
    							length = max_len
    						End If
    					End If
    					len(i1) = length
    							' 遺伝子の決定
    					For i2 = 0 To length-1
    						sw2 = 0
    						Do While sw2 = 0
    							lid = Math.Floor(rn.NextDouble() * (allele_u - allele_l + 1) + allele_l)
    							If lid > allele_u
    								lid = allele_u
    							End If
    							ind(i1,i2) = lid
    								' 重複遺伝子のチェック
    							sw2 = 1
    							If dup_a = 0
    								i3 = 0
    								Do While i3 < i2 and sw2 > 0
    									If lid = ind(i1,i3)
    										sw2 = 0
    									End If
    									i3 += 1
    								Loop
    							End If
    						Loop
    					Next
    							' 重複個体のチェック
    					sw1 = 1
    					If dup_s = 0
    						i2 = 0
    						Do While i2 < i1 and sw1 > 0
    							If len(i1) = len(i2)
    								sw2 = 0
    								i3  = 0
    								Do While i3 < len(i1) and sw2 = 0
    									If ind(i1,i3) <> ind(i2,i3)
    										sw2 = 1
    									End If
    									i3 += 1
    								Loop
    								If sw2 = 0
    									sw1 = 0
    								End If
    							End If
    							i2 += 1
    						Loop
    					End If
    				Loop
    			Next
    
    		End Sub
    
    		'**************************************************'
    		' 標準的な出力                                     '
    		'      sw : 出力レベル                             '
    		'             =0 : 最終出力だけ                    '
    		'             n>0 : n世代毎に出力(負はファイル) '
    		'      out_m : 出力方法                            '
    		'                =0 : すべての個体を出力           '
    		'                =1 : 最大適応度の個体だけを出力   '
    		'      gen : 現在の世代番号                        '
    		'      name : 出力ファイル名                       '
    		'**************************************************'
    		Sub Out_std(sw As Integer, out_m As Integer, gen As Integer, name As String)
    
    			Dim pr As Integer = -1
    			If sw >= 0
    				Console.Write("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ")
    				pr = Integer.Parse(Console.ReadLine())
    			End If
    	
    			If pr <> 0
    	
    				Dim OUT As StreamWriter = new StreamWriter(name, true)
    							' 出力先の決定と評価値の出力
    				If pr < 0
    					Dim now1 As DateTime = DateTime.Now   ' 現在時刻の獲得
    					OUT.WriteLine("***世代 " & gen & " 適応度 max " & max &
    	                              " (" & max_n & ") mean " & mean & " 時間 " & now1)
    				End If
    							' 詳細出力
    				Dim k As Integer = 0
    				For i1 As Integer = 0 To size+max_ch-1
    					If (pi_w(i1) > 1) and (out_m = 0 or out_m = 1 and i1 = max_n)
    						If pr < 0
    							OUT.Write(i1 & " allele")
    							For i2 As Integer = 0 To len(i1)-1
    								OUT.Write(" " & ind(i1,i2))
    							Next
    							OUT.WriteLine(" value " & pi(i1))
    						Else
    							Console.Write(i1 & " allele")
    							For i2 As Integer = 0 To len(i1)-1
    								Console.Write(" " & ind(i1,i2))
    							Next
    							Console.WriteLine(" value " & pi(i1))
    						End If
    						If pr > 0
    							k += 1
    							If k = pr
    								Console.ReadLine()
    								k = 0
    							End If
    						End If
    					End If
    				Next
    
    				OUT.Close()
    
    			End If
    
    		End Sub
    
    		'*****************************************************************'
    		' 交叉(親のコピー)                                              '
    		'      method : =2 : 有性(2つの親から2つの子供)               '
    		'               =1 : 1つの親から1つの子供                       '
    		'      pair : method=2 の時は親のペア数                           '
    		'             method=1 の時は親の数(=子供の数)                 '
    		'      k_method : 選択方法                                        '
    		'                 =-1 : ランダム                                  '
    		'                 =0 : 適応度をそのまま使用                       '
    		'                 =1 : 最小値からの差(ただし,α以下の場合はα) '
    		'                 =2 : 評価値に順位をつけ,減少率βで線形化       '
    		'      k_bias : α,または,method=2の場合は初期値                '
    		'      k_step : β                                                '
    		'*****************************************************************'
    		Sub C_copy(method As Integer, pair As Integer, k_method As Integer,
    		           k_bias As Double, k_step As Double)
    
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim i3 As Integer
    			Dim k As Integer
    			Dim p As Integer
    			Dim p1 As Integer
    			Dim p2 As Integer = 0
    			Dim sw As Integer
    					'
    					' 初期設定とデータチェック
    					'
    			If method <> 1
    				method = 2
    			End If
    
    			If pair <= 0
    				If method = 2
    					pair = max_ch / 2
    				Else
    					pair = max_ch
    				End If
    			Else
    				If method = 2 and 2*pair > max_ch or method = 1 and pair > max_ch
    					Console.WriteLine("***error  子供が多すぎる (C_copy)")
    					Environment.Exit(1)
    				End If
    			End If
    					'
    					' 実行
    					'
    			For i1 = 0 To pair-1
    							' 親の選択
    				p1 = Select_f(k_method, k_bias, k_step)
    				sw = 0
    
    				Do while sw = 0
    					p2 = Select_f(k_method, k_bias, k_step)
    					If p1 <> p2
    						sw = 1
    					End If
    				Loop
    							' コピー
    				For i2 = 0 To method-1
    					If i2 = 0
    						p = p1
    					Else
    						p = p2
    					End If
    					k       = Position(-1)
    					len(k)  = len(p)
    					pi_w(k) = 1
    					For i3 = 0 To len(k)-1
    						ind(k,i3) = ind(p,i3)
    					Next
    				Next
    			Next
    
    		End Sub
    
    		'*****************************************************************'
    		' 交叉(多点交叉)                                                '
    		'      kosa : 交叉確率                                            '
    		'      k_point : 交叉点の数                                       '
    		'                (負の時は,1から-k_point間のランダム)          '
    		'      k_vr : =0 : 両親とも同じ位置で交叉                         '
    		'             =1 : 両親が異なる位置で交叉(遺伝子長は可変)       '
    		'      k_method : 選択方法                                        '
    		'                 =-1 : ランダム                                  '
    		'                 =0 : 適応度をそのまま使用                       '
    		'                 =1 : 最小値からの差(ただし,α以下の場合はα) '
    		'                 =2 : 評価値に順位をつけ,減少率βで線形化       '
    		'      k_bias : α,または,method=2の場合は初期値                '
    		'      k_step : β                                                '
    		'*****************************************************************'
    		Sub C_point(kosa As Double, k_point As Integer, k_vr As Integer, 
    		            k_method As Integer, k_bias As Double, k_step As Double)
    
    			Dim abs_p As Integer
    			Dim c1 As Integer
    			Dim c2 As Integer
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim i3 As Integer
    			Dim k1 As Integer
    			Dim k2 As Integer
    			Dim mn As Integer = 0
    			Dim num As Integer
    			Dim p1 As Integer
    			Dim p2 As Integer = 0
    			Dim pair As Integer
    			Dim sw As Integer
    			Dim t11 As Integer
    			Dim t12 As Integer
    			Dim t21 As Integer
    			Dim t22 As Integer
    					'
    					' 初期設定とデータのチェック
    					'
    			pair = max_ch / 2
    	
    			If dup_a = 0
    				Console.WriteLine("***error  交叉方法が不適当 (C_point)")
    				Environment.Exit(1)
    			End If
    	
    			abs_p = Math.Abs(k_point)
    			If abs_p = 0 or abs_p > max_len-1 or min_len > 0 and abs_p > min_len-1
    				Console.WriteLine("***error  交叉点の数が不適当 (C_point)")
    				Environment.Exit(1)
    			End If
    	
    			If k_vr > 0 and min_len < 0
    				Console.WriteLine("***error  遺伝子長は可変でなければならない (C_point)")
    				Environment.Exit(1)
    			End If
    					'
    					' 交叉
    					'
    			num = k_point
    	
    			For i1 = 0 To pair-1
    							' 交叉しない場合
    				If rn.NextDouble() > kosa
    					C_copy(2, 1, -1, 0.0, 0.0)
    							' 交叉する場合
    				Else
    								' 親の選択
    					p1 = Select_f(k_method, k_bias, k_step)
    					sw = 0
    					Do While sw = 0
    						p2 = Select_f(k_method, k_bias, k_step)
    						If p1 <> p2
    							sw = 1
    						End If
    					Loop
    								' 交叉位置の数の決定
    					If k_point < 0
    						num = Math.Floor(rn.NextDouble() * abs_p + 1)
    						If num > abs_p
    							num = abs_p
    						End If
    					End If
    								' 交叉位置の決定(点の後ろで交叉)
    					For i2 = 0 To num-1
    									' 親1の交叉位置
    						sw = 0
    						Do While sw = 0
    							sw       = 1
    							kou1(i2) = Math.Floor(rn.NextDouble() * (len(p1) - 1))
    							If kou1(i2) > len(p1)-2
    								kou1(i2) = len(p1) - 2
    							End If
    							If k_vr = 0 and kou1(i2) > len(p2)-2
    								kou1(i2) = len(p2) - 2
    							End If
    							i3 = 0
    							Do While i3 < i2 and sw > 0
    								If kou1(i3) = kou1(i2)
    									sw = 0
    								End If
    								i3 += 1
    							Loop
    						Loop
    									' 親2の交叉位置
    						If k_vr > 0
    							sw = 0
    							Do While sw = 0
    								sw       = 1
    								kou2(i2) = Math.Floor(rn.NextDouble() * (len(p2) - 1))
    								If kou2(i2) > len(p2)-2
    									kou2(i2) = len(p2) - 2
    								End If
    								i3 = 0
    								Do While i3 < i2 and sw > 0
    									If kou2(i3) = kou2(i2)
    										sw = 0
    									End If
    									i3 += 1
    								Loop
    							Loop
    						End If
    					Next
    								' 交叉の実行
    								'   親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 To num
    								' 次の交叉位置を求める
    						If i2 = num            ' 最後
    							t12 = len(p1)
    							t22 = len(p2)
    						Else
    									' 親1
    							t12 = max_len
    							For i3 = 0 To num-1
    								If kou1(i3) >= 0 and kou1(i3) <= t12
    									t12 = kou1(i3)
    									mn  = i3
    								End If
    							Next
    							kou1(mn) = -1
    							t12 += 1
    									' 親2
    							If k_vr = 0
    								t22 = t12
    							Else
    								t22 = max_len
    								For i3 = 0 To num-1
    									If kou2(i3) >= 0 and kou2(i3) <= t22
    										t22 = kou2(i3)
    										mn  = i3
    									End If
    								Next
    								kou2(mn) = -1
    								t22 += 1
    							End If
    						End If
    								' 指定箇所のコピー
    						For i3 = t11 To t12-1
    							If (i2 Mod 2) = 0
    								If c1 < max_len
    									ind(k1,c1) = ind(p1,i3)
    									c1 += 1
    								End If
    							Else
    								If c2 < max_len
    									ind(k2,c2) = ind(p1,i3)
    									c2 += 1
    								End If
    							End If
    						Next
    
    						For i3 = t21 To t22-1
    							If (i2 Mod 2) = 0
    								If c2 < max_len
    									ind(k2,c2) = ind(p2,i3)
    									c2 += 1
    								End If
    							Else
    								If c1 < max_len
    									ind(k1,c1) = ind(p2,i3)
    									c1 += 1
    								End If
    							End If
    						Next
    								' 交叉位置の移動
    						t11 = t12
    						t21 = t22
    					Next
    				End If
    			Next
    
    		End Sub
    
    		'*****************************************************************'
    		' 交叉(一様交叉.(0,1)を等確率で発生させ,1であれば,            '
    		'       親1,0であれば親2の遺伝子を子1が受け継ぐ)             '
    		'      kosa : 交叉確率                                            '
    		'      k_method : 選択方法                                        '
    		'                 =-1 : ランダム                                  '
    		'                 =0 : 適応度をそのまま使用                       '
    		'                 =1 : 最小値からの差(ただし,α以下の場合はα) '
    		'                 =2 : 評価値に順位をつけ,減少率βで線形化       '
    		'      k_bias : α,または,method=2の場合は初期値                '
    		'      k_step : β                                                '
    		'*****************************************************************'
    		Sub C_uniform(kosa As Double, k_method As Integer, k_bias As Double,
    		              k_step As Double)
    
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim k1 As Integer
    			Dim k2 As Integer
    			Dim p1 As Integer
    			Dim p2 As Integer = 0
    			Dim pair As Integer
    			Dim sw As Integer
    					'
    					' 初期設定とデータのチェック
    					'
    			pair = max_ch / 2
    	
    			If dup_a = 0
    				Console.WriteLine("***error  交叉方法が不適当 (C_unIForm)")
    				Environment.Exit(1)
    			End If
    	
    			If min_len > 0
    				Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_unIForm)")
    				Environment.Exit(1)
    			End If
    					'
    					' 交叉
    					'
    			For i1 = 0 To pair-1
    							' 交叉しない場合
    				If rn.NextDouble() > kosa
    					C_copy(2, 1, -1, 0.0, 0.0)
    							' 交叉する場合
    				Else
    								' 親の選択
    					p1 = Select_f(k_method, k_bias, k_step)
    					sw = 0
    					Do While sw = 0
    						p2 = Select_f(k_method, k_bias, k_step)
    						If p1 <> p2
    							sw = 1
    						End If
    					Loop
    							' 遺伝子長
    					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 To len(p1)-1
    						If rn.NextDouble() > 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)
    						End If
    					Next
    				End If
    			Next
    
    		End Sub
    
    		'*****************************************************************'
    		' 交叉(平均化交叉.2つの親の平均値を受け継ぐ)                  '
    		'      kosa : 交叉確率                                            '
    		'      k_method : 選択方法                                        '
    		'                 =-1 : ランダム                                  '
    		'                 =0 : 適応度をそのまま使用                       '
    		'                 =1 : 最小値からの差(ただし,α以下の場合はα) '
    		'                 =2 : 評価値に順位をつけ,減少率βで線形化       '
    		'      k_bias : α,または,method=2の場合は初期値                '
    		'      k_step : β                                                '
    		'*****************************************************************'
    		Sub C_mean(kosa As Double, k_method As Integer, k_bias As Double,
    		           k_step As Double)
    
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim k As Integer
    			Dim p1 As Integer
    			Dim p2 As Integer = 0
    			Dim sw As Integer
    					'
    					' 初期設定とデータのチェック
    					'
    			If min_len > 0
    				Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_mean)")
    				Environment.Exit(1)
    			End If
    					'
    					' 交叉
    					'
    			For i1 = 0 To max_ch-1
    							' 交叉しない場合
    				If rn.NextDouble() > kosa
    					C_copy(1, 1, -1, 0.0, 0.0)
    							' 交叉する場合
    				Else
    								' 親の選択
    					p1 = Select_f(k_method, k_bias, k_step)
    					sw = 0
    					Do While sw = 0
    						p2 = Select_f(k_method, k_bias, k_step)
    						If p1 <> p2
    							sw = 1
    						End If
    					Loop
    								' 遺伝子長
    					k       = Position(-1)
    					len(k)  = len(p1)
    					pi_w(k) = 1
    								' 交叉
    					For i2 = 0 To len(k)-1
    						ind(k,i2) = (ind(p1,i2) + ind(p2,i2)) / 2
    					Next
    				End If
    			Next
    
    		End Sub
    
    		'*****************************************************************'
    		' 交叉(循環交叉.ランダムに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 : ランダム                                  '
    		'                 =0 : 適応度をそのまま使用                       '
    		'                 =1 : 最小値からの差(ただし,α以下の場合はα) '
    		'                 =2 : 評価値に順位をつけ,減少率βで線形化       '
    		'      k_bias : α,または,method=2の場合は初期値                '
    		'      k_step : β                                                '
    		'*****************************************************************'
    		Sub C_cycle(kosa As Double, k_method As Integer, k_bias As Double,
    		            k_step As Double)
    	
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim i3 As Integer
    			Dim k1 As Integer
    			Dim k2 As Integer
    			Dim p As Integer
    			Dim pair As Integer
    			Dim p1 As Integer
    			Dim p2 As Integer = 0
    			Dim sw As Integer
    					'
    					' 初期設定とデータのチェック
    					'
    			pair = max_ch / 2
    		
    			If dup_a <> 0
    				Console.WriteLine("***error  交叉方法が不適当 (C_cycle)")
    				Environment.Exit(1)
    			End If
    		
    			If min_len > 0
    				Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_cycle)")
    				Environment.Exit(1)
    			End If
    					'
    					' 交叉
    					'
    			For i1 = 0 To pair-1
    							' 交叉しない場合
    				If rn.NextDouble() > kosa
    					C_copy(2, 1, -1, 0.0, 0.0)
    						' 交叉する場合
    				Else
    							' 親の選択
    					p1 = Select_f(k_method, k_bias, k_step)
    					sw = 0
    					Do While sw = 0
    						p2 = Select_f(k_method, k_bias, k_step)
    						If p1 <> p2
    							sw = 1
    						End If
    					Loop
    							' 初期設定
    					For i2 = 0 To len(p1)-1
    						kou1(i2) = 0
    						kou2(i2) = 0
    					Next
    							' 遺伝子長
    					k1       = Position(-1)
    					pi_w(k1) = 1
    					len(k1)  = len(p1)
    					k2       = Position(-1)
    					pi_w(k2) = 1
    					len(k2)  = len(p2)
    							' 交叉
    					sw = 0
    	
    					Do While sw = 0
    						sw = 1
    						p  = Math.Floor(rn.NextDouble() * len(p1))
    						If p >= len(p1)
    							p = len(p1) - 1
    						End If
    						If kou1(p) = 0 and kou2(p) = 0
    							kou1(p)   = 1
    							kou2(p)   = 1
    							ind(k1,p) = ind(p1,p)
    							ind(k2,p) = ind(p2,p)
    							i2        = 0
    							Do While i2 < len(p1) and sw > 0
    								If ind(p2,p) = ind(p1,i2)
    									ind(k1,i2) = ind(p1,i2)
    									kou1(i2)   = 1
    									sw         = 0
    								End If
    								i2 += 1
    							Loop
    							sw = 1
    							i2 = 0
    							Do While i2 < len(p2) and sw > 0
    								If ind(p1,p) = ind(p2,i2)
    									ind(k2,i2) = ind(p2,i2)
    									kou2(i2)   = 1
    									sw         = 0
    								End If
    								i2 += 1
    							Loop
    						End If
    					Loop
    	
    					sw = 0
    					i2 = 0
    					i3 = 0
    					Do While sw = 0
    						Do While sw = 0 and i2 < len(p1)
    							If kou1(i2) = 0
    								sw = 1
    							Else
    								i2 += 1
    							End If
    						Loop
    						sw = 0
    						Do While sw = 0 and i3 < len(p2)
    							If kou2(i3) = 0
    								sw = 1
    							Else
    								i3 += 1
    							End If
    						Loop
    						If i2 < len(p1) and i3 < len(p2)
    							ind(k1,i2) = ind(p2,i3)
    							ind(k2,i3) = ind(p1,i2)
    							sw         = 0
    							i2 += 1
    							i3 += 1
    						Else
    							sw = 1
    						End If
    					Loop
    				End If
    			Next
    
    		End Sub
    
    		'*****************************************************************'
    		' 交叉(部分的交叉.ランダムに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 : ランダム                                  '
    		'                 =0 : 適応度をそのまま使用                       '
    		'                 =1 : 最小値からの差(ただし,α以下の場合はα) '
    		'                 =2 : 評価値に順位をつけ,減少率βで線形化       '
    		'      k_bias : α,または,method=2の場合は初期値                '
    		'      k_step : β                                                '
    		'*****************************************************************'
    		Sub C_part(kosa As Double, k_method As Integer, k_bias As Double, 
    		           k_step As Double)
    
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim i3 As Integer
    			Dim k1 As Integer
    			Dim k2 As Integer
    			Dim lv As Integer
    			Dim p As Integer
    			Dim pair As Integer
    			Dim p1 As Integer
    			Dim p2 As Integer = 0
    			Dim sw As Integer
    					'
    					' 初期設定とデータのチェック
    					'
    			pair = max_ch / 2
    		
    			If dup_a <> 0
    				Console.WriteLine("***error  交叉方法が不適当 (C_part)")
    				Environment.Exit(1)
    			End If
    		
    			If min_len > 0
    				Console.WriteLine("***error  遺伝子長は固定長でなければならない (C_part)")
    				Environment.Exit(1)
    			End If
    					'
    					' 交叉
    					'
    			For i1 = 0 To pair-1
    							' 交叉しない場合
    				If rn.NextDouble() > kosa
    					C_copy(2, 1, -1, 0.0, 0.0)
    							' 交叉する場合
    				Else
    							' 親の選択
    					p1 = Select_f(k_method, k_bias, k_step)
    					sw = 0
    					Do While sw = 0
    						p2 = Select_f(k_method, k_bias, k_step)
    						If p1 <> p2
    							sw = 1
    						End If
    					Loop
    							' 遺伝子長
    					k1       = Position(-1)
    					pi_w(k1) = 1
    					len(k1)  = len(p1)
    					k2       = Position(-1)
    					pi_w(k2) = 1
    					len(k2)  = len(p2)
    							' 交叉
    					p = Math.Floor(rn.NextDouble() * len(p1))
    					If p >= len(p1)
    						p = len(p1) - 1
    					End If
    	
    					For i2 = 0 To len(p1)-1
    						ind(k1,i2) = ind(p1,i2)
    						ind(k2,i2) = ind(p2,i2)
    					Next
    	
    					For i2 = p To len(p1)-1
    						sw = 0
    						lv = ind(k1,i2)
    						i3 = 0
    						Do While i3 < len(p1) and sw = 0
    							If ind(k2,i2) = ind(k1,i3)
    								ind(k1,i2) = ind(k1,i3)
    								ind(k1,i3) = lv
    								sw         = 1
    							End If
    							i3 += 1
    						Loop
    						sw = 0
    						i3 = 0
    						Do While i3 < len(p1) and sw = 0
    							If lv = ind(k2,i3)
    								ind(k2,i3) = ind(k2,i2)
    								ind(k2,i2) = lv
    								sw         = 1
    							End If
    							i3 += 1
    						Loop
    					Next
    				End If
    			Next
    
    		End Sub
    
    		'*****************************************************************'
    		' 交叉(順序交叉.ランダムに切れ目を決定し,子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_me