------------------------規則ファイル--------------
推論方法 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;
}
}