------------------------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;
}