Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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();
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement