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

データ例とプログラム

  以下,複数のファイル構成になっています.ファイル間の区切りを「---・・・」で示します.

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

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

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

------------------------クラスSpecies-------------
/***********************/
/* クラスSpeciesの定義 */
/***********************/
import java.io.*;
import java.util.Random;
import java.util.Date;
import java.util.StringTokenizer;

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-----------------
/*******************/
/* クラスTSPの定義 */
/*******************/
import java.io.*;
import java.util.Date;
import java.util.Random;
import java.util.StringTokenizer;

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-----------------
/*******************/
/* クラスWinの定義 */
/*******************/
import java.awt.*;
import java.awt.event.*;

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);
		}
	}
}

------------------------クラスTSP_r(main)---------
/***********************************/
/* 遺伝的アルゴリズムによるTSPの解 */
/*      coded by Y.Suganuma        */
/***********************************/
import java.io.*;
import java.util.StringTokenizer;

class TSP_r {

	/****************/
	/* main program */
	/****************/
	public static void main(String args[]) throws IOException, FileNotFoundException
	{
		int i1, n, seed[];
		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());

			seed    = new int [n];
			i_file1 = new String [n];
			i_file2 = new String [n];

			for (i1 = 0; i1 < n; i1++) {
				line = in.readLine();
				dt   = new StringTokenizer(line, " ");
				seed[i1] = Integer.parseInt(dt.nextToken());
				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], seed[i1]);
								// 最適化
				tsp.Control();
			}
		}
	}
}
		

  コンパイルした後,

java TSP_r ケーススタディファイル名

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

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

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

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

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

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

遺伝子の重複

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

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

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

集団サイズ

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

子供

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

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

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

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

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

出力ファイル名

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

表示間隔

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

交叉方法

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

交叉確率

  交叉確率を入力します.

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

位置

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

方法

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

バイアス

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

ステップ

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

突然変異方法

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

突然変異率

  突然変異率を入力します

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

平均

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

標準偏差

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

エリート

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

方法

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

バイアス

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

ステップ

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

都市数

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

最大世代交代数

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

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

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

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

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

図示(0:しない,1:結果,2:初期状態と結果,3:ステップ)

結果を図示するか否かを入力します.
=0 : 図示しない
=1 : 最終結果だけを図示
=2 : 初期状態と最終結果を図示
=3 : 初期状態,最終結果,および,出力レベルで指定した回数毎に中間結果を図示します.

都市番号

  都市番号を表示する際,その字の大きさを入力します.0を入力すると都市番号を表示しません.

図の大きさ(幅,高さ)

  図の幅と高さの最大値を入力します.実際に表示される画面の大きさは,これらの値と都市座標の分布状況によって,上下,左右の縮尺が等しくなるように決められます.

-58 37
55 -19
・・・

  以下,各都市の x 座標と y 座標です.都市の数だけ必要になります.この入力された順番が,その都市の都市番号になります( 0 から始まる).
  なお,図示する場合,対応する図が表示される毎に,コマンドプロンプトの画面に

  図を確認したらreturnキーを押してください

のようなメッセージが出力されますので,メッセージに従い return を押して継続してください.