Click here to Skip to main content
15,881,768 members
Articles / Desktop Programming / Windows Forms

Fuzzinator: A Fuzzy Logic Controller

Rate me:
Please Sign up or sign in to vote.
4.67/5 (26 votes)
20 Jan 2010CPOL5 min read 142.5K   8.3K   60   41
Fuzzy Logic Controller C# Library based on mamdani Inference Engine + Windows Forms GUI

FuzzyLogicInterface.jpg

FLCInterface2.jpg

Introduction  

This article is about a fuzzy logic controller based on mamdani Inference Engine. Fuzzy logic is an approximation process, in which crisp inputs are turned to fuzzy values based on linguistic variables, set of rules and the inference engine provided. For example:

I have a train, I considered the Linguistic Variable "Speed" of the train has 2 membership functions Low and High, in which "Low" has range from 0 mph - 10 mph and "High" from 10 mph - 20 mph.

So If I got a Crisp input of 5 -> its fuzzy value is Low.

Imagine more if the range from 0-10 is not constant but a triangular graph with the max height of 1 and for Low a triangle graph with 3 distinct points 0,5,10.

Now for a singleton input of 4, the fuzzy value = y = (4-0)/(5-0) = 0.8, therefore our fuzzy input = 0.8 Low, imagine that the linguistic variables are intersecting so that a single input can be defined as (0.8 Low 0.4 High).

This process is called fuzzification...

After we get the fuzzy inputs, we compare it against a rule base. A rule base is a set of rules that is responsible for final output.

For example, if I said my rules are:

Rule 1: If Speed is High, Then Brake is Pushed

Rule 2: If Speed is Low, Then Brake is Released

So now using our Inference Engine, the Engine that would compare and deduct our fuzzy output, with fuzzy input ( 0.8 Low , 0.4 High) we can say based upon the rules mentioned above that the brakes will be down by (0.4 Pushed 0.8 Released) --> Fuzzy output.

This is the Rule Base and Inference Engine Process using mamdani concept...

Then the fuzzy output enters the defuzzification method, which is a method to weigh the fuzzy outputs and return a crisp output force which will be applied to the brakes.

FuzzySystem.png

Fig. 1-1

Using the Code

In the project attached with this article, 3 sub projects exist:

  1. A C# class library contains the engine that implements the steps talked about in the above example.
  2. A Window Forms Project FuzzyLogicUI which is a User Interface built for this fuzzy logic controller, you can add linguistic variables and membership functions, rules and a result panel to show you the different steps of the system.
  3. A console based test to the Fuzzy Logic Controller for better understanding of the system.

The Fuzzy Library (DLL)

The Class Diagram

ClassDiagram1.png - Click to enlarge image

Steps

1- Configure Your Fuzzy Controller

The allowed configuration for this system, is the (And Logic Connection) and Implication.

For a Rule: IF X1 is Low And X2 is High -> Y1 is Low.

How to calculate the final firing strength, if X1-> 0.8 X2-> 0.4 so Y1-> ?

If we use an (AND Connection) in this system you can define the AND Method between product or minimum , so for Y1 = min(0.8,0.4) = 0.4 due to an "AND" connection between X1 & X2.

C#
Config configure = new Config(ImpMethod.Prod,ConnMethod.Min);

2- Create Your Linguistic Variables and its Membership Functions

Using above Train example: we define the Train to have speed for input. For speed: High, Med, Low for the result (output) Brake: Release, Push.

C#
LingVariable speed = new LingVariable("Speed", VarType.Input); //declare new lingustic variable
speed.setRange(0, 35); // set max - min range for our variables 0 mph -35 mph
speed.addMF(new Trapmf("Low", -10, 0, 10, 15)); // trapmf: trapazoid shape behaviour
speed.addMF(new Trimf("Medium", 10, 20, 30)); // trimf: triangle shape behaviour
speed.addMF(new Trapmf("High", 25, 30, 35, 40));

