Go言語によるファジィ(Fuzzy)推論コード
をGo言語に移植してみました。
で、できるだけ、
に近づけてみました。
コメントのPrint分は、C++のを残しています(面倒だったので)。あとenum型がないので、テキトーに文字列を使うことにしました。
以前のコードには、豪快なバグがありましたので、ソックリ差し替えします。
設定条件は以下の通りです(テーブルの内容は、負荷量です)
package main
import (
"fmt"
"os"
)
func max_2(a, b float64) float64 {
if a > b {
return a
} else {
return b
}
}
func min_2(a, b float64) float64 {
if a > b {
return b
} else {
return a
}
}
type condition_MF3 struct { // condition_MF3の基底クラス
center float64
width float64
express string
}
func new_condition_MF3(_center, _width float64, _express string) *condition_MF3 {
c3 := new(condition_MF3)
c3.center = _center
c3.width = _width
c3.express = _express
return c3
}
// 前件部メンバーシップ関数(山3つ)クラス
func (c3 *condition_MF3) func_X(_x float64) float64 {
// x,yは、メンバーシップ関数上の座標を示す
x := _x
y := 0.0 // yの値は、必ず0以上1以下になる
if c3.express == "LESS" {
if x <= c3.center-c3.width {
y = 1.0
} else if x <= c3.center {
y = -1.0 / c3.width * (x - c3.center)
} else {
y = 0.0
}
} else if c3.express == "COMMON" {
if x <= c3.center-c3.width {
y = 0.0
} else if x <= c3.center {
y = 1.0/c3.width*(x-c3.center) + 1.0
} else if x <= c3.center+c3.width {
y = -1.0/c3.width*(x-c3.center) + 1.0
} else {
y = 0.0
}
} else if c3.express == "MORE" {
if x <= c3.center {
y = 0.0
} else if x <= c3.center+c3.width {
y = 1.0 / c3.width * (x - c3.center)
} else {
y = 1.0
}
} else {
fmt.Println("MF3: wrong expression")
os.Exit(1)
}
return y
}
type condition_MF5 struct { // condition_MF5の基底クラス
center float64
width float64
express string
}
func new_condition_MF5(_center, _width float64, _express string) *condition_MF5 {
c5 := new(condition_MF5)
c5.center = _center
c5.width = _width
c5.express = _express
return c5
}
func (c5 *condition_MF5) func_X(_x float64) float64 {
// 前件部メンバーシップ関数(山5つ)クラス
// x,yは、メンバーシップ関数上の座標を示す
x := _x
y := 0.0 // yの値は、必ず0以上1以下になる
if c5.express == "LESSLESS" {
if x <= c5.center-2.0*c5.width {
y = 1.0
} else if x <= c5.center-c5.width {
y = -1.0/c5.width*(x-(c5.center-2.0*c5.width)) + 1.0
} else {
y = 0.0
}
} else if c5.express == "LESS" {
if x <= c5.center-2.0*c5.width {
y = 0.0
} else if x <= c5.center-c5.width {
y = 1.0/c5.width*(x-(c5.center-c5.width)) + 1.0
} else if x <= c5.center {
y = -1.0/c5.width*(x-(c5.center-c5.width)) + 1.0
} else {
y = 0.0
}
} else if c5.express == "COMMON" {
if x <= c5.center-c5.width {
y = 0.0
} else if x <= c5.center {
y = 1.0/c5.width*(x-c5.center) + 1.0
} else if x <= c5.center+c5.width {
y = -1.0/c5.width*(x-c5.center) + 1.0
} else {
y = 0.0
}
} else if c5.express == "MORE" {
if x <= c5.center {
y = 0.0
} else if x <= c5.center+c5.width {
y = 1.0/c5.width*(x-(c5.center+c5.width)) + 1.0
} else if x <= c5.center+2.0*c5.width {
y = -1.0/c5.width*(x-(c5.center+c5.width)) + 1.0
} else {
y = 0.0
}
} else if c5.express == "MOREMORE" {
if x <= c5.center+c5.width {
y = 0.0
} else if x <= c5.center+2.0*c5.width {
y = 1.0/c5.width*(x-(c5.center+2.0*c5.width)) + 1.0
} else {
y = 1.0
}
} else {
fmt.Println("MF5 func_X(): wrong expression")
os.Exit(1)
}
return y
}
/////////////////////////////
type action_MF5 struct { // condition_MF5の基底クラス
center float64
width float64
express string
x float64
y float64
}
func new_action_MF5(_center, _width float64, _express string) *action_MF5 {
a5 := new(action_MF5)
a5.center = _center
a5.width = _width
a5.express = _express
if a5.express == "LESSLESS" {
a5.x = a5.center - 2.0*a5.width
} else if a5.express == "LESS" {
a5.x = a5.center - a5.width
} else if a5.express == "COMMON" {
a5.x = a5.center
} else if a5.express == "MORE" {
a5.x = a5.center + a5.width
} else if a5.express == "MOREMORE" {
a5.x = a5.center + 2.0*a5.width
} else {
fmt.Println("new_action_MF5: wrong scale expression")
os.Exit(-1)
}
a5.y = 0.0
return a5
}
// 後件部メンバーシップ関数(山3つ)クラス
func (a5 *action_MF5) func_Y() float64 {
// x,yは、メンバーシップ関数上の座標を示す
return a5.y
}
func (a5 *action_MF5) func_Max(b float64) {
a5.y = max_2(b, a5.y)
}
func (a5 *action_MF5) func_X() float64 {
return a5.x
}
func complain_reasoning(dis, age float64) float64 {
// Walking(前件部)
Walk_Less := new_condition_MF3(1.4, 0.4, "LESS")
Walk_Common := new_condition_MF3(1.4, 0.4, "COMMON")
Walk_More := new_condition_MF3(1.4, 0.4, "MORE")
// Age(前件部)
Age_LessLess := new_condition_MF5(42, 15, "LESSLESS")
Age_Less := new_condition_MF5(42, 15, "LESS")
Age_Common := new_condition_MF5(42, 15, "COMMON") // 中央が 42歳
Age_More := new_condition_MF5(42, 15, "MORE")
Age_MoreMore := new_condition_MF5(42, 15, "MOREMORE")
// Complain(後件部)
Complain_LessLess := new_action_MF5(0.5, 0.25, "LESSLESS") // 不満の中央値が0.5 0.0/0.25/0.50/0.75/1.00 の5段階
Complain_Less := new_action_MF5(0.5, 0.25, "LESS")
Complain_Common := new_action_MF5(0.5, 0.25, "COMMON")
Complain_More := new_action_MF5(0.5, 0.25, "MORE")
Complain_MoreMore := new_action_MF5(0.5, 0.25, "MOREMORE")
// [ルール00] 歩行距離:少0 年令:子供0
Rule00 := min_2(Walk_Less.func_X(dis), Age_LessLess.func_X(age))
Complain_LessLess.func_Max(Rule00) // 後件部は上書きされていく
//fmt.Println("Rule00", Rule00)
// [ルール01] 歩行距離:少0 年令:若年1
Rule01 := min_2(Walk_Less.func_X(dis), Age_Less.func_X(age))
Complain_LessLess.func_Max(Rule01) // 後件部は上書きされていく
//fmt.Println("Rule01", Rule01)
// [ルール02] 歩行距離:少0 年令:壮年2
Rule02 := min_2(Walk_Less.func_X(dis), Age_Common.func_X(age))
Complain_Common.func_Max(Rule02) // 後件部は上書きされていく
//fmt.Println("Rule02", Rule02)
// [ルール03] 歩行距離:少0 年令:高齢3
Rule03 := min_2(Walk_Less.func_X(dis), Age_More.func_X(age))
Complain_Common.func_Max(Rule03) // 後件部は上書きされていく
//fmt.Println("Rule03", Rule03)
// [ルール04] 歩行距離:少0 年令:老齢4
Rule04 := min_2(Walk_Less.func_X(dis), Age_MoreMore.func_X(age))
Complain_More.func_Max(Rule04) // 後件部は上書きされていく
//fmt.Println("Rule04", Rule04)
// [ルール10] 歩行距離:普通1 年令:子供0
Rule10 := min_2(Walk_Common.func_X(dis), Age_LessLess.func_X(age))
Complain_LessLess.func_Max(Rule10) // 後件部は上書きされていく
//fmt.Println("Rule10", Rule10)
// [ルール11] 歩行距離:普通1 年令:若年1
Rule11 := min_2(Walk_Common.func_X(dis), Age_Less.func_X(age))
Complain_Less.func_Max(Rule11) // 後件部は上書きされていく
//fmt.Println("Rule11", Rule11)
// [ルール12] 歩行距離:普通1 年令:壮年2
Rule12 := min_2(Walk_Common.func_X(dis), Age_Common.func_X(age))
Complain_Common.func_Max(Rule12) // 後件部は上書きされていく
//fmt.Println("Rule12", Rule12)
// [ルール13] 歩行距離:普通1 年令:高齢3
Rule13 := min_2(Walk_Common.func_X(dis), Age_More.func_X(age))
Complain_More.func_Max(Rule13) // 後件部は上書きされていく
//fmt.Println("Rule13", Rule13)
// [ルール14] 歩行距離:普通1 年令:老齢4
Rule14 := min_2(Walk_Common.func_X(dis), Age_MoreMore.func_X(age))
Complain_MoreMore.func_Max(Rule14) // 後件部は上書きされていく
//fmt.Println("Rule14", Rule14)
// [ルール20] 歩行距離:多2 年令:こども0
Rule20 := min_2(Walk_More.func_X(dis), Age_LessLess.func_X(age))
Complain_Less.func_Max(Rule20) // 後件部は上書きされていく
//fmt.Println("Rule20", Rule20)
// [ルール21] 歩行距離:多2 年令:若年1
Rule21 := min_2(Walk_More.func_X(dis), Age_Less.func_X(age))
Complain_Common.func_Max(Rule21) // 後件部は上書きされていく
//fmt.Println("Rule21", Rule21)
// [ルール22] 歩行距離:多2 年令:壮年2
Rule22 := min_2(Walk_More.func_X(dis), Age_Common.func_X(age))
Complain_More.func_Max(Rule22) // 後件部は上書きされていく
//fmt.Println("Rule22", Rule22)
// [ルール23] 歩行距離:多2 年令:高齢3
Rule23 := min_2(Walk_More.func_X(dis), Age_More.func_X(age))
Complain_MoreMore.func_Max(Rule23) // 後件部は上書きされていく
//fmt.Println("Rule23", Rule23)
// [ルール24] 歩行距離:多2 年令:老齢4
Rule24 := min_2(Walk_More.func_X(dis), Age_MoreMore.func_X(age))
Complain_MoreMore.func_Max(Rule24) // 後件部は上書きされていく
//fmt.Println("Rule24", Rule24)
// 推論計算
numerator :=
Complain_LessLess.func_X()*Complain_LessLess.func_Y() +
Complain_Less.func_X()*Complain_Less.func_Y() +
Complain_Common.func_X()*Complain_Common.func_Y() +
Complain_More.func_X()*Complain_More.func_Y() +
Complain_MoreMore.func_X()*Complain_MoreMore.func_Y()
denominator :=
Complain_LessLess.func_Y() +
Complain_Less.func_Y() +
Complain_Common.func_Y() +
Complain_More.func_Y() +
Complain_MoreMore.func_Y()
complain := numerator / denominator
return complain
}