GA の実行例(1の数)

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