LingVariable brake = new LingVariable("Brake", VarType.Output);
brake.setRange(0, 65);  // Brake Force
brake.addMF(new Trapmf("Released", -10, 0, 20, 41));
brake.addMF(new Trapmf("Pushed", 41, 60, 65, 70)); 

3- Crisp Inputs and Fuzzification Process

Fuzzification is the process of evaluating the crisp input against the membership functions of the lingstic variable Speed, membershipfunction is an abstract class, with an abstract method "getOutput", any object inheriting this class needs to define their getOutput(double) function, such as in Trimf and Trapmf. Based upon this feature, more membershipfunctions can be implemented to extend the fuzzy controller capabilities.

Fuzzification method then returns a list of fuzzy numbers, each fuzzy number consists of a function name and firing strength from getOutput(double).

Example: fuzzynumber(0.8,"Low") FuzzyNumber(0.4,"High")

The list of fuzzy numbers is then added to a fuzzy Set with list of Fuzzy numbers and linguistic Variable name for further processing.

C#
FLC c = new FLC(conf);
double speedCrispVal = 30;
FuzzySet fuzzy_speed = new FuzzySet(c.Fuzzification(speedCrispVal,speed), speed.Name); 

After we fuzzify all our inputs, add it to a list of fuzzysets:

C#
List<FuzzySet> input_sets = new List<FuzzySet>();
input_sets.Add(fuzzy_speed);

4- Make the rules !

Define the rulebase, the rules that our system uses to approximate.

For Rule 1, from the above example:

"IF Speed is High, Then Brake is pushed."

C#
List<ruleitem> rule1in = new List<ruleitem>();
List<ruleitem> rule1out = new List<ruleitem>();

// the if part of the Rule, add more than one if X1 and X2, 
// add another RuleItem in the list
rule1in.AddRange(new RuleItem[1] { new RuleItem("Speed", "High") } );

// the then part in the Rule
rule1out.AddRange(new RuleItem[1] { new RuleItem("Brake", "Pushed") } );

// List of rules "RuleBase" passed to the Inference Engine
List<rule> rules = new List<rule>();
rules.Add(new Rule(rule1in, rule1out, Connector.And));

5- Evaluate the Rule

During the rules evaluation at the Inference system, the firing strength of the output is determined as in this example:

Fuzzy input: X1 = 0.8 Low X2 = 0.5 High.

Rule: "IF X1 Low and X2 High Then Y1 is Low."

Configuration: And connection evaluated by min(X1,X2).

Evaluation: min(X1,X2) => min(0.8,0.5) = Y1 = 0.5 Low.

Fuzzy out: Y1 = 0.5 Low.

If more rules are overlapping, such as "IF X1 is High, THEN Y1 is Low" where the Y1 is 0.7 Low, the maximum of Y1 firing strengths is taken, in this case ( 0.7 ).

C#
InferEngine engine = new InferEngine(configure, rules, input_sets);
List<FuzzySet> fuzzy_out = engine.evaluateRules();

6- DeFuzzification and Crisp Output

The Defuzzification method is a method to calculate the fuzzy out to convert to a crisp value. In this system, two methods of defuzzification are used, you can choose between them in Configuration.

Centroid Defuzzification, Modified High Defuzzification.

C#
double crisp_brake_force = c.DeFuzzification(fuzzy_out, brake); 

Points of Interest

This project has been made very flexible and extendable for future development and upgrading. The GUI is made to realise the Fuzzy Logic controller and to try it out, it is made mainly for educational purposes. The FuzzySets and FuzzyNumber classes are provided for more depth in fuzzy process.

For more tests and examples, try GUI Project Predefined Tests, or the console based test project "FuzzyTest". 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Egypt Egypt
My Name is Hesham Omran, I am a researcher in Human Computer Interaction and a Phd Candidate (Looking for a new supervisor). I graduated with a master of science from RWTH Aachen University in Media Informatics and a bachelor degree in Digital Media Engineer from the German University in Cairo,

