------------------------規則ファイル-------------- 推論方法 0 規則の数 3 変数の数 1 積分の分割数 100 規則1 変数1 1 中心と幅 1.0 1.0 右辺(中心と幅) 1.0 15.0 規則2 変数1 1 中心と幅 2.0 1.0 右辺(中心と幅) 11.0 15.0 規則3 変数1 1 中心と幅 3.0 1.0 右辺(中心と幅) 21.0 15.0 ------------------------推論ファイル-------------- 変数の数 1 データ数 21 変数1 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 ---------------------プログラム------------------ /****************************/ /* ファジイ推論 */ /* coded by Y.Suganuma */ /****************************/ import java.io.*; import java.util.StringTokenizer; public class Test { /****************/ /* main program */ /****************/ public static void main(String args[]) throws IOException, FileNotFoundException { double x[], xx[][], y; int i1, i2, n_d, n_val; StringTokenizer str; // エラー if (args.length != 3) { System.out.print("***error 入力データファイル名を指定して下さい\n"); System.exit(1); } else { // オブジェクトの生成 Fuzzy fz = new Fuzzy (args[0]); // 推論データの読み込み BufferedReader in = new BufferedReader(new FileReader(args[1])); str = new StringTokenizer(in.readLine(), " "); str.nextToken(); n_val = Integer.parseInt(str.nextToken()); str.nextToken(); n_d = Integer.parseInt(str.nextToken()); x = new double [n_val]; xx = new double [n_val][n_d]; for (i1 = 0; i1 < n_val; i1++) { str = new StringTokenizer(in.readLine(), " "); str.nextToken(); for (i2 = 0; i2 < n_d; i2++) { if (!str.hasMoreTokens()) str = new StringTokenizer(in.readLine(), " "); xx[i1][i2] = Double.parseDouble(str.nextToken()); } } in.close(); // 推論とその結果の出力 PrintStream out = new PrintStream(new FileOutputStream(args[2])); for (i1 = 0; i1 < n_d; i1++) { for (i2 = 0; i2 < n_val; i2++) { x[i2] = xx[i2][i1]; out.print(x[i2] + " "); } y = fz.Inf(x); // 推論 out.println(y); } } } } class Fuzzy { private double left[][][]; // [i][j][0] : 中心 // [1] : 幅 private double right[][]; // [i][0] : 中心 // [1] : 幅 private double omega[]; // ωの値 private int bun; // 積分の分割数 private int method; // 推論方法 // =0 : and,or // =1 : *,or // =2 : *,+ private int n_rule; // 規則の数 private int n_val; // 変数の数 private int rule[][]; // [i][j] =0 : i番目の規則はj番目の変数を使用しない // =1 : i番目の規則はj番目の変数を使用する /************************************/ /* コンストラクタ */ /* name : 入力データファイル名 */ /************************************/ Fuzzy (String name) throws IOException, FileNotFoundException { int i1, i2; StringTokenizer str; BufferedReader in = new BufferedReader(new FileReader(name)); /* 基本データの入力 */ str = new StringTokenizer(in.readLine(), " "); str.nextToken(); method = Integer.parseInt(str.nextToken()); str.nextToken(); n_rule = Integer.parseInt(str.nextToken()); str.nextToken(); n_val = Integer.parseInt(str.nextToken()); str.nextToken(); bun = Integer.parseInt(str.nextToken()); /* 領域の確保 */ left = new double [n_rule][n_val][2]; right = new double [n_rule][2]; omega = new double [n_rule]; rule = new int [n_rule][n_val]; /* 規則データの入力 */ for (i1 = 0; i1 < n_rule; i1++) { in.readLine(); // 左辺 for (i2 = 0; i2 < n_val; i2++) { str = new StringTokenizer(in.readLine(), " "); str.nextToken(); rule[i1][i2] = Integer.parseInt(str.nextToken()); if (rule[i1][i2] > 0) { str.nextToken(); left[i1][i2][0] = Double.parseDouble(str.nextToken()); left[i1][i2][1] = Double.parseDouble(str.nextToken()); } } // 右辺 str = new StringTokenizer(in.readLine(), " "); str.nextToken(); right[i1][0] = Double.parseDouble(str.nextToken()); right[i1][1] = Double.parseDouble(str.nextToken()); } in.close(); } /*******************************************/ /* 交点の計算 */ /* x : x */ /* c : 中心 */ /* h : 幅 */ /* r : <0 : 左辺のメンバーシップ関数 */ /* >=0 : 右辺(ω) */ /* return : 交点 */ /*******************************************/ double Cross(double x, double c, double h, double r) { double x1, x2, y, y1, y2; if (x < c) { x1 = c - h; x2 = c; y1 = 0.0; y2 = (r < 0.0 || (r >= 0.0 && method == 0)) ? 1.0 : r; } else { x1 = c; x2 = c + h; y1 = (r < 0.0 || (r >= 0.0 && method == 0)) ? 1.0 : r; y2 = 0.0; } y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); if (y < 0.0) y = 0.0; else { if (r >= 0.0 && method == 0 && y > r) y = r; } return y; } /**********************************************/ /* 右辺の計算 */ /* x : 値 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : xにおける右辺の値 */ /**********************************************/ double Height(double x, double [] om) { double y = 0.0, y1; int i1, sw; sw = 0; for (i1 = 0; i1 < n_rule; i1++) { if (om[i1] >= 0.0) { y1 = Cross(x, right[i1][0], right[i1][1], om[i1]); if (sw == 0) { y = y1; sw = 1; } else { if (method < 2) { if (y1 > y) y = y1; } else y += y1; } } } return y; } /**************************/ /* 推論の実行 */ /* x[i] : 各変数の値 */ /* return : 推論値 */ /**************************/ double Inf(double [] x) { double x1, y; int i1, i2; /* ωの計算 */ for (i1 = 0; i1 < n_rule; i1++) { omega[i1] = -1.0; for (i2 = 0; i2 < n_val; i2++) { if (rule[i1][i2] > 0) { if (x[i2] > left[i1][i2][0]-left[i1][i2][1] && x[i2] < left[i1][i2][0]+left[i1][i2][1]) x1 = Cross(x[i2], left[i1][i2][0], left[i1][i2][1], -1.0); else x1 = 0.0; if (omega[i1] < 0.0) omega[i1] = x1; else { if (method == 0) { if (x1 < omega[i1]) omega[i1] = x1; } else omega[i1] *= x1; } } } } /* 右辺の計算 */ y = Result(omega); return y; } /**********************************************/ /* 右辺による推論 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : 推論値 */ /**********************************************/ double Result(double [] om) { double h, max = 0.0, min = 0.0, x1, x2, y = 0.0, y1, y2, z1, z2; int i1, sw; /* 積分範囲と積分幅の計算 */ sw = 0; for (i1 = 0; i1 < n_rule; i1++) { if (om[i1] >= 0.0) { x1 = right[i1][0] - right[i1][1]; x2 = right[i1][0] + right[i1][1]; if (sw == 0) { min = x1; max = x2; sw = 1; } else { if (x1 < min) min = x1; if (x2 > max) max = x2; } } } h = (max - min) / bun; if (h < 1.0e-15) { System.out.print("***error invalid data (h = 0) ***\n"); System.exit(1); } /* 積分(重心の計算,台形則) */ z1 = Height(min, om); z2 = Height(max, om); y1 = 0.5 * (min * z1 + max * z2); y2 = 0.5 * (z1 + z2); x1 = min; for (i1 = 0; i1 < bun-1; i1++) { x1 += h; z1 = Height(x1, om); y1 += x1 * z1; y2 += z1; } y1 *= h; y2 *= h; if (Math.abs(y2) > 1.0e-10) y = y1 / y2; else { System.out.print("***error invalid data (y2 = 0) ***\n"); System.exit(1); } return y; } }
推論方法 0 規則の数 3 変数の数 1 積分の分割数 100 規則1 変数1 1 中心と幅 1.0 1.0 右辺(中心と幅) 1.0 15.0 規則2 変数1 1 中心と幅 2.0 1.0 右辺(中心と幅) 11.0 15.0 規則3 変数1 1 中心と幅 3.0 1.0 右辺(中心と幅) 21.0 15.0
変数の数 1 データ数 21 変数1 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0