ファジイ推論

# -*- coding: UTF-8 -*-
import sys
from math import *
from random import *
import numpy as np

############################
# クラスFuzzyの定義
#      coded by Y.Suganuma
############################

class Fuzzy :
	
	#####################################
	# コンストラクタ
	#      name : 入力データファイル名
	#####################################
	
	def __init__(self, name) :

		in_f = open(name, "r")
			# 基本データの入力
		s           = in_f.readline().split()
		self.method = int(s[1])   # 推論方法
	                              #    =0 : and,or
	                              #    =1 : *,or
	                              #    =2 : *,+
		self.n_rule = int(s[3])   # 規則の数
		self.n_val = int(s[5])   # 変数の数
		self.bun = int(s[7])   # 積分の分割数
			# 領域の確保
		self.omega = np.empty(self.n_rule, np.float)   # ωの値
		self.rule  = np.empty((self.n_rule, self.n_val), np.int)
		               # [i][j] =0 : i番目の規則はj番目の変数を使用しない
		               #        =1 : i番目の規則はj番目の変数を使用する
		self.right = np.empty((self.n_rule, 2), np.float)
		               # [i][0] : 中心
		               # [i][1] : 幅
		self.left  = np.empty((self.n_rule, self.n_rule, 2), np.float)
		               # [i][j][0] : 中心
		               # [i][j][1] : 幅
			# 規則データの入力
		for i1 in range(0, self.n_rule) :
	
			in_f.readline()
							# 左辺
			for i2 in range(0, self.n_val) :
				s                 = in_f.readline().split()
				self.rule[i1][i2] = int(s[1])
				if self.rule[i1][i2] > 0 :
					self.left[i1][i2][0] = float(s[3])
					self.left[i1][i2][1] = float(s[4])
							# 右辺
			s                 = in_f.readline().split()
			self.right[i1][0] = float(s[1])
			self.right[i1][1] = float(s[2])
	
		in_f.close()
	
	###########################################
	# 交点の計算
	#      x : x
	#      c : 中心
	#      h : 幅
	#      r : <0 : 左辺のメンバーシップ関数
	#          >=0 : 右辺(ω) 
	#      return : 交点
	###########################################
	
	def Cross(self, x, c, h, r) :
	
		if x < c :
			x1 = c - h
			x2 = c
			y1 = 0.0
			if r < 0.0 or (r >= 0.0 and self.method == 0) :
				y2 = 1.0
			else :
				y2 = r
		else :
			x1 = c
			x2 = c + h
			if r < 0.0 or (r >= 0.0 and self.method == 0) :
				y1 = 1.0
			else :
				y1 = r
			y2 = 0.0
	
		y = y1 + (y2 - y1) * (x - x1) / (x2 - x1)
	
		if y < 0.0 :
			y = 0.0
		else :
			if r >= 0.0 and self.method == 0 and y > r :
				y = r
	
		return y
	
	##############################################
	# 右辺の計算
	#      x : 値
	#      om[i] : <0 : i番目の規則を使用しない
	#              >=0 : ωの値
	#      return : xにおける右辺の値
	##############################################
	
	def Height(self, x, om) :

		y  = 0.0
		sw = 0
	
		for i1 in range(0, self.n_rule) :
	
			if om[i1] >= 0.0 :
	
				y1 = self.Cross(x, self.right[i1][0], self.right[i1][1], om[i1])
	
				if sw == 0 :
					y  = y1
					sw = 1
				else :
					if self.method < 2 :
						if y1 > y :
							y = y1
					else :
						y += y1
	
		return y
	
	##########################
	# 推論の実行
	#      x[i] : 各変数の値
	#      return : 推論値
	##########################
	
	def Inf(self, x) :
	
			# ωの計算
		for i1 in range(0, self.n_rule) :
	
			self.omega[i1] = -1.0
	
			for i2 in range(0, self.n_val) :
	
				if self.rule[i1][i2] > 0 :
	
					if x[i2] > self.left[i1][i2][0]-self.left[i1][i2][1] and x[i2] < self.left[i1][i2][0]+self.left[i1][i2][1] :
						x1 = self.Cross(x[i2], self.left[i1][i2][0], self.left[i1][i2][1], -1.0)
					else :
						x1 = 0.0
	
					if self.omega[i1] < 0.0 :
						self.omega[i1] = x1
					else :
						if self.method == 0 :
							if x1 < self.omega[i1] :
								self.omega[i1] = x1
						else :
							self.omega[i1] *= x1
			# 右辺の計算
		y = self.Result(self.omega)
	
		return y
	
	##############################################
	# 右辺による推論
	#      om[i] : <0 : i番目の規則を使用しない
	#              >=0 : ωの値
	#      return : 推論値
	##############################################
	
	def Result(self, om) :

		max = 0.0
		min = 0.0
		y   = 0.0
		sw  = 0
			# 積分範囲と積分幅の計算
		for i1 in range(0, self.n_rule) :
			if om[i1] >= 0.0 :
				x1 = self.right[i1][0] - self.right[i1][1]
				x2 = self.right[i1][0] + self.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) / self.bun
	
		if h < 1.0e-15 :
			print("***error  invalid data (h = 0) ***")
			# 積分(重心の計算,台形則)
		z1 = self.Height(min, om)
		z2 = self.Height(max, om)
		y1 = 0.5 * (min * z1 + max * z2)
		y2 = 0.5 * (z1 + z2)
		x1 = min
	
		for i1 in range(0, self.bun-1) :
			x1 += h
			z1  = self.Height(x1, om)
			y1 += x1 * z1
			y2 += z1
	
		y1 *= h
		y2 *= h
	
		if abs(y2) > 1.0e-10 :
			y = y1 / y2
		else :
			print("***error  invalid data (y2 = 0) ***")
	
		return y

----------------------------------

# -*- coding: UTF-8 -*-
import numpy as np
import sys
from math import *
from random import *
from function import Fuzzy

############################
# ファジイ推論
#      coded by Y.Suganuma
############################

if len(sys.argv) == 4 :
				# オブジェクトの生成
	fz = Fuzzy(sys.argv[1])
				# 推論データの読み込み
	in_f  = open(sys.argv[2], "r")
	s     = in_f.readline().split()
	n_val = int(s[1])
	n_d   = int(s[3])
	x     = np.empty(n_val, np.float)
	xx    = np.empty((n_val, n_d), np.float)
	for i1 in range(0, n_val) :
		s = in_f.readline().split()
		for i2 in range(0, n_d) :
			xx[i1][i2] = float(s[i2+1])
	in_f.close()
				# 推論とその結果の出力
	out = open(sys.argv[3], "w")
	for i1 in range(0, n_d) :
		for i2 in range(0, n_val) :
			x[i2] = xx[i2][i1]
			out.write(str(x[i2]) + " ")
		y = fz.Inf(x)   # 推論
		out.write(str(y) + "\n")
	out.close()

else :
	print("***error   入力データファイル名を指定して下さい")

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