My background in various languages C++/VC++, PHP, SQL, C#, MATLAB, Python, JS, Objective-C, Swift...etc.

Topic I am interested in topic such as UX, IoT, Emotional AI.

I am a big fan of CodeProject, it saved my life a couple of time, so I thought of giving back some.

Comments and Discussions

 
QuestionFuzzinator is coming to the cloud Pin
homran30-May-19 4:11
homran30-May-19 4:11 
Questionfuzzy Pin
Esra'a Edenat12-Nov-16 9:43
Esra'a Edenat12-Nov-16 9:43 
AnswerRe: fuzzy Pin
OriginalGriff12-Nov-16 9:48
mveOriginalGriff12-Nov-16 9:48 
GeneralRe: fuzzy Pin
Esra'a Edenat12-Nov-16 23:52
Esra'a Edenat12-Nov-16 23:52 
GeneralRe: fuzzy Pin
OriginalGriff12-Nov-16 23:54
mveOriginalGriff12-Nov-16 23:54 
GeneralRe: fuzzy Pin
homran13-Nov-16 0:00
homran13-Nov-16 0:00 
Questionc# to c++, its possible? Pin
Tima Sama3-May-15 6:34
Tima Sama3-May-15 6:34 
Questionsave Pin
Member 1048880914-May-14 5:50
Member 1048880914-May-14 5:50 
AnswerRe: save Pin
homran10-Dec-14 2:04
homran10-Dec-14 2:04 
QuestionGood Work. Pin
swad986-Apr-13 10:18
swad986-Apr-13 10:18 
GeneralMy vote of 5 Pin
Shayan Ali Bhatti6-Mar-13 0:15
Shayan Ali Bhatti6-Mar-13 0:15 
GeneralMy vote of 5 Pin
Kanasz Robert6-Nov-12 0:02
professionalKanasz Robert6-Nov-12 0:02 
QuestionA problem with project Pin
Mariusz Domagała16-Jan-12 11:55
Mariusz Domagała16-Jan-12 11:55 
QuestionFuzzy Wang Mendel Pin
aeranginkaman17-Dec-11 20:06
aeranginkaman17-Dec-11 20:06 
AnswerRe: Fuzzy Wang Mendel Pin
homran18-Dec-11 0:18
homran18-Dec-11 0:18 
Questionmany many thanks Pin
outta1323-Sep-11 12:47
professionaloutta1323-Sep-11 12:47 
GeneralVery nice article Pin
anupamaz29-Dec-10 7:00
anupamaz29-Dec-10 7:00 
GeneralGaussian MF Pin
AlbertoBenavides23-Nov-10 7:06
AlbertoBenavides23-Nov-10 7:06 
AnswerRe: Gaussian MF Pin
homran23-Nov-10 17:17
homran23-Nov-10 17:17 
GeneralHaving issues adding more than one rule, it just appends new rules to old rule Pin
pharaohautomation29-Jul-10 18:15
pharaohautomation29-Jul-10 18:15 
Hello, i am a student in eleventh grade. I am trying to implement a fuzzy logic controller in a project. I attempted to clone your software in vb.net, but i cannot add multiple rules. The rules are appended to one another.

For example instead of 2 separate rules i get 2 large joined rules:
1.IF InternalTemp is Zero And ExternalTemp is Zero And InternalTemp is Neg And ExternalTemp is Zero Then Actions is NoAction And Actions is TurnVentOn<br />
2.IF InternalTemp is Zero And ExternalTemp is Zero And InternalTemp is Neg And ExternalTemp is Zero Then Actions is NoAction And Actions is TurnVentOn


here is my vb.net code for this
Imports FuzzyLogicController
Imports System.IO

