Exercise (Fuzzy Reasoning)

I hope you could understand the min-max method of Fuzzy reasoning, using the following Go programming list.

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 { // Base class for 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
}

// Class for the membership function (3 mountains) of the former case
func (c3 *condition_MF3) func_X(_x float64) float64 {
		// x,y denote coordinates on the membership function
	x := _x
	y := 0.0 // The value of y is always greater than or equal to 0 and less than or equal to 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 { // Base class for 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 {
	// Class for the former membership function (5 mountains)
	// x,y are the coordinates on the membership function

	x := _x
	y := 0.0 // The value of y is always greater than or equal to 0 and less than or equal to 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 { // Base class for action_MF5
	center  float64
	width   float64
	express string
	x       float64
	y       float64
}

type action_MF3 struct { // Base class for action_MF3
	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
}

func new_action_MF3(_center, _width float64, _express string) *action_MF3 {
	a3 := new(action_MF3)
	a3.center = _center
	a3.width = _width
	a3.express = _express

	if a3.express == "LESS" {
		a3.x = a3.center - a3.width
	} else if a3.express == "COMMON" {
		a3.x = a3.center
	} else if a3.express == "MORE" {
		a3.x = a3.center + a3.width
	} else {
		fmt.Println("new_action_MF3: wrong scale expression")
		os.Exit(-1)
	}

	a3.y = 0.0

	return a3
}


// The latter membership function (5 mountains) class
func (a5 *action_MF5) func_Y() float64 {
	return a5.y
}

// The latter membership function (3 mountains) class
func (a3 *action_MF3) func_Y() float64 {
	return a3.y
}

func (a5 *action_MF5) func_Max(b float64) {
	a5.y = max_2(b, a5.y)
}


func (a3 *action_MF3) func_Max(b float64) {
	a3.y = max_2(b, a3.y)
}


func (a5 *action_MF5) func_X() float64 {
	return a5.x
}

func (a3 *action_MF3) func_X() float64 {
	return a3.x
}


func fuzzy_reasoning(temp, humi float64) float64 {

	// Temperature(former)
	Temp_Less := new_condition_MF3(20, 10, "LESS")
	Temp_Common := new_condition_MF3(20, 10, "COMMON")
	Temp_More := new_condition_MF3(20, 10, "MORE")

	// Humidity(former)
	Humi_Less := new_condition_MF3(50, 20, "LESS")
	Humi_Common := new_condition_MF3(50, 20, "COMMON")
	Humi_More := new_condition_MF3(50, 20, "MORE")

	// Switch(前件部)
	Switch_Less := new_action_MF3(0,1,"LESS")
	Switch_Common := new_action_MF3(0,1,"COMMON")
	Switch_More := new_action_MF3(0,1,"MORE")

	// [Rule 01] 
	Rule01 := min_2(Temp_More.func_X(temp), Humi_More.func_X(humi))
	Switch_Less.func_Max(Rule01) // the latters values are overwritten if the value is large enough.
	fmt.Println("Rule01", Rule01)

	// [Rule 02] 
	Rule02 := min_2(Temp_Common.func_X(temp), Humi_More.func_X(humi))
	Switch_Common.func_Max(Rule02) // the latters values are overwritten if the value is large enough.
	fmt.Println("Rule02", Rule02)

	// [Rule 03] 
	Rule03 := min_2(Temp_More.func_X(temp), Humi_Common.func_X(humi))
	Switch_Less.func_Max(Rule03) // the latters values are overwritten if the value is large enough.
	fmt.Println("Rule03", Rule03)

	// [Rule 04] 
	Rule04 := min_2(Temp_Less.func_X(temp), Humi_Less.func_X(humi))
	Switch_More.func_Max(Rule04) // the latters values are overwritten if the value is large enough.
	fmt.Println("Rule04", Rule04)


	// Reasoning calculations
	numerator :=
			Switch_Less.func_X()*Switch_Less.func_Y() +
			Switch_Common.func_X()*Switch_Common.func_Y() +
			Switch_More.func_X()*Switch_More.func_Y() 

	denominator :=
			Switch_Less.func_Y() +
			Switch_Common.func_Y() +
			Switch_More.func_Y() 


	reasoning := numerator / denominator

	return reasoning

}

func main(){

	 fmt.Println(fuzzy_reasoning(27.0, 67.0))
}

2023,江端さんの技術メモ

Posted by ebata