// このプログラムをfuzzy.cpp"という名前で保存して、
// gcc -g fuzzy.cpp -o fuzzy
// でコンパイルして下さい。
#include <stdio.h>
#include <stdlib.h>
// 共通関数
double max(double a){
return a;
}
double max(double a, double b){
if (a > b)
return a;
else
return b;
};
double max(double a, double b, double c ){
return max(max(a,b), c);
};
double max(double a, double b, double c, double d ){
return max(max(a,b,c), d);
};
double min(double a){
return a;
}
double min(double a, double b){
if (b > a)
return a;
else
return b;
};
double min(double a, double b, double c ){
return min(min(a,b), c);
};
double min(double a, double b, double c, double d ){
return min(min(a,b,c), d);
};
// ファジィ表現
typedef enum scale {LESSLESS, LESS, ZERO, MORE, MOREMORE} SCALE;
// 前件部メンバーシップ関数(山3つ)クラス
class condition_MF3
{
private:
double center;
double width;
SCALE express;
public:
condition_MF3(double _center, double _witdth, SCALE _express){
center = _center;
width = _witdth;
express = _express;
};
double func(double x);
};
double condition_MF3::func(double x)
{
// x,yは、メンバーシップ関数上の座標を示す
double y = 0.0; // yの値は、必ず0以上1以下になる
if (express == LESS){
if (x <= center - width){
y = 1.0;
}
else if (x <= center){
y = - 1.0 / width * (x - center);
}
else{
y = 0.0;
}
}
else if (express == ZERO){
if (x <= center - width){
y = 0.0;
}
else if (x <= center){
y = 1.0 / width * (x - center) + 1.0;
}
else if (x <= center + width){
y = -1.0 / width * (x - center) + 1.0;
}
else{
y = 0.0;
}
}
else if (express == MORE){
if (x <= center){
y = 0.0;
}
else if (x <= center + width){
y = 1.0 / width * (x - center);
}
else{
y = 1.0;
}
}
return y;
};
// 後件部メンバーシップ関数(山3つ)クラス
class action_MF3
{
private:
double center;
double width;
SCALE express;
double x;
double y;
public:
action_MF3(double _center, double _witdth, SCALE _express){
y = 0.0; // yの値は、必ず0以上1以下になる
center = _center;
width = _witdth;
express = _express;
if (express == LESS){
x = center - width;
}
else if (express == ZERO){
x = center;
}
else if (express == MORE){
x = center + width;
}
else{
printf("wrong scale expression\n");
exit(0);
}
};
// Y座標の値を最大値で更新する
void func_Max(double b){
y = max(b, y);
};
// Y座標の値をリセット(y=0)する
void func_Reset(){
y = 0.0;
};
// X座標を返す
double func_X(void){
return x;
};
// (最大値で更新された、最後の)Y座標を返す
double func_Y(){
return y;
};
};
int main()
{
condition_MF3 temp_High(20.0, 10.0, MORE);
condition_MF3 temp_Middle(20.0, 10.0, ZERO);
condition_MF3 temp_Low(20.0, 10.0, LESS);
condition_MF3 humi_High(50.0, 20.0, MORE);
condition_MF3 humi_Middle(50.0, 20.0, ZERO);
condition_MF3 humi_Low(50.0, 20.0, LESS);
// エアコンの温度設定を上げる("+1"にする)
action_MF3 switch_High(0.0, 1.0, MORE);
// エアコンの温度設定に何もしない("0"にする)
action_MF3 switch_Middle(0.0, 1.0, ZERO);
// エアコンの温度設定を下げる("-1"にする)
action_MF3 switch_Low(0.0, 1.0, LESS);
// 入力値(温度27度、湿度57%)
double t = 27.0;
double h = 57.0;
// (1)「もし温度が高くて湿度が高ければ、エアコンの温度設定を下げる」
double a1 = min(temp_High.func(t),humi_High.func(h));
printf("%f\n", a1);
switch_Low.func_Max(a1);
// (2)「もし温度が普通で湿度が高ければ、何もしない」
double a2 = min(temp_Middle.func(t),humi_High.func(h));
switch_Middle.func_Max(a2);
printf("Middle");
printf("%f\n", switch_Middle.func_Y());
// (3)「もし温度が高くて湿度が普通なら、エアコンの温度設定を下げる」
double a3 = min(temp_High.func(t),humi_Middle.func(h));
switch_Low.func_Max(a3) ;
printf("Low");
printf("%f\n", switch_Low.func_Y());
// (4)「もし温度が低くて湿度が低ければ、エアコンの温度設定を上げる」
double a4 = min(temp_Middle.func(t),humi_Low.func(h));
switch_High.func_Max(a4) ;
printf("High" );
printf("%f\n", switch_High.func_Y());
// (5)(追加)もし温度が普通で、湿度が普通なら、何もしない
double a5 = min(temp_Middle.func(t),humi_Middle.func(h));
switch_Middle.func_Max(a5) ;
printf( "Middle" );
printf("%f\n", switch_Middle.func_Y() );
// 推論値(重心値)を求める
double reasoning =
(switch_High.func_X() * switch_High.func_Y() +
switch_Middle.func_X() * switch_Middle.func_Y() +
switch_Low.func_X() * switch_Low.func_Y())
/
(switch_High.func_Y() +
switch_Middle.func_Y() +
switch_Low.func_Y());
printf("\n reasoning = %f\n",reasoning);
// 後件部メンバーシップ関数のリセット(ループする時は必ずリセットする)
switch_High.func_Reset();
switch_Middle.func_Reset();
switch_Low.func_Reset();
}