Public Class frmmain
    Dim internaltemprange As String
    Dim externaltemprange As String

    Dim tempruleparse As ArrayList

    Dim optimum As String
    Dim deltainttemp As Double
    Dim deltaexttemp As Double
    Dim temprules As New ArrayList

    Dim interrange As String
    Dim interneglow As String
    Dim interneg As String
    Dim interzero As String
    Dim interpos As String
    Dim interposhigh As String

    Dim exterrange As String
    Dim externeglow As String
    Dim externeg As String
    Dim exterzero As String
    Dim exterpos As String
    Dim exterposhigh As String

    Dim config As New RuleEngine.Config(RuleEngine.ImpMethod.Prod, RuleEngine.ConnMethod.Min)
    Dim InternalTemp As New LingVariable("InternalTemp", VarType.Input)
    Dim ExternalTemp As New LingVariable("ExternalTemp", VarType.Input)
    Dim Actions As New LingVariable("Actions", VarType.Output)
    Dim c As New FLC.FLC(config)
    Private Sub frmmain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        '--------------------------------READ VARIABLE DATA FROM FILES----------------------------------------
        'read optimum temp and the fuzzy rules for temp in "temprules.dat"
        Dim w As New System.IO.StreamReader(Application.StartupPath & "\temprules.dat")
        optimum = w.ReadLine()
        While w.Peek <> -1
            temprules.Insert(0, w.ReadLine)
        End While
        w.Close()

        tempruleparse = temprules.Clone

        For x = 0 To tempruleparse.Count - 1
            tempruleparse(x) = tempruleparse(x).ToString.Replace("If internal temperature is ", "")
            tempruleparse(x) = tempruleparse(x).ToString.Replace("and external temperature is ", "")
            tempruleparse(x) = tempruleparse(x).ToString.Replace(" then:", "")
            tempruleparse(x) = tempruleparse(x).ToString.Trim
            tempruleparse(x) = tempruleparse(x).ToString.Replace(" ", ",")
        Next

        'read internal temperature member functions to "internaltemp.dat"
        Dim h As New System.IO.StreamReader(Application.StartupPath & "\internaltemp.dat")
        interrange = h.ReadLine
        interneglow = h.ReadLine
        interneg = h.ReadLine
        interzero = h.ReadLine
        interpos = h.ReadLine
        interposhigh = h.ReadLine
        h.Close()
        'read external temperature member functions to "externaltemp.dat"
        Dim q As New System.IO.StreamReader(Application.StartupPath & "\externaltemp.dat")
        exterrange = q.ReadLine
        externeglow = q.ReadLine
        externeg = q.ReadLine
        exterzero = q.ReadLine
        exterpos = q.ReadLine
        exterposhigh = q.ReadLine
        q.Close()
        '--------------------------------------SET TEXTBOXES,COMBOBOXES,LISTS,ETC-----------------------------
        opttemp.Text = optimum
        intrange.Text = interrange
        intneglow.Text = interneglow
        intneg.Text = interneg
        intzero.Text = interzero
        intpos.Text = interpos
        intposhigh.Text = interposhigh
        extrange.Text = exterrange
        extneglow.Text = externeglow
        extneg.Text = externeg
        extzero.Text = exterzero
        extpos.Text = exterpos
        extposhigh.Text = exterposhigh
        For x = 0 To (temprules.Count - 1)
            lsttemprules.Items.Add(temprules(x))
        Next


        'Internal Temperature Variable and Membership Function Declaration/Assignment
        InternalTemp.setRange(interrange.Split(",")(0), interrange.Split(",")(1))
        InternalTemp.addMF(New MFs.Trimf("NegLow", interneglow.Split(",")(0), interneglow.Split(",")(1), interneglow.Split(",")(2)))
        InternalTemp.addMF(New MFs.Trimf("Neg", interneg.Split(",")(0), interneg.Split(",")(1), interneg.Split(",")(2)))
        InternalTemp.addMF(New MFs.Trimf("Zero", interzero.Split(",")(0), interzero.Split(",")(1), interzero.Split(",")(2)))
        InternalTemp.addMF(New MFs.Trimf("Pos", interpos.Split(",")(0), interpos.Split(",")(1), interpos.Split(",")(2)))
        InternalTemp.addMF(New MFs.Trimf("PosHigh", interposhigh.Split(",")(0), interposhigh.Split(",")(1), interposhigh.Split(",")(2)))

        'External Temperature Variable and Membership Function Declaration/Assignment
        ExternalTemp.setRange(exterrange.Split(",")(0), exterrange.Split(",")(1))
        ExternalTemp.addMF(New MFs.Trimf("NegLow", externeglow.Split(",")(0), externeglow.Split(",")(1), externeglow.Split(",")(2)))
        ExternalTemp.addMF(New MFs.Trimf("Neg", externeg.Split(",")(0), externeg.Split(",")(1), externeg.Split(",")(2)))
        ExternalTemp.addMF(New MFs.Trimf("Zero", exterzero.Split(",")(0), exterzero.Split(",")(1), exterzero.Split(",")(2)))
        ExternalTemp.addMF(New MFs.Trimf("Pos", exterpos.Split(",")(0), exterpos.Split(",")(1), exterpos.Split(",")(2)))
        ExternalTemp.addMF(New MFs.Trimf("PosHigh", exterposhigh.Split(",")(0), exterposhigh.Split(",")(1), exterposhigh.Split(",")(2)))

        'Actions Variable and Membership Function Assignment/Declaration
        Actions.setRange(0, 6)
        Actions.addMF(New MFs.Trimf("TurnHeatOn", 1, 1, 1))
        Actions.addMF(New MFs.Trimf("Forecast", 2, 2, 2))
        Actions.addMF(New MFs.Trimf("TurnVentOn", 3, 3, 3))
        Actions.addMF(New MFs.Trimf("NoAction", 4, 4, 4))
        Actions.addMF(New MFs.Trimf("TurnCoolOn", 5, 5, 5))

        'Set them for my testing
        deltainttemp = -6
        deltaexttemp = -7

        Dim fuzzy_internaltemp As New FuzzySet(c.Fuzzification(deltainttemp, InternalTemp), InternalTemp.Name)
        Dim fuzzy_externaltemp As New FuzzySet(c.Fuzzification(deltaexttemp, ExternalTemp), ExternalTemp.Name)


        Dim input_sets As New List(Of FuzzySet)()
        input_sets.Add(fuzzy_internaltemp)
        input_sets.Add(fuzzy_externaltemp)

        Dim rule1in As New List(Of RuleEngine.RuleItem)()

        Dim rule1out As New List(Of RuleEngine.RuleItem)()
        Dim rules As New List(Of RuleEngine.Rule)

        ' the if part of the Rule, add more than one if X1 and X2, 
        ' add another RuleItem in the list
        For x = 0 To tempruleparse.Count - 1
            rule1in.Add(New RuleEngine.RuleItem("InternalTemp", tempruleparse(x).split(",")(0)))
            rule1in.Add(New RuleEngine.RuleItem("ExternalTemp", tempruleparse(x).split(",")(1)))
            rule1out.Add(New RuleEngine.RuleItem("Actions", tempruleparse(x).split(",")(2)))
            rules.Add(New RuleEngine.Rule(rule1in, rule1out, RuleEngine.Connector.And))
        Next
        For x = 0 To rules.Count
            MsgBox(rules(x).ToString)
        Next
        'rule1in.AddRange(New RuleEngine.RuleItem(1) {New RuleEngine.RuleItem("InternalTemp", "Zero"), New RuleEngine.RuleItem("ExternalTemp", "Zero")})

        ' the then part in the Rule

        ' List of rules "RuleBase" passed to the Inference Engine

        Dim engine As New RuleEngine.InferEngine(config, rules, input_sets)
        Dim fuzzy_out As List(Of FuzzySet) = engine.evaluateRules()
        MsgBox(engine.FiredRules.Count)
        For x = 0 To fuzzy_out.Count - 1
            For y = 0 To fuzzy_out(x).Set.Count - 1
                MsgBox(fuzzy_out(x).Set(y).MemberShipName.ToString & ":" & fuzzy_out(x).Set(y).FuzzyValue)
            Next
        Next
        'MsgBox(fuzzy_out(fuzzy_out.Count - 1).Set(0).MemberShipName.ToString & ":" & fuzzy_out(fuzzy_out.Count - 1).Set(0).FuzzyValue.ToString)

    End Sub

    Private Sub cmdsave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdsave.Click
        cmdsave.Enabled = False
        '-------------------------------------SAVE TO DAT FILES------------------------------------------------------
        'write optimum temp and the fuzzy rules for temp in "temprules.dat"
        Dim w As New System.IO.StreamWriter(Application.StartupPath & "\temprules.dat")
        w.WriteLine(opttemp.Text)
        For x = 0 To (lsttemprules.Items.Count - 1)
            w.WriteLine(lsttemprules.Items(x))
        Next
        w.Close()
        'write internal temperature member functions to "internaltemp.dat"
        Dim h As New System.IO.StreamWriter(Application.StartupPath & "\internaltemp.dat")
        h.WriteLine(intrange.Text)
        h.WriteLine(intneglow.Text)
        h.WriteLine(intneg.Text)
        h.WriteLine(intzero.Text)
        h.WriteLine(intpos.Text)
        h.WriteLine(intposhigh.Text)
        h.Close()
        'write external temperature member functions to "externaltemp.dat"
        Dim q As New System.IO.StreamWriter(Application.StartupPath & "\externaltemp.dat")
        q.WriteLine(extrange.Text)
        q.WriteLine(extneglow.Text)
        q.WriteLine(extneg.Text)
        q.WriteLine(extzero.Text)
        q.WriteLine(extpos.Text)
        q.WriteLine(extposhigh.Text)
        q.Close()

        MsgBox("Changes Saved Successfully", , "Settings Changed")
        cmdsave.Enabled = True
    End Sub

    Private Sub cmdaddrule_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdaddrule.Click

        For x = 0 To lsttemprules.Items.Count - 1
            If InStr(lsttemprules.Items(x), "If internal temperature is " & cmbinttemp.Text & " and external temperature is " & cmbexttemp.Text & " then: " & cmbaction.Text) Then
                MsgBox("Rule already added", , "Duplicate Rule")
                Exit Sub
            End If
        Next
        lsttemprules.Items.Insert(0, "If internal temperature is " & cmbinttemp.Text & " and external temperature is " & cmbexttemp.Text & " then: " & cmbaction.Text)

    End Sub

    Private Sub cmddeleterule_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmddeleterule.Click
        If lsttemprules.SelectedItems.Count = 0 Then
            MsgBox("You must select a rule to remove", , "No Rule Selected")
        End If
        lsttemprules.Items.RemoveAt(lsttemprules.SelectedIndex)
    End Sub
End Class


heres the pastebin link
http://pastebin.ca/1911495
and heres a link to the entire vb.net project
http://www.mediafire.com/?4ldcq4b8jgllm3a

any help would be greatly appreciated
thanks
GeneralRe: Having issues adding more than one rule, it just appends new rules to old rule Pin
homran23-Nov-10 17:23
homran23-Nov-10 17:23 
NewsFuzzinator's Cousin is here : JFuzzinator Pin
homran6-Jun-10 22:12
homran6-Jun-10 22:12 
GeneralRe: Fuzzinator's Cousin is here : JFuzzinator Pin
MG Husny Ahmad24-Jan-14 17:16
MG Husny Ahmad24-Jan-14 17:16 
GeneralPlease give some explanation Pin
sammeeah20-Jan-10 19:31
sammeeah20-Jan-10 19:31 
GeneralRe: Please give some explanation Pin
homran20-Jan-10 20:06
homran20-Jan-10 20:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.