/****************************/ /* GA の実行例(1の数) */ /* coded by Y.Suganuma */ /****************************/ import java.io.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.Random; public class Test { public static void main (String[] args) { GA win = new GA("GA の実行例(1の数)"); } } class GA extends JFrame implements ActionListener { Random rn = new Random(12345); // 乱数の初期設定 JPanel pn[] = new JPanel[12]; JLabel lb1[] = new JLabel[11]; JLabel lb2[] = new JLabel[10]; JLabel lb; JButton bt; JTextField tx1, tx2; int gen; // 現在の世代番号 int state; // 現在の状態 int oya1, oya2; // 選択された親 int c_p; // 交叉点の位置 /******************/ /* コンストラクタ */ /******************/ GA(String name) { // JFrameクラスのコンストラクタ(Windowのタイトルを引き渡す) super(name); // Windowの大きさ setSize(490, 520); // 変数の初期設定 int i1, k; String str; gen = 1; state = 0; // フォント,背景色 setBackground(Color.white); Font f = new Font("TimesRoman", Font.BOLD, 20); // レイアウトの変更 Container cp = getContentPane(); cp.setBackground(Color.white); JPanel jp = new JPanel(); jp.setLayout(new GridLayout(12, 1, 0, 0)); jp.setBackground(Color.white); cp.add(jp, BorderLayout.CENTER); // パネル,ラベル,ボタンの準備 for (i1 = 0; i1 < 12; i1++) { pn[i1] = new JPanel(); pn[i1].setBackground(Color.white); jp.add(pn[i1]); if (i1 > 0) { if (i1 < 10) { lb1[i1] = new JLabel(); lb1[i1].setOpaque(true); lb1[i1].setBackground(Color.white); lb1[i1].setFont(f); pn[i1].add(lb1[i1]); lb2[i1] = new JLabel(); lb2[i1].setFont(f); pn[i1].add(lb2[i1]); } else { if (i1 == 10) { lb1[i1] = new JLabel(); lb1[i1].setFont(f); pn[i1].add(lb1[i1]); pn[i1].setLayout(new FlowLayout(FlowLayout.LEFT)); } } } else { lb = new JLabel(); lb.setFont(f); pn[i1].add(lb); } } tx1 = new JTextField(2); tx1.setBackground(Color.white); tx1.setFont(f); tx1.setHorizontalAlignment(JTextField.CENTER); pn[11].add(tx1); tx2 = new JTextField(2); tx2.setBackground(Color.white); tx2.setFont(f); tx2.setHorizontalAlignment(JTextField.CENTER); pn[11].add(tx2); bt = new JButton("OK"); bt.setFont(f); bt.addActionListener(this); pn[11].add(bt); // 初期個体の表示 for (i1 = 1; i1 <= 9; i1++) { if (i1 <= 5) { str = setInit(); k = countOne(str); lb1[i1].setText("(" + String.valueOf(i1) + ") " + str); if (k < 10) lb2[i1].setText(" 適応度 " + String.valueOf(k)); else lb2[i1].setText(" 適応度 " + String.valueOf(k)); } else { lb1[i1].setText(" "); lb2[i1].setText(" "); } } lb.setText("第 " + String.valueOf(gen) + " 世代"); lb1[10].setText("親を2つ選んで下さい (1~5) "); // ウィンドウを表示 setVisible(true); // イベントアダプタ addWindowListener(new WinEnd()); } /******************/ /* 初期個体の設定 */ /******************/ String setInit() { int i1; String str = ""; for (i1 = 0; i1 < 10; i1++) { if (rn.nextDouble() < 0.5) str += "0"; else str += "1"; } return str; } /******************/ /* 1の数を数える */ /******************/ int countOne(String str) { int i1, k = 0, pos1 = 0, pos2 = 0; while (pos2 >= 0) { pos2 = str.indexOf("1", pos1); if (pos2 >= 0) { k++; pos1 = pos2 + 1; } } return k; } /************************************/ /* ボタンがクリックされたときの処理 */ /************************************/ public void actionPerformed(ActionEvent e) { int i1, sw = 0; String str1, str2; switch (state) { // 最初の親の選択 case 0: str1 = tx1.getText(); str2 = tx2.getText(); if (str1.equals("") || str2.equals("")) sw = 1; else { oya1 = Integer.parseInt(str1); oya2 = Integer.parseInt(str2); if (oya1 < 1 || oya1 > 5 || oya2 < 1 || oya2 > 5) sw = 1; } if (sw > 0) { tx1.setText(""); tx2.setText(""); } else { state = 1; for (i1 = 1; i1 <= 9; i1++) lb1[i1].setBackground(Color.white); lb1[oya1].setBackground(Color.green); lb1[oya2].setBackground(Color.green); lb1[10].setText("交叉位置を入力して下さい (1~9)"); tx1.setText(""); tx2.setVisible(false); } break; // 最初の親の交叉点の選択 case 1: str1 = tx1.getText(); if (str1.equals("")) sw = 1; else { c_p = Integer.parseInt(str1); if (c_p < 1 || c_p > 9) sw = 1; } if (sw > 0) tx1.setText(""); else { state = 2; cross(oya1, oya2, c_p, 6, 7); lb1[10].setText("親を2つ選んで下さい (1~7) "); tx1.setText(""); tx2.setVisible(true); tx2.setText(""); } break; // 2番目の親の選択 case 2: str1 = tx1.getText(); str2 = tx2.getText(); if (str1.equals("") || str2.equals("")) sw = 1; else { oya1 = Integer.parseInt(str1); oya2 = Integer.parseInt(str2); if (oya1 < 1 || oya1 > 7 || oya2 < 1 || oya2 > 7) sw = 1; } if (sw > 0) { tx1.setText(""); tx2.setText(""); } else { state = 3; for (i1 = 1; i1 <= 9; i1++) lb1[i1].setBackground(Color.white); lb1[oya1].setBackground(Color.green); lb1[oya2].setBackground(Color.green); lb1[10].setText("交叉位置を入力して下さい (1~9)"); tx1.setText(""); tx2.setVisible(false); } break; // 2番目の親の交叉点の選択 case 3: str1 = tx1.getText(); if (str1.equals("")) sw = 1; else { c_p = Integer.parseInt(str1); if (c_p < 1 || c_p > 9) sw = 1; } if (sw > 0) tx1.setText(""); else { state = 4; cross(oya1, oya2, c_p, 8, 9); lb1[10].setText("確認後,ボタンをクリックして下さい"); tx1.setVisible(false); tx2.setVisible(false); } break; // 次世代へ(淘汰) case 4: gen++; if (gen < 10) lb.setText("第 " + String.valueOf(gen) + " 世代"); else lb.setText("第 " + String.valueOf(gen) + " 世代"); tota(); state = 0; for (i1 = 6; i1 <= 9; i1++) { lb1[i1].setText(" "); lb2[i1].setText(" "); } for (i1 = 1; i1 <= 9; i1++) lb1[i1].setBackground(Color.white); lb1[10].setText("親を2つ選んで下さい (1~5) "); tx1.setVisible(true); tx2.setVisible(true); tx1.setText(""); tx2.setText(""); break; } } /**********************/ /* 1点交叉 */ /* o1, o2 : 親 */ /* p : 交叉位置 */ /* k1, k2 : 子供 */ /**********************/ void cross(int o1, int o2, int p, int k1, int k2) { int k; String str, str0, str1, str2; str0 = lb1[o1].getText(); str1 = str0.substring(4); str0 = lb1[o2].getText(); str2 = str0.substring(4); str = str1.substring(0, p) + str2.substring(p); k = countOne(str); lb1[k1].setText("(" + String.valueOf(k1) + ") " + str); if (k < 10) lb2[k1].setText(" 適応度 " + String.valueOf(k)); else lb2[k1].setText(" 適応度 " + String.valueOf(k)); str = str2.substring(0, p) + str1.substring(p); k = countOne(str); lb1[k2].setText("(" + String.valueOf(k2) + ") " + str); if (k < 10) lb2[k2].setText(" 適応度 " + String.valueOf(k)); else lb2[k2].setText(" 適応度 " + String.valueOf(k)); lb1[k1].setBackground(Color.yellow); lb1[k2].setBackground(Color.yellow); } /************************/ /* 淘汰(エリート選択) */ /************************/ void tota() { int i1, count = 0, k = 0, max; int w[] = new int [10]; int n[] = new int [10]; String str; for (i1 = 1; i1 <= 9; i1++) { w[i1] = 0; str = lb2[i1].getText(); if (str.indexOf(" ", 5) < 0) n[i1] = Integer.parseInt(str.substring(5)); else n[i1] = Integer.parseInt(str.substring(6)); } while (count < 5) { max = 0; for (i1 = 1; i1 <= 9; i1++) { if (w[i1] == 0 && n[i1] > max) { max = n[i1]; k = i1; } } w[k] = 1; count++; } k = 1; for (i1 = 1; i1 <= 9; i1++) { if (w[i1] > 0) { str = (lb1[i1].getText()).substring(3); lb1[k].setText("(" + String.valueOf(k) + ")" + str); lb2[k].setText(lb2[i1].getText()); k++; } } } /******************************/ /* 上,左,下,右の余白の設定 */ /******************************/ public Insets getInsets() { return new Insets(50, 20, 20, 20); } /************/ /* 終了処理 */ /************/ class WinEnd extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } }