Fuzzy Logic

Blitz3D Forums/Blitz3D Programming/Fuzzy Logic

patmaba(Posted 2010) [#1]
Hello,

Fuzzy logic Do you know?

Since Bobysait placing his excellent blitz3d TMap lib, I reused to design my Blitz3d Fuzzy Logic Library.

Fuzzy logic is used for decision support in inaccurate cases .

For example, say you're playing a friendly game of basketball with your buddies. When sizing up an opponent on the court to decide whether you or someone else should guard him, you might base your decision on the opponent's height and dexterity. You might decide the opponent is tall and quick, and therefore, you'd be better off guarding someone else. Or perhaps you'd say he is very tall but somewhat slow, so you might do fine against him. You normally wouldn't say to yourself something such as, "He's 6 feet 5.5 inches tall and can run the length of the court in 5.7 seconds."

Fuzzy logic enables you to pose and solve problems using linguistic terms similar to what you might use; fuzzy logic enables you to think as you normally do while using very precise tools such as computers.

For more info in game programming, I suggest you read
Programming Game AI by Example by Mat Buckland ISBN: 1556220782 "

My code implements the example of
Chapter 10: Designing for FLV weapon selection "

The code has nothing graphic, he is sober.

http://www.box.net/shared/3dvkszddj0

patmaba


Charrua(Posted 2010) [#2]
nice work

i haven't time to read all that book yet (and understand it). seems that you implement the fussy class presented in chapter 10, isn't it?

thank's

Juan


patmaba(Posted 2010) [#3]
thanx

have you tested ?

i appreciate feedback :)


Charrua(Posted 2010) [#4]
hi, simply load and run ok but as i say, no time to read the entire book.
say that run isnīt much help, let me read some and see whats you have done.

i'll try to test it more seriously
Juan


patmaba(Posted 2010) [#5]
Thnks Charrua

If anyone can test and give feedback please ?

Pat


Charrua(Posted 2010) [#6]
hi
first: so much work! congratulations

in general it seems that you have implemented a whole fuzzy system

are you planning to implement other functions to calculate the final crisp value other than Centroid? Average of Maxima seems to be less time consuming, because the "representative value" should be given as a parameter or precalculated based on the shape of the fuzzy set itself, isn't it?

dont't know if it worth the effort to add Very and Farirly hedges. What do you think?

let me do some tests to see what happens with other values, i'm thinking in do a loop wiht values in the domain to get the values returned by your Membership functions to do a graphical represetation, (i saw better a graph than a table of results...)

should it be helpful that you write a simple demo wiht simple usage instructions (because fuzzy situations are almost every where), i think that should be a great contrubution to the comunity

Juan


Charrua(Posted 2010) [#7]
hi, creating a function to graph the fuzzysets in a fuzzyvariable i started with a modification of the FuzzyCentroyd because it iterates over all the sets defined for a particular fuzzyvariable and, modifying the p_fStepFactor i could reach more samples to plot. I think i encounter a bug!

if i'm not wrong, the last value to try should be MaxBound or MinBound+l_diff, as you like. When i do my firs version I Saw that the graph didn't reach the end of the domain

For i#=p_fzv\MinBound To p_fzv\MinBound+l_diff# ;>>>>> modificacion!!!!
;For i#=p_fzv\MinBound To l_diff# ;old one

here is your sample code with a function that graphs the variables, please correct the code in the "inc_fuzzy.bb" if you think that my sugestion is ok



my brain is exausted for today, i think that should be nice to adjust the for/next in the graph function so the Range of the x axis of the graph should be adjustable. At this time is a function of MinBound and MaxBound and for the AmmoStatus is only 30 units and the graph is very poor.

the good part is that if the graph work, the Functions you made work and the Centroid do what is supposed to do
(if you try my modification, you see no difference in the result, i think is because only 10 points are used to calculate the centroid and the part of the range not included in the for/nex is less than 10%)

best regards

Juan


patmaba(Posted 2010) [#8]
Charrua hi,

Firstly, thanks to spend a little your time to analyze my code.

About your first comment on a graphic log , I thought but the implementation of the code I hardest. That's why I concentrated on the core code.

Sure, it will be a real advantage. Your function will be very useful for the first step.

Your second comment about a bug. I will analyse and re-check my result.

As always the real problem is filling these gaps, for it takes time to achieve it.

Charrua, I will try to complete the fuzzy lib.

If another person have more idea, I am ready to read.

Yours

Pat Maba


Charrua(Posted 2010) [#9]
you are very welcome!

when i said "simple demo" i didn't have a 3D demo in mind, to make not a tutorial neither a master on fussy logic but simple rules of usage of both your work and the variables initilization, so, it will be useful for one that has none or little knowlegde on fussy logic.

Step one: define which variables to use, wich are "antecedent" or input, which are "consequent" or output.

Step two: define the vars and the idea of slope on some ranges defining the shape of slope (what means Triangle and ReverseGrade for example)

and then wich funtion to call to construct the system and wich to call to get the Fuzzy results.

no more than that with a simple, very simple demo with some 2D world with dots moving and taking fuzzy desitions, nothing more than that, but as always, probably that is too much.

My intention is that in this way your work should be good for more than one!

Juan


patmaba(Posted 2010) [#10]
Charrua

I have begin an implementation of drawing variable "Function DrawFuzzyVariable( p_FzVar.TFuzzyVariable )",
only reverse grade, triangle and reverse grade have result.

Clear, it's not functional but it's a begin.

; ------------------------------------
; Main Code
; Demo fuzzy logic 
; author patmaba
; mail: patmaba@...
; date 2010 01 15
; modified 
; When			What				comment
; 2001/01/16	       Comment on desirability	bad comment on desirability 
;									thx bobysait to find this 
; ------------------------------------

Include "Inc_Fuzzy.bb"
Include "Inc_TMap.bb" 

Graphics 800,600,16,2 
Cls  
Locate 0,1 
Print "Example applyed in blitz, come from following Book" 
Print " Programming Game AI by Example by Mat Buckland  ISBN:1556220782" 
Print " Chapter 10 Designing FLV for weapon selection " 
Print " " 

; ================================================================== 
; Defining the FLV's 
; FLV Mean Fuzzy linguistic variable 
; ================================================================== 
 
; Input Variable
Global DistanceToTarget.TFuzzyVariable   = CreateFuzzyVariable( "DistanceToTarget" )
Global AmmoStatus.TFuzzyVariable         = CreateFuzzyVariable( "AmmoStatus" )

; Output Variable 
Global Desirability.TFuzzyVariable 		 = CreateFuzzyVariable( "Desirability" )



; ------------------------------------------------------------------ 
; Designing the Distance to Target FLV 
; ------------------------------------------------------------------ 
; distance of the player and enemy is the domain and contain 3 value 
; Fuzzy linguistic variable 
; CLOSE Domain = [25..150] 
; MEDIUM Domain = [25..150...300] 
; FAR Domain = [150..300] 
; ------------------------------------------------------------------ 
; Describe the Set{close,medium,far} of first Input fuzzy vaiable 'DistanceToTarget'
Global close.TFuzzySet  = CreateFuzzySet_ReverseGrade( DistanceToTarget, "CLOSE", 150.0, 25, 0 )
Global medium.TFuzzySet = CreateFuzzySet_Triangle( DistanceToTarget, "MEDIUM", 25.0,150.0,300.0 )
Global far.TFuzzySet    = CreateFuzzySet_Grade( DistanceToTarget, "FAR", 150.0,300.0,325.0 )

Print "DistanceToTarget Min=" + DistanceToTarget\MinBound + "   Max=" + DistanceToTarget\MaxBound

; ------------------------------------------------------------------ 
; Designing the Distance to Target FLV 
; ------------------------------------------------------------------ 
; Ammo Status is the domain and contain 3 value. 
; LOW Domain range (0.0, 10.0)  
; OKAY Domain range (0.0, 10.0, 30.0) 
; LOADS Domain range (10.0, 30.0) 
; ------------------------------------------------------------------ 
Global low.TFuzzySet   = CreateFuzzySet_ReverseGrade( AmmoStatus, "LOW", 0, 10.0 )
Global okay.TFuzzySet  = CreateFuzzySet_Triangle( AmmoStatus, "OKAY", 0,10.0,30.0)
Global loads.TFuzzySet = CreateFuzzySet_Grade( AmmoStatus, "LOADS", 10.0,30.0)
Print "AmmoStatus Min=" + AmmoStatus\MinBound + "   Max=" + AmmoStatus\MaxBound

; ----------------------------------------------------------------------- 
; Designing the Desirability for final choice, It's the output
; ----------------------------------------------------------------------- 
; Desirability is the domain and contain 3 value. 
; UNDESIRABLE Domain range (50.0, 25.0,0)  
; DESIRABLE Domain range (25.0, 50.0, 75.0) 
; VERY_DESIRABLE Domain range (50.0, 75.0,100.0) 
; ------------------------------------------------------------------ 
Global undesirable.TFuzzySet    = CreateFuzzySet_ReverseGrade( Desirability, "UNDESIRABLE", 50.0, 25.0, 0 )
Global desirable.TFuzzySet      = CreateFuzzySet_Triangle( Desirability, "DESIRABLE", 25.0, 50.0, 75.0 )
Global very_desirable.TFuzzySet = CreateFuzzySet_Grade( Desirability, "VERY_DESIRABLE", 50.0, 75.0,100 )
Print "Desirability Min=" + Desirability\MinBound + "   Max=" + Desirability\MaxBound


; ================================================================== 
; Defining the FLV's 
; ================================================================== 
; ------------------------------------------------------------------ 
; Designing the Ammo Status FLV 
; ------------------------------------------------------------------ 
Global Input_Distance# = 200 


Print "Input distance of the player and enemy is " + Input_Distance# 
Print "My Fuzzy linguistic variables(FLV) is DistanceToTarget can be close, medium and far" 
Print " CLOSE =" + FuzzyCalculateDOM#( close, Input_Distance )
Print " MEDIUM=" + FuzzyCalculateDOM#( medium, Input_Distance )
Print " FAR  =" + FuzzyCalculateDOM#( far, Input_Distance ) 
 
Print " "  
 
Global Input_Ammo# = 8

Print "My Fuzzy second FLV is Ammo Status can be low, okay and loads" 
Print "Input Power level of the player is " + Input_Ammo# 

Print " LOW   = " + FuzzyCalculateDOM( low, Input_Ammo# )
Print " OKAY  = " + FuzzyCalculateDOM( okay, Input_Ammo# ) 
Print " LOADS = " + FuzzyCalculateDOM( loads, Input_Ammo# ) 
Print " "  
 
 
 
Print "List All Business Rules" 
Print "-----------------------" 
 
;If Target_Far And Ammo_Loads Then Desirable  
;If Target_Far And Ammo_Okay Then Undesirable  
;If Target_Far And Ammo_Low Then Undesirable  
;If Target_Medium And Ammo_Loads Then VeryDesirable  
;If Target_Medium And Ammo_Okay Then VeryDesirable  
;If Target_Medium And Ammo_Low Then Desirable  
;If Target_Close And Ammo_Loads Then Undesirable  
;If Target_Close And Ammo_Okay Then Undesirable  
;If Target_Close And Ammo_Low Then Undesirable  
 
;Rule 1.  
Print "If Target_far    And Ammo_Loads -> desirable      = " + FuzzyAND(  far, loads ) 
FuzzyRule( FuzzyAND(  far, loads ), desirable ) 

;Rule 2.  
;If Target_Far And Ammo_Okay Then Undesirable = FuzzyAND(  Target_Far, Ammo_Okay )  
Print "If Target_Far    And Ammo_Okay  -> Undesirable    = " + FuzzyAND(  far, okay )  
FuzzyRule( FuzzyAND(  far, okay ), undesirable ) 

;Rule 3.  
;If Target_Far And Ammo_Low Then Undesirable = FuzzyAND(  Target_Far, Ammo_Low )  
Print "If Target_Far    And Ammo_Low   -> Undesirable    = " + FuzzyAND(  far, low )  
FuzzyRule( FuzzyAND(  far, low ), undesirable ) 

;Rule 4.  
;If Target_Medium And Ammo_Loads Then VeryDesirable = FuzzyAND(  Target_Medium, Ammo_Loads ) 
Print "If Target_Medium And Ammo_Loads -> VeryDesirable  = " + FuzzyAND(  medium, loads ) 
FuzzyRule( FuzzyAND( medium, loads ), very_desirable ) 

;Rule 5.  
;If Target_Medium And Ammo_Okay Then VeryDesirable = FuzzyAND(  Target_Medium, Ammo_Okay )  
Print "If Target_Medium And Ammo_Okay  -> VeryDesirable  = " + FuzzyAND(  medium, okay )  
FuzzyRule( FuzzyAND( medium, okay ) , very_desirable ) 

;Rule 6.  
;If Target_Medium And Ammo_Low Then Desirable = FuzzyAND(  Target_Medium, Ammo_Low )  
Print "If Target_Medium And Ammo_Low   -> Desirable      = " + FuzzyAND(  medium, low )  
FuzzyRule( FuzzyAND( medium, low ) , desirable ) 

;Rule 7.  
;If Target_Close And Ammo_Loads Then Undesirable = FuzzyAND(  Target_Close, Ammo_Loads ) 
Print "If Target_Close  And Ammo_Loads -> Undesirable    = " + FuzzyAND(  close, loads ) 
FuzzyRule( FuzzyAND( close, loads ) , undesirable ) 

;Rule 8.  
;If Target_Close And Ammo_Okay Then Undesirable = FuzzyAND(  Target_Close, Ammo_Okay )  
Print "If Target_Close  And Ammo_Okay  -> Undesirable    = " +  FuzzyAND( close, okay )  
FuzzyRule( FuzzyAND( close, okay ) , undesirable ) 

;Rule 9.  
;If Target_Close And Ammo_Low Then Undesirable = FuzzyAND(  Target_Close, Ammo_Low )  
Print "If Target_Close  And Ammo_Low   -> Undesirable    = " + FuzzyAND(  close, low )  
FuzzyRule( FuzzyAND( close, low ) , undesirable ) 
 
Print " " 

 
Print "Lists the inferred conclusions of applying the values of distance to target = "+Input_Distance#+" And " 
Print "---------------------------------------------------------------------------------------" 
Print "ammo status = "+Input_Ammo#+" To all the rules." 
Print "----------------------------------" 

Print "Desirability.DESIRABLE=" + desirable\Confidence
Print "Desirability.UNDESIRABLE=" + undesirable\Confidence
Print "Desirability.VERY_DESIRABLE=" + very_desirable\Confidence 
Print 
Print "Desirability Crisp value = "+ FuzzyCentroid(Desirability)
Print 


WaitKey
Cls 
DrawFuzzyVariable( DistanceToTarget )
WaitKey
FuzzyReleaseAll() 
End   


Function DrawFuzzyVariable( p_FzVar.TFuzzyVariable )
	Local l_yLow = 300
	Local l_yHigh = 200
	Local l_xMin=100
	Local l_yMin=l_yLow
	
	Local l_xMax=500
	Local l_yMax=l_yLow
	Line l_xMin,l_yMin,l_xMax,l_yMax
	
	Local list.TMapList=MapList(p_FzVar\m_mFuzzySet) 
	Local node.TNode=FirstNode(list) 
	Local l_val = 0.0
	Local l_fs.TFuzzySet
	
	Local x0,y0,x1,y1,x2,y2,x3,y3
	While node<>Null 
		
		l_fs = Object.TFuzzySet(NodeValue(node))
		If l_fs\Shape = FUZZY_REVERSE_GRADE
			x0=GetXCoord( l_fs\x0, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y0=l_yLow
			Rect x0-2,y0-2,4,4,1
			Text x0,y0-20, l_fs\x0
			
			x1=GetXCoord( l_fs\x1, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y1=l_yHigh
			Rect x1-2,y1-2,4,4,1
			Text x1,y1+10, l_fs\x1
			
			x2=GetXCoord( l_fs\x2, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y2=l_yHigh
			Rect x2-2,y2-2,4,4,1
			Text x2,y2+10, l_fs\x2
			
			x3=GetXCoord( l_fs\x3, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y3=l_yLow
			Rect x3-2,y3-2,4,4,1
			Text x3,y3+10, l_fs\x3
			
			Line x0,y0,x1,y1
			Line x1,y1,x2,y2
		EndIf 
		
		If l_fs\Shape = FUZZY_GRADE
		    Color 200,200,0
			x0=GetXCoord( l_fs\x0, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y0=l_yLow+1
			Rect x0-2,y0-2,4,4,1
			Text x0,y0+10, l_fs\x0
			
			x1=GetXCoord( l_fs\x1, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y1=l_yHigh
			Rect x1-2,y1-2,4,4,1
			Text x1,y1+10, l_fs\x1
			
			x2=GetXCoord( l_fs\x2, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y2=l_yHigh
			Rect x2-2,y2-2,4,4,1
			Text x2,y2-20, l_fs\x2
			
			
			Line x0,y0,x1,y1
			Line x1,y1,x2,y2
		EndIf 
		
		If l_fs\Shape = FUZZY_TRIANGLE
			Color 0,200,200		
			x0=GetXCoord( l_fs\x0, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y0=l_yLow+1
			Rect x0-2,y0-2,4,4,1
			Text x0,y0+10, l_fs\x0
			
			x1=GetXCoord( l_fs\x1, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y1=l_yHigh
			Rect x1-2,y1-2,4,4,1
			Text x1,y1-20, l_fs\x1
			
			x2=GetXCoord( l_fs\x2, p_FzVar\MinBound, p_FzVar\MaxBound, l_xMin, l_xMax )
			y2=l_yLow
			Rect x2-2,y2-2,4,4,1
			Text x2,y2+10, l_fs\x2
			
			Line x0,y0,x1,y1
			Line x1,y1,x2,y2
			
		EndIf 
		
		node=NextNode(list,node) 
	Wend 
	
	
End Function 

Function GetXCoord( p_fVal#, p_fMinVal#, p_fMaxVal#, p_ixMin, p_ixMax )
	Local l_fDistMinMaxVal# = Abs(p_fMaxVal#) + Abs(p_fMinVal#)
	Local l_fVal# = (((p_ixMax-p_ixMin)/l_fDistMinMaxVal#)*p_fVal#)+p_ixMin
	Return Int(l_fVal#) 
End Function 
 



Charrua(Posted 2010) [#11]
the look is great!

may i ask why you don't use the functions that actually work in the lib to get the Y axis?

i modify the centroid funtion and in this way i realize that the correct functions are called and they return the correct values.

In the way you are writing the Draw funtion you have to rewrite a func to return the value depending on the shape, chances are that the graph and the function retruns different values, or, if a modification will be made, then it will be made on 2 places instead of one.

i supose you know that and you have a reason for doing that this way.

(hope you understandme, my englis is so and so)

Juan


patmaba(Posted 2010) [#12]
Charrua

my code is update for a new debug mode
It's no complet but a first approach.

I need your feedback please.

last code here :http://www.box.net/shared/3dvkszddj0


patmaba(Posted 2010) [#13]
Charrua

my code is updated for a new debug mode
It's no complet but a first approach.

I need your feedback please.

Now, i'm using svg.

http://www.box.net/shared/3dvkszddj0


Charrua(Posted 2010) [#14]
hi again!
i'm sorry but i'm getting a White screen when i suposse the graphs will appear (after a key press).

Juan


Charrua(Posted 2010) [#15]
i see the *.svg files with Safari (web browser from apple, you know it?)
and are exelent ones! but only a white screen from blitz.
Juan


patmaba(Posted 2010) [#16]
a white screen ? humm. i don't know why. I will seek.

but yes the result are svg file to watch their definitions.