/****************************/ /* Fisher の直接確率(AWT) */ /* coded by Y.Suganuma */ /****************************/ import java.awt.*; import java.awt.event.*; public class Test { public static void main (String[] args) { Fisher fr = new Fisher("Fisher の直接確率"); } } class Fisher extends Frame implements ActionListener, TextListener { double bunshi, bunbo, d_sum, base; int n_row, n_col, matrix[][], sum; TextField row, col, tx[][]; TextArea ta; Button bt; ScrollPane sp; /******************/ /* コンストラクタ */ /******************/ Fisher(String name) { // Frameクラスのコンストラクタ super(name); // Windowの大きさ setSize(600, 400); // レイアウト,背景色,フォント setLayout(new BorderLayout(5, 10)); setBackground(new Color(225, 255, 225)); Font f = new Font("TimesRoman", Font.BOLD, 20); setFont(f); // 上のパネル Panel pn1 = new Panel(); add(pn1, BorderLayout.NORTH); pn1.add(new Label("行の数")); row = new TextField(3); row.addTextListener(this); pn1.add(row); pn1.add(new Label("列の数")); col = new TextField(3); col.addTextListener(this); pn1.add(col); pn1.add(new Label(" ")); bt = new Button("OK"); bt.setBackground(Color.pink); bt.addActionListener(this); pn1.add(bt); // 中央のパネル sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); add(sp, BorderLayout.CENTER); // 下のパネル Panel pn3 = new Panel(); add(pn3, BorderLayout.SOUTH); ta = new TextArea(3, 35); pn3.add(ta); // ウィンドウを表示 setVisible(true); // イベントアダプタ addWindowListener(new WinEnd()); } /******************************/ /* 上,左,下,右の余白の設定 */ /******************************/ public Insets getInsets() { return new Insets(70, 20, 20, 20); } /******************************/ /* ボタンが押されたときの処理 */ /******************************/ public void actionPerformed(ActionEvent e) { double x, s; int i1, i2, k; String str; // 和の計算 for (i1 = 0; i1 < n_row; i1++) matrix[i1][n_col] = 0; for (i1 = 0; i1 < n_col; i1++) matrix[n_row][i1] = 0; sum = 0; for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) { str = tx[i1][i2].getText(); if (str.length() > 0) { matrix[i1][i2] = Integer.parseInt(str); sum += matrix[i1][i2]; } else matrix[i1][i2] = 0; matrix[i1][n_col] += matrix[i1][i2]; matrix[n_row][i2] += matrix[i1][i2]; } } // 実行 if (sum == 0) { ta.setForeground(Color.red); ta.setText(" データを入力してください\n"); } else { ta.setForeground(Color.black); d_sum = kaijo(sum); // 生起確率の計算 bunshi = 0.0; for (i1 = 0; i1 < n_row; i1++) bunshi += kaijo(matrix[i1][n_col]); for (i1 = 0; i1 < n_col; i1++) bunshi += kaijo(matrix[n_row][i1]); bunbo = cal(matrix); base = Math.exp(bunshi - bunbo); ta.setText("生起確率: " + base + "\n"); // base より小さい確率の和 int mx[][] = new int [n_row+1][n_col+1]; k = 0; s = 0.0; while (k <= matrix[0][n_col] && k <= matrix[n_row][0]) { for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) mx[i1][i2] = 0; } mx[0][0] = k; s += set(mx, 0); k++; } ta.append("確率の和: " + s + "\n"); } } /*******************************************/ /* 特定の状態における確率の分母(対数計算) */ /*******************************************/ double cal(int mx[][]) { double s = d_sum; int i1, i2; for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) s += kaijo(mx[i1][i2]); } return s; } /**********************/ /* n の階乗(対数計算) */ /**********************/ double kaijo(int n) { double s = 0.0; for (int i1 = 2; i1 <= n; i1++) s += Math.log((double)i1); return s; } /************************************/ /* 様々な状態における確率を計算 */ /* mx : 状態 */ /* i : 値を設定する位置 */ /* i/n_col 行 i%n_col 列 */ /************************************/ double set(int mx1[][], int i) { double x, y, s = 0.0; int i1, i2, k, k1, k2, n, n1, n2, sw = 0, ss = 0; // 周辺度数と一致しているかのチェック for (i1 = 0; i1 < n_row; i1++) mx1[i1][n_col] = 0; for (i1 = 0; i1 < n_col; i1++) mx1[n_row][i1] = 0; for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) { mx1[i1][n_col] += mx1[i1][i2]; mx1[n_row][i2] += mx1[i1][i2]; ss += mx1[i1][i2]; } } for (i1 = 0; i1 < n_row && sw == 0; i1++) { if (mx1[i1][n_col] != matrix[i1][n_col]) sw = 1; } if (sw == 0) { for (i1 = 0; i1 < n_col && sw == 0; i1++) { if (mx1[n_row][i1] != matrix[n_row][i1]) sw = 1; } } // 一致している場合 if (sw == 0) { y = cal(mx1); x = Math.exp(bunshi - y); if (x < base + 1.0e-10) s = x; // デバッグ用(計算した組み合わせの出力) // for (i1 = 0; i1 < n_row; i1++) { // for (i2 = 0; i2 < n_col; i2++) // System.out.print(" " + mx1[i1][i2]); // System.out.println(); // } // System.out.println(); } // 一致していない場合 else { if (i < n_row*n_col-1 && (cal(mx1) + kaijo(sum-ss)) > bunbo - 1.0e-10) { i++; k1 = i / n_col; k2 = i % n_col; n1 = 0; n2 = 0; for (i1 = 0; i1 < n_row; i1++) n1 += mx1[i1][k2]; for (i1 = 0; i1 < n_col; i1++) n2 += mx1[k1][i1]; n1 = matrix[n_row][k2] - n1; n2 = matrix[k1][n_col] - n2; n = (n1 < n2) ? n1 : n2; k = 0; int mx2[][] = new int [n_row+1][n_col+1]; while (k <= n) { if (k2 < n_col-1 || k2 == n_col-1 && mx1[k1][n_col]+k == matrix[k1][n_col]) { if (k1 < n_row-1 || k1 == n_row-1 && mx1[n_row][k2]+k == matrix[n_row][k2]) { for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) mx2[i1][i2] = mx1[i1][i2]; } mx2[k1][k2] = k; s += set(mx2, i); } } k++; } } } return s; } /******************************/ /* 列数が変更されたときの処理 */ /******************************/ public void textValueChanged(TextEvent e) { try { if ((row.getText()).length() > 0 && (col.getText()).length() > 0) { ta.setForeground(Color.black); n_row = Integer.parseInt(row.getText()); n_col = Integer.parseInt(col.getText()); matrix = new int [n_row+1][n_col+1]; tx = new TextField [n_row][n_col]; remove(sp); sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); add(sp, BorderLayout.CENTER); Panel pn2 = new Panel(); pn2.setLayout(new GridLayout(n_row, n_col, 10, 10)); for (int i1 = 0; i1 < n_row; i1++ ) { for (int i2 = 0; i2 < n_col; i2++) { tx[i1][i2] = new TextField(2); pn2.add(tx[i1][i2]); } } sp.add(pn2); validate(); } } catch (NumberFormatException em) {} } /************/ /* 終了処理 */ /************/ class WinEnd extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } }
/*****************************/ /* Fisher の直接確率(Swing)*/ /* coded by Y.Suganuma */ /*****************************/ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; public class Test { public static void main (String[] args) { Fisher fr = new Fisher("Fisher の直接確率"); } } class Fisher extends JFrame implements ActionListener, DocumentListener { double bunshi, bunbo, d_sum, base; int n_row, n_col, matrix[][], sum; JTextField row, col, tx[][]; JTextArea ta; JButton bt; JScrollPane sp; Container cp; Font f = new Font("TimesRoman", Font.BOLD, 20); /******************/ /* コンストラクタ */ /******************/ Fisher(String name) { // Frameクラスのコンストラクタ super(name); // Windowの大きさ setSize(600, 400); // レイアウト,背景色,フォント cp = getContentPane(); cp.setLayout(new BorderLayout(5, 5)); cp.setBackground(new Color(225, 255, 225)); cp.setFont(f); // 上のパネル Panel pn1 = new Panel(); cp.add(pn1, BorderLayout.NORTH); pn1.add(new Label("行の数")); row = new JTextField(3); row.setFont(f); row.getDocument().addDocumentListener(this); pn1.add(row); pn1.add(new Label("列の数")); col = new JTextField(3); col.setFont(f); col.getDocument().addDocumentListener(this); pn1.add(col); pn1.add(new Label(" ")); bt = new JButton("OK"); bt.setBackground(Color.pink); bt.setFont(f); bt.addActionListener(this); pn1.add(bt); // 中央のパネル sp = new JScrollPane(); cp.add(sp, BorderLayout.CENTER); // 下のパネル Panel pn3 = new Panel(); cp.add(pn3, BorderLayout.SOUTH); ta = new JTextArea(3, 24); ta.setFont(f); JScrollPane scroll2 = new JScrollPane(ta); pn3.add(scroll2); // ウィンドウを表示 setVisible(true); // イベントアダプタ addWindowListener(new WinEnd()); } /******************************/ /* 上,左,下,右の余白の設定 */ /******************************/ public Insets getInsets() { return new Insets(70, 20, 20, 20); } /******************************/ /* ボタンが押されたときの処理 */ /******************************/ public void actionPerformed(ActionEvent e) { double x, s; int i1, i2, k; String str; // 和の計算 for (i1 = 0; i1 < n_row; i1++) matrix[i1][n_col] = 0; for (i1 = 0; i1 < n_col; i1++) matrix[n_row][i1] = 0; sum = 0; for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) { str = tx[i1][i2].getText(); if (str.length() > 0) { matrix[i1][i2] = Integer.parseInt(str); sum += matrix[i1][i2]; } else matrix[i1][i2] = 0; matrix[i1][n_col] += matrix[i1][i2]; matrix[n_row][i2] += matrix[i1][i2]; } } // 実行 if (sum == 0) { ta.setForeground(Color.red); ta.setText(" データを入力してください\n"); } else { ta.setForeground(Color.black); d_sum = kaijo(sum); // 生起確率の計算 bunshi = 0.0; for (i1 = 0; i1 < n_row; i1++) bunshi += kaijo(matrix[i1][n_col]); for (i1 = 0; i1 < n_col; i1++) bunshi += kaijo(matrix[n_row][i1]); bunbo = cal(matrix); base = Math.exp(bunshi - bunbo); ta.setText("生起確率: " + base + "\n"); // base より小さい確率の和 int mx[][] = new int [n_row+1][n_col+1]; k = 0; s = 0.0; while (k <= matrix[0][n_col] && k <= matrix[n_row][0]) { for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) mx[i1][i2] = 0; } mx[0][0] = k; s += set(mx, 0); k++; } ta.append("確率の和: " + s + "\n"); } } /*******************************************/ /* 特定の状態における確率の分母(対数計算) */ /*******************************************/ double cal(int mx[][]) { double s = d_sum; int i1, i2; for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) s += kaijo(mx[i1][i2]); } return s; } /**********************/ /* n の階乗(対数計算) */ /**********************/ double kaijo(int n) { double s = 0.0; for (int i1 = 2; i1 <= n; i1++) s += Math.log((double)i1); return s; } /************************************/ /* 様々な状態における確率を計算 */ /* mx : 状態 */ /* i : 値を設定する位置 */ /* i/n_col 行 i%n_col 列 */ /************************************/ double set(int mx1[][], int i) { double x, y, s = 0.0; int i1, i2, k, k1, k2, n, n1, n2, sw = 0, ss = 0; // 周辺度数と一致しているかのチェック for (i1 = 0; i1 < n_row; i1++) mx1[i1][n_col] = 0; for (i1 = 0; i1 < n_col; i1++) mx1[n_row][i1] = 0; for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) { mx1[i1][n_col] += mx1[i1][i2]; mx1[n_row][i2] += mx1[i1][i2]; ss += mx1[i1][i2]; } } for (i1 = 0; i1 < n_row && sw == 0; i1++) { if (mx1[i1][n_col] != matrix[i1][n_col]) sw = 1; } if (sw == 0) { for (i1 = 0; i1 < n_col && sw == 0; i1++) { if (mx1[n_row][i1] != matrix[n_row][i1]) sw = 1; } } // 一致している場合 if (sw == 0) { y = cal(mx1); x = Math.exp(bunshi - y); if (x < base + 1.0e-10) s = x; // デバッグ用(計算した組み合わせの出力) // for (i1 = 0; i1 < n_row; i1++) { // for (i2 = 0; i2 < n_col; i2++) // System.out.print(" " + mx1[i1][i2]); // System.out.println(); // } // System.out.println(); } // 一致していない場合 else { if (i < n_row*n_col-1 && (cal(mx1) + kaijo(sum-ss)) > bunbo - 1.0e-10) { i++; k1 = i / n_col; k2 = i % n_col; n1 = 0; n2 = 0; for (i1 = 0; i1 < n_row; i1++) n1 += mx1[i1][k2]; for (i1 = 0; i1 < n_col; i1++) n2 += mx1[k1][i1]; n1 = matrix[n_row][k2] - n1; n2 = matrix[k1][n_col] - n2; n = (n1 < n2) ? n1 : n2; k = 0; int mx2[][] = new int [n_row+1][n_col+1]; while (k <= n) { if (k2 < n_col-1 || k2 == n_col-1 && mx1[k1][n_col]+k == matrix[k1][n_col]) { if (k1 < n_row-1 || k1 == n_row-1 && mx1[n_row][k2]+k == matrix[n_row][k2]) { for (i1 = 0; i1 < n_row; i1++) { for (i2 = 0; i2 < n_col; i2++) mx2[i1][i2] = mx1[i1][i2]; } mx2[k1][k2] = k; s += set(mx2, i); } } k++; } } } return s; } /******************************/ /* 列数が変更されたときの処理 */ /******************************/ public void changedUpdate(DocumentEvent e) {} public void removeUpdate(DocumentEvent e) {} public void insertUpdate(DocumentEvent e) { try { if ((row.getText()).length() > 0 && (col.getText()).length() > 0) { remove(sp); ta.setForeground(Color.black); n_row = Integer.parseInt(row.getText()); n_col = Integer.parseInt(col.getText()); matrix = new int [n_row+1][n_col+1]; tx = new JTextField [n_row][n_col]; Panel pn2 = new Panel(); pn2.setBackground(new Color(225, 255, 225)); pn2.setLayout(new GridLayout(n_row, n_col, 5, 5)); for (int i1 = 0; i1 < n_row; i1++ ) { for (int i2 = 0; i2 < n_col; i2++) { tx[i1][i2] = new JTextField(2); tx[i1][i2].setFont(f); pn2.add(tx[i1][i2]); } } sp = new JScrollPane(pn2); cp.add(sp, BorderLayout.CENTER); validate(); } } catch (NumberFormatException em) {} } /************/ /* 終了処理 */ /************/ class WinEnd extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } }