Fuzzy Logic function set

Share your advanced PureBasic knowledge/code with the community.
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Fuzzy Logic function set

Post by Guimauve »

Hello everyone,

This is a set of Fuzzy Logic function for use in developpement, but not limited to, AI systems.

Best Regards

Guimauve

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project name : FuzzyLogic function
; File Mame : Lib_FuzzyLogic.pb
; File Version : 1.0.0
; Programmation : OK
; Programmed by : Guimauve
; Date : 11-09-2007
; Last Update : 10-05-2009
; Coded for PureBasic V4.30
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Procedure.d FuzzyGrade(Value.d, x0.d, x1.d) 
  
  If Value <= x0 
    FuzzyResult.d = 0.0 
  ElseIf Value >= x1
    FuzzyResult = 1.0
  Else 
    FuzzyResult = (Value - x0) / (x1 - x0)
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzyReverseGrade(Value.d, x0.d, x1.d) 

  If Value <= x0 
    FuzzyResult.d = 1.0 
  ElseIf Value >= x1
    FuzzyResult = 0.0
  Else 
    FuzzyResult = (x1 - Value) / (x1 - x0)
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzyTriangle(Value.d, x0.d, x1.d, x2.d) 

  If Value <= x0 
    FuzzyResult.d = 0.0 
  ElseIf Value = x1
    FuzzyResult = 1.0
  ElseIf (Value > x0) And (Value < x1)
    FuzzyResult = (Value - x0) / (x1 - x0)
  ElseIf (Value > x1) And (Value < x2)
    FuzzyResult = (x2 - Value) / (x2 - x1)
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzyTrapezoid(Value.d, x0.d, x1.d, x2.d, x3.d) 
   
  If Value <= x0 
    FuzzyResult.d = 0.0 
  ElseIf (Value >= x1) And (Value <= x2)
    FuzzyResult = 1.0
  ElseIf (Value > x0) And (Value < x1) 
    FuzzyResult = (Value-x0) - / (x1 - x0)
  ElseIf (Value > x2) And (Value < x3) 
    FuzzyResult = (x3 - Value) / (x3 - x2)
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzyAND(A.d, B.d) 
  
  If A > B
    FuzzyResult.d = B
  ElseIf A <= B
    FuzzyResult = A
  Else 
    FuzzyResult = A
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzyOR(A.d, B.d) 
  
  If A < B
    FuzzyResult.d = B
  ElseIf A >= B
    FuzzyResult = A
  Else 
    FuzzyResult = A
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzyNOT(A.d) 
   
  ProcedureReturn 1.0 - A
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Last edited by Guimauve on Mon May 11, 2009 1:20 am, edited 1 time in total.
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

Just a note, you can get a 10% speed increase just by changing equations of the form:

Code: Select all

FuzzyResult = (Value/(x1 - x0)) - (x0/(x1 - x0))
;and
FuzzyResult = (-Value/(x3 - x2)) + (x3/(x3 - x2))
to:

Code: Select all

FuzzyResult = (Value - x0)/(x1 - x0)
;or
FuzzyResult = (x3 - Value)/(x3 - x2)
User avatar
idle
Always Here
Always Here
Posts: 5917
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Post by idle »

That could useful thanks.
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Post by Guimauve »

Demivec wrote:Just a note, you can get a 10% speed increase just by changing equations of the form:

Code: Select all

FuzzyResult = (Value/(x1 - x0)) - (x0/(x1 - x0))
;and
FuzzyResult = (-Value/(x3 - x2)) + (x3/(x3 - x2))
to:

Code: Select all

FuzzyResult = (Value - x0)/(x1 - x0)
;or
FuzzyResult = (x3 - Value)/(x3 - x2)
It's done, see previous post.

Thanks

Best Regards

Guimauve
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

The procedures FuzzyTriangle() and FuzzyTrapezoid() seem to have some errors in their logic. This means they don't function properly. Here's one way that they can be rewritten:

Code: Select all

ProcedureDLL.d FuzzyTriangle(Value.d, x0.d, x1.d, x2.d)
  Protected FuzzyResult.d

  If Value = x1
    FuzzyResult = 1.0
  ElseIf Value <= x0 Or Value >= x2
    FuzzyResult = 0.0
  ElseIf (Value > x0) And (Value < x1)
    FuzzyResult = (Value - x0) / (x1 - x0)
  ElseIf (Value > x1) And (Value < x2)
    FuzzyResult = (x2 - Value) / (x2 - x1)
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

ProcedureDLL.d FuzzyTrapezoid(Value.d, x0.d, x1.d, x2.d, x3.d)
  Protected FuzzyResult.d
  
  If (Value >= x1) And (Value <= x2)
    FuzzyResult = 1.0
  ElseIf Value <= x0 Or Value >= x3 
    FuzzyResult = 0.0
  ElseIf (Value > x0) And (Value < x1)
    FuzzyResult = (Value - x0) / (x1 - x0)
  ElseIf (Value > x2) And (Value < x3)
    FuzzyResult = (x3 - Value) / (x3 - x2)
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure
This allows a value to be evaluated correctly where the peak of the triangle is over one of the ends (a right triangle). It also returns a value of 0.0 if the value is greater than the maximum range (outside the shape).

I've rewritten both of these functions with new variable names and supplied an optional height value (i.e. instead of a default value of 1.0, the optional height value would be returned instead) . I've also replaced the intermediate variable "FuzzyResult" and return the values directly. You may find some of these changes helpful

Code: Select all

ProcedureDLL.d FuzzyTriangle(Value.d, min.d, peak.d, max.d, height.d = 1.0)
  
  If Value = peak
    ProcedureReturn height
  ElseIf Value <= min Or Value >= max
    ProcedureReturn 0.0
  ElseIf (Value > min) And (Value < peak)
    ProcedureReturn ((Value - min) / (peak - min)) * height
  ElseIf (Value > peak) And (Value < max)
    ProcedureReturn ((max - Value) / (max - peak)) * height
  EndIf
  
EndProcedure

ProcedureDLL.d FuzzyTrapezoid(Value.d, lbMin.d, ubMin.d, ubMax.d, lbMax.d, height.d = 1.0)
  
  If (Value >= ubMin) And (Value <= ubMax)
    ProcedureReturn height
  ElseIf Value <= lbMin Or Value >= lbMax
    ProcedureReturn 0.0
  ElseIf (Value > lbMin) And (Value < ubMin)
    ProcedureReturn ((Value - lbMin) / (ubMin - lbMin)) * height
  ElseIf (Value > ubMax) And (Value < lbMax)
    ProcedureReturn ((lbMax - Value) / (lbMax - ubMax)) * height
  EndIf
  
EndProcedure
Were you thinking of implementing anything else? I thought about adding at least a few more functions such as FuzzyBell(), FuzzySigmoid(), and/or FuzzyGaussian().
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Post by Guimauve »

Demivec wrote:The procedures FuzzyTriangle() and FuzzyTrapezoid() seem to have some errors in their logic. This means they don't function properly.
The original function C source code came from "AI for Game Developers" book (www.oreilly.com). I have forget to include this information, sorry.
Demivec wrote:Were you thinking of implementing anything else? I thought about adding at least a few more functions such as FuzzyBell(), FuzzySigmoid(), and/or FuzzyGaussian().
Why not, but I'm very buzzy right now. You can add them if you wish.

Best Regards.

Guimauve
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Post by Guimauve »

Hello everyone,

There is the FuzzyBell(), FuzzySigmoid(), FuzzyGaussian(), FuzzySmoothGrade() and FuzzySmoothReverseGrade() function.

Best Regards
Guimauve

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project name : More Fuzzy Logic Function
; File Name : More Fuzzy Logic Function.pb
; File Version : 1.0.0
; Programmation : OK
; Programmed by : Guimauve
; Date : 14-05-2009
; Last Update : 14-05-2009
; Coded for PureBasic V4.30
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Procedure.d FuzzyBell(Value.d, Va.d, Vb.d, Vc.d, ChopValue.d = 0.0001)
  
  FuzzyResult.d = 1/(1+Pow(Abs((Value-Vc)/Va),2*Vb))
  
  If FuzzyResult <= ChopValue
    FuzzyResult = 0.0
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzySigmoid(Value.d, Va01.d, Vc01.d, Va02.d, Vc02.d, ChopValue.d = 0.0001)
  
  FuzzyResult.d = (1.0/(1+Pow(2.71828182846, -Va01*(Value-Vc01)))) * (1.0/(1+Pow(2.71828182846, -Va02*(Value-Vc02))))
  
  If FuzzyResult <= ChopValue
    FuzzyResult = 0.0
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzyGaussian(Value.d, Mu01.d, Sigma01.d, ChopValue.d = 0.0001)
  
  FuzzyResult.d = Pow(2.71828182846, -((Value - Mu01)*(Value - Mu01))/(2*Sigma01*Sigma01))
  
  If FuzzyResult <= ChopValue
    FuzzyResult = 0.0
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzySmoothGrade(Value.d, Va.d, Vb.d) 
  
  If Value <= Va 
    FuzzyResult.d = 0.0 
  ElseIf Value >= Vb
    FuzzyResult = 1.0
  ElseIf (Value >= Va And Value <= (Va+Vb)/2) 
    FuzzyResult = 2*((Value - Va)/(Vb-Va))*((Value - Va)/(Vb-Va))
  ElseIf (Value >= (Va+Vb)/2 And Value <= Vb)
    FuzzyResult = 1 - 2*((Value - Vb)/(Vb-Va))*((Value - Vb)/(Vb-Va))
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

Procedure.d FuzzySmoothReverseGrade(Value.d, Va.d, Vb.d) 
  
  If Value <= Va 
    FuzzyResult.d = 1.0 
  ElseIf Value >= Vb
    FuzzyResult = 0.0
  ElseIf Value >= Va And Value <= (Va+Vb)/2 
    FuzzyResult = 1 - 2 * ((Value - Va) / (Vb - Va)) * ((Value - Va) / (Vb - Va))
  ElseIf Value >= (Va + Vb)/2 And Value <= Vb
    FuzzyResult = 2*((Value - Vb)/(Vb - Va)) * ((Value - Vb)/(Vb - Va))
  EndIf
  
  ProcedureReturn FuzzyResult
EndProcedure

;/ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;/ <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<<
;/ <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<<
;/ <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<<
;/ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

For Index = 0 To 100 Step 5
  Debug "FuzzyBell = " + StrD(FuzzyBell(Index/10, 2.0,4.0,6.0), 4)
Next 

Debug ""

For Index = 1 To 100 Step 5
  Debug "FuzzySigmoid = " + StrD(FuzzySigmoid(Index/10, 2.0,3.0,-5.0, 8.0), 4)
Next 

Debug ""

For Index = 0 To 100 Step 5
  Debug "FuzzyGaussian = " + StrD(FuzzyGaussian(Index/10, 5.0, 2.0), 4)
Next 

Debug ""

For Weight = 170 To 200
  Debug "FuzzySmoothGrade = " + StrD(FuzzySmoothGrade(Weight, 175, 195), 4)
Next 

Debug ""

For Weight = 170 To 200
  Debug "FuzzySmoothReverseGrade = " + StrD(FuzzySmoothReverseGrade(Weight, 175, 195), 4)
Next 

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

I'm glad you added the additional functions.

Here's a variation of FuzzySigmoid(), yours seems to be based on the difference between two sigmoid functions. This one uses less parameters and is just a single sigmoid function. Use a negative value for "s" to reverse the direction of the curve from left to right. I've also included a makeshift FuzzyPlot() routine for visualizing these functions. It works with the others as well.

Code: Select all

Procedure FuzzyPlot(x, Value.d, imageid, Color, opt = -1, scale = -1) ;x = x coordinate, scale = image height
  Static drawOpt = #False ;if drawOpt = #True points are connected
  Static drawScale = 1
  Static lastX = 0
  Static lastY = 0

  If opt <> -1
    drawOpt = opt
    lastX = 0
    lastY = 0
    If scale <> -1
      drawScale = scale
    EndIf
  EndIf
  
  If IsImage(imageid)
    StartDrawing(ImageOutput(imageid))
      If drawOpt
        LineXY(lastX, lastY, x, 100 - (Value * drawScale), Color)
        lastX = x
        lastY = 100 - (Value * drawScale)
      EndIf 
      Circle(x, 100 - (Value * drawScale), 2, Color)
    StopDrawing()
  EndIf 
EndProcedure

Procedure.d FuzzySigmoid(Value.d, crossover.d, s.d, ChopValue.d = 0.0001) ;s is the slope at the crossover point
  Protected FuzzyResult.d = 1.0 / (1.0 + Pow(2.71828182846, -s * (Value - crossover)))
    
  If FuzzyResult > ChopValue
    ProcedureReturn FuzzyResult
  Else
    ProcedureReturn 0.0
  EndIf 
EndProcedure


OpenWindow(0,0,0,300,300,"Test",#PB_Window_SystemMenu)
CreateImage(0,200,100)

FuzzyPlot(0, 0, 0, 0, 1, ImageHeight(0)) ;init plot values
For i = 0 To 500
  FuzzyPlot(i, FuzzySigmoid(i, 50, -0.2), 0, $FF00FF)
Next

StartDrawing(WindowOutput(0))
  DrawImage(ImageID(0),0,0)
StopDrawing()

Repeat:Until WaitWindowEvent(10) = #PB_Event_CloseWindow
Last edited by Demivec on Fri May 15, 2009 10:54 pm, edited 6 times in total.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

is there some literature about fuzzy locig, that could teach me short and descriptive how to use these functions?

atm those names are just african villages to me...
oh... and have a nice day.
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

Kaeru Gaman wrote:is there some literature about fuzzy locig, that could teach me short and descriptive how to use these functions?

atm those names are just african villages to me...
In the future I'm going to try to work up some demonstration code that illustrates how they are used. You can find sources by searching for "Fuzzy Logic Tutorials".



Here is a basic outline:

Fuzzy Values are values that represent a degree of truth. So instead of #True (1) or #False (0) you would have #MostlyTrue (0.8 ), #Unclear (0.5), or #MostlyFalse (0.1). These values would be used in a rule evaluation process with comprisons to obtain a result (i.e. If Truth >= #MostlyTrue And Understanding <> #Cofused Then Action = #ContinueReading).

Fuzzy Logic generally involves three operations:

Fuzzyfication: Translation from real world values to Fuzzy values.

Rule evaluation: Computing rule strengths based on rules and inputs.

Defuzzyfication: Translate results back to the real world values.


The functions in the above code are used in the Fuzzyification process (i.e. FuzzyTriangle()) and in the Rule evalation process (i.e. FuzzyAnd()) . I don't believe there's been any code presented for Defuzzyification yet.

Fuzzy Logic is used to improve decision making when things aren't so clear (yes/no). It can be used in artificial intelligence in games, to controlling devices, or to make financial decisions and such.

:wink:
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Post by Guimauve »

The source is the MatLab website http://www.mathworks.com/access/helpdes ... ellmf.html.

Some explanation about how to use such functions are also available.

Best Regards

Guimauve
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

I have some old source code in another language that resembles this. It accepts a number of
logic inputs, and the corresponding logic output, so that it can learn from the data.

After a while, it will begin to predict the correct output all on itself, based on the input
and its stored knowledge base.

A bit scary in my opinion, but very fascinating.
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

utopiomania wrote:I have some old source code in another language that resembles this. It accepts a number of
logic inputs, and the corresponding logic output, so that it can learn from the data.

After a while, it will begin to predict the correct output all on itself, based on the input
and its stored knowledge base.

A bit scary in my opinion, but very fascinating.
That seems to be more along the lines of a Neural Net, they have to be trained. Fuzzy Logic can be used in connection with a Neural Net.
Post Reply