------------------------makefile------------------ # # リンク # CFLAGS = -c -Wall -O2 OBJECT = fz.o cons.o dest.o Cross.o Height.o Inf.o Result.o pgm: $(OBJECT) g++ $(OBJECT) -o fz -lm # # コンパイル # fz.o: fuzzy.h fz.cpp g++ $(CFLAGS) fz.cpp cons.o: fuzzy.h cons.cpp g++ $(CFLAGS) cons.cpp dest.o: fuzzy.h dest.cpp g++ $(CFLAGS) dest.cpp Cross.o: fuzzy.h Cross.cpp g++ $(CFLAGS) Cross.cpp Height.o: fuzzy.h Height.cpp g++ $(CFLAGS) Height.cpp Inf.o: fuzzy.h Inf.cpp g++ $(CFLAGS) Inf.cpp Result.o: fuzzy.h Result.cpp g++ $(CFLAGS) Result.cpp ------------------------規則ファイル-------------- 推論方法 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 ------------------------fuzzy.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 *); }; ------------------------constructor--------------- /************************************/ /* コンストラクタ */ /* name : 入力データファイル名 */ /************************************/ #include <stdio.h> #include "fuzzy.h" 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); } ------------------------destructor---------------- /****************/ /* デストラクタ */ /****************/ #include "fuzzy.h" 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; } ------------------------Cross.cpp---------------- /*******************************************/ /* 交点の計算 */ /* x : x */ /* c : 中心 */ /* h : 幅 */ /* r : <0 : 左辺のメンバーシップ関数 */ /* >=0 : 右辺(ω) */ /* return : 交点 */ /*******************************************/ #include "fuzzy.h" 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; } ------------------------Height.cpp---------------- /**********************************************/ /* 右辺の計算 */ /* x : 値 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : xにおける右辺の値 */ /**********************************************/ #include "fuzzy.h" 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; } ------------------------Inf.cpp------------------- /**************************/ /* 推論の実行 */ /* x[i] : 各変数の値 */ /* return : 推論値 */ /**************************/ #include "fuzzy.h" 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; } ------------------------Result.cpp---------------- /**********************************************/ /* 右辺による推論 */ /* om[i] : <0 : i番目の規則を使用しない */ /* >=0 : ωの値 */ /* return : 推論値 */ /**********************************************/ #include <stdio.h> #include <math.h> #include "fuzzy.h" 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---------------------- /****************************/ /* ファジイ推論 */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> #include <stdlib.h> #include "fuzzy.h" /****************/ /* 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; }