############################
# ファジイ推論
# 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