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