情報学部 | 菅沼ホーム | 目次 | 索引 |
/****************************/ /* ファジイ推論 */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> #include <stdlib.h> #include <math.h> /*********************/ /* クラスFuzzyの定義 */ /*********************/ class Fuzzy { double ***left; // [i][j][0] : 中心 // [1] : 幅 double **right; // [i][0] : 中心 // [1] : 幅 double *omega; // ωの値 int bun; // 積分の分割数 int method; // 推論方法 // =0 : and,or // =1 : *,or // =2 : *,+ int n_rule; // 規則の数 int n_val; // 変数の数 int **rule; // [i][j] =0 : i番目の規則はj番目の変数を使用しない // =1 : i番目の規則はj番目の変数を使用する public: Fuzzy(char *); // コンストラクタ ~Fuzzy(); // デストラクタ double Cross(double, double, double, double); double Height(double, double *); double Inf(double *); // 推論の実行 double Result(double *); }; /************************************/ /* コンストラクタ */ /* name : 入力データファイル名 */ /************************************/ Fuzzy::Fuzzy(char *name) { int i1, i2; FILE *in; in = fopen(name, "r"); /* 基本データの入力 */ fscanf(in, "%*s %d %*s %d %*s %d %*s %d", &method, &n_rule, &n_val, &bun); /* 領域の確保 */ left = new double ** [n_rule]; right = new double * [n_rule]; omega = new double [n_rule]; rule = new int * [n_rule]; for (i1 = 0; i1 < n_rule; i1++) { left[i1] = new double * [n_val]; right[i1] = new double [2]; rule[i1] = new int [n_val]; for (i2 = 0; i2 < n_val; i2++) left[i1][i2] = new double [2]; } /* 規則データの入力 */ for (i1 = 0; i1 < n_rule; i1++) { fscanf(in, "%*s"); // 左辺 for (i2 = 0; i2 < n_val; i2++) { fscanf(in, "%*s %d", &(rule[i1][i2])); if (rule[i1][i2] > 0) fscanf(in, "%*s %lf %lf", &(left[i1][i2][0]), &(left[i1][i2][1])); } // 右辺 fscanf(in, "%*s %lf %lf", &(right[i1][0]), &(right[i1][1])); } fclose(in); } /****************/ /* デストラクタ */ /****************/ Fuzzy::~Fuzzy() { int i1, i2; for (i1 = 0; i1 < n_rule; i1++) { for (i2 = 0; i2 < n_val; i2++) delete [] left[i1][i2]; delete [] left[i1]; delete [] right[i1]; delete [] rule[i1]; } delete [] left; delete [] right; delete [] rule; } /*******************************************/ /* 交点の計算 */ /* x : x */ /* c : 中心 */ /* h : 幅 */ /* r : < 0 : 左辺のメンバーシップ関数 */ /* >=0 : 右辺(ω) */ /* return : 交点 */ /*******************************************/ double Fuzzy::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 Fuzzy::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 Fuzzy::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 Fuzzy::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) { printf("***error invalid data (h = 0) ***\n"); 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 (fabs(y2) > 1.0e-10) y = y1 / y2; else { printf("***error invalid data (y2 = 0) ***\n"); exit(1); } return y; } /****************/ /* main program */ /****************/ int main(int argc, char *argv[]) { double *x, **xx, y; int i1, i2, n_d, n_val; FILE *in, *out; if (argc == 4) { // オブジェクトの生成 Fuzzy fz(argv[1]); // 推論データの読み込み in = fopen(argv[2], "r"); fscanf(in, "%*s %d %*s %d", &n_val, &n_d); x = new double [n_val]; xx = new double * [n_val]; for (i1 = 0; i1 < n_val; i1++) { fscanf(in, "%*s"); xx[i1] = new double [n_d]; for (i2 = 0; i2 < n_d; i2++) fscanf(in, "%lf", &xx[i1][i2]); } fclose(in); // 推論とその結果の出力 out = fopen(argv[3], "w"); for (i1 = 0; i1 < n_d; i1++) { for (i2 = 0; i2 < n_val; i2++) { x[i2] = xx[i2][i1]; fprintf(out, "%f ", x[i2]); } y = fz.Inf(x); // 推論 fprintf(out, "%f\n", y); } fclose(out); } else { printf("***error 入力データファイル名を指定して下さい\n"); exit(1); } return 0; } /* ------------------------規則ファイル-------------- 推論方法 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 */
<!DOCTYPE HTML> <HTML> <HEAD> <TITLE>ファジー推論</TITLE> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"> <SCRIPT TYPE="text/javascript"> res = ""; fz = null; /****************/ /* main program */ /****************/ function main() { // オブジェクトの生成 fz = new Fuzzy(); // 推論データの読み込み let lines = (document.getElementById("data2").value).split('\n'); let str = lines[0].split(' ').filter(function(e){return e.length > 0;}); let n_val = parseInt(str[1]); let n_d = parseInt(str[3]); let x = new Array(n_val); let xx = new Array(n_val); for (let i1 = 0; i1 < n_val; i1++) { xx[i1] = new Array(n_d); str = lines[i1+1].split(' ').filter(function(e){return e.length > 0;}); for (let i2 = 0; i2 < n_d; i2++) xx[i1][i2] = parseFloat(str[i2+1]); } // 推論とその結果の出力 for (let i1 = 0; i1 < n_d; i1++) { for (let i2 = 0; i2 < n_val; i2++) { x[i2] = xx[i2][i1]; res += (x[i2] + " "); } let y = fz.Inf(x); // 推論 res += (y + "\n"); } document.getElementById("result").value = res; } /**********************/ /* Fuzzy オブジェクト */ /**********************/ function Fuzzy () { // // 基本データの入力 // let lines = (document.getElementById("data1").value).split('\n'); let str = lines[0].split(' ').filter(function(e){return e.length > 0;}); this.method = parseInt(str[1]); this.n_rule = parseInt(str[3]); this.n_val = parseInt(str[5]); this.bun = parseInt(str[7]); // // 領域の確保 // this.omega = new Array(this.n_rule); // ωの値 this.right = new Array(this.n_rule); // [i][0] : 中心 // [1] : 幅 this.rule = new Array(this.n_rule); // [i][j] =0 : i番目の規則はj番目の変数を使用しない // =1 : i番目の規則はj番目の変数を使用する this.left = new Array(this.n_rule); // [i][j][0] : 中心 // [1] : 幅 for (let i1 = 0; i1 < this.n_rule; i1++) { this.right[i1] = new Array(2); this.rule[i1] = new Array(this.n_val); this.left[i1] = new Array(this.n_val); for (let i2 = 0; i2 < this.n_val; i2++) this.left[i1][i2] = new Array(2); } // // 規則データの入力 // for (let i1 = 0; i1 < this.n_rule; i1++) { // 左辺 for (let i2 = 0; i2 < this.n_val; i2++) { str = lines[(this.n_val+2)*i1+i2+2].split(' ').filter(function(e){return e.length > 0;}); this.rule[i1][i2] = parseInt(str[1]); if (this.rule[i1][i2] > 0) { this.left[i1][i2][0] = parseFloat(str[3]); this.left[i1][i2][1] = parseFloat(str[4]); } } // 右辺 str = lines[(this.n_val+2)*i1+this.n_val+2].split(' ').filter(function(e){return e.length > 0;}); this.right[i1][0] = parseFloat(str[1]); this.right[i1][1] = parseFloat(str[2]); } } /*******************************************/ /* 交点の計算 */ /* x : x */ /* c : 中心 */ /* h : 幅 */ /* r : <0 : 左辺のメンバーシップ関数 */ /* >=0 : 右辺(ω) */ /* return : 交点 */ /*******************************************/ Fuzzy.prototype.Cross = function(x, c, h, r) { let x1, x2, y1, y2; if (x < c) { x1 = c - h; x2 = c; y1 = 0.0; y2 = (r < 0.0 || (r >= 0.0 && fz.method == 0)) ? 1.0 : r; } else { x1 = c; x2 = c + h; y1 = (r < 0.0 || (r >= 0.0 && fz.method == 0)) ? 1.0 : r; y2 = 0.0; } let y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); if (y < 0.0) y = 0.0; else { if (r >= 0.0 && fz.method == 0 && y > r) y = r; } return y; } /**********************************************/ /* 右辺の計算 */ /* x : 値 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : xにおける右辺の値 */ /**********************************************/ Fuzzy.prototype.Height = function(x, om) { let y = 0.0; let sw = 0; for (let i1 = 0; i1 < fz.n_rule; i1++) { if (om[i1] >= 0.0) { let y1 = fz.Cross(x, fz.right[i1][0], fz.right[i1][1], om[i1]); if (sw == 0) { y = y1; sw = 1; } else { if (fz.method < 2) { if (y1 > y) y = y1; } else y += y1; } } } return y; } /**************************/ /* 推論の実行 */ /* x[i] : 各変数の値 */ /* return : 推論値 */ /**************************/ Fuzzy.prototype.Inf = function(x) { // // ωの計算 // for (let i1 = 0; i1 < fz.n_rule; i1++) { fz.omega[i1] = -1.0; for (let i2 = 0; i2 < fz.n_val; i2++) { if (fz.rule[i1][i2] > 0) { let x1 = 0.0; if (x[i2] > fz.left[i1][i2][0]-fz.left[i1][i2][1] && x[i2] < fz.left[i1][i2][0]+fz.left[i1][i2][1]) x1 = fz.Cross(x[i2], fz.left[i1][i2][0], fz.left[i1][i2][1], -1.0); else x1 = 0.0; if (fz.omega[i1] < 0.0) fz.omega[i1] = x1; else { if (fz.method == 0) { if (x1 < fz.omega[i1]) fz.omega[i1] = x1; } else fz.omega[i1] *= x1; } } } } // // 右辺の計算 // let y = fz.Result(fz.omega); return y; } /**********************************************/ /* 右辺による推論 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : 推論値 */ /**********************************************/ Fuzzy.prototype.Result = function(om) { // // 積分範囲と積分幅の計算 // let max = 0.0, min = 0.0, x1, x2, y = 0.0, y1, y2, z1, z2; let sw = 0; for (let i1 = 0; i1 < fz.n_rule; i1++) { if (om[i1] >= 0.0) { x1 = fz.right[i1][0] - fz.right[i1][1]; x2 = fz.right[i1][0] + fz.right[i1][1]; if (sw == 0) { min = x1; max = x2; sw = 1; } else { if (x1 < min) min = x1; if (x2 > max) max = x2; } } } let h = (max - min) / fz.bun; if (h < 1.0e-15) alert("***error invalid data (h = 0) ***"); // // 積分(重心の計算,台形則) // z1 = fz.Height(min, om); z2 = fz.Height(max, om); y1 = 0.5 * (min * z1 + max * z2); y2 = 0.5 * (z1 + z2); x1 = min; for (let i1 = 0; i1 < fz.bun-1; i1++) { x1 += h; z1 = fz.Height(x1, om); y1 += x1 * z1; y2 += z1; } y1 *= h; y2 *= h; if (Math.abs(y2) > 1.0e-10) y = y1 / y2; else alert("***error invalid data (y2 = 0) ***"); return y; } </SCRIPT> </HEAD> <BODY STYLE="font-size: 130%; text-align:center; background-color: #eeffee;"> <H2><B>ファジー推論</B></H2> <BUTTON STYLE="font-size: 100%; background-color: pink" onClick="return main()">実行</BUTTON><BR> <DIV STYLE="width: 800px; margin-right: auto; margin-left: auto"> <DIV STYLE="text-align:center; float: right; width: 400px"> <DIV STYLE="text-align:center">推論ファイル</DIV> <TEXTAREA ID="data2" COLS="40" ROWS="10" STYLE="font-size: 100%; width: 380px"> 変数の数 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 </TEXTAREA> </DIV> <DIV STYLE="text-align:center; width: 400px"> <DIV STYLE="text-align:center">規則ファイル</DIV> <TEXTAREA ID="data1" COLS="40" ROWS="10" STYLE="font-size: 100%; width: 380px"> 推論方法 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 </TEXTAREA> </DIV> </DIV> <DIV STYLE="text-align:center">推論結果</DIV> <TEXTAREA ID="result" COLS="50" ROWS="10" STYLE="font-size: 100%;"></TEXTAREA> </BODY> </HTML>
<?php /****************************/ /* ファジイ推論 */ /* coded by Y.Suganuma */ /****************************/ /*********************/ /* クラスFuzzyの定義 */ /*********************/ class Fuzzy { private $left; // [i][j][0] : 中心 // [1] : 幅 private $right; // [i][0] : 中心 // [1] : 幅 private $omega; // ωの値 private $bun; // 積分の分割数 private $method; // 推論方法 // =0 : and,or // =1 : *,or // =2 : *,+ private $n_rule; // 規則の数 private $n_val; // 変数の数 private $rule; // [i][j] =0 : i番目の規則はj番目の変数を使用しない // =1 : i番目の規則はj番目の変数を使用する /************************************/ /* コンストラクタ */ /* name : 入力データファイル名 */ /************************************/ function Fuzzy($name) { $in = fopen($name, "r"); /* 基本データの入力 */ fscanf($in, "%*s %d %*s %d %*s %d %*s %d", $this->method, $this->n_rule, $this->n_val, $this->bun); /* 領域の確保 */ $this->left = array($this->n_rule); $this->right = array($this->n_rule); $this->omega = array($this->n_rule); $this->rule = array($this->n_rule); for ($i1 = 0; $i1 < $this->n_rule; $i1++) { $this->left[$i1] = array($this->n_val); $this->right[$i1] = array(2); $this->rule[$i1] = array($this->n_val); for ($i2 = 0; $i2 < $this->n_val; $i2++) $this->left[$i1][$i2] = array(2); } /* 規則データの入力 */ for ($i1 = 0; $i1 < $this->n_rule; $i1++) { fgets($in); // 左辺 for ($i2 = 0; $i2 < $this->n_val; $i2++) { $str = trim(fgets($in)); strtok($str, " "); $this->rule[$i1][$i2] = intval(strtok(" ")); if ($this->rule[$i1][$i2] > 0) { strtok(" "); $this->left[$i1][$i2][0] = floatval(strtok(" ")); $this->left[$i1][$i2][1] = floatval(strtok(" ")); } } // 右辺 fscanf($in, "%*s %lf %lf", $this->right[$i1][0], $this->right[$i1][1]); } fclose($in); } /*******************************************/ /* 交点の計算 */ /* x : x */ /* c : 中心 */ /* h : 幅 */ /* r : <0 : 左辺のメンバーシップ関数 */ /* >=0 : 右辺(ω) */ /* return : 交点 */ /*******************************************/ function Cross($x, $c, $h, $r) { if ($x < $c) { $x1 = $c - $h; $x2 = $c; $y1 = 0.0; $y2 = ($r < 0.0 || ($r >= 0.0 && $this->method == 0)) ? 1.0 : $r; } else { $x1 = $c; $x2 = $c + $h; $y1 = ($r < 0.0 || ($r >= 0.0 && $this->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 && $this->method == 0 && $y > $r) $y = $r; } return $y; } /**********************************************/ /* 右辺の計算 */ /* x : 値 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : xにおける右辺の値 */ /**********************************************/ function Height($x, $om) { $y = 0.0; $sw = 0; for ($i1 = 0; $i1 < $this->n_rule; $i1++) { if ($om[$i1] >= 0.0) { $y1 = $this->Cross($x, $this->right[$i1][0], $this->right[$i1][1], $om[$i1]); if ($sw == 0) { $y = $y1; $sw = 1; } else { if ($this->method < 2) { if ($y1 > $y) $y = $y1; } else $y += $y1; } } } return $y; } /**************************/ /* 推論の実行 */ /* x[i] : 各変数の値 */ /* return : 推論値 */ /**************************/ function Inf($x) { /* ωの計算 */ for ($i1 = 0; $i1 < $this->n_rule; $i1++) { $this->omega[$i1] = -1.0; for ($i2 = 0; $i2 < $this->n_val; $i2++) { if ($this->rule[$i1][$i2] > 0) { if ($x[$i2] > $this->left[$i1][$i2][0]-$this->left[$i1][$i2][1] && $x[$i2] < $this->left[$i1][$i2][0]+$this->left[$i1][$i2][1]) $x1 = $this->Cross($x[$i2], $this->left[$i1][$i2][0], $this->left[$i1][$i2][1], -1.0); else $x1 = 0.0; if ($this->omega[$i1] < 0.0) $this->omega[$i1] = $x1; else { if ($this->method == 0) { if ($x1 < $this->omega[$i1]) $this->omega[$i1] = $x1; } else $this->omega[$i1] *= $x1; } } } } /* 右辺の計算 */ $y = $this->Result($this->omega); return $y; } /**********************************************/ /* 右辺による推論 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : 推論値 */ /**********************************************/ function Result($om) { $max = 0.0; $min = 0.0; $y = 0.0; $sw = 0; /* 積分範囲と積分幅の計算 */ for ($i1 = 0; $i1 < $this->n_rule; $i1++) { if ($om[$i1] >= 0.0) { $x1 = $this->right[$i1][0] - $this->right[$i1][1]; $x2 = $this->right[$i1][0] + $this->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) / $this->bun; if ($h < 1.0e-15) exit("***error invalid data (h = 0) ***\n"); /* 積分(重心の計算,台形則) */ $z1 = $this->Height($min, $om); $z2 = $this->Height($max, $om); $y1 = 0.5 * ($min * $z1 + $max * $z2); $y2 = 0.5 * ($z1 + $z2); $x1 = $min; for ($i1 = 0; $i1 < $this->bun-1; $i1++) { $x1 += $h; $z1 = $this->Height($x1, $om); $y1 += $x1 * $z1; $y2 += $z1; } $y1 *= $h; $y2 *= $h; if (abs($y2) > 1.0e-10) $y = $y1 / $y2; else exit("***error invalid data (y2 = 0) ***\n"); return $y; } } /****************/ /* main program */ /****************/ if (count($argv) == 4) { // オブジェクトの生成 $fz = new Fuzzy($argv[1]); // 推論データの読み込み $in = fopen($argv[2], "rb"); fscanf($in, "%*s %d %*s %d", $n_val, $n_d); $x = array($n_val); $xx = array($n_val); for ($i1 = 0; $i1 < $n_val; $i1++) { $xx[$i1] = array($n_d); $str = trim(fgets($in)); strtok($str, " "); for ($i2 = 0; $i2 < $n_d; $i2++) $xx[$i1][$i2] = floatval(strtok(" ")); } fclose($in); // 推論とその結果の出力 $out = fopen($argv[3], "w"); for ($i1 = 0; $i1 < $n_d; $i1++) { $str = ""; for ($i2 = 0; $i2 < $n_val; $i2++) { $x[$i2] = $xx[$i2][$i1]; $str = $str.$x[$i2]." "; } $y = $fz->Inf($x); // 推論 $str = $str."res ".$y."\n"; fwrite($out, $str); } fclose($out); } else exit("***error 入力データファイル名を指定して下さい\n"); /* ------------------------規則ファイル-------------- 推論方法 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 ############################ ############################ # クラスFuzzyの定義 # coded by Y.Suganuma ############################ class Fuzzy ##################################### # コンストラクタ # name : 入力データファイル名 ##################################### def initialize(name) in_f = open(name, "r") # 基本データの入力 s = in_f.gets().split(" ") @_method = Integer(s[1]) # 推論方法 # =0 : and,or # =1 : *,or # =2 : *,+ @_n_rule = Integer(s[3]) # 規則の数 @_n_val = Integer(s[5]) # 変数の数 @_bun = Integer(s[7]) # 積分の分割数 # 領域の確保 @_omega = Array.new(@_n_rule) # ωの値 @_rule = Array.new(@_n_rule) # [i][j] =0 : i番目の規則はj番目の変数を使用しない # =1 : i番目の規則はj番目の変数を使用する @_right = Array.new(@_n_rule) # [i][0] : 中心 # [i][1] : 幅 @_left = Array.new(@_n_rule) # [i][j][0] : 中心 # [i][j][1] : 幅 for i1 in 0 ... @_n_rule @_rule[i1] = Array.new(@_n_val) @_right[i1] = Array.new(2) @_left[i1] = Array.new(@_n_rule) for i2 in 0 ... @_n_rule @_left[i1][i2] = Array.new(2) end end # 規則データの入力 for i1 in 0 ... @_n_rule in_f.gets() # 左辺 for i2 in 0 ... @_n_val s = in_f.gets().split(" ") @_rule[i1][i2] = Integer(s[1]) if @_rule[i1][i2] > 0 @_left[i1][i2][0] = Float(s[3]) @_left[i1][i2][1] = Float(s[4]) end end # 右辺 s = in_f.gets().split(" ") @_right[i1][0] = Float(s[1]) @_right[i1][1] = Float(s[2]) end in_f.close() end ########################################### # 交点の計算 # x : x # c : 中心 # h : 幅 # r : <0 : 左辺のメンバーシップ関数 # >=0 : 右辺(ω) # return : 交点 ########################################### def Cross(x, c, h, r) if x < c x1 = c - h x2 = c y1 = 0.0 if r < 0.0 or (r >= 0.0 and @_method == 0) y2 = 1.0 else y2 = r end else x1 = c x2 = c + h if r < 0.0 or (r >= 0.0 and @_method == 0) y1 = 1.0 else y1 = r end y2 = 0.0 end y = y1 + (y2 - y1) * (x - x1) / (x2 - x1) if y < 0.0 y = 0.0 else if r >= 0.0 and @_method == 0 and y > r y = r end end return y end ############################################## # 右辺の計算 # x : 値 # om[i] : <0 : i番目の規則を使用しない # >=0 : ωの値 # return : xにおける右辺の値 ############################################## def Height(x, om) y = 0.0 sw = 0 for i1 in 0 ... @_n_rule 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 end else y += y1 end end end end return y end ########################## # 推論の実行 # x[i] : 各変数の値 # return : 推論値 ########################## def Inf(x) # ωの計算 for i1 in 0 ... @_n_rule @_omega[i1] = -1.0 for i2 in 0 ... @_n_val if @_rule[i1][i2] > 0 if x[i2] > @_left[i1][i2][0]-@_left[i1][i2][1] and 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 end if @_omega[i1] < 0.0 @_omega[i1] = x1 else if @_method == 0 if x1 < @_omega[i1] @_omega[i1] = x1 end else @_omega[i1] *= x1 end end end end end # 右辺の計算 y = Result(@_omega) return y end ############################################## # 右辺による推論 # om[i] : <0 : i番目の規則を使用しない # >=0 : ωの値 # return : 推論値 ############################################## def Result(om) max = 0.0 min = 0.0 y = 0.0 sw = 0 # 積分範囲と積分幅の計算 for i1 in 0 ... @_n_rule 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 end if x2 > max max = x2 end end end end h = (max - min) / @_bun if h < 1.0e-15 print("***error invalid data (h = 0) ***\n") end # 積分(重心の計算,台形則) z1 = Height(min, om) z2 = Height(max, om) y1 = 0.5 * (min * z1 + max * z2) y2 = 0.5 * (z1 + z2) x1 = min for i1 in 0 ... @_bun-1 x1 += h z1 = Height(x1, om) y1 += x1 * z1 y2 += z1 end y1 *= h y2 *= h if y2.abs() > 1.0e-10 y = y1 / y2 else print("***error invalid data (y2 = 0) ***\n") end return y end end if ARGV.length == 3 file1 = ARGV[0] file2 = ARGV[1] file3 = ARGV[2] # オブジェクトの生成 fz = Fuzzy.new(file1) # 推論データの読み込み in_f = open(file2, "r") s = in_f.gets().split(" ") n_val = Integer(s[1]) n_d = Integer(s[3]) x = Array.new(n_val) xx = Array.new(n_val) for i1 in 0 ... n_val xx[i1] = Array.new(n_d) s = in_f.gets().split(" ") for i2 in 0 ... n_d xx[i1][i2] = Float(s[i2+1]) end end in_f.close() # 推論とその結果の出力 out = open(file3, "w") for i1 in 0 ... n_d for i2 in 0 ... n_val x[i2] = xx[i2][i1] out.print(String(x[i2]) + " ") end y = fz.Inf(x) # 推論 out.print(String(y) + "\n") end out.close() else print("***error 入力データファイル名を指定して下さい\n") end =begin ------------------------規則ファイル-------------- 推論方法 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 =end
# -*- coding: UTF-8 -*- import numpy as np import sys from math import * from random import * ############################ # クラスFuzzyの定義 # coded by Y.Suganuma ############################ class Fuzzy : ##################################### # コンストラクタ # name : 入力データファイル名 ##################################### def __init__(self, name) : in_f = open(name, "r") # 基本データの入力 s = in_f.readline().split() self.method = int(s[1]) # 推論方法 # =0 : and,or # =1 : *,or # =2 : *,+ self.n_rule = int(s[3]) # 規則の数 self.n_val = int(s[5]) # 変数の数 self.bun = int(s[7]) # 積分の分割数 # 領域の確保 self.omega = np.empty(self.n_rule, np.float) # ωの値 self.rule = np.empty((self.n_rule, self.n_val), np.int) # [i][j] =0 : i番目の規則はj番目の変数を使用しない # =1 : i番目の規則はj番目の変数を使用する self.right = np.empty((self.n_rule, 2), np.float) # [i][0] : 中心 # [i][1] : 幅 self.left = np.empty((self.n_rule, self.n_rule, 2), np.float) # [i][j][0] : 中心 # [i][j][1] : 幅 # 規則データの入力 for i1 in range(0, self.n_rule) : in_f.readline() # 左辺 for i2 in range(0, self.n_val) : s = in_f.readline().split() self.rule[i1][i2] = int(s[1]) if self.rule[i1][i2] > 0 : self.left[i1][i2][0] = float(s[3]) self.left[i1][i2][1] = float(s[4]) # 右辺 s = in_f.readline().split() self.right[i1][0] = float(s[1]) self.right[i1][1] = float(s[2]) in_f.close() ########################################### # 交点の計算 # x : x # c : 中心 # h : 幅 # r : <0 : 左辺のメンバーシップ関数 # >=0 : 右辺(ω) # return : 交点 ########################################### def Cross(self, x, c, h, r) : if x < c : x1 = c - h x2 = c y1 = 0.0 if r < 0.0 or (r >= 0.0 and self.method == 0) : y2 = 1.0 else : y2 = r else : x1 = c x2 = c + h if r < 0.0 or (r >= 0.0 and self.method == 0) : y1 = 1.0 else : y1 = r y2 = 0.0 y = y1 + (y2 - y1) * (x - x1) / (x2 - x1) if y < 0.0 : y = 0.0 else : if r >= 0.0 and self.method == 0 and y > r : y = r return y ############################################## # 右辺の計算 # x : 値 # om[i] : <0 : i番目の規則を使用しない # >=0 : ωの値 # return : xにおける右辺の値 ############################################## def Height(self, x, om) : y = 0.0 sw = 0 for i1 in range(0, self.n_rule) : if om[i1] >= 0.0 : y1 = self.Cross(x, self.right[i1][0], self.right[i1][1], om[i1]) if sw == 0 : y = y1 sw = 1 else : if self.method < 2 : if y1 > y : y = y1 else : y += y1 return y ########################## # 推論の実行 # x[i] : 各変数の値 # return : 推論値 ########################## def Inf(self, x) : # ωの計算 for i1 in range(0, self.n_rule) : self.omega[i1] = -1.0 for i2 in range(0, self.n_val) : if self.rule[i1][i2] > 0 : if x[i2] > self.left[i1][i2][0]-self.left[i1][i2][1] and x[i2] < self.left[i1][i2][0]+self.left[i1][i2][1] : x1 = self.Cross(x[i2], self.left[i1][i2][0], self.left[i1][i2][1], -1.0) else : x1 = 0.0 if self.omega[i1] < 0.0 : self.omega[i1] = x1 else : if self.method == 0 : if x1 < self.omega[i1] : self.omega[i1] = x1 else : self.omega[i1] *= x1 # 右辺の計算 y = self.Result(self.omega) return y ############################################## # 右辺による推論 # om[i] : <0 : i番目の規則を使用しない # >=0 : ωの値 # return : 推論値 ############################################## def Result(self, om) : max = 0.0 min = 0.0 y = 0.0 sw = 0 # 積分範囲と積分幅の計算 for i1 in range(0, self.n_rule) : if om[i1] >= 0.0 : x1 = self.right[i1][0] - self.right[i1][1] x2 = self.right[i1][0] + self.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) / self.bun if h < 1.0e-15 : print("***error invalid data (h = 0) ***") # 積分(重心の計算,台形則) z1 = self.Height(min, om) z2 = self.Height(max, om) y1 = 0.5 * (min * z1 + max * z2) y2 = 0.5 * (z1 + z2) x1 = min for i1 in range(0, self.bun-1) : x1 += h z1 = self.Height(x1, om) y1 += x1 * z1 y2 += z1 y1 *= h y2 *= h if abs(y2) > 1.0e-10 : y = y1 / y2 else : print("***error invalid data (y2 = 0) ***") return y ############################ # ファジイ推論 # coded by Y.Suganuma ############################ if len(sys.argv) == 4 : # オブジェクトの生成 fz = Fuzzy(sys.argv[1]) # 推論データの読み込み in_f = open(sys.argv[2], "r") s = in_f.readline().split() n_val = int(s[1]) n_d = int(s[3]) x = np.empty(n_val, np.float) xx = np.empty((n_val, n_d), np.float) for i1 in range(0, n_val) : s = in_f.readline().split() for i2 in range(0, n_d) : xx[i1][i2] = float(s[i2+1]) in_f.close() # 推論とその結果の出力 out = open(sys.argv[3], "w") for i1 in range(0, n_d) : for i2 in range(0, n_val) : x[i2] = xx[i2][i1] out.write(str(x[i2]) + " ") y = fz.Inf(x) # 推論 out.write(str(y) + "\n") out.close() else : print("***error 入力データファイル名を指定して下さい") """ ------------------------規則ファイル-------------- 推論方法 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 */ /****************************/ using System; using System.IO; class Program { /****************/ /* main program */ /****************/ static void Main(String[] args) { // エラー if (args.Length != 3) { Console.WriteLine("***error 入力データファイル名を指定して下さい"); Environment.Exit(1); } else { // オブジェクトの生成 Fuzzy fz = new Fuzzy (args[0]); // 推論データの読み込み char[] charSep = new char[] {' '}; String[] lines = File.ReadAllLines(args[1]); String[] str = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries); int n_val = int.Parse(str[1]); int n_d = int.Parse(str[3]); double[] x = new double [n_val]; double[][] xx = new double [n_val][]; for (int i1 = 0; i1 < n_val; i1++) { xx[i1] = new double [n_d]; str = lines[i1+1].Split(charSep, StringSplitOptions.RemoveEmptyEntries); for (int i2 = 0; i2 < n_d; i2++) xx[i1][i2] = double.Parse(str[i2+1]); } // 推論とその結果の出力 StreamWriter OUT = new StreamWriter(args[2]); for (int i1 = 0; i1 < n_d; i1++) { for (int i2 = 0; i2 < n_val; i2++) { x[i2] = xx[i2][i1]; OUT.Write(x[i2] + " "); } double y = fz.Inf(x); // 推論 OUT.WriteLine(y); } OUT.Close(); } } } class Fuzzy { double[][][] left; // [i][j][0] : 中心 // [1] : 幅 double[][] right; // [i][0] : 中心 // [1] : 幅 double[] omega; // ωの値 int bun; // 積分の分割数 int method; // 推論方法 // =0 : and,or // =1 : *,or // =2 : *,+ int n_rule; // 規則の数 int n_val; // 変数の数 int[][] rule; // [i][j] =0 : i番目の規則はj番目の変数を使用しない // =1 : i番目の規則はj番目の変数を使用する /************************************/ /* コンストラクタ */ /* name : 入力データファイル名 */ /************************************/ public Fuzzy (String name) { char[] charSep = new char[] {' '}; String[] lines = File.ReadAllLines(name); // // 基本データの入力 // String[] str = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries); method = int.Parse(str[1]); n_rule = int.Parse(str[3]); n_val = int.Parse(str[5]); bun = int.Parse(str[7]); // // 領域の確保 // omega = new double [n_rule]; right = new double [n_rule][]; rule = new int [n_rule][]; left = new double [n_rule][][]; for (int i1 = 0; i1 < n_rule; i1++) { right[i1] = new double [2]; rule[i1] = new int [n_val]; left[i1] = new double [n_val][]; for (int i2 = 0; i2 < n_val; i2++) left[i1][i2] = new double [2]; } // // 規則データの入力 // for (int i1 = 0; i1 < n_rule; i1++) { // 左辺 for (int i2 = 0; i2 < n_val; i2++) { str = lines[(n_val+2)*i1+i2+2].Split(charSep, StringSplitOptions.RemoveEmptyEntries); rule[i1][i2] = int.Parse(str[1]); if (rule[i1][i2] > 0) { left[i1][i2][0] = double.Parse(str[3]); left[i1][i2][1] = double.Parse(str[4]); } } // 右辺 str = lines[(n_val+2)*i1+n_val+2].Split(charSep, StringSplitOptions.RemoveEmptyEntries); right[i1][0] = double.Parse(str[1]); right[i1][1] = double.Parse(str[2]); } } /*******************************************/ /* 交点の計算 */ /* x : x */ /* c : 中心 */ /* h : 幅 */ /* r : <0 : 左辺のメンバーシップ関数 */ /* >=0 : 右辺(ω) */ /* return : 交点 */ /*******************************************/ double Cross(double x, double c, double h, double r) { double x1, x2, 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; } double 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; int sw = 0; for (int i1 = 0; i1 < n_rule; i1++) { if (om[i1] >= 0.0) { double 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 : 推論値 */ /**************************/ public double Inf(double[] x) { // // ωの計算 // for (int i1 = 0; i1 < n_rule; i1++) { omega[i1] = -1.0; for (int i2 = 0; i2 < n_val; i2++) { if (rule[i1][i2] > 0) { double x1 = 0.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; } } } } // // 右辺の計算 // double y = Result(omega); return y; } /**********************************************/ /* 右辺による推論 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : 推論値 */ /**********************************************/ double Result(double [] om) { // // 積分範囲と積分幅の計算 // double max = 0.0, min = 0.0, x1, x2, y = 0.0, y1, y2, z1, z2; int sw = 0; for (int 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; } } } double h = (max - min) / bun; if (h < 1.0e-15) { Console.WriteLine("***error invalid data (h = 0) ***"); Environment.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 (int 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 { Console.WriteLine("***error invalid data (y2 = 0) ***"); Environment.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 */
'**************************' ' ファジイ推論 ' ' coded by Y.Suganuma ' '**************************' Imports System.IO Imports System.Text.RegularExpressions Module Test Sub Main(args() As String) ' エラー If args.Length <> 3 Console.WriteLine("***error 入力データファイル名を指定して下さい") Environment.Exit(1) Else ' オブジェクトの生成 Dim fz As Fuzzy = new Fuzzy (args(0)) ' 推論データの読み込み Dim inp As StreamReader = New StreamReader(args(1)) Dim MS As Regex = New Regex("\s+") Dim str() As String = MS.Split(inp.ReadLine().Trim()) Dim n_val As Integer = Integer.Parse(str(1)) Dim n_d As Integer = Integer.Parse(str(3)) Dim x(n_val) As Double Dim xx(n_val,n_d) As Double For i1 As Integer = 0 To n_val-1 str = MS.Split(inp.ReadLine().Trim()) For i2 As Integer = 0 To n_d-1 xx(i1,i2) = Double.Parse(str(i2+1)) Next Next inp.Close() ' 推論とその結果の出力 Dim OUT As StreamWriter = new StreamWriter(args(2)) For i1 As Integer = 0 To n_d-1 For i2 As Integer = 0 To n_val-1 x(i2) = xx(i2,i1) OUT.Write(x(i2) & " ") Next Dim y As Double = fz.Inf(x) ' 推論 OUT.WriteLine(y) Next OUT.Close() End If End Sub Class Fuzzy Private left(,,) As Double ' (i,j,0) : 中心 ' (i,j,1) : 幅 Private right(,) As Double ' (i,0) : 中心 ' (i,1) : 幅 Private omega() As Double ' ωの値 Private bun As Integer ' 積分の分割数 Private method As Integer ' 推論方法 ' =0 : and,or ' =1 : *,or ' =2 : *,+ Private n_rule As Integer ' 規則の数 Private n_val As Integer ' 変数の数 Private rule(,) As Integer ' (i,j) =0 : i番目の規則はj番目の変数を使用しない ' =1 : i番目の規則はj番目の変数を使用する '**********************************' ' コンストラクタ ' ' name : 入力データファイル名 ' '**********************************' Public Sub New(name As String) ' ' 基本データの入力 ' Dim inp As StreamReader = New StreamReader(name) Dim MS As Regex = New Regex("\s+") Dim str() As String = MS.Split(inp.ReadLine().Trim()) method = Integer.Parse(str(1)) n_rule = Integer.Parse(str(3)) n_val = Integer.Parse(str(5)) bun = Integer.Parse(str(7)) ' ' 領域の確保 ' ReDim omega(n_rule) ReDim right(n_rule,2) ReDim rule(n_rule,n_val) ReDim left(n_rule,n_val,2) ' ' 規則データの入力 ' For i1 As Integer = 0 To n_rule-1 inp.ReadLine() ' 左辺 For i2 As Integer = 0 To n_val-1 str = MS.Split(inp.ReadLine().Trim()) rule(i1,i2) = Integer.Parse(str(1)) If rule(i1,i2) > 0 left(i1,i2,0) = Double.Parse(str(3)) left(i1,i2,1) = Double.Parse(str(4)) End If Next ' 右辺 str = MS.Split(inp.ReadLine().Trim()) right(i1,0) = Double.Parse(str(1)) right(i1,1) = Double.Parse(str(2)) Next inp.Close() End Sub '*****************************************' ' 交点の計算 ' ' x : x ' ' c : 中心 ' ' h : 幅 ' ' r : <0 : 左辺のメンバーシップ関数 ' ' >=0 : 右辺(ω) ' ' return : 交点 ' '*****************************************' Function Cross(x As Double, c As Double, h As Double, r As Double) Dim x1 As Double Dim x2 As Double Dim y1 As Double Dim y2 As Double If x < c x1 = c - h x2 = c y1 = 0.0 If r < 0.0 or (r >= 0.0 and method = 0) y2 = 1.0 Else y2 = r End If Else x1 = c x2 = c + h if r < 0.0 or (r >= 0.0 and method = 0) y1 = 1.0 Else y1 = r End If y2 = 0.0 End If Dim y As Double = y1 + (y2 - y1) * (x - x1) / (x2 - x1) If y < 0.0 y = 0.0 Else If r >= 0.0 and method = 0 and y > r y = r End If End If Return y End Function '********************************************' ' 右辺の計算 ' ' x : 値 ' ' om(i) : <0 : i番目の規則を使用しない ' ' >=0 : ωの値 ' ' return : xにおける右辺の値 ' '********************************************' Function Height(x As Double, om() As Double) Dim y As Double = 0.0 Dim sw As Integer = 0 For i1 As Integer = 0 To n_rule-1 If om(i1) >= 0.0 Dim y1 As Double = 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 End If Else y += y1 End If End If End If Next Return y End Function '************************' ' 推論の実行 ' ' x(i) : 各変数の値 ' ' return : 推論値 ' '************************' Function Inf(x() As Double) ' ' ωの計算 ' For i1 As Integer = 0 To n_rule-1 omega(i1) = -1.0 For i2 As Integer = 0 To n_val-1 If rule(i1,i2) > 0 Dim x1 As Double = 0.0 If x(i2) > left(i1,i2,0)-left(i1,i2,1) and 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 End If If omega(i1) < 0.0 omega(i1) = x1 Else If method = 0 If x1 < omega(i1) omega(i1) = x1 End If Else omega(i1) *= x1 End If End If End If Next Next ' ' 右辺の計算 ' Dim y As Double = Result(omega) Return y End Function '********************************************' ' 右辺による推論 ' ' om(i) : <0 : i番目の規則を使用しない ' ' >=0 : ωの値 ' ' return : 推論値 ' '********************************************' Function Result(om() As Double) ' ' 積分範囲と積分幅の計算 ' Dim max As Double = 0.0 Dim min As Double = 0.0 Dim x1 As Double Dim x2 As Double Dim y As Double = 0.0 Dim y1 As Double Dim y2 As Double Dim z1 As Double Dim z2 As Double Dim sw As Integer = 0 For i1 As Integer = 0 To n_rule-1 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 End If If x2 > max max = x2 End If End If End If Next Dim h As Double = (max - min) / bun If h < 1.0e-15 Console.WriteLine("***error invalid data (h = 0) ***") Environment.Exit(1) End If ' ' 積分(重心の計算,台形則) ' z1 = Height(min, om) z2 = Height(max, om) y1 = 0.5 * (min * z1 + max * z2) y2 = 0.5 * (z1 + z2) x1 = min For i1 As Integer = 0 To bun-2 x1 += h z1 = Height(x1, om) y1 += x1 * z1 y2 += z1 Next y1 *= h y2 *= h If Math.Abs(y2) > 1.0e-10 y = y1 / y2 Else Console.WriteLine("***error invalid data (y2 = 0) ***") Environment.Exit(1) End If Return y End Function End Class End Module /* ------------------------規則ファイル-------------- 推論方法 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 */
情報学部 | 菅沼ホーム | 目次 | 索引 |