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