Advertisement
Guest User

Untitled

a guest
Oct 15th, 2019
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 89.97 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.Random;
  3. import java.util.Date;
  4. import java.util.StringTokenizer;
  5.  
  6. class Species {
  7.  
  8. protected double max; // 最大適応度
  9. protected double mean; // 平均適応度
  10. protected double [] pi; // 適応度
  11. protected double [] ro; // ルーレット板
  12. protected int allele_u; // 対立遺伝子上限
  13. protected int allele_l; // 対立遺伝子下限
  14. protected int size; // 個体総数
  15. protected int max_ch; // 子供の数の最大値
  16. protected int max_len; // 最大遺伝子長
  17. protected int min_len; // 最小遺伝子長(負の時は,最大遺伝子長で固定)
  18. protected int max_n; // 最大適応度の個体番号
  19. protected int dup_a; // 遺伝子の重複
  20. // =0 : 重複を許さない
  21. // =1 : 重複を許す
  22. protected int dup_s; // 個体の重複(同じ染色体の個体)
  23. // =0 : 重複を許さない
  24. // =1 : 重複を許す
  25. protected int [][] ind; // 集団(個体の集まり)
  26. protected int [] len; // 各個体の遺伝子長
  27. protected int [] kou1; // 交叉・突然変異用作業場所1
  28. protected int [] kou2; // 交叉・突然変異用作業場所2
  29. protected int [] s_w; // 淘汰用指標(選択された回数)
  30. protected int [][] edge; // エッジ組み替え交叉用ワークエリア
  31. protected byte [] pi_w; // 適応度計算指標
  32. // =0 : 未使用
  33. // =1 : 適応度計算前(突然変異はこの個体だけに適用)
  34. // =2 : 適応度計算済み(交叉時に親とみなす)
  35. protected Random rn; // 乱数
  36.  
  37. /***********************************/
  38. /* 正規分布変量の発生 */
  39. /* m : 平均 */
  40. /* s : 標準偏差 */
  41. /* return : 正規分布変量 */
  42. /***********************************/
  43. double norm_d(double m, double s)
  44. {
  45. double x = 0.0;
  46. int i1;
  47.  
  48. for (i1 = 0; i1 < 12; i1++)
  49. x += rn.nextDouble();
  50.  
  51. x = s * (x - 6.0) + m;
  52.  
  53. return x;
  54. }
  55.  
  56. /**************************************************/
  57. /* 場所を探す */
  58. /* n : >=0 : n番目の親を捜す */
  59. /* -1 : 空いている場所を探す */
  60. /* return : 親の場所,または,空いている場所 */
  61. /* (存在しないときは負の値) */
  62. /**************************************************/
  63. int Position(int n)
  64. {
  65. int i1, k = -1, sw = 0;
  66. /*
  67. 空いている場所を探す
  68. */
  69. if (n < 0) {
  70. for (i1 = 0; i1 < size+max_ch && k < 0; i1++) {
  71. if (pi_w[i1] == 0)
  72. k = i1;
  73. }
  74. if (k < 0) {
  75. System.out.print("***error 空いている場所がない --Position--\n");
  76. System.exit(1);
  77. }
  78. }
  79. /*
  80. n番目の親(pi_w[i]=2)を捜す
  81. */
  82. else {
  83. for (i1 = 0; i1 < size+max_ch && sw == 0; i1++) {
  84. if (pi_w[i1] == 2) {
  85. k++;
  86. if (k == n) {
  87. sw = 1;
  88. k = i1;
  89. }
  90. }
  91. }
  92. }
  93.  
  94. return k;
  95. }
  96.  
  97. /*******************************************************************/
  98. /* 個体の選択 */
  99. /* method : 選択方法 */
  100. /* =-1 : ランダム */
  101. /* =0 : 適応度をそのまま使用 */
  102. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  103. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  104. /* bias : α,または,method=2の場合は初期値 */
  105. /* step : β */
  106. /* return : 個体番号 */
  107. /*******************************************************************/
  108. int Select(int method, double bias, double step)
  109. {
  110. double sum = 0.0, x;
  111. int i1, k, min, n, sw;
  112. // ルーレット板の用意
  113. switch (method) {
  114. // ランダム
  115. case -1:
  116. n = 0;
  117. for (i1 = 0; i1 < size+max_ch; i1++) {
  118. if (pi_w[i1] > 1)
  119. n++;
  120. }
  121. sum = 1.0 / n;
  122. for (i1 = 0; i1 < size+max_ch; i1++) {
  123. if (pi_w[i1] > 1)
  124. ro[i1] = sum;
  125. }
  126. break;
  127. // 評価値をそのまま利用
  128. case 0:
  129. n = 0;
  130. for (i1 = 0; i1 < size+max_ch; i1++) {
  131. if (pi_w[i1] > 1) {
  132. sum += pi[i1];
  133. n++;
  134. }
  135. }
  136. if (Math.abs(sum) > 1.0e-10) {
  137. sum = 1.0 / Math.abs(sum);
  138. for (i1 = 0; i1 < size+max_ch; i1++) {
  139. if (pi_w[i1] > 1)
  140. ro[i1] = pi[i1] * sum;
  141. }
  142. }
  143. else {
  144. sum = 1.0 / n;
  145. for (i1 = 0; i1 < size+max_ch; i1++) {
  146. if (pi_w[i1] > 1)
  147. ro[i1] = sum;
  148. }
  149. }
  150. break;
  151. // 最小値からの差
  152. case 1:
  153. min = -1;
  154. n = 0;
  155. for (i1 = 0; i1 < size+max_ch; i1++) {
  156. if (pi_w[i1] > 1) {
  157. n++;
  158. if (min < 0 || pi[i1] < pi[min])
  159. min = i1;
  160. }
  161. }
  162. for (i1 = 0; i1 < size+max_ch; i1++) {
  163. if (pi_w[i1] > 1) {
  164. ro[i1] = pi[i1] - pi[min];
  165. if (ro[i1] < bias)
  166. ro[i1] = bias;
  167. sum += ro[i1];
  168. }
  169. }
  170. if (sum > 1.0e-10) {
  171. sum = 1.0 / sum;
  172. for (i1 = 0; i1 < size+max_ch; i1++) {
  173. if (pi_w[i1] > 1)
  174. ro[i1] *= sum;
  175. }
  176. }
  177. else {
  178. sum = 1.0 / n;
  179. for (i1 = 0; i1 < size+max_ch; i1++) {
  180. if (pi_w[i1] > 1)
  181. ro[i1] = sum;
  182. }
  183. }
  184. break;
  185. // 線形化
  186. case 2:
  187. n = 0;
  188. for (i1 = 0; i1 < size+max_ch; i1++) {
  189. if (pi_w[i1] > 1) {
  190. ro[i1] = -1.0;
  191. n++;
  192. }
  193. else
  194. ro[i1] = 1.0;
  195. }
  196. sw = 0;
  197. sum = bias;
  198. while (sw == 0) {
  199. min = -1;
  200. for (i1 = 0; i1 < size+max_ch; i1++) {
  201. if (ro[i1] < 0.0 && (min < 0 || pi[i1] < pi[min]))
  202. min = i1;
  203. }
  204. if (min < 0)
  205. sw = 1;
  206. else {
  207. ro[min] = sum;
  208. sum += step;
  209. }
  210. }
  211. sum = 1.0 / (0.5 * (2.0 * bias + step * (n - 1)) * n);
  212. for (i1 = 0; i1 < size+max_ch; i1++) {
  213. if (pi_w[i1] > 1)
  214. ro[i1] *= sum;
  215. }
  216. break;
  217. }
  218.  
  219. sum = 0.0;
  220. for (i1 = 0; i1 < size+max_ch; i1++) {
  221. if (pi_w[i1] > 1) {
  222. sum += ro[i1];
  223. ro[i1] = sum;
  224. }
  225. }
  226. // 選択
  227. x = rn.nextDouble();
  228. sw = 0;
  229. k = 0;
  230. for (i1 = 0; i1 < size+max_ch && sw == 0; i1++) {
  231. if (pi_w[i1] > 1) {
  232. if (x <= ro[i1]) {
  233. sw = 1;
  234. k = i1;
  235. }
  236. }
  237. }
  238.  
  239. return k;
  240. }
  241.  
  242. /****************************/
  243. /* コンストラクタ */
  244. /* name : ファイル名 */
  245. /* seed : 乱数の初期値 */
  246. /****************************/
  247. Species (String name, int seed) throws IOException, FileNotFoundException
  248. {
  249. int kind, num;
  250. String line;
  251. StringTokenizer dt;
  252. BufferedReader in = new BufferedReader(new FileReader(name));
  253. /*
  254. データの入力
  255. */
  256. line = in.readLine();
  257. dt = new StringTokenizer(line, " ");
  258. dt.nextToken();
  259. allele_u = Integer.parseInt(dt.nextToken());
  260. dt.nextToken();
  261. allele_l = Integer.parseInt(dt.nextToken());
  262.  
  263. line = in.readLine();
  264. dt = new StringTokenizer(line, " ");
  265. dt.nextToken();
  266. max_len = Integer.parseInt(dt.nextToken());
  267. dt.nextToken();
  268. min_len = Integer.parseInt(dt.nextToken());
  269.  
  270. line = in.readLine();
  271. dt = new StringTokenizer(line, " ");
  272. dt.nextToken();
  273. dup_a = Integer.parseInt(dt.nextToken());
  274. dt.nextToken();
  275. dup_s = Integer.parseInt(dt.nextToken());
  276.  
  277. line = in.readLine();
  278. dt = new StringTokenizer(line, " ");
  279. dt.nextToken();
  280. size = Integer.parseInt(dt.nextToken());
  281. dt.nextToken();
  282. max_ch = Integer.parseInt(dt.nextToken());
  283. /*
  284. データのチェック
  285. */
  286. if (size <= 0) {
  287. System.out.print("***error 個体総数≦0 (Constructor)\n");
  288. System.exit(1);
  289. }
  290.  
  291. if (max_ch < 0) {
  292. System.out.print("***error 子供の数<0 (Constructor)\n");
  293. System.exit(1);
  294. }
  295.  
  296. if (max_len <= 0 || min_len == 0) {
  297. System.out.print("***error 遺伝子長≦0 (Constructor)\n");
  298. System.exit(1);
  299. }
  300.  
  301. if (max_len < min_len) {
  302. System.out.print("***error 最大遺伝子長<最小遺伝子長 (Constructor)\n");
  303. System.exit(1);
  304. }
  305.  
  306. if (allele_u <= allele_l) {
  307. System.out.print("***error 対立遺伝子上限≦対立遺伝子下限 (Constructor)\n");
  308. System.exit(1);
  309. }
  310.  
  311. kind = allele_u - allele_l + 1;
  312. if (dup_a == 0 && max_len > kind) {
  313. System.out.print("***error 遺伝子の重複を防ぐことはできない (Constructor)\n");
  314. System.exit(1);
  315. }
  316. /*
  317. 領域の確保
  318. */
  319. num = size + max_ch;
  320.  
  321. ind = new int [num][max_len];
  322. edge = new int [max_len][5];
  323. pi = new double [num];
  324. ro = new double [num];
  325. len = new int [num];
  326. kou1 = new int [max_len];
  327. kou2 = new int [max_len];
  328. s_w = new int [num];
  329. pi_w = new byte [num];
  330. /*
  331. 乱数の初期設定
  332. */
  333. rn = new Random (seed);
  334. }
  335.  
  336. /********************/
  337. /* 標準的な初期設定 */
  338. /********************/
  339. void Init_std()
  340. {
  341. int i1, i2, i3, length, lid, sw1, sw2;
  342. /*
  343. 初期設定
  344. */
  345. for (i1 = 0; i1 < size+max_ch; i1++) {
  346. if (i1 < size)
  347. pi_w[i1] = 1; // 適応度の計算前
  348. else
  349. pi_w[i1] = 0; // 未使用
  350. }
  351. /*
  352. 遺伝子の決定
  353. */
  354. for (i1 = 0; i1 < size; i1++) {
  355.  
  356. sw1 = 0;
  357.  
  358. while (sw1 == 0) {
  359. // 遺伝子長の決定
  360. if (min_len < 0)
  361. length = max_len;
  362. else {
  363. length = (int)(rn.nextDouble() * (max_len - min_len + 1) + min_len);
  364. if (length > max_len)
  365. length = max_len;
  366. }
  367. len[i1] = length;
  368. // 遺伝子の決定
  369. for (i2 = 0; i2 < length; i2++) {
  370. sw2 = 0;
  371. while (sw2 == 0) {
  372. lid = (int)(rn.nextDouble() * (allele_u - allele_l + 1) + allele_l);
  373. if (lid > allele_u)
  374. lid = allele_u;
  375. ind[i1][i2] = lid;
  376. // 重複遺伝子のチェック
  377. sw2 = 1;
  378. if (dup_a == 0) {
  379. for (i3 = 0; i3 < i2 && sw2 > 0; i3++) {
  380. if (lid == ind[i1][i3])
  381. sw2 = 0;
  382. }
  383. }
  384. }
  385. }
  386. // 重複個体のチェック
  387. sw1 = 1;
  388. if (dup_s == 0) {
  389. for (i2 = 0; i2 < i1 && sw1 > 0; i2++) {
  390. if (len[i1] == len[i2]) {
  391. sw2 = 0;
  392. for (i3 = 0; i3 < len[i1] && sw2 == 0; i3++) {
  393. if (ind[i1][i3] != ind[i2][i3])
  394. sw2 = 1;
  395. }
  396. if (sw2 == 0)
  397. sw1 = 0;
  398. }
  399. }
  400. }
  401. }
  402. }
  403. }
  404.  
  405. /****************************************************/
  406. /* 標準的な出力 */
  407. /* sw : 出力レベル */
  408. /* =0 : 最終出力だけ */
  409. /* n>0 : n世代毎に出力(負はファイル) */
  410. /* out_m : 出力方法 */
  411. /* =0 : すべての個体を出力 */
  412. /* =1 : 最大適応度の個体だけを出力 */
  413. /* gen : 現在の世代番号 */
  414. /* name : 出力ファイル名 */
  415. /****************************************************/
  416. void Out_std(int sw, int out_m, int gen, String name) throws IOException, FileNotFoundException
  417. {
  418. int i1, i2, k = 0, pr;
  419. String now;
  420. PrintStream out = null;
  421. BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  422.  
  423. if (sw >= 0) {
  424. System.out.print(" 出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
  425. pr = Integer.parseInt(in.readLine());
  426. }
  427. else
  428. pr = -1;
  429.  
  430. if (pr != 0) {
  431. // 出力先の決定と評価値の出力
  432. if (pr > 0)
  433. out = System.out;
  434. else {
  435. Date newtime = new Date(); // 現在時刻の獲得
  436. now = newtime.toString(); // 文字列への変換
  437. out = new PrintStream(new FileOutputStream(name, true));
  438. out.println("***世代 " + gen + " 適応度 max " + max +
  439. " (" + max_n + ") mean " + mean + " 時間 " + now);
  440. }
  441. // 詳細出力
  442. for (i1 = 0; i1 < size+max_ch; i1++) {
  443. if ((pi_w[i1] > 1) && (out_m ==0 || out_m == 1 && i1 == max_n)) {
  444. out.print(i1 + " allele");
  445. for (i2 = 0; i2 < len[i1]; i2++)
  446. out.print(" " + ind[i1][i2]);
  447. out.println(" value " + pi[i1]);
  448. if (pr > 0) {
  449. k++;
  450. if (k == pr) {
  451. in.readLine();
  452. k = 0;
  453. }
  454. }
  455. }
  456. }
  457.  
  458. if (pr < 0)
  459. out.close();
  460. }
  461. }
  462.  
  463. /*******************************************************************/
  464. /* 交叉(親のコピー) */
  465. /* method : =2 : 有性(2つの親から2つの子供) */
  466. /* =1 : 1つの親から1つの子供 */
  467. /* pair : method=2 の時は親のペア数 */
  468. /* method=1 の時は親の数(=子供の数) */
  469. /* k_method : 選択方法 */
  470. /* =-1 : ランダム */
  471. /* =0 : 適応度をそのまま使用 */
  472. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  473. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  474. /* k_bias : α,または,method=2の場合は初期値 */
  475. /* k_step : β */
  476. /*******************************************************************/
  477. void C_copy(int method, int pair, int k_method, double k_bias,
  478. double k_step)
  479. {
  480. int i1, i2, i3, k, p, p1, p2 = 0, sw;
  481. /*
  482. 初期設定とデータチェック
  483. */
  484. if (method != 1)
  485. method = 2;
  486.  
  487. if (pair <= 0)
  488. pair = (method==2) ? max_ch/2 : max_ch;
  489. else {
  490. if (method == 2 && 2*pair > max_ch || method == 1 && pair > max_ch) {
  491. System.out.print("***error 子供が多すぎる (C_copy)\n");
  492. System.exit(1);
  493. }
  494. }
  495. /*
  496. 実行
  497. */
  498. for (i1 = 0; i1 < pair; i1++) {
  499. // 親の選択
  500. p1 = Select(k_method, k_bias, k_step);
  501. sw = 0;
  502.  
  503. while (sw == 0) {
  504. p2 = Select(k_method, k_bias, k_step);
  505. if (p1 != p2)
  506. sw = 1;
  507. }
  508. // コピー
  509. for (i2 = 0; i2 < method; i2++) {
  510. p = (i2 == 0) ? p1 : p2;
  511. k = Position(-1);
  512. len[k] = len[p];
  513. pi_w[k] = 1;
  514. for (i3 = 0; i3 < len[k]; i3++)
  515. ind[k][i3] = ind[p][i3];
  516. }
  517. }
  518. }
  519.  
  520. /*******************************************************************/
  521. /* 交叉(多点交叉) */
  522. /* kosa : 交叉確率 */
  523. /* k_point : 交叉点の数 */
  524. /* (負の時は,1から-k_point間のランダム) */
  525. /* k_vr : =0 : 両親とも同じ位置で交叉 */
  526. /* =1 : 両親が異なる位置で交叉(遺伝子長は可変) */
  527. /* k_method : 選択方法 */
  528. /* =-1 : ランダム */
  529. /* =0 : 適応度をそのまま使用 */
  530. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  531. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  532. /* k_bias : α,または,method=2の場合は初期値 */
  533. /* k_step : β */
  534. /*******************************************************************/
  535. void C_point(double kosa, int k_point, int k_vr, int k_method,
  536. double k_bias, double k_step)
  537. {
  538. int abs_p, c1, c2, i1, i2, i3, k1, k2, mn = 0, num, p1, p2 = 0,
  539. pair, sw, t11, t12, t21, t22;
  540. /*
  541. 初期設定とデータのチェック
  542. */
  543. pair = max_ch / 2;
  544.  
  545. if (dup_a == 0) {
  546. System.out.print("***error 交叉方法が不適当 (C_point)\n");
  547. System.exit(1);
  548. }
  549.  
  550. abs_p = Math.abs(k_point);
  551. if (abs_p == 0 || abs_p > max_len-1 || min_len > 0 && abs_p > min_len-1) {
  552. System.out.print("***error 交叉点の数が不適当 (C_point)\n");
  553. System.exit(1);
  554. }
  555.  
  556. if (k_vr > 0 && min_len < 0) {
  557. System.out.print("***error 遺伝子長は可変でなければならない (C_point)\n");
  558. System.exit(1);
  559. }
  560. /*
  561. 交叉
  562. */
  563. num = k_point;
  564.  
  565. for (i1 = 0; i1 < pair; i1++) {
  566. // 交叉しない場合
  567. if (rn.nextDouble() > kosa)
  568. C_copy(2, 1, -1, 0.0, 0.0);
  569. // 交叉する場合
  570. else {
  571. // 親の選択
  572. p1 = Select(k_method, k_bias, k_step);
  573. sw = 0;
  574. while (sw == 0) {
  575. p2 = Select(k_method, k_bias, k_step);
  576. if (p1 != p2)
  577. sw = 1;
  578. }
  579. // 交叉位置の数の決定
  580. if (k_point < 0) {
  581. num = (int)(rn.nextDouble() * abs_p + 1);
  582. if (num > abs_p)
  583. num = abs_p;
  584. }
  585. // 交叉位置の決定(点の後ろで交叉)
  586. for (i2 = 0; i2 < num; i2++) {
  587. // 親1の交叉位置
  588. sw = 0;
  589. while (sw == 0) {
  590. sw = 1;
  591. kou1[i2] = (int)(rn.nextDouble() * (len[p1] - 1));
  592. if (kou1[i2] > len[p1]-2)
  593. kou1[i2] = len[p1] - 2;
  594. if (k_vr == 0 && kou1[i2] > len[p2]-2)
  595. kou1[i2] = len[p2] - 2;
  596. for (i3 = 0; i3 < i2 && sw > 0; i3++) {
  597. if (kou1[i3] == kou1[i2])
  598. sw = 0;
  599. }
  600. }
  601. // 親2の交叉位置
  602. if (k_vr > 0) {
  603. sw = 0;
  604. while (sw == 0) {
  605. sw = 1;
  606. kou2[i2] = (int)(rn.nextDouble() * (len[p2] - 1));
  607. if (kou2[i2] > len[p2]-2)
  608. kou2[i2] = len[p2] - 2;
  609. for (i3 = 0; i3 < i2 && sw > 0; i3++) {
  610. if (kou2[i3] == kou2[i2])
  611. sw = 0;
  612. }
  613. }
  614. }
  615. }
  616. // 交叉の実行
  617. // 親1のt11からt12を子1のc1へコピー
  618. // 親2のt21からt22を子2のc2へコピー
  619. // 次は,
  620. // 親1のt11からt12を子2のc2へコピー
  621. // 親2のt21からt22を子1のc1へコピー
  622. // ・・・・・
  623. c1 = 0;
  624. c2 = 0;
  625. t11 = 0;
  626. t21 = 0;
  627. // 遺伝子長
  628. k1 = Position(-1);
  629. pi_w[k1] = 1;
  630. len[k1] = len[p1];
  631. k2 = Position(-1);
  632. pi_w[k2] = 1;
  633. len[k2] = len[p2];
  634.  
  635. for (i2 = 0; i2 < num+1; i2++ ) {
  636. // 次の交叉位置を求める
  637. if (i2 == num) { // 最後
  638. t12 = len[p1];
  639. t22 = len[p2];
  640. }
  641. else {
  642. // 親1
  643. t12 = max_len;
  644. for (i3 = 0; i3 < num; i3++) {
  645. if (kou1[i3] >= 0 && kou1[i3] <= t12) {
  646. t12 = kou1[i3];
  647. mn = i3;
  648. }
  649. }
  650. kou1[mn] = -1;
  651. t12++;
  652. // 親2
  653. if (k_vr == 0)
  654. t22 = t12;
  655. else {
  656. t22 = max_len;
  657. for (i3 = 0; i3 < num; i3++) {
  658. if (kou2[i3] >= 0 && kou2[i3] <= t22) {
  659. t22 = kou2[i3];
  660. mn = i3;
  661. }
  662. }
  663. kou2[mn] = -1;
  664. t22++;
  665. }
  666. }
  667. // 指定箇所のコピー
  668. for (i3 = t11; i3 < t12; i3++) {
  669. if (i2%2 == 0) {
  670. if (c1 < max_len) {
  671. ind[k1][c1] = ind[p1][i3];
  672. c1++;
  673. }
  674. }
  675. else {
  676. if (c2 < max_len) {
  677. ind[k2][c2] = ind[p1][i3];
  678. c2++;
  679. }
  680. }
  681. }
  682.  
  683. for (i3 = t21; i3 < t22; i3++) {
  684. if (i2%2 == 0) {
  685. if (c2 < max_len) {
  686. ind[k2][c2] = ind[p2][i3];
  687. c2++;
  688. }
  689. }
  690. else {
  691. if (c1 < max_len) {
  692. ind[k1][c1] = ind[p2][i3];
  693. c1++;
  694. }
  695. }
  696. }
  697. // 交叉位置の移動
  698. t11 = t12;
  699. t21 = t22;
  700. }
  701. }
  702. }
  703. }
  704.  
  705. /*******************************************************************/
  706. /* 交叉(一様交叉.[0,1]を等確率で発生させ,1であれば, */
  707. /* 親1,0であれば親2の遺伝子を子1が受け継ぐ) */
  708. /* kosa : 交叉確率 */
  709. /* k_method : 選択方法 */
  710. /* =-1 : ランダム */
  711. /* =0 : 適応度をそのまま使用 */
  712. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  713. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  714. /* k_bias : α,または,method=2の場合は初期値 */
  715. /* k_step : β */
  716. /*******************************************************************/
  717. void C_uniform(double kosa, int k_method, double k_bias, double k_step)
  718. {
  719. int i1, i2, k1, k2, p1, p2 = 0, pair, sw;
  720. /*
  721. 初期設定とデータのチェック
  722. */
  723. pair = max_ch / 2;
  724.  
  725. if (dup_a == 0) {
  726. System.out.print("***error 交叉方法が不適当 (C_uniform)\n");
  727. System.exit(1);
  728. }
  729.  
  730. if (min_len > 0) {
  731. System.out.print("***error 遺伝子長は固定長でなければならない (C_uniform)\n");
  732. System.exit(1);
  733. }
  734. /*
  735. 交叉
  736. */
  737. for (i1 = 0; i1 < pair; i1++) {
  738. // 交叉しない場合
  739. if (rn.nextDouble() > kosa)
  740. C_copy(2, 1, -1, 0.0, 0.0);
  741. // 交叉する場合
  742. else {
  743. // 親の選択
  744. p1 = Select(k_method, k_bias, k_step);
  745. sw = 0;
  746. while (sw == 0) {
  747. p2 = Select(k_method, k_bias, k_step);
  748. if (p1 != p2)
  749. sw = 1;
  750. }
  751. // 遺伝子長
  752. k1 = Position(-1);
  753. pi_w[k1] = 1;
  754. len[k1] = len[p1];
  755. k2 = Position(-1);
  756. pi_w[k2] = 1;
  757. len[k2] = len[p2];
  758. // 交叉
  759. for (i2 = 0; i2 < len[p1]; i2++) {
  760. if (rn.nextDouble() > 0.5) {
  761. ind[k1][i2] = ind[p1][i2];
  762. ind[k2][i2] = ind[p2][i2];
  763. }
  764. else {
  765. ind[k1][i2] = ind[p2][i2];
  766. ind[k2][i2] = ind[p1][i2];
  767. }
  768. }
  769. }
  770. }
  771. }
  772.  
  773. /*******************************************************************/
  774. /* 交叉(平均化交叉.2つの親の平均値を受け継ぐ) */
  775. /* kosa : 交叉確率 */
  776. /* k_method : 選択方法 */
  777. /* =-1 : ランダム */
  778. /* =0 : 適応度をそのまま使用 */
  779. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  780. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  781. /* k_bias : α,または,method=2の場合は初期値 */
  782. /* k_step : β */
  783. /*******************************************************************/
  784. void C_mean(double kosa, int k_method, double k_bias, double k_step)
  785. {
  786. int i1, i2, k, p1, p2 = 0, sw;
  787. /*
  788. 初期設定とデータのチェック
  789. */
  790. if (min_len > 0) {
  791. System.out.print("***error 遺伝子長は固定長でなければならない (C_mean)\n");
  792. System.exit(1);
  793. }
  794. /*
  795. 交叉
  796. */
  797. for (i1 = 0; i1 < max_ch; i1++) {
  798. // 交叉しない場合
  799. if (rn.nextDouble() > kosa)
  800. C_copy(1, 1, -1, 0.0, 0.0);
  801. // 交叉する場合
  802. else {
  803. // 親の選択
  804. p1 = Select(k_method, k_bias, k_step);
  805. sw = 0;
  806. while (sw == 0) {
  807. p2 = Select(k_method, k_bias, k_step);
  808. if (p1 != p2)
  809. sw = 1;
  810. }
  811. // 遺伝子長
  812. k = Position(-1);
  813. len[k] = len[p1];
  814. pi_w[k] = 1;
  815. // 交叉
  816. for (i2 = 0; i2 < len[k]; i2++)
  817. ind[k][i2] = (ind[p1][i2] + ind[p2][i2]) / 2;
  818. }
  819. }
  820. }
  821.  
  822. /*******************************************************************/
  823. /* 交叉(循環交叉.ランダムに1点を選択し,その位置にある遺伝子を */
  824. /* そのまま各子供が選択する.その位置にある親2(1)の遺伝 */
  825. /* 子を,その遺伝子の親1(2)の場所に,子1(2)が受け継 */
  826. /* ぐ(ただし,doubleの場合は,この手続きをのぞく).この手 */
  827. /* 続きを,すでに受け継いだ遺伝子の位置が選択されるまで繰り */
  828. /* 返し,残りの遺伝子については,子1(2)は,親2(1)の */
  829. /* 遺伝子をその順番通りに受け継ぐ) */
  830. /* 2 4 1 3 6 5 + + 1 + + 5 3 2 1 4 6 5 */
  831. /* * → → */
  832. /* 3 2 5 4 1 6 + + 5 + 1 + 2 4 5 3 1 6 */
  833. /* kosa : 交叉確率 */
  834. /* k_method : 選択方法 */
  835. /* =-1 : ランダム */
  836. /* =0 : 適応度をそのまま使用 */
  837. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  838. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  839. /* k_bias : α,または,method=2の場合は初期値 */
  840. /* k_step : β */
  841. /*******************************************************************/
  842. void C_cycle(double kosa, int k_method, double k_bias, double k_step)
  843. {
  844. int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
  845. /*
  846. 初期設定とデータのチェック
  847. */
  848. pair = max_ch / 2;
  849.  
  850. if (dup_a != 0) {
  851. System.out.print("***error 交叉方法が不適当 (C_cycle)\n");
  852. System.exit(1);
  853. }
  854.  
  855. if (min_len > 0) {
  856. System.out.print("***error 遺伝子長は固定長でなければならない (C_cycle)\n");
  857. System.exit(1);
  858. }
  859. /*
  860. 交叉
  861. */
  862. for (i1 = 0; i1 < pair; i1++) {
  863. // 交叉しない場合
  864. if (rn.nextDouble() > kosa)
  865. C_copy(2, 1, -1, 0.0, 0.0);
  866. // 交叉する場合
  867. else {
  868. // 親の選択
  869. p1 = Select(k_method, k_bias, k_step);
  870. sw = 0;
  871. while (sw == 0) {
  872. p2 = Select(k_method, k_bias, k_step);
  873. if (p1 != p2)
  874. sw = 1;
  875. }
  876. // 初期設定
  877. for (i2 = 0; i2 < len[p1]; i2++) {
  878. kou1[i2] = 0;
  879. kou2[i2] = 0;
  880. }
  881. // 遺伝子長
  882. k1 = Position(-1);
  883. pi_w[k1] = 1;
  884. len[k1] = len[p1];
  885. k2 = Position(-1);
  886. pi_w[k2] = 1;
  887. len[k2] = len[p2];
  888. // 交叉
  889. sw = 0;
  890.  
  891. while (sw == 0) {
  892. sw = 1;
  893. p = (int)(rn.nextDouble() * len[p1]);
  894. if (p >= len[p1])
  895. p = len[p1] - 1;
  896. if (kou1[p] == 0 && kou2[p] == 0) {
  897. kou1[p] = 1;
  898. kou2[p] = 1;
  899. ind[k1][p] = ind[p1][p];
  900. ind[k2][p] = ind[p2][p];
  901. for (i2 = 0; i2 < len[p1] && sw > 0; i2++) {
  902. if (ind[p2][p] == ind[p1][i2]) {
  903. ind[k1][i2] = ind[p1][i2];
  904. kou1[i2] = 1;
  905. sw = 0;
  906. }
  907. }
  908. sw = 1;
  909. for (i2 = 0; i2 < len[p2] && sw > 0; i2++) {
  910. if (ind[p1][p] == ind[p2][i2]) {
  911. ind[k2][i2] = ind[p2][i2];
  912. kou2[i2] = 1;
  913. sw = 0;
  914. }
  915. }
  916. }
  917. }
  918.  
  919. sw = 0;
  920. i2 = 0;
  921. i3 = 0;
  922. while (sw == 0) {
  923. while (sw == 0 && i2 < len[p1]) {
  924. if (kou1[i2] == 0)
  925. sw = 1;
  926. else
  927. i2++;
  928. }
  929. sw = 0;
  930. while (sw == 0 && i3 < len[p2]) {
  931. if (kou2[i3] == 0)
  932. sw = 1;
  933. else
  934. i3++;
  935. }
  936. if (i2 < len[p1] && i3 < len[p2]) {
  937. ind[k1][i2] = ind[p2][i3];
  938. ind[k2][i3] = ind[p1][i2];
  939. sw = 0;
  940. i2++;
  941. i3++;
  942. }
  943. else
  944. sw = 1;
  945. }
  946. }
  947. }
  948. }
  949.  
  950. /*******************************************************************/
  951. /* 交叉(部分的交叉.ランダムに1点を選択し,その位置にある親1と */
  952. /* 親2の遺伝子を取り出す.次に,親1と親2の染色体上で,こ */
  953. /* の2つの遺伝子の位置を交換する.この操作を,選択した点よ */
  954. /* り右にあるすべての遺伝子に対して実施する */
  955. /* 2 4 1 3 6 5 2 4 5 3 6 1 */
  956. /* * → → ・・・・・ */
  957. /* 3 2 5 4 1 6 3 2 1 4 5 6 */
  958. /* kosa : 交叉確率 */
  959. /* k_method : 選択方法 */
  960. /* =-1 : ランダム */
  961. /* =0 : 適応度をそのまま使用 */
  962. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  963. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  964. /* k_bias : α,または,method=2の場合は初期値 */
  965. /* k_step : β */
  966. /*******************************************************************/
  967. void C_part(double kosa, int k_method, double k_bias, double k_step)
  968. {
  969. int i1, i2, i3, k1, k2, lv, p, pair, p1, p2 = 0, sw;
  970. /*
  971. 初期設定とデータのチェック
  972. */
  973. pair = max_ch / 2;
  974.  
  975. if (dup_a != 0) {
  976. System.out.print("***error 交叉方法が不適当 (C_part)\n");
  977. System.exit(1);
  978. }
  979.  
  980. if (min_len > 0) {
  981. System.out.print("***error 遺伝子長は固定長でなければならない (C_part)\n");
  982. System.exit(1);
  983. }
  984. /*
  985. 交叉
  986. */
  987. for (i1 = 0; i1 < pair; i1++) {
  988. // 交叉しない場合
  989. if (rn.nextDouble() > kosa)
  990. C_copy(2, 1, -1, 0.0, 0.0);
  991. // 交叉する場合
  992. else {
  993. // 親の選択
  994. p1 = Select(k_method, k_bias, k_step);
  995. sw = 0;
  996. while (sw == 0) {
  997. p2 = Select(k_method, k_bias, k_step);
  998. if (p1 != p2)
  999. sw = 1;
  1000. }
  1001. // 遺伝子長
  1002. k1 = Position(-1);
  1003. pi_w[k1] = 1;
  1004. len[k1] = len[p1];
  1005. k2 = Position(-1);
  1006. pi_w[k2] = 1;
  1007. len[k2] = len[p2];
  1008. // 交叉
  1009. p = (int)(rn.nextDouble() * len[p1]);
  1010. if (p >= len[p1])
  1011. p = len[p1] - 1;
  1012.  
  1013. for (i2 = 0; i2 < len[p1]; i2++) {
  1014. ind[k1][i2] = ind[p1][i2];
  1015. ind[k2][i2] = ind[p2][i2];
  1016. }
  1017.  
  1018. for (i2 = p; i2 < len[p1]; i2++) {
  1019. sw = 0;
  1020. lv = ind[k1][i2];
  1021. for (i3 = 0; i3 < len[p1] && sw == 0; i3++) {
  1022. if (ind[k2][i2] == ind[k1][i3]) {
  1023. ind[k1][i2] = ind[k1][i3];
  1024. ind[k1][i3] = lv;
  1025. sw = 1;
  1026. }
  1027. }
  1028. sw = 0;
  1029. for (i3 = 0; i3 < len[p1] && sw == 0; i3++) {
  1030. if (lv == ind[k2][i3]) {
  1031. ind[k2][i3] = ind[k2][i2];
  1032. ind[k2][i2] = lv;
  1033. sw = 1;
  1034. }
  1035. }
  1036. }
  1037. }
  1038. }
  1039. }
  1040.  
  1041. /*******************************************************************/
  1042. /* 交叉(順序交叉.ランダムに切れ目を決定し,子1に対し,切れ目の */
  1043. /* 左側では,親1の遺伝子をそのまま受け継ぎ,右側では,親1 */
  1044. /* の遺伝子を親2の遺伝子の出現順序に並べ替える. */
  1045. /* 2 4 1 3 6 5 2 4 1 3 5 6 */
  1046. /* * → */
  1047. /* 3 2 5 4 1 6 3 2 5 4 1 6 */
  1048. /* kosa : 交叉確率 */
  1049. /* k_method : 選択方法 */
  1050. /* =-1 : ランダム */
  1051. /* =0 : 適応度をそのまま使用 */
  1052. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  1053. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  1054. /* k_bias : α,または,method=2の場合は初期値 */
  1055. /* k_step : β */
  1056. /*******************************************************************/
  1057. void C_seq(double kosa, int k_method, double k_bias, double k_step)
  1058. {
  1059. int i1, i2, i3, i4, k1, k2, p, pair, pp, p1, p2 = 0, sw;
  1060. /*
  1061. 初期設定とデータのチェック
  1062. */
  1063. pair = max_ch / 2;
  1064.  
  1065. if (dup_a != 0) {
  1066. System.out.print("***error 交叉方法が不適当 (C_seq)\n");
  1067. System.exit(1);
  1068. }
  1069.  
  1070. if (min_len > 0) {
  1071. System.out.print("***error 遺伝子長は固定長でなければならない (C_seq)\n");
  1072. System.exit(1);
  1073. }
  1074. /*
  1075. 交叉
  1076. */
  1077. for (i1 = 0; i1 < pair; i1++) {
  1078. // 交叉しない場合
  1079. if (rn.nextDouble() > kosa)
  1080. C_copy(2, 1, -1, 0.0, 0.0);
  1081. // 交叉する場合
  1082. else {
  1083. // 親の選択
  1084. p1 = Select(k_method, k_bias, k_step);
  1085. sw = 0;
  1086. while (sw == 0) {
  1087. p2 = Select(k_method, k_bias, k_step);
  1088. if (p1 != p2)
  1089. sw = 1;
  1090. }
  1091. // 遺伝子長
  1092. k1 = Position(-1);
  1093. pi_w[k1] = 1;
  1094. len[k1] = len[p1];
  1095. k2 = Position(-1);
  1096. pi_w[k2] = 1;
  1097. len[k2] = len[p2];
  1098. // 交叉
  1099. p = (int)(rn.nextDouble() * (len[p1] - 1));
  1100. if (p >= len[p1]-1)
  1101. p = len[p1] - 2;
  1102.  
  1103. for (i2 = 0; i2 <= p; i2++) {
  1104. ind[k1][i2] = ind[p1][i2];
  1105. ind[k2][i2] = ind[p2][i2];
  1106. }
  1107.  
  1108. pp = 0;
  1109. for (i2 = p+1; i2 < len[p1]; i2++) {
  1110. sw = 0;
  1111. for (i3 = pp; i3 < len[p2] && sw == 0; i3++) {
  1112. for (i4 = p+1; i4 < len[p1] && sw == 0; i4++) {
  1113. if (ind[p2][i3] == ind[p1][i4]) {
  1114. sw = 1;
  1115. pp = i3 + 1;
  1116. ind[k1][i2] = ind[p1][i4];
  1117. }
  1118. }
  1119. }
  1120. }
  1121. pp = 0;
  1122. for (i2 = p+1; i2 < len[p2]; i2++) {
  1123. sw = 0;
  1124. for (i3 = pp; i3 < len[p1] && sw == 0; i3++) {
  1125. for (i4 = p+1; i4 < len[p2] && sw == 0; i4++) {
  1126. if (ind[p1][i3] == ind[p2][i4]) {
  1127. sw = 1;
  1128. pp = i3 + 1;
  1129. ind[k2][i2] = ind[p2][i4];
  1130. }
  1131. }
  1132. }
  1133. }
  1134. }
  1135. }
  1136. }
  1137.  
  1138. /*******************************************************************/
  1139. /* 交叉(一様順序交叉.位置の集合をランダムに選択し,一方の親の選 */
  1140. /* 択された位置における遺伝子の順序に従って,他の親の遺伝子 */
  1141. /* を並べ替える */
  1142. /* 2 4 1 3 6 5 2 4 1 3 6 5 */
  1143. /* * * → */
  1144. /* 3 2 5 4 1 6 4 2 5 3 1 6 */
  1145. /* kosa : 交叉確率 */
  1146. /* k_method : 選択方法 */
  1147. /* =-1 : ランダム */
  1148. /* =0 : 適応度をそのまま使用 */
  1149. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  1150. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  1151. /* k_bias : α,または,method=2の場合は初期値 */
  1152. /* k_step : β */
  1153. /*******************************************************************/
  1154. void C_useq(double kosa, int k_method, double k_bias, double k_step)
  1155. {
  1156. int i1, i2, i3, i4, k1, k2, p, pair, p1, p2 = 0, sw;
  1157. /*
  1158. 初期設定とデータのチェック
  1159. */
  1160. pair = max_ch / 2;
  1161.  
  1162. if (dup_a != 0) {
  1163. System.out.print("***error 交叉方法が不適当 (C_useq)\n");
  1164. System.exit(1);
  1165. }
  1166.  
  1167. if (min_len > 0) {
  1168. System.out.print("***error 遺伝子長は固定長でなければならない (C_useq)\n");
  1169. System.exit(1);
  1170. }
  1171. /*
  1172. 交叉
  1173. */
  1174. for (i1 = 0; i1 < pair; i1++) {
  1175. // 交叉しない場合
  1176. if (rn.nextDouble() > kosa)
  1177. C_copy(2, 1, -1, 0.0, 0.0);
  1178. // 交叉する場合
  1179. else {
  1180. // 親の選択
  1181. p1 = Select(k_method, k_bias, k_step);
  1182. sw = 0;
  1183. while (sw == 0) {
  1184. p2 = Select(k_method, k_bias, k_step);
  1185. if (p1 != p2)
  1186. sw = 1;
  1187. }
  1188. // 遺伝子長
  1189. k1 = Position(-1);
  1190. pi_w[k1] = 1;
  1191. len[k1] = len[p1];
  1192. k2 = Position(-1);
  1193. pi_w[k2] = 1;
  1194. len[k2] = len[p2];
  1195. // 交叉
  1196. for (i2 = 0; i2 < len[p1]; i2++) {
  1197. ind[k1][i2] = ind[p1][i2];
  1198. ind[k2][i2] = ind[p2][i2];
  1199. kou1[i2] = (rn.nextDouble() < 0.5) ? 0 : 1;
  1200. }
  1201.  
  1202. p = 0;
  1203. for (i2 = 0; i2 < len[p1]; i2++) {
  1204. if (kou1[i2] > 0) {
  1205. sw = 0;
  1206. for (i3 = p; i3 < len[p2] && sw == 0; i3++) {
  1207. for (i4 = 0; i4 < len[p1] && sw == 0; i4++) {
  1208. if (ind[p2][i3] == ind[p1][i4] && kou1[i4] > 0) {
  1209. sw = 1;
  1210. p = i3 + 1;
  1211. ind[k1][i2] = ind[p1][i4];
  1212. }
  1213. }
  1214. }
  1215. }
  1216. }
  1217. p = 0;
  1218. for (i2 = 0; i2 < len[p2]; i2++) {
  1219. if (kou1[i2] > 0) {
  1220. sw = 0;
  1221. for (i3 = p; i3 < len[p1] && sw == 0; i3++) {
  1222. for (i4 = 0; i4 < len[p2] && sw == 0; i4++) {
  1223. if (ind[p1][i3] == ind[p2][i4] && kou1[i4] > 0) {
  1224. sw = 1;
  1225. p = i3 + 1;
  1226. ind[k2][i2] = ind[p2][i4];
  1227. }
  1228. }
  1229. }
  1230. }
  1231. }
  1232. }
  1233. }
  1234. }
  1235.  
  1236. /*******************************************************************/
  1237. /* 交叉(一様位置交叉.位置の集合をランダムに選択し,一方の親の選 */
  1238. /* 択された位置における遺伝子の位置に,他の親の同じ遺伝子を */
  1239. /* 配置する.残りの遺伝子は,親と同じ順序に配置する. */
  1240. /* 2 4 1 3 6 5 + + 5 + 1 + 2 4 5 3 1 6 */
  1241. /* * * → → */
  1242. /* 3 2 5 4 1 6 + + 1 + 6 + 3 2 1 5 6 4 */
  1243. /* kosa : 交叉確率 */
  1244. /* k_method : 選択方法 */
  1245. /* =-1 : ランダム */
  1246. /* =0 : 適応度をそのまま使用 */
  1247. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  1248. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  1249. /* k_bias : α,または,method=2の場合は初期値 */
  1250. /* k_step : β */
  1251. /*******************************************************************/
  1252. void C_upos(double kosa, int k_method, double k_bias, double k_step)
  1253. {
  1254. int i1, i2, i3, k1, k2, p, pair, p1, p2 = 0, sw;
  1255. /*
  1256. 初期設定とデータのチェック
  1257. */
  1258. pair = max_ch / 2;
  1259.  
  1260. if (dup_a != 0) {
  1261. System.out.print("***error 交叉方法が不適当 (C_upos)\n");
  1262. System.exit(1);
  1263. }
  1264.  
  1265. if (min_len > 0) {
  1266. System.out.print("***error 遺伝子長は固定長でなければならない (C_upos)\n");
  1267. System.exit(1);
  1268. }
  1269. /*
  1270. 交叉
  1271. */
  1272. for (i1 = 0; i1 < pair; i1++) {
  1273. // 交叉しない場合
  1274. if (rn.nextDouble() > kosa)
  1275. C_copy(2, 1, -1, 0.0, 0.0);
  1276. // 交叉する場合
  1277. else {
  1278. // 親の選択
  1279. p1 = Select(k_method, k_bias, k_step);
  1280. sw = 0;
  1281. while (sw == 0) {
  1282. p2 = Select(k_method, k_bias, k_step);
  1283. if (p1 != p2)
  1284. sw = 1;
  1285. }
  1286. // 遺伝子長
  1287. k1 = Position(-1);
  1288. pi_w[k1] = 1;
  1289. len[k1] = len[p1];
  1290. k2 = Position(-1);
  1291. pi_w[k2] = 1;
  1292. len[k2] = len[p2];
  1293. // 交叉
  1294. for (i2 = 0; i2 < len[p1]; i2++) {
  1295. kou1[i2] = (rn.nextDouble() < 0.5) ? 0 : 1;
  1296. if (kou1[i2] > 0) {
  1297. ind[k1][i2] = ind[p2][i2];
  1298. ind[k2][i2] = ind[p1][i2];
  1299. }
  1300. }
  1301.  
  1302. p = 0;
  1303. for (i2 = 0; i2 < len[p1]; i2++) {
  1304. sw = 0;
  1305. for (i3 = 0; i3 < len[p1] && sw == 0; i3++) {
  1306. if (kou1[i3] > 0 && ind[p1][i2] == ind[k1][i3])
  1307. sw = 1;
  1308. }
  1309. if (sw == 0) {
  1310. for (i3 = p; i3 < len[p1] && sw == 0; i3++) {
  1311. if (kou1[i3] == 0) {
  1312. ind[k1][i3] = ind[p1][i2];
  1313. p = i3 + 1;
  1314. sw = 1;
  1315. }
  1316. }
  1317. }
  1318. }
  1319. p = 0;
  1320. for (i2 = 0; i2 < len[p2]; i2++) {
  1321. sw = 0;
  1322. for (i3 = 0; i3 < len[p2] && sw == 0; i3++) {
  1323. if (kou1[i3] > 0 && ind[p2][i2] == ind[k2][i3])
  1324. sw = 1;
  1325. }
  1326. if (sw == 0) {
  1327. for (i3 = p; i3 < len[p2] && sw == 0; i3++) {
  1328. if (kou1[i3] == 0) {
  1329. ind[k2][i3] = ind[p2][i2];
  1330. p = i3 + 1;
  1331. sw = 1;
  1332. }
  1333. }
  1334. }
  1335. }
  1336. }
  1337. }
  1338. }
  1339.  
  1340. /*******************************************************************/
  1341. /* 交叉(エッジ組み替え交叉.以下の手順に従って行う.対立遺伝子は */
  1342. /* 0~(max_len-1)である必要がある) */
  1343. /* (0) エッジマップを作成する.エッジマップとは,2つの親 */
  1344. /* を見て,ノードがどこに接続されているのかを表すもの */
  1345. /* であり,例えば,2つの親が, */
  1346. /* [A B C D E F] */
  1347. /* [B D C A E F] */
  1348. /* である場合は, */
  1349. /* A : B F C E */
  1350. /* B : A C D F */
  1351. /* C : B D A */
  1352. /* D : C E B */
  1353. /* E : D F A */
  1354. /* F : A E B */
  1355. /* となる. */
  1356. /* (1) 両親の2つの出発点の内1つで初期化する.ランダムま */
  1357. /* たはステップ(4)の基準に従って選ぶ(現在のノード) */
  1358. /* (2) エッジマップから,現在のノードを除く */
  1359. /* (3) 現在のノードが接続先のノードを持っていたら,(4)に */
  1360. /* 進む.さもなければ,(5)に進む */
  1361. /* (4) 現在のノードが持っている接続先ノードの内,最も少な */
  1362. /* い接続先ノードを持ったノードを選択し(同じ条件の場 */
  1363. /* 合は,ランダム),それを現在のノードとし,(2)に進む */
  1364. /* (5) 未接続のノードが残っていればランダムに選択し,(2)に */
  1365. /* 戻る.さもなければ,終了する */
  1366. /* kosa : 交叉確率 */
  1367. /* k_method : 選択方法 */
  1368. /* =-1 : ランダム */
  1369. /* =0 : 適応度をそのまま使用 */
  1370. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  1371. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  1372. /* k_bias : α,または,method=2の場合は初期値 */
  1373. /* k_step : β */
  1374. /*******************************************************************/
  1375. void C_edge(double kosa, int k_method, double k_bias, double k_step)
  1376. {
  1377. int i1, i2, i3, i4, i5, k, kk, k0 = 0, k1, k2, min, num,
  1378. p, pair, p1, p2 = 0, sw;
  1379. int e[] = new int [2];
  1380. /*
  1381. 初期設定とデータのチェック
  1382. */
  1383. pair = max_ch;
  1384.  
  1385. if (dup_a != 0) {
  1386. System.out.print("***error 交叉方法が不適当 (C_edge)\n");
  1387. System.exit(1);
  1388. }
  1389.  
  1390. if (min_len > 0) {
  1391. System.out.print("***error 遺伝子長は固定長でなければならない (C_edge)\n");
  1392. System.exit(1);
  1393. }
  1394. /*
  1395. 交叉
  1396. */
  1397. for (i1 = 0; i1 < pair; i1++) {
  1398. // 交叉しない場合
  1399. if (rn.nextDouble() > kosa)
  1400. C_copy(1, 1, -1, 0.0, 0.0);
  1401. // 交叉する場合
  1402. else {
  1403. // 親の選択
  1404. p1 = Select(k_method, k_bias, k_step);
  1405. sw = 0;
  1406. while (sw == 0) {
  1407. p2 = Select(k_method, k_bias, k_step);
  1408. if (p1 != p2)
  1409. sw = 1;
  1410. }
  1411. // 遺伝子長
  1412. k = Position(-1);
  1413. pi_w[k] = 1;
  1414. len[k] = len[p1];
  1415. // エッジマップの初期化
  1416. for (i2 = 0; i2 < len[k]; i2++) {
  1417. edge[i2][0] = 0;
  1418. for (i3 = 1; i3 <= 4; i3++)
  1419. edge[i2][i3] = -1;
  1420. }
  1421. // 交叉
  1422. // エッジマップの作成
  1423. for (i2 = 0; i2 < len[k]; i2++) {
  1424.  
  1425. sw = 0;
  1426. for (i3 = 0; i3 < len[k] && sw == 0; i3++) {
  1427. if (i2 == ind[p1][i3]) {
  1428. sw = 1;
  1429. if (i3 == 0) {
  1430. e[0] = ind[p1][len[k]-1];
  1431. e[1] = ind[p1][1];
  1432. }
  1433. else {
  1434. if (i3 == len[k]-1) {
  1435. e[0] = ind[p1][i3-1];
  1436. e[1] = ind[p1][0];
  1437. }
  1438. else {
  1439. e[0] = ind[p1][i3-1];
  1440. e[1] = ind[p1][i3+1];
  1441. }
  1442. }
  1443. for (i4 = 0; i4 < 2; i4++) {
  1444. edge[i2][0]++;
  1445. edge[i2][edge[i2][0]] = e[i4];
  1446. }
  1447. }
  1448. }
  1449.  
  1450. sw = 0;
  1451. for (i3 = 0; i3 < len[k] && sw == 0; i3++) {
  1452. if (i2 == ind[p2][i3]) {
  1453. sw = 1;
  1454. if (i3 == 0) {
  1455. e[0] = ind[p2][len[k]-1];
  1456. e[1] = ind[p2][1];
  1457. }
  1458. else {
  1459. if (i3 == len[k]-1) {
  1460. e[0] = ind[p2][i3-1];
  1461. e[1] = ind[p2][0];
  1462. }
  1463. else {
  1464. e[0] = ind[p2][i3-1];
  1465. e[1] = ind[p2][i3+1];
  1466. }
  1467. }
  1468. for (i4 = 0; i4 < 2; i4++) {
  1469. sw = 1;
  1470. for (i5 = 1; i5 <= edge[i2][0] && sw == 1; i5++) {
  1471. if (edge[i2][i5] == e[i4])
  1472. sw = 2;
  1473. }
  1474. if (sw == 1) {
  1475. edge[i2][0]++;
  1476. edge[i2][edge[i2][0]] = e[i4];
  1477. }
  1478. }
  1479. }
  1480. }
  1481. }
  1482. // 交叉の実行
  1483. // 出発点の決定
  1484. k1 = ind[p1][0];
  1485. k2 = ind[p2][0];
  1486. if (edge[k1][0] == edge[k2][0])
  1487. kk = (rn.nextDouble() > 0.5) ? k2 : k1;
  1488. else
  1489. kk = (edge[k1][0] < edge[k2][0]) ? k1 : k2;
  1490. ind[k][0] = kk;
  1491. p = 1;
  1492.  
  1493. while (p < len[k]) {
  1494. // ノードの除去
  1495. for (i2 = 0; i2 < len[k]; i2++) {
  1496. sw = 0;
  1497. if (edge[i2][0] > 0) {
  1498. for (i3 = 1; i3 <= 4 && sw == 0; i3++) {
  1499. if (edge[i2][i3] == kk) {
  1500. sw = 1;
  1501. edge[i2][i3] = -1;
  1502. edge[i2][0]--;
  1503. }
  1504. }
  1505. }
  1506. }
  1507. // 次の現在ノードの選択
  1508. min = 10;
  1509. num = 0;
  1510. for (i2 = 1; i2 <= 4; i2++) {
  1511. if (edge[kk][i2] >= 0) {
  1512. k1 = edge[kk][i2];
  1513. if (edge[k1][0] >= 0 && edge[k1][0] < min) {
  1514. num = 1;
  1515. min = edge[k1][0];
  1516. k0 = k1;
  1517. }
  1518. else {
  1519. if (edge[k1][0] == min)
  1520. num++;
  1521. }
  1522. }
  1523. }
  1524. if (num > 1) {
  1525. k1 = (int)(rn.nextDouble() * num) + 1;
  1526. if (k1 > num)
  1527. k1 = num;
  1528. k2 = 0;
  1529. k0 = -1;
  1530. for (i2 = 1; i2 <= 4 && k0 < 0; i2++) {
  1531. if (edge[kk][i2] >= 0) {
  1532. if (edge[edge[kk][i2]][0] == min) {
  1533. k2++;
  1534. if (k1 == k2)
  1535. k0 = edge[kk][i2];
  1536. }
  1537. }
  1538. }
  1539. }
  1540. else {
  1541. if (num <= 0) {
  1542. num = 0;
  1543. for (i2 = 0; i2 < len[k]; i2++) {
  1544. if (i2 != kk && edge[i2][0] >= 0)
  1545. num++;
  1546. }
  1547. if (num <= 0) {
  1548. System.out.print("***error invalid data (C_edge)\n");
  1549. System.exit(1);
  1550. }
  1551. else {
  1552. k1 = (int)(rn.nextDouble() * num) + 1;
  1553. if (k1 > num)
  1554. k1 = num;
  1555. k2 = 0;
  1556. k0 = -1;
  1557. for (i2 = 0; i2 < len[k] && k0 < 0; i2++) {
  1558. if (i2 != kk && edge[i2][0] >= 0) {
  1559. k2++;
  1560. if (k1 == k2)
  1561. k0 = i2;
  1562. }
  1563. }
  1564. }
  1565. }
  1566. }
  1567. edge[kk][0] = -1;
  1568. ind[k][p] = k0;
  1569. kk = k0;
  1570. p++;
  1571. }
  1572. }
  1573. }
  1574. }
  1575.  
  1576. /*************************************************************/
  1577. /* 交叉(サブツアー交叉.2点交叉の拡張である.ただし,相手に*/
  1578. /* 同じ遺伝子のグループがない限り実行されない.たとえば*/
  1579. /* ***abcd** */
  1580. /* *cdab**** */
  1581. /* のような両親の時実行され,以下の4つの子供が生成され*/
  1582. /* る) */
  1583. /* ***cdab** */
  1584. /* *abcd**** */
  1585. /* ***badc** */
  1586. /* *dcba**** */
  1587. /* 最大,4*交叉回数*個体総数*(個体総数-1) 個の子 */
  1588. /* 供が生成される可能性があるので,子供の数としてこの値*/
  1589. /* 以上のデータを入力しておく必要がある. */
  1590. /* kosa : 交叉確率 */
  1591. /* count : 1つのペアーに対する交差回数 */
  1592. /*************************************************************/
  1593. void C_sub(double kosa, int count)
  1594. {
  1595. int i1, i2, i3, i4, i5, k1, k2, k3, k4, p1, p2,
  1596. t11, t12 = 0, t21, t22 = 0, sw;
  1597. /*
  1598. 初期設定とデータのチェック
  1599. */
  1600. if ((4*count*size*(size-1)) > max_ch) {
  1601. System.out.print("***error 子供が多すぎる (C_sub)\n");
  1602. System.exit(1);
  1603. }
  1604. /*
  1605. 交叉
  1606. */
  1607. for (i1 = 0; i1 < size-1; i1++) {
  1608. // 親1
  1609. p1 = Position(i1);
  1610.  
  1611. if (p1 >= 0) {
  1612.  
  1613. for (i2 = i1; i2 < size; i2++) {
  1614. // 親2
  1615. p2 = Position(i2);
  1616.  
  1617. if (p2 >= 0) {
  1618. // 交叉しない場合
  1619. if (rn.nextDouble() > kosa)
  1620. C_copy(2, 1, -1, 0.0, 0.0);
  1621. // 交叉する場合
  1622. else {
  1623. // 交叉回数の制御
  1624. for (i3 = 0; i3 < count; i3++) {
  1625. // 交叉位置の決定(点の後ろで交叉)
  1626. // 親1の交叉位置
  1627. t11 = (int)(rn.nextDouble() * len[p1]);
  1628. if (t11 > (len[p1]-1))
  1629. t11 = len[p1] - 1;
  1630. sw = 0;
  1631. while (sw == 0) {
  1632. t12 = (int)(rn.nextDouble() * len[p1]);
  1633. if (t12 > (len[p1]-1))
  1634. t12 = len[p1] - 1;
  1635. if (t12 != t11)
  1636. sw = 1;
  1637. }
  1638. if (t11 > t12) {
  1639. k1 = t11;
  1640. t11 = t12;
  1641. t12 = k1;
  1642. }
  1643. // 親2の交叉位置
  1644. sw = 0;
  1645. t21 = -1;
  1646. for (i4 = 0; i4 < len[p2] && t21 < 0; i4++) {
  1647. for (i5 = t11; i5 <= t12 && t21 < 0; i5++) {
  1648. if (ind[p2][i4] == ind[p1][i5])
  1649. t21 = i4;
  1650. }
  1651. }
  1652. if (t21 >= 0) {
  1653. t22 = t21 + t12 - t11;
  1654. if (t22 < len[p2]) {
  1655. sw = 1;
  1656. for (i4 = t21+1; i4 <= t22 && sw > 0; i4++) {
  1657. sw = 0;
  1658. for (i5 = t11; i5 <= t12 && sw == 0; i5++) {
  1659. if (ind[p2][i4] == ind[p1][i5])
  1660. sw = 1;
  1661. }
  1662. }
  1663. }
  1664. }
  1665. // 交叉の実行
  1666. if (sw > 0) {
  1667.  
  1668. k1 = Position(-1);
  1669. pi_w[k1] = 1;
  1670. len[k1] = len[p1];
  1671. k2 = Position(-1);
  1672. pi_w[k2] = 1;
  1673. len[k2] = len[p1];
  1674. k3 = Position(-1);
  1675. pi_w[k3] = 1;
  1676. len[k3] = len[p2];
  1677. k4 = Position(-1);
  1678. pi_w[k4] = 1;
  1679. len[k4] = len[p2];
  1680.  
  1681. for (i4 = 0; i4 < t11; i4++) {
  1682. ind[k1][i4] = ind[p1][i4];
  1683. ind[k2][i4] = ind[p1][i4];
  1684. }
  1685. for (i4 = t11; i4 <= t12; i4++) {
  1686. ind[k1][i4] = ind[p2][t21+i4-t11];
  1687. ind[k2][i4] = ind[p2][t22-i4+t11];
  1688. }
  1689. for (i4 = t12+1; i4 < len[p1]; i4++) {
  1690. ind[k1][i4] = ind[p1][i4];
  1691. ind[k2][i4] = ind[p1][i4];
  1692. }
  1693. for (i4 = 0; i4 < t21; i4++) {
  1694. ind[k3][i4] = ind[p2][i4];
  1695. ind[k4][i4] = ind[p2][i4];
  1696. }
  1697. for (i4 = t21; i4 <= t22; i4++) {
  1698. ind[k3][i4] = ind[p1][t11+i4-t21];
  1699. ind[k4][i4] = ind[p1][t12-i4+t21];
  1700. }
  1701. for (i4 = t22+1; i4 < len[p2]; i4++) {
  1702. ind[k3][i4] = ind[p2][i4];
  1703. ind[k4][i4] = ind[p2][i4];
  1704. }
  1705. }
  1706. }
  1707. }
  1708. }
  1709. }
  1710. }
  1711. }
  1712. }
  1713.  
  1714. /**************************************/
  1715. /* 突然変異(対立遺伝子との置き換え) */
  1716. /* pr : 突然変異率 */
  1717. /**************************************/
  1718. void M_alle(double pr)
  1719. {
  1720. int i1, i2, lid;
  1721. /*
  1722. データのチェックと初期設定
  1723. */
  1724. if (dup_a == 0) {
  1725. System.out.print("***error 突然変異方法が不適当 (M_alle)\n");
  1726. System.exit(1);
  1727. }
  1728. /*
  1729. 実行
  1730. */
  1731. for (i1 = 0; i1 < size+max_ch; i1++) {
  1732. if (pi_w[i1] == 1) {
  1733. for (i2 = 0; i2 < len[i1]; i2++) {
  1734. if (rn.nextDouble() <= pr) {
  1735. lid = (int)(rn.nextDouble() * (allele_u - allele_l + 1) + allele_l);
  1736. if (lid > allele_u)
  1737. lid = allele_u;
  1738. if (lid != ind[i1][i2])
  1739. ind[i1][i2] = lid;
  1740. }
  1741. }
  1742. }
  1743. }
  1744. }
  1745.  
  1746. /**********************************************************************/
  1747. /* 突然変異(移動.2点を選択し,2番目の遺伝子を1番目の遺伝子の前に */
  1748. /* 移動する) */
  1749. /* pr : 突然変異率 */
  1750. /**********************************************************************/
  1751. void M_move(double pr)
  1752. {
  1753. int i1, i2, ld, p1, p2 = 0, sw;
  1754.  
  1755. for (i1 = 0; i1 < size+max_ch; i1++) {
  1756.  
  1757. if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
  1758. /*
  1759. 位置の決定
  1760. */
  1761. // p1
  1762. p1 = (int)(rn.nextDouble() * len[i1]);
  1763. if (p1 >= len[i1])
  1764. p1 = len[i1] - 1;
  1765. // p2
  1766. sw = 0;
  1767. while (sw == 0) {
  1768. p2 = (int)(rn.nextDouble() * len[i1]);
  1769. if (p2 >= len[i1])
  1770. p2 = len[i1] - 1;
  1771. if (p2 != p1)
  1772. sw = 1;
  1773. }
  1774. /*
  1775. 実行
  1776. */
  1777. if (p2 > p1) {
  1778. ld = ind[i1][p2];
  1779. for (i2 = p2; i2 > p1; i2--)
  1780. ind[i1][i2] = ind[i1][i2-1];
  1781. ind[i1][p1] = ld;
  1782. }
  1783. else {
  1784. ld = ind[i1][p2];
  1785. for (i2 = p2; i2 < p1-1; i2++)
  1786. ind[i1][i2] = ind[i1][i2+1];
  1787. ind[i1][p1-1] = ld;
  1788. }
  1789. }
  1790. }
  1791. }
  1792.  
  1793. /********************************************************/
  1794. /* 突然変異(逆位.2点間の遺伝子順序を逆に並べ替える) */
  1795. /* pr : 突然変異率 */
  1796. /* wd : >0 : 幅を固定 */
  1797. /* =0 : 幅をランダム */
  1798. /********************************************************/
  1799. void M_inv(double pr, int wd)
  1800. {
  1801. int i1, lid, p, p1, p2 = 0, sw;
  1802.  
  1803. for (i1 = 0; i1 < size+max_ch; i1++) {
  1804.  
  1805. if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
  1806. /*
  1807. 区間の決定
  1808. */
  1809. if (wd == 0) {
  1810. p1 = (int)(rn.nextDouble() * len[i1]);
  1811. if (p1 >= len[i1])
  1812. p1 = len[i1] - 1;
  1813. sw = 0;
  1814. while (sw == 0) {
  1815. p2 = (int)(rn.nextDouble() * len[i1]);
  1816. if (p2 >= len[i1])
  1817. p2 = len[i1] - 1;
  1818. if (p2 != p1)
  1819. sw = 1;
  1820. }
  1821. if (p1 > p2) {
  1822. p = p1;
  1823. p1 = p2;
  1824. p2 = p;
  1825. }
  1826. }
  1827.  
  1828. else {
  1829. p1 = len[i1];
  1830. while (p1 > len[i1]-2)
  1831. p1 = (int)(rn.nextDouble() * len[i1]);
  1832. p2 = p1 + wd - 1;
  1833. if (p2 >= len[i1])
  1834. p2 = len[i1] - 1;
  1835. }
  1836. /*
  1837. 実行
  1838. */
  1839. sw = 0;
  1840. while (sw == 0) {
  1841. lid = ind[i1][p1];
  1842. ind[i1][p1] = ind[i1][p2];
  1843. ind[i1][p2] = lid;
  1844. p1++;
  1845. p2--;
  1846. if (p1 >= p2)
  1847. sw = 1;
  1848. }
  1849. }
  1850. }
  1851. }
  1852.  
  1853. /**********************************************************************/
  1854. /* 突然変異(スクランブル.2点間の遺伝子順序をランダムに並べ替える) */
  1855. /* pr : 突然変異率 */
  1856. /* wd : >0 : 幅を固定 */
  1857. /* =0 : 幅をランダム */
  1858. /**********************************************************************/
  1859. void M_scram(double pr, int wd)
  1860. {
  1861. int i1, i2, ld, p, p1, p2 = 0, sw;
  1862.  
  1863. for (i1 = 0; i1 < size+max_ch; i1++) {
  1864.  
  1865. if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
  1866. /*
  1867. 区間の決定
  1868. */
  1869. if (wd == 0) {
  1870. p1 = (int)(rn.nextDouble() * len[i1]);
  1871. if (p1 >= len[i1])
  1872. p1 = len[i1] - 1;
  1873. sw = 0;
  1874. while (sw == 0) {
  1875. p2 = (int)(rn.nextDouble() * len[i1]);
  1876. if (p2 >= len[i1])
  1877. p2 = len[i1] - 1;
  1878. if (p2 != p1)
  1879. sw = 1;
  1880. }
  1881. if (p1 > p2) {
  1882. p = p1;
  1883. p1 = p2;
  1884. p2 = p;
  1885. }
  1886. }
  1887.  
  1888. else {
  1889. p1 = len[i1];
  1890. while (p1 > len[i1]-2)
  1891. p1 = (int)(rn.nextDouble() * len[i1]);
  1892. p2 = p1 + wd - 1;
  1893. if (p2 >= len[i1])
  1894. p2 = len[i1] - 1;
  1895. }
  1896. /*
  1897. 実行
  1898. */
  1899. for (i2 = p1; i2 <= p2; i2++) {
  1900. p = (int)(rn.nextDouble() * (p2 - p1 + 1) + p1);
  1901. if (p > p2)
  1902. p = p2;
  1903. ld = ind[i1][i2];
  1904. ind[i1][i2] = ind[i1][p];
  1905. ind[i1][p] = ld;
  1906. }
  1907. }
  1908. }
  1909. }
  1910.  
  1911. /**********************************************************************/
  1912. /* 突然変異(転座.2点間の遺伝子を他の位置のものと置き換える.ただし */
  1913. /* 重複部分はそのままとする) */
  1914. /* pr : 突然変異率 */
  1915. /* wd : >0 : 幅を固定 */
  1916. /* =0 : 幅をランダム */
  1917. /**********************************************************************/
  1918. void M_chg(double pr, int wd)
  1919. {
  1920. int i1, i2, ld, p, p1, p2, p3 = 0, p4, sw;
  1921.  
  1922. for (i1 = 0; i1 < size+max_ch; i1++) {
  1923.  
  1924. if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
  1925. /*
  1926. 区間等の決定([p1,p2]と[p3,p4]の入れ替え)
  1927. */
  1928. // p1
  1929. p1 = (int)(rn.nextDouble() * len[i1]);
  1930. if (p1 >= len[i1])
  1931. p1 = len[i1] - 1;
  1932. // p3
  1933. sw = 0;
  1934. while (sw == 0) {
  1935. p3 = (int)(rn.nextDouble() * len[i1]);
  1936. if (p3 >= len[i1])
  1937. p3 = len[i1] - 1;
  1938. if (p3 != p1)
  1939. sw = 1;
  1940. }
  1941. // 小さい方をp1,p2にする
  1942. if (p1 > p3) {
  1943. p = p1;
  1944. p1 = p3;
  1945. p3 = p;
  1946. }
  1947. // p4, p2
  1948. p4 = (wd == 0) ? (int)(rn.nextDouble() * (len[i1] - p3)) + p3 :
  1949. p1 + wd - 1;
  1950. if (p4 >= len[i1])
  1951. p4 = len[i1] - 1;
  1952. p2 = p1 + (p4 - p3);
  1953. // 重複部分のチェック
  1954. if (p2 >= p3) {
  1955. p = p3 - 1;
  1956. p3 = p2 + 1;
  1957. p2 = p;
  1958. p4 = p3 + (p2 - p1);
  1959. }
  1960. /*
  1961. 実行
  1962. */
  1963. p = p3;
  1964. for (i2 = p1; i2 <= p2; i2++) {
  1965. ld = ind[i1][i2];
  1966. ind[i1][i2] = ind[i1][p];
  1967. ind[i1][p] = ld;
  1968. p++;
  1969. }
  1970. }
  1971. }
  1972. }
  1973.  
  1974. /**********************************************************************/
  1975. /* 突然変異(重複.2点間の遺伝子を他の位置にコピーする */
  1976. /* pr : 突然変異率 */
  1977. /* wd : >0 : 幅を固定 */
  1978. /* =0 : 幅をランダム */
  1979. /**********************************************************************/
  1980. void M_dup(double pr, int wd)
  1981. {
  1982. int i1, i2, p, p1, p2, p3 = 0, p4, sw;
  1983. /*
  1984. データのチェック
  1985. */
  1986. if (dup_a == 0) {
  1987. System.out.print("***error 突然変異方法が不適当 (M_dup)\n");
  1988. System.exit(1);
  1989. }
  1990. /*
  1991. 実行
  1992. */
  1993. for (i1 = 0; i1 < size+max_ch; i1++) {
  1994.  
  1995. if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
  1996. // 区間の決定([p1,p2]を[p3,p4]にコピー)
  1997. // p1
  1998. p1 = (int)(rn.nextDouble() * len[i1]);
  1999. if (p1 >= len[i1])
  2000. p1 = len[i1] - 1;
  2001. // p3
  2002. sw = 0;
  2003. while (sw == 0) {
  2004. p3 = (int)(rn.nextDouble() * len[i1]);
  2005. if (p3 >= len[i1])
  2006. p3 = len[i1] - 1;
  2007. if (p3 != p1)
  2008. sw = 1;
  2009. }
  2010. // 区間を決める
  2011. if (p3 > p1) {
  2012. p4 = (wd == 0) ? (int)(rn.nextDouble() * (len[i1] - p3)) + p3 :
  2013. p3 + wd - 1;
  2014. if (p4 >= len[i1])
  2015. p4 = len[i1] - 1;
  2016. p2 = p1 + (p4 - p3);
  2017. }
  2018. else {
  2019. p2 = (wd == 0) ? (int)(rn.nextDouble() * (len[i1] - p1)) + p1 :
  2020. p1 + wd - 1;
  2021. if (p2 >= len[i1])
  2022. p2 = len[i1] - 1;
  2023. p4 = p3 + (p2 - p1);
  2024. }
  2025. // 実行
  2026. p = p4;
  2027. for (i2 = p2; i2 >= p1; i2--) {
  2028. ind[i1][p] = ind[i1][i2];
  2029. p--;
  2030. }
  2031. }
  2032. }
  2033. }
  2034.  
  2035. /******************************************************/
  2036. /* 突然変異(摂動.値をある量だけ変化させる) */
  2037. /* pr : 突然変異率 */
  2038. /* method : =0 : 正規分布 */
  2039. /* =1 : 一様分布 */
  2040. /* m : 平均または一様分布の下限 */
  2041. /* s : 標準偏差または一様分布の上限 */
  2042. /******************************************************/
  2043. void M_per(double pr, int method, double m, double s)
  2044. {
  2045. double w, wd = 0.0, x1;
  2046. int i1, i2;
  2047. /*
  2048. データのチェックと初期設定
  2049. */
  2050. if (dup_a == 0) {
  2051. System.out.print("***error 突然変異方法が不適当 (M_per)\n");
  2052. System.exit(1);
  2053. }
  2054.  
  2055. if (method > 0)
  2056. wd = s - m;
  2057. /*
  2058. 実行
  2059. */
  2060. for (i1 = 0; i1 < size+max_ch; i1++) {
  2061. if (pi_w[i1] == 1) {
  2062. for (i2 = 0; i2 < len[i1]; i2++) {
  2063. if (rn.nextDouble() <= pr) {
  2064. if (method == 0)
  2065. w = norm_d(m, s);
  2066. else {
  2067. w = rn.nextDouble() * wd;
  2068. if (rn.nextDouble() < 0.5)
  2069. w = -w;
  2070. }
  2071. x1 = (double)ind[i1][i2] + w;
  2072. if (x1 > allele_u)
  2073. x1 = allele_u;
  2074. else {
  2075. if (x1 < allele_l)
  2076. x1 = allele_l;
  2077. }
  2078. ind[i1][i2] = (int)x1;
  2079. }
  2080. }
  2081. }
  2082. }
  2083. }
  2084.  
  2085. /**********************************************************************/
  2086. /* 突然変異(挿入.ある長さの遺伝子を挿入する) */
  2087. /* pr : 突然変異率 */
  2088. /* wd : >0 : 幅を固定 */
  2089. /* =0 : 幅をランダム */
  2090. /**********************************************************************/
  2091. void M_ins(double pr, int wd)
  2092. {
  2093. int i1, i2, l, ld, p;
  2094. /*
  2095. データのチェック
  2096. */
  2097. if (dup_a == 0 || min_len < 0) {
  2098. System.out.print("***error 突然変異方法が不適当 (M_ins)\n");
  2099. System.exit(1);
  2100. }
  2101. /*
  2102. 実行
  2103. */
  2104. for (i1 = 0; i1 < size+max_ch; i1++) {
  2105.  
  2106. if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
  2107. // 挿入位置の決定
  2108. p = (int)(rn.nextDouble() * (len[i1]+1));
  2109. if (p > len[i1])
  2110. p = len[i1];
  2111. // 挿入する遺伝子長の決定
  2112. l = (wd == 0) ? (int)(rn.nextDouble() * (max_len - len[i1] + 1)) : wd;
  2113. if (l > max_len-len[i1])
  2114. l = max_len - len[i1];
  2115. else {
  2116. if (l <= 0)
  2117. l = 1;
  2118. }
  2119. // 実行
  2120. // 挿入場所の確保
  2121. if (p < len[i1]) {
  2122. for (i2 = len[i1]+l-1; i2 >= p; i2--)
  2123. ind[i1][i2] = ind[i1][i2-l];
  2124. }
  2125. // 挿入場所の遺伝子の決定
  2126. for (i2 = p; i2 < p+l; i2++) {
  2127. ld = (int)(rn.nextDouble() * (allele_u - allele_l + 1) + allele_l);
  2128. if (ld > allele_u)
  2129. ld = allele_u;
  2130. ind[i1][i2] = ld;
  2131. }
  2132.  
  2133. len[i1] += l;
  2134. }
  2135. }
  2136. }
  2137.  
  2138. /**********************************************************************/
  2139. /* 突然変異(削除.ある長さの遺伝子を削除する) */
  2140. /* pr : 突然変異率 */
  2141. /* wd : >0 : 幅を固定 */
  2142. /* =0 : 幅をランダム */
  2143. /**********************************************************************/
  2144. void M_del(double pr, int wd)
  2145. {
  2146. int i1, i2, l, max, p;
  2147. /*
  2148. データのチェック
  2149. */
  2150. if (dup_a == 0 || min_len < 0) {
  2151. System.out.print("***error 突然変異方法が不適当 (M_del)\n");
  2152. System.exit(1);
  2153. }
  2154. /*
  2155. 実行
  2156. */
  2157. for (i1 = 0; i1 < size+max_ch; i1++) {
  2158.  
  2159. if (pi_w[i1] == 1 && rn.nextDouble() <= pr) {
  2160. // 削除位置の決定
  2161. p = (int)(rn.nextDouble() * len[i1]);
  2162. if (p >= len[i1])
  2163. p = len[i1] - 1;
  2164. // 削除する遺伝子長の決定
  2165. max = (len[i1]-min_len < len[i1]-p) ? len[i1] - min_len : len[i1] - p;
  2166. l = (wd == 0) ? (int)(rn.nextDouble() * max + 1) : wd;
  2167. if (l > max)
  2168. l = max;
  2169. // 実行
  2170. for (i2 = 0; i2 < len[i1]-p-l; i2++)
  2171. ind[i1][p+i2] = ind[i1][p+i2+l];
  2172.  
  2173. len[i1] -= l;
  2174. }
  2175. }
  2176. }
  2177.  
  2178. /*********************************************************************/
  2179. /* 淘汰(エリート・ルーレット選択) */
  2180. /* elite : エリートで残す個体数(default=0) */
  2181. /* s_method : ルーレット板の作成方法(default=1) */
  2182. /* =0 : 適応度をそのまま使用 */
  2183. /* =1 : 最小値からの差(ただし,α以下の場合はα) */
  2184. /* =2 : 評価値に順位をつけ,減少率βで線形化 */
  2185. /* s_bias : α,または,method=2の場合は初期値(default=0) */
  2186. /* s_step : β(default=1) */
  2187. /*********************************************************************/
  2188. void S_roul(int elite, int s_method, double s_bias, double s_step)
  2189. {
  2190. int count = 0, i1, i2, i3, k = 0, max, n = 0, p, sw;
  2191. /*
  2192. 値のチェックと初期設定
  2193. */
  2194. if (s_method != 0 && s_method != 2)
  2195. s_method = 1;
  2196.  
  2197. if (elite > size) {
  2198. System.out.print("***error エリートで残す数が多すぎる (S_roul)\n");
  2199. System.exit(1);
  2200. }
  2201.  
  2202. if (s_method == 2 && s_step <= 0.0)
  2203. s_step = 1.0;
  2204.  
  2205. for (i1 = 0; i1 < size+max_ch; i1++)
  2206. s_w[i1] = 0;
  2207. /*
  2208. 重複個体を削除
  2209. */
  2210. if (dup_s == 0) {
  2211. for (i1 = 0; i1 < size+max_ch; i1++) {
  2212. if (pi_w[i1] > 0) {
  2213. for (i2 = i1+1; i2 < size+max_ch; i2++) {
  2214. if (pi_w[i2] > 0 && len[i1] == len[i2]) {
  2215. sw = 0;
  2216. for (i3 = 0; i3 < len[i1] && sw == 0; i3++) {
  2217. if (ind[i1][i3] != ind[i2][i3])
  2218. sw = 1;
  2219. }
  2220. if (sw == 0)
  2221. pi_w[i2] = 0;
  2222. }
  2223. }
  2224. }
  2225. }
  2226. }
  2227.  
  2228. for (i1 = 0; i1 < size+max_ch; i1++) {
  2229. if (pi_w[i1] > 1)
  2230. n++;
  2231. }
  2232.  
  2233. if (n < 0 || dup_s == 0 && n < size) {
  2234. System.out.print("***error 残す個体がない (S_roul)\n");
  2235. System.exit(1);
  2236. }
  2237. /*
  2238. 淘汰して残す個体を選ぶ
  2239. */
  2240. // エリートの選択
  2241. sw = 0;
  2242.  
  2243. while (k < elite && k < n && sw == 0) {
  2244. max = -1;
  2245. for (i1 = 0; i1 < size+max_ch; i1++) {
  2246. if (pi_w[i1] > 1 && s_w[i1] == 0) {
  2247. if (max < 0 || pi[i1] > pi[max])
  2248. max = i1;
  2249. }
  2250. }
  2251. if (max < 0)
  2252. sw = 1;
  2253. else {
  2254. s_w[max] = 1;
  2255. k++;
  2256. }
  2257. }
  2258. // ルーレット選択
  2259. while (count < size+max_ch && k < size) {
  2260. p = Select(s_method, s_bias, s_step);
  2261. if (dup_s == 0 && s_w[p] > 0)
  2262. count++;
  2263. else {
  2264. count = 0;
  2265. s_w[p]++;
  2266. k++;
  2267. }
  2268. }
  2269. // 選択に失敗した場合の処理
  2270. if (dup_s == 0 && k < size) {
  2271. for (i1 = 0; i1 < size+max_ch && k < size; i1++) {
  2272. if (pi_w[i1] > 1 && s_w[i1] == 0) {
  2273. s_w[i1] = 1;
  2274. k++;
  2275. }
  2276. }
  2277. }
  2278. // 複数回選択されたものの処理
  2279. for (i1 = 0; i1 < size+max_ch; i1++) {
  2280. if (s_w[i1] == 0)
  2281. pi_w[i1] = 0;
  2282. }
  2283.  
  2284. for (i1 = 0; i1 < size+max_ch; i1++) {
  2285. if (s_w[i1] > 0) {
  2286. if (s_w[i1] > 1) {
  2287. for (i2 = 2; i2 <= s_w[i1]; i2++) {
  2288. k = Position(-1);
  2289. len[k] = len[i1];
  2290. pi_w[k] = 2;
  2291. pi[k] = pi[i1];
  2292. for (i3 = 0; i3 < len[i1]; i3++)
  2293. ind[k][i3] = ind[i1][i3];
  2294. }
  2295. }
  2296. }
  2297. }
  2298. }
  2299. }
  2300.  
  2301. ------------------------クラスTSP-----------------
  2302. /*******************/
  2303. /* クラスTSPの定義 */
  2304. /*******************/
  2305. import java.io.*;
  2306. import java.util.Date;
  2307. import java.util.Random;
  2308. import java.util.StringTokenizer;
  2309.  
  2310. class TSP extends Species {
  2311.  
  2312. private int max_gen; // 最大世代交代数
  2313. private int kosa_m; // 交叉方法
  2314. // =-1 : 交叉を使用しない
  2315. // =0 : 親のコピー
  2316. // =1 : 循環交叉
  2317. // =2 : 部分的交叉
  2318. // =3 : 順序交叉
  2319. // =4 : 一様順序交叉
  2320. // =5 : 一様位置交叉
  2321. // =6 : エッジ組み替え交叉
  2322. // =7 : サブツアー交叉
  2323. private double kosa; // 交叉確率
  2324. private int k_point; // 交差点の数(負の時は,1から-point間のランダム)
  2325. private int k_vr; // =0 : 両親とも同じ位置で交叉
  2326. // =1 : 両親が異なる位置で交叉(遺伝子長は可変)
  2327. private int k_method; // 交叉の時の親の選択方法
  2328. // =-1 : ランダム
  2329. // =0 : 適応度をそのまま使用
  2330. // =1 : 最小値からの差(ただし,α以下の場合はα)
  2331. // =2 : 評価値に順位をつけ,減少率βで線形化
  2332. private double k_bias; // α,または,method=2の場合は初期値
  2333. private double k_step; // β
  2334. private int mute_m; // 突然変異方法
  2335. // =-1 : 突然変異を使用しない
  2336. // =0 : 移動
  2337. // =1 : 逆位
  2338. // =2 : スクランブル
  2339. // =3 : 転座
  2340. private double mute; // 突然変異率
  2341. private int wd; // 突然変異に使用する部分遺伝子長
  2342. private double m_mean; // 摂動の平均値
  2343. private double m_std; // 摂動の標準偏差
  2344. private int elite; // エリート選択で残す数
  2345. private int s_method; // ルーレット板の作成方法
  2346. // =0 : 適応度をそのまま使用
  2347. // =1 : 最小値からの差(ただし,α以下の場合はα)
  2348. // =2 : 評価値に順位をつけ,減少率βで線形化
  2349. private double s_bias; // α,または,s_method=2の場合は初期値
  2350. private double s_step; // β
  2351. private int out_d; // 表示間隔
  2352. private int out_lvl; // 出力レベル
  2353. // =0 : 最終出力だけ
  2354. // n>0 : n世代毎に出力(負の時はファイル)
  2355. private int out_m; // 出力方法
  2356. // =0 : すべてを出力
  2357. // =1 : 最大適応度の個体だけを出力
  2358. private String o_file; // 出力ファイル名
  2359. private int n_city; // 都市の数
  2360. private int [][] rg; // 都市間の距離
  2361. private int kinbo; // 近傍探索(0:行わない,1:行う)
  2362. private int neib; // 近傍(2 or 3)
  2363. private int sel; // エッジの選択方法
  2364. // =0 : 最良のものを選択
  2365. // =1 : 最初のものを選択
  2366. private Win wn; // Winオブジェクト
  2367.  
  2368. int [][] city; //都市の位置データ
  2369. int display; // 画面表示
  2370. // =0 : 画面表示を行わない
  2371. // =1 : 結果だけを表示
  2372. // =2 : 初期状態と結果を表示
  2373. // =3 : out_lvlで指定された世代毎に表示
  2374.  
  2375. /***************************************/
  2376. /* コンストラクタ */
  2377. /* name1 : Species定義ファイル名 */
  2378. /* name2 : TSP定義ファイル名 */
  2379. /* seed : 乱数の初期値 */
  2380. /***************************************/
  2381. TSP (String name1, String name2, int seed) throws IOException, FileNotFoundException
  2382. {
  2383. super (name1, seed);
  2384.  
  2385. double x, y;
  2386. int i1, i2;
  2387. String line;
  2388. StringTokenizer dt;
  2389. BufferedReader in = new BufferedReader(new FileReader(name2));
  2390. // 基本データの入力
  2391. line = in.readLine();
  2392. dt = new StringTokenizer(line, " ");
  2393. dt.nextToken();
  2394. out_lvl = Integer.parseInt(dt.nextToken());
  2395. dt.nextToken();
  2396. out_m = Integer.parseInt(dt.nextToken());
  2397.  
  2398. line = in.readLine();
  2399. dt = new StringTokenizer(line, " ");
  2400. dt.nextToken();
  2401. o_file = dt.nextToken();
  2402. dt.nextToken();
  2403. out_d = Integer.parseInt(dt.nextToken());
  2404.  
  2405. line = in.readLine();
  2406. dt = new StringTokenizer(line, " ");
  2407. dt.nextToken();
  2408. kosa_m = Integer.parseInt(dt.nextToken());
  2409. dt.nextToken();
  2410. kosa = Double.parseDouble(dt.nextToken());
  2411. dt.nextToken();
  2412. k_point = Integer.parseInt(dt.nextToken());
  2413. dt.nextToken();
  2414. k_vr = Integer.parseInt(dt.nextToken());
  2415. dt.nextToken();
  2416. k_method = Integer.parseInt(dt.nextToken());
  2417. dt.nextToken();
  2418. k_bias = Double.parseDouble(dt.nextToken());
  2419. dt.nextToken();
  2420. k_step = Double.parseDouble(dt.nextToken());
  2421.  
  2422. line = in.readLine();
  2423. dt = new StringTokenizer(line, " ");
  2424. dt.nextToken();
  2425. mute_m = Integer.parseInt(dt.nextToken());
  2426. dt.nextToken();
  2427. mute = Double.parseDouble(dt.nextToken());
  2428. dt.nextToken();
  2429. wd = Integer.parseInt(dt.nextToken());
  2430. dt.nextToken();
  2431. m_mean = Double.parseDouble(dt.nextToken());
  2432. dt.nextToken();
  2433. m_std = Double.parseDouble(dt.nextToken());
  2434.  
  2435. line = in.readLine();
  2436. dt = new StringTokenizer(line, " ");
  2437. dt.nextToken();
  2438. elite = Integer.parseInt(dt.nextToken());
  2439. dt.nextToken();
  2440. s_method = Integer.parseInt(dt.nextToken());
  2441. dt.nextToken();
  2442. s_bias = Double.parseDouble(dt.nextToken());
  2443. dt.nextToken();
  2444. s_step = Double.parseDouble(dt.nextToken());
  2445.  
  2446. line = in.readLine();
  2447. dt = new StringTokenizer(line, " ");
  2448. dt.nextToken();
  2449. n_city = Integer.parseInt(dt.nextToken());
  2450. dt.nextToken();
  2451. max_gen = Integer.parseInt(dt.nextToken());
  2452.  
  2453. line = in.readLine();
  2454. dt = new StringTokenizer(line, " ");
  2455. dt.nextToken();
  2456. kinbo = Integer.parseInt(dt.nextToken());
  2457. dt.nextToken();
  2458. neib = Integer.parseInt(dt.nextToken());
  2459.  
  2460. line = in.readLine();
  2461. dt = new StringTokenizer(line, " ");
  2462. dt.nextToken();
  2463. sel = Integer.parseInt(dt.nextToken());
  2464.  
  2465. line = in.readLine();
  2466. dt = new StringTokenizer(line, " ");
  2467. dt.nextToken();
  2468. display = Integer.parseInt(dt.nextToken());
  2469.  
  2470. line = in.readLine();
  2471. dt = new StringTokenizer(line, " ");
  2472. dt.nextToken();
  2473. int font = Integer.parseInt(dt.nextToken());
  2474. dt.nextToken();
  2475. int width = Integer.parseInt(dt.nextToken());
  2476. int height = Integer.parseInt(dt.nextToken());
  2477.  
  2478. if (kinbo > 0 && neib != 2 && neib != 3) {
  2479. System.out.print("***error 近傍の値が不適当 \n");
  2480. System.exit(1);
  2481. }
  2482.  
  2483. if (n_city != max_len) {
  2484. System.out.print("***error 都市数が不適当 \n");
  2485. System.exit(1);
  2486. }
  2487. // 都市の位置データ
  2488. city = new int [n_city][2];
  2489. for (i1 = 0; i1 < n_city; i1++) {
  2490. line = in.readLine();
  2491. dt = new StringTokenizer(line, " ");
  2492. city[i1][0] = Integer.parseInt(dt.nextToken());
  2493. city[i1][1] = Integer.parseInt(dt.nextToken());
  2494. }
  2495. // 距離テーブル
  2496. rg = new int [n_city][n_city];
  2497.  
  2498. for (i1 = 0; i1 < n_city; i1++) {
  2499. for (i2 = i1+1; i2 < n_city; i2++) {
  2500. x = city[i2][0] - city[i1][0];
  2501. y = city[i2][1] - city[i1][1];
  2502. rg[i1][i2] = (int)(Math.sqrt(x * x + y * y) + 0.5);
  2503. }
  2504. }
  2505.  
  2506. for (i1 = 1; i1 < n_city; i1++) {
  2507. for (i2 = 0; i2 < i1; i2++)
  2508. rg[i1][i2] = rg[i2][i1];
  2509. }
  2510.  
  2511. in.close();
  2512. // Windowの生成
  2513. if (display > 0)
  2514. wn = new Win (this, font, width, height, n_city);
  2515. }
  2516.  
  2517. /**************/
  2518. /* 全体の制御 */
  2519. /**************/
  2520. void Control() throws IOException, FileNotFoundException
  2521. {
  2522. int gen = 1, k1;
  2523. BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  2524. // 初期集団の発生
  2525. Init_std();
  2526. // 評価
  2527. if (kinbo > 0)
  2528. Kinbo();
  2529. else
  2530. Adap();
  2531. // 画面表示
  2532. System.out.println("***世代 " + gen + " 適応度 max " + max +
  2533. " (" + max_n + ") mean " + mean);
  2534. // 初期状態の出力(図)
  2535. if (display >= 2) {
  2536. wn.Draw(max, ind[max_n]);
  2537. System.out.println(" 図を確認したらreturnキーを押してください");
  2538. in.readLine();
  2539. }
  2540. // 出力
  2541. if (Math.abs(out_lvl) > 0)
  2542. Output(gen);
  2543. // 世代交代
  2544. for (gen = 2; gen <= max_gen; gen++) {
  2545. // 交叉
  2546. switch (kosa_m) {
  2547. case -1:
  2548. break;
  2549. case 0:
  2550. C_copy(2, max_ch/2, k_method, k_bias, k_step); // 親のコピー
  2551. break;
  2552. case 1:
  2553. C_cycle(kosa, k_method, k_bias, k_step); // 循環交叉
  2554. break;
  2555. case 2:
  2556. C_part(kosa, k_method, k_bias, k_step); // 部分的交叉
  2557. break;
  2558. case 3:
  2559. C_seq(kosa, k_method, k_bias, k_step); // 順序交叉
  2560. break;
  2561. case 4:
  2562. C_useq(kosa, k_method, k_bias, k_step); // 一様順序交叉
  2563. break;
  2564. case 5:
  2565. C_upos(kosa, k_method, k_bias, k_step); // 一様位置交叉
  2566. break;
  2567. case 6:
  2568. C_edge(kosa, k_method, k_bias, k_step); // エッジ組み替え交叉
  2569. break;
  2570. case 7:
  2571. C_sub(kosa, k_point); // サブツアー交叉
  2572. break;
  2573. default:
  2574. break;
  2575. }
  2576. // 突然変異
  2577. switch (mute_m) {
  2578. case -1:
  2579. break;
  2580. case 0:
  2581. M_move(mute); // 移動
  2582. break;
  2583. case 1:
  2584. M_inv(mute, wd); // 逆位
  2585. break;
  2586. case 2:
  2587. M_scram(mute, wd); // スクランブル
  2588. break;
  2589. case 3:
  2590. M_chg(mute, wd); // 転座
  2591. break;
  2592. default:
  2593. break;
  2594. }
  2595. // 適応度
  2596. if (kinbo > 0)
  2597. Kinbo();
  2598. else
  2599. Adap();
  2600. // 淘汰
  2601. S_roul(elite, s_method, s_bias, s_step);
  2602. // 画面表示
  2603. if (gen%out_d == 0)
  2604. System.out.println("***世代 " + gen + " 適応度 max " + max +
  2605. " (" + max_n + ") mean " + mean);
  2606. // 文字出力と図示
  2607. if (Math.abs(out_lvl) > 0) {
  2608. if (gen%Math.abs(out_lvl) == 0) {
  2609. if (display == 3) {
  2610. wn.Draw(max, ind[max_n]);
  2611. System.out.println(" 図を確認したらreturnキーを押してください");
  2612. in.readLine();
  2613. }
  2614. Output(gen);
  2615. }
  2616. }
  2617. }
  2618.  
  2619. gen--;
  2620. k1 = out_m;
  2621. out_m = 0;
  2622. System.out.println("***世代 " + gen + " 適応度 max " + max +
  2623. " (" + max_n + ") mean " + mean);
  2624. if (display >= 1) {
  2625. wn.Draw(max, ind[max_n]);
  2626. System.out.println(" 図を確認したらreturnキーを押してください");
  2627. in.readLine();
  2628. }
  2629. Output(gen);
  2630. out_m = k1;
  2631. }
  2632.  
  2633. /*********************************/
  2634. /* 距離の計算 */
  2635. /* n_c : 都市の数 */
  2636. /* p : 都市番号 */
  2637. /* return : 距離(負) */
  2638. /*********************************/
  2639. int Kyori(int n_c, int [] p)
  2640. {
  2641. int i1, n1, n2, range = 0;
  2642.  
  2643. n1 = p[0];
  2644.  
  2645. for (i1 = 1; i1 < n_c; i1++) {
  2646. n2 = p[i1];
  2647. range -= rg[n1][n2];
  2648. n1 = n2;
  2649. }
  2650.  
  2651. n2 = p[0];
  2652. range -= rg[n1][n2];
  2653.  
  2654. return range;
  2655. }
  2656.  
  2657. /****************/
  2658. /* 適応度の計算 */
  2659. /****************/
  2660. void Adap()
  2661. {
  2662. int i1, k = 0;
  2663.  
  2664. mean = 0.0;
  2665. max = 0.0;
  2666. max_n = -1;
  2667.  
  2668. for (i1 = 0; i1 < size+max_ch; i1++) {
  2669. if (pi_w[i1] == 1) {
  2670. pi_w[i1] = 2;
  2671. pi[i1] = Kyori(len[i1], ind[i1]);
  2672. }
  2673. if (pi_w[i1] > 0) {
  2674. k++;
  2675. mean += pi[i1];
  2676. if (max_n < 0 || pi[i1] > max) {
  2677. max = pi[i1];
  2678. max_n = i1;
  2679. }
  2680. }
  2681. }
  2682.  
  2683. if (k > 0)
  2684. mean /= k;
  2685. }
  2686.  
  2687. /**************************************/
  2688. /* エッジの入れ替え */
  2689. /* n_city : 都市の数 */
  2690. /* seq : 訪問する順番 */
  2691. /* r_m : 距離の負値 */
  2692. /* return : =0 : 改善がなかった */
  2693. /* =1 : 改善があった */
  2694. /**************************************/
  2695. int Change(int n_city, int [] seq, int [] r_m)
  2696. {
  2697. int ch = 0, i1, i2, i3, i4, k, k1, k2, max, n1, n2, n3, nn, r, sw = 0;
  2698.  
  2699. max = r_m[0];
  2700.  
  2701. n3 = (int)(rn.nextDouble() * (n_city - 2));
  2702. if (n3 > n_city-3)
  2703. n3 = n_city - 3;
  2704. // 2近傍
  2705. for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {
  2706.  
  2707. if (n3 == 0)
  2708. n1 = n_city - 2;
  2709. else
  2710. n1 = n_city - 1;
  2711.  
  2712. for (i2 = n3+2; i2 <= n1 && ch == 0; i2++) {
  2713. // 枝の場所((n3,n3+1), (k1,k2))
  2714. k1 = i2;
  2715. if (i2 == n_city-1)
  2716. k2 = 0;
  2717. else
  2718. k2 = i2 + 1;
  2719. // 枝の入れ替え
  2720. kou1[0] = seq[n3];
  2721. k = 1;
  2722. for (i3 = k1; i3 >= n3+1; i3--) {
  2723. kou1[k] = seq[i3];
  2724. k++;
  2725. }
  2726.  
  2727. nn = k2;
  2728. while (nn != n3) {
  2729. kou1[k] = seq[nn];
  2730. k++;
  2731. nn++;
  2732. if (nn > n_city-1)
  2733. nn = 0;
  2734. }
  2735. // 評価
  2736. r = Kyori(n_city, kou1);
  2737.  
  2738. if (r > max) {
  2739. max = r;
  2740. sw = 1;
  2741. for (i3 = 0; i3 < n_city; i3++)
  2742. kou2[i3] = kou1[i3];
  2743. if (sel > 0)
  2744. ch = 1;
  2745. }
  2746. }
  2747.  
  2748. n3++;
  2749. if (n3 > n_city-3)
  2750. n3 = 0;
  2751. }
  2752. // 3近傍
  2753. if (neib == 3 && ch == 0) {
  2754.  
  2755. for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {
  2756.  
  2757. n1 = n_city - 2;
  2758. n2 = n_city - 1;
  2759.  
  2760. for (i2 = n3+1; i2 <= n1 && ch == 0; i2++) {
  2761.  
  2762. for (i3 = i2+1; i3 <= n2 && ch == 0; i3++) {
  2763. // 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
  2764. k1 = i3;
  2765. if (i3 == n_city-1)
  2766. k2 = 0;
  2767. else
  2768. k2 = i3 + 1;
  2769. // 枝の入れ替えと評価
  2770. // 入れ替え(その1)
  2771. kou1[0] = seq[n3];
  2772. k = 1;
  2773. for (i4 = i2; i4 >= n3+1; i4--) {
  2774. kou1[k] = seq[i4];
  2775. k++;
  2776. }
  2777.  
  2778. for (i4 = k1; i4 >= i2+1; i4--) {
  2779. kou1[k] = seq[i4];
  2780. k++;
  2781. }
  2782.  
  2783. nn = k2;
  2784. while (nn != n3) {
  2785. kou1[k] = seq[nn];
  2786. k++;
  2787. nn++;
  2788. if (nn > n_city-1)
  2789. nn = 0;
  2790. }
  2791. // 評価(その1)
  2792. r = Kyori(n_city, kou1);
  2793.  
  2794. if (r > max) {
  2795. max = r;
  2796. sw = 1;
  2797. for (i3 = 0; i3 < n_city; i3++)
  2798. kou2[i3] = kou1[i3];
  2799. if (sel > 0)
  2800. ch = 1;
  2801. }
  2802. // 入れ替え(その2)
  2803. kou1[0] = seq[n3];
  2804. k = 1;
  2805. for (i4 = k1; i4 >= i2+1; i4--) {
  2806. kou1[k] = seq[i4];
  2807. k++;
  2808. }
  2809.  
  2810. for (i4 = n3+1; i4 <= i2; i4++) {
  2811. kou1[k] = seq[i4];
  2812. k++;
  2813. }
  2814.  
  2815. nn = k2;
  2816. while (nn != n3) {
  2817. kou1[k] = seq[nn];
  2818. k++;
  2819. nn++;
  2820. if (nn > n_city-1)
  2821. nn = 0;
  2822. }
  2823. // 評価(その2)
  2824. r = Kyori(n_city, kou1);
  2825.  
  2826. if (r > max) {
  2827. max = r;
  2828. sw = 1;
  2829. for (i3 = 0; i3 < n_city; i3++)
  2830. kou2[i3] = kou1[i3];
  2831. if (sel > 0)
  2832. ch = 1;
  2833. }
  2834. // 入れ替え(その3)
  2835. kou1[0] = seq[n3];
  2836. k = 1;
  2837. for (i4 = i2+1; i4 <= k1; i4++) {
  2838. kou1[k] = seq[i4];
  2839. k++;
  2840. }
  2841.  
  2842. for (i4 = i2; i4 >= n3+1; i4--) {
  2843. kou1[k] = seq[i4];
  2844. k++;
  2845. }
  2846.  
  2847. nn = k2;
  2848. while (nn != n3) {
  2849. kou1[k] = seq[nn];
  2850. k++;
  2851. nn++;
  2852. if (nn > n_city-1)
  2853. nn = 0;
  2854. }
  2855. // 評価(その3)
  2856. r = Kyori(n_city, kou1);
  2857.  
  2858. if (r > max) {
  2859. max = r;
  2860. sw = 1;
  2861. for (i3 = 0; i3 < n_city; i3++)
  2862. kou2[i3] = kou1[i3];
  2863. if (sel > 0)
  2864. ch = 1;
  2865. }
  2866. // 入れ替え(その4)
  2867. kou1[0] = seq[n3];
  2868. k = 1;
  2869. for (i4 = i2+1; i4 <= k1; i4++) {
  2870. kou1[k] = seq[i4];
  2871. k++;
  2872. }
  2873.  
  2874. for (i4 = n3+1; i4 <= i2; i4++) {
  2875. kou1[k] = seq[i4];
  2876. k++;
  2877. }
  2878.  
  2879. nn = k2;
  2880. while (nn != n3) {
  2881. kou1[k] = seq[nn];
  2882. k++;
  2883. nn++;
  2884. if (nn > n_city-1)
  2885. nn = 0;
  2886. }
  2887. // 評価(その4)
  2888. r = Kyori(n_city, kou1);
  2889.  
  2890. if (r > max) {
  2891. max = r;
  2892. sw = 1;
  2893. for (i3 = 0; i3 < n_city; i3++)
  2894. kou2[i3] = kou1[i3];
  2895. if (sel > 0)
  2896. ch = 1;
  2897. }
  2898. }
  2899. }
  2900.  
  2901. n3++;
  2902. if (n3 > n_city-3)
  2903. n3 = 0;
  2904. }
  2905. }
  2906. // 設定
  2907. if (sw > 0) {
  2908. r_m[0] = max;
  2909. for (i1 = 0; i1 < n_city; i1++)
  2910. seq[i1] = kou2[i1];
  2911. }
  2912.  
  2913. return sw;
  2914. }
  2915.  
  2916. /**************/
  2917. /* 近傍の探索 */
  2918. /**************/
  2919. void Kinbo()
  2920. {
  2921. int i1, k = 0, sw;
  2922. int r [] = new int [1];
  2923. max = 0.0;
  2924. max_n = -1;
  2925. mean = 0.0;
  2926.  
  2927. for (i1 = 0; i1 < size+max_ch; i1++) {
  2928. if (pi_w[i1] == 1) {
  2929. pi_w[i1] = 2;
  2930. sw = 1;
  2931. r[0] = Kyori(len[i1], ind[i1]);
  2932. while (sw > 0)
  2933. sw = Change(len[i1], ind[i1], r);
  2934. pi[i1] = r[0];
  2935. }
  2936. if (pi_w[i1] > 0) {
  2937. k++;
  2938. mean += pi[i1];
  2939. if (max_n < 0 || pi[i1] > max) {
  2940. max = pi[i1];
  2941. max_n = i1;
  2942. }
  2943. }
  2944. }
  2945.  
  2946. if (k > 0)
  2947. mean /= k;
  2948. }
  2949.  
  2950. /*****************************/
  2951. /* 結果の出力 */
  2952. /* gen : 現在の世代番号 */
  2953. /*****************************/
  2954. void Output(int gen) throws IOException, FileNotFoundException
  2955. {
  2956. double x, y;
  2957. int i1, i2, k = 0, n, pr;
  2958. String now;
  2959. PrintStream out = null;
  2960. BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  2961.  
  2962. if (out_lvl >= 0) {
  2963. System.out.print(" 出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
  2964. pr = Integer.parseInt(in.readLine());
  2965. }
  2966. else
  2967. pr = -1;
  2968.  
  2969. if (pr != 0) {
  2970. // 出力先の決定と評価値の出力
  2971. if (pr > 0)
  2972. out = System.out;
  2973. else {
  2974. Date newtime = new Date(); // 現在時刻の獲得
  2975. now = newtime.toString(); // 文字列への変換
  2976. out = new PrintStream(new FileOutputStream(o_file, true));
  2977. out.println("***世代 " + gen + " 適応度 max " + max +
  2978. " (" + max_n + ") mean " + mean + " 時間 " + now);
  2979. }
  2980. // 巡回順序の出力
  2981. if (out_m == 0) {
  2982. for (i1 = 0; i1 < len[max_n]; i1++) {
  2983. n = ind[max_n][i1];
  2984. out.println(n + " " + city[n][0] + " " + city[n][1]);
  2985. if (pr > 0) {
  2986. k++;
  2987. if (k == pr) {
  2988. in.readLine();
  2989. k = 0;
  2990. }
  2991. }
  2992. }
  2993. }
  2994.  
  2995. if (pr < 0)
  2996. out.close();
  2997. }
  2998. }
  2999. }
  3000.  
  3001. ------------------------クラスWin-----------------
  3002. /*******************/
  3003. /* クラスWinの定義 */
  3004. /*******************/
  3005. import java.awt.*;
  3006. import java.awt.event.*;
  3007.  
  3008. class Win extends Frame {
  3009.  
  3010. double ritu; // 表示倍率
  3011. private int font; // フォントサイズ
  3012. private int min_x, max_x, min_y, max_y; // 都市の存在範囲
  3013. private int next, yoyu_x, yoyu_y; // 表示位置
  3014. private int n_city; // 都市の数
  3015. private int [] seq; // 都市を訪問する順番
  3016. private int range; // 距離
  3017. private TSP tsp;
  3018.  
  3019. /*************************************/
  3020. /* コンストラクタ */
  3021. /* tsp_i : TSPのオブジェクト */
  3022. /* city_i : 都市の位置データ */
  3023. /* font_i : フォントサイズ */
  3024. /* width,height : 表示範囲 */
  3025. /* nc : 都市の数 */
  3026. /*************************************/
  3027. Win (TSP tsp_i, int font_i, int width, int height, int nc)
  3028. {
  3029. // Frameクラスのコンストラクタの呼び出し
  3030. super("巡回セールスマン問題");
  3031. // 値の設定と領域の確保
  3032. double k1, k2;
  3033. int i1;
  3034.  
  3035. tsp = tsp_i;
  3036. font = font_i;
  3037. next = 70;
  3038. yoyu_x = 30;
  3039. yoyu_y = 80;
  3040. n_city = nc;
  3041. seq = new int [n_city];
  3042. // 描画領域の計算
  3043. min_x = tsp.city[0][0];
  3044. max_x = tsp.city[0][0];
  3045. min_y = tsp.city[0][1];
  3046. max_y = tsp.city[0][1];
  3047.  
  3048. for (i1 = 1; i1 < n_city; i1++) {
  3049. if (tsp.city[i1][0] < min_x)
  3050. min_x = tsp.city[i1][0];
  3051. else {
  3052. if (tsp.city[i1][0] > max_x)
  3053. max_x = tsp.city[i1][0];
  3054. }
  3055. if (tsp.city[i1][1] < min_y)
  3056. min_y = tsp.city[i1][1];
  3057. else {
  3058. if (tsp.city[i1][1] > max_y)
  3059. max_y = tsp.city[i1][1];
  3060. }
  3061. }
  3062.  
  3063. k1 = (double)(width - 2 * yoyu_x) / (max_x - min_x);
  3064. k2 = (double)(height - yoyu_y - yoyu_x) / (max_y - min_y);
  3065. ritu = (k1 < k2) ? k1 : k2;
  3066. // ボタンの設定とWindowサイズ
  3067. // 指定された大きさにWindowサイズを変更
  3068. width = 2 * yoyu_x + (int)(ritu * (max_x - min_x));
  3069. height = yoyu_y + yoyu_x + (int)(ritu * (max_y - min_y));
  3070.  
  3071. setSize(width, height);
  3072. // ウィンドウを表示
  3073. setVisible(true);
  3074. // イベントアダプタ
  3075. addWindowListener(new WinEnd());
  3076. }
  3077.  
  3078. /*****************************/
  3079. /* 描画指示 */
  3080. /* max : 距離の負値 */
  3081. /* seq_i : 訪問する順序 */
  3082. /*****************************/
  3083. void Draw(double max, int [] seq_i)
  3084. {
  3085. int i1;
  3086.  
  3087. range = (int)(-max + 0.5);
  3088.  
  3089. for (i1 = 0; i1 < n_city; i1++)
  3090. seq[i1] = seq_i[i1];
  3091.  
  3092. repaint();
  3093. }
  3094.  
  3095. /********/
  3096. /* 描画 */
  3097. /********/
  3098. public void paint (Graphics g)
  3099. {
  3100. int i1, k, n1, n2, size = 6, x1, x2, y1, y2;
  3101. Font f;
  3102. // 距離の表示
  3103. f = new Font("TimesRoman", Font.BOLD, 25);
  3104. g.setFont(f);
  3105. g.drawString("Length : "+Integer.toString(range), yoyu_x, yoyu_y-30);
  3106. // 都市番号のフォントサイズ
  3107. if (font > 0) {
  3108. f = new Font("TimesRoman", Font.PLAIN, font);
  3109. g.setFont(f);
  3110. }
  3111. // 点と直線のプロット
  3112. k = size / 2;
  3113.  
  3114. for (i1 = 0; i1 < n_city; i1++) {
  3115.  
  3116. n2 = seq[i1];
  3117. x2 = yoyu_x + (int)(ritu * (tsp.city[n2][0] - min_x));
  3118. y2 = yoyu_y + (int)(ritu * (max_y - tsp.city[n2][1]));
  3119.  
  3120. g.fillOval(x2, y2, size, size);
  3121.  
  3122. if (font > 0)
  3123. g.drawString(Integer.toString(n2), x2+k, y2-k);
  3124.  
  3125. if (i1 > 0) {
  3126. n1 = seq[i1-1];
  3127. x1 = yoyu_x + (int)(ritu * (tsp.city[n1][0] - min_x));
  3128. y1 = yoyu_y + (int)(ritu * (max_y - tsp.city[n1][1]));
  3129. g.drawLine(x1+k, y1+k, x2+k, y2+k);
  3130. if (i1 == n_city-1) {
  3131. n1 = seq[0];
  3132. x1 = yoyu_x + (int)(ritu * (tsp.city[n1][0] - min_x));
  3133. y1 = yoyu_y + (int)(ritu * (max_y - tsp.city[n1][1]));
  3134. g.drawLine(x1+k, y1+k, x2+k, y2+k);
  3135. }
  3136. }
  3137. }
  3138. }
  3139.  
  3140. /************/
  3141. /* 終了処理 */
  3142. /************/
  3143. class WinEnd extends WindowAdapter
  3144. {
  3145. public void windowClosing(WindowEvent e) {
  3146. System.exit(0);
  3147. }
  3148. }
  3149. }
  3150.  
  3151. ------------------------クラスTSP_r(main)---------
  3152. /***********************************/
  3153. /* 遺伝的アルゴリズムによるTSPの解 */
  3154. /* coded by Y.Suganuma */
  3155. /***********************************/
  3156. import java.io.*;
  3157. import java.util.StringTokenizer;
  3158.  
  3159. class TSP_r {
  3160.  
  3161. /****************/
  3162. /* main program */
  3163. /****************/
  3164. public static void main(String args[]) throws IOException, FileNotFoundException
  3165. {
  3166. int i1, n, seed[];
  3167. String i_file1[], i_file2[], line;
  3168. TSP tsp;
  3169. StringTokenizer dt;
  3170. BufferedReader in = new BufferedReader(new FileReader(args[0]));
  3171. // 入力ミス
  3172. if (args.length == 0) {
  3173. System.out.print("***error ファイル名を入力して下さい\n");
  3174. System.exit(1);
  3175. }
  3176. // 入力OK
  3177. else {
  3178. // 乱数の初期値と入力データファイル名の入力
  3179. n = Integer.parseInt(in.readLine());
  3180.  
  3181. seed = new int [n];
  3182. i_file1 = new String [n];
  3183. i_file2 = new String [n];
  3184.  
  3185. for (i1 = 0; i1 < n; i1++) {
  3186. line = in.readLine();
  3187. dt = new StringTokenizer(line, " ");
  3188. seed[i1] = Integer.parseInt(dt.nextToken());
  3189. i_file1[i1] = dt.nextToken();
  3190. i_file2[i1] = dt.nextToken();
  3191. }
  3192.  
  3193. in.close();
  3194. // 実行(乱数の初期値を変える)
  3195. for (i1 = 0; i1 < n; i1++) {
  3196. System.out.print("\n+++++ケース " + (i1+1) + "+++++\n");
  3197. // 入力と初期設定
  3198. tsp = new TSP (i_file1[i1], i_file2[i1], seed[i1]);
  3199. // 最適化
  3200. tsp.Control();
  3201. }
  3202. }
  3203. }
  3204. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement