Fuzzy Logic problem
Join us in Vienna for the nucl.ai Conference 2015, on July 20-22... Don't miss it!
double mStrategicValue // 0..1
It seems you have been reading too much about fuzzy logic and forgot to actually address the problem you are trying to solve. That is, a solution in search of a problem.
All you are doing is describing the strategic value of a spot. Therefore, to describe a single feature of the spot, you need a single variable. It can be assigned, manipulated, compared to other spots, and even used in larger calculations. For example, you could combine it with other single variables describing other traits that it has and come up with a higher level concept.
Don't make all of this harder than it is.
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit
Author of the book, Behavioral Mathematics for Game AI
Blogs I write:
IA News - What's happening at IA | IA on AI - AI news and notes | Post-Play'em - Observations on AI of games I play
"Reducing the world to mathematical equations!"
"I think what Alex was trying to say is, why don't you have a single variable for the strategic value... that is:
double mStrategicValue // 0..1"
That's what i'm trying to get....
I have used fuzzy logic to do calculations, now i need to turn it into another fuzzy set (0 to 1).
I don't understand what you mean by why dont i have a single value. Thats my entire problem, I'm trying to get it into one var
I did the calculations with those four vars, and now i want to turn it into one var. I don't think i can start with one var, because my calculations require more than one.
Besides. if i was to use one var, i wouldn't be using fuzzy logic, and i would be losing the entire advantage of fuzzylogic.
If you're saying i shouldn't have all those vars at all, then could you tell me how I calculate the value of mStrategicValue, without fuzzy logic?
these are my calculations:
var mWeak:Number = fuzzyReverseGrade (nrShips, 1, 2);
var mStable:Number = fuzzyTriangle (nrShips, 1, 3, 5);
var mStrong:Number = fuzzyTriangle (nrShips, 4, 6, 9);
var mVeryStrong:Number = fuzzyGrade (nrShips, 7, 10);
//above calculates the value of the amount of ships.
var mClose:Number = fuzzyReverseGrade (dist, , );
var mNearby:Number = fuzzyTrapezoid (dist, , , , );
var mFar:Number = fuzzyTrapezoid (dist, , , , );
var mVeryFar:Number = fuzzyGrade (dist, , );
//the above calculates the value of the distance from the player (i haven't filled in the constants yet.)
var mNotStrategic:Number = OR(AND(mWeak,mClose), AND(mWeak,mNearby), AND(mVeryFar, OR(mWeak,mStable,notVery(mStrong))) );
//above means that a place is not strategic if it is weak and close or weak and nearby or very far and (weak,stable or kind of strong)
var mStrategic:Number = OR(AND(mStable,mNearby), AND(mWeak,mFar), AND(mStrong,mFar), AND(very(mVeryStrong),mVeryFar) );
//meaning the place is strategic if it's stable and nearby or weak and far or strong and far or verystrong and very far
var mVeryStrategic:Number = OR(AND(mStrong, OR(notVery(mClose), mNearby)), AND(mVeryStrong, OR(notVery(mNearby),vFar) );
//etc.
var mUnbeatable:Number = OR(AND(mVeryStrong,OR(mClose,very(mNearby))), AND(very(mVeryStrong), mNearby) );
I wouldn't know how i would have to do something like this without fuzzylogic. But I'm open to suggestions.
[Edited by - omniscient on July 19, 2009 11:54:39 AM]
For instance what linguistic wedges would model well is contradicting orders ie "Attack","Defend" and then you would have to defuzzify in your FAM. However the terms you have employed are very CRISP and don't seem to really contradict from a naming convention sense.
Also what information you feeding into the axis that you are drawing your linguistic wedges? x,y? units nearby?
Just tossing some ideas to get the ball rolling :-)
Quote: Original post by omniscient
//in C++:
double mNotStrategic
double mStrategic
double mVeryStrategic
double mUnbeatable
all these vars are ofcourse from 0 to 1.
It seems to me (and others) that this is all measuring the same stuff. That is, one variable could represent different ranges that determine whether it is representing crappy strategic places all the way up to unbeatable ones. All that fancy if/then/and/or stuff is adding a layer of complexity that then paints you into a corner.
As for combining multiple factors into one value, weighted sums will get you a lot of mileage.
Perhaps rather than diving into code, you should give us a better idea of what factors you are measuring and why.
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit
Author of the book, Behavioral Mathematics for Game AI
Blogs I write:
IA News - What's happening at IA | IA on AI - AI news and notes | Post-Play'em - Observations on AI of games I play
"Reducing the world to mathematical equations!"
the points that are the most strategic, will be mroe desirable for the AI to go to. The strategic value of the point, combined with the distance of that ai unit to that point is the eventual value of the point. the unit will then choose the best point to go to. so the most strategic point, but that is not too far away.
I hope that answers the question.
so i am measuring 3 aspects of the point. 2 aspects determine the strategic value of the point, namely distance from the player, and the amount of cover there is.
the mWeak till mVeryStrong represent the cover value. (nrShields is the amount of cover the place has).
this function only calculates the strategic value. the third value, distance from the ai unit to that point, is evaluated in that ai unit itself. i want the ai unit to have a strategic value of the point, so he can use that in combination with his own distance from the point to come to a conclusion of the desirability to go to that point. he then chooses the best point to go to, and goes there.
input in this function is distance between player and the strategic (or not very strategic) point, and the amount of shields there are at that point.
by ptroen:
"For instance what linguistic wedges would model well is contradicting orders ie "Attack","Defend" and then you would have to defuzzify in your FAM. However the terms you have employed are very CRISP and don't seem to really contradict from a naming convention sense."
I'm not entirely sure if i understand the question, but what i am doing is saying that if the shield-amount is low, then being close to the player is bad, and if it is high then being close to the player is good. bad means the ai don't go there, good means the ai go there. So that would make sense right? thats kinda like "Flee" and "Attack".
Is there something wrong with me using four vars for strength, distance, and strategicness? (is that a word?). That's the whole point of fuzzy logic right?
And fuzzy logic helps me set specific strategies. i.e. that being close and weak is bad, but being close and strong is good, and being far and strong is bad, but being far and weak is good.
Should i just return the four values for strategicness instead of one value? or should i just return a crisp value?
I'm a little confused now. are you guys saying I shouldn't use fuzzy logic here?
If not, then when do you use fuzzy logic? And how should i do it here then?
I hope I'm not being annoying, but I'm a little confused as to what I'm supposed to do right now.
I think where you are getting confused is with the concept of "defuzzification". That is where you subdivide a single continuous value into segments that can then be described. For example, you could say that:
0.0 to 0.1 -> "very short"
0.1 to 0.3 -> "rather short"
0.3 to 0.5 -> "shorter than average"
0.5 to 0.7 -> "taller than average"
0.7 to 0.9 -> "rather tall"
0.9 to 1.0 -> "very tall"
That way, if your mTallness = 0.44, I would have known that (in general) you are shorter than average.
In your model, you would have created 6 different variables... one for each of the categories above. But, as we know, height is a single value.
The other issue here is that defuzzification is simply for convenience' sake in naming. Only rarely is it actually useful for making further decisions.
Continuing my example, if I were to ask you how heavy you were (mWeight = 0..1), we could construct a similar arrangement of named ranges. However, what if we wanted to know how you were built as a whole? That is a combination of height and weight. We could take those two values of mTallness and mWeight (both of which are floating point values from 0 to 1) and multiply them together. The resulting value (mBuild) would also be from 0..1. We now have an idea of how bulky you are. Are you a tall, heavy guy or a tall thin guy?
Sure, that example is a little contrived, but you get the point. We didn't have to use the fuzzy named ranges for tallness or weight in order to use their values to proceed with the calculation of build.
The same should be in play here with your example.
You can accumulate data about a point such as its proximity to allies and enemies (each of which is its own value), and other such items in order to build ONE value for the strategic value of the point. (0..1 would be optimal). Then, if you have also measured other factors that are specific to the unit making the decision such as the distance to the point, you can combine it with the strategic value of the point to decide if it is preferable for that unit to go there. (BTW, instead of using the distance, think in terms of time.)
An overly simple example of how to do this would be to combine them somehow just like we did above. Let's define mProximity as a value that shows the nearness of the point where 0 = very far and 1 = right nearby. Then, we could use the following weighted sum formula (just pulling this out of the air):
mPointPreference = ( mStrategicValue + (2 * mProximity) ) / 3
So, a moderately valuable point (0.5) that is close by (0.8):
0.7 = ( 0.5 + ( 2 * 0.8 ) ) / 3
...would be more preferable than a very valuable point (0.8) that takes a long time to get to (0.2):
0.4 = ( 0.8 + ( 2 * 0.2 ) ) / 3
When you then combine these items in whatever mathematical juggling you see fit to use, you arrive at ONE score for each point. That score is a combination of its strategic value and the commitment it would take to reach it. Your agent could then opt for a moderately strategic one that is nearby rather than the more distant target. ( 0.7 > 0.4 )
You could score numerous targets this way and simply select the highest-scoring one of the bunch.
Incidentally, if you want a fancy name for this technique, it is generally referred to as maximum expected utility and is part of utility theory (especially multi-attribute utility theory).
If you really want to know more, it is the significant basis for my book, linked below.
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit
Author of the book, Behavioral Mathematics for Game AI
Blogs I write:
IA News - What's happening at IA | IA on AI - AI news and notes | Post-Play'em - Observations on AI of games I play
"Reducing the world to mathematical equations!"
Obviously, you know more about this than I do, but whay i understand from teh book , isn't the whole point of fuzzy logic to have a continuous truthness instead of a boolean?
so using:
0.0 to 0.1 -> "very short"
0.1 to 0.3 -> "rather short"
0.3 to 0.5 -> "shorter than average"
0.5 to 0.7 -> "taller than average"
0.7 to 0.9 -> "rather tall"
0.9 to 1.0 -> "very tall"
How do i then do the 'linguistic wedges'? and how do i decide the value of strategicness, if he's moderately far and veryStrong etc?
if i'd be using the Strings: if tallness == "very short" that wouldn't be continuous, right?
this is what Bourg says in his book:
mClose = FuzzyTriangle(25, -30, 0, 30);
mMedium = FuzzyTrapezoid(25, 10, 30, 50, 70);
mFar = FuzzyGrade(25, 50, 70);
mTiny = FuzzyTriangle(8, -10, 0, 10);
mSmall = FuzzyTrapezoid(8, 2.5, 10, 15, 20);
mModerate = FuzzyTrapezoid(8, 15, 20, 25, 30);
mLarge = FuzzyGrade(8, 25, 30);
//Threat level:
mLow = FuzzyOr(FuzzyAND(mMedium, mTiny), FuzzyAND(mMedium, mSmall));
mMedium = FuzzyAND(mClose, mTiny);
mHigh = FuzzyAND(mClose, mSmall);
//units to deploy as a response:
nDeploy = ( mLow * 10 + mMedium * 30 + mHigh * 50) /
(mLow + mMedium + mHigh);
Back to my problem. you say:
"You can accumulate data about a point such as its proximity to allies and enemies (each of which is its own value), and other such items in order to build ONE value for the strategic value of the point. (0..1 would be optimal)."
If i were to use one var for distance to player, and one var for amount of shields and one var for strategic value(the latter two combined), how would I then calculate the strategic value, considering that it's better to be far if its weak, than to be close, but its better to be close if you're strong, than to be far if your strong, and other complicated things, that aren't really easily described in formula's, since it's not linearly, the closer the better, and the stronger the better.
You say i need to build ONE value of the strategic value of the point. this is exactly what i'm trying to do, but how do i do this, without the way in Bourg's book, with only 1 var?
Because allthough i don't know how to do it with only one var, i ofcourse do find it a bit strange to have 4 vars for 1 value.
What you said about calculating the eventual value of the point with the strategic value (once i got that) and proximity to it and allies etc. I get that, thanks.
ps. Thanks for the help already.
In my height example, I used simple linear thresholds because it is easier to show in type. However, who is to say 0.3 is the specific point at which someone crosses from "rather short" into merely "shorter than average"? In fact, those two ranges would overlap somewhat. As the height value increases, the membership in the set of "rather short" would start to decrease at some point and the membership in the set of "shorter than average" would increase" However, none of this would change the fact that you are 132cm tall.
Similarly, a distance measurement is counted in whatever unit you use in the game. you don't build the distance from other components... you take what you have measured and then categorize it (if you want).
Quote: Obviously, you know more about this than I do, but whay i understand from teh book , isn't the whole point of fuzzy logic to have a continuous truthness instead of a boolean?
so using:
0.0 to 0.1 -> "very short"
0.1 to 0.3 -> "rather short"
0.3 to 0.5 -> "shorter than average"
0.5 to 0.7 -> "taller than average"
0.7 to 0.9 -> "rather tall"
0.9 to 1.0 -> "very tall"
How do i then do the 'linguistic wedges'? and how do i decide the value of strategicness, if he's moderately far and veryStrong etc?
if i'd be using the Strings: if tallness == "very short" that wouldn't be continuous, right?
That being said, there is nothing binary in my example. The initial value of "height" was 0..1. As I mentioned above, the ranges can be either binary or not. That is entirely based on the necessity of your design.
However, I really think that using true fuzzy logic is NOT what you want in this case. Sure, it can be used, but if all you are doing is trying to categorize the distance to the target or the defensibility of a position, a simple categorization would be sufficient. It doesn't help you to know that your position is 0.3 moderately defensible and 0.7 very defensible. In fact, it generates a layer of complexity that is begging for errors but really yields you no extra value.
As I explained in my examples above, you could do away with categorization entirely and simply use the values that you arrive at - whether they are measured ones such as distance, or subjective ones such as the calculations that go into defensibility.
If you truly look at what you posted, you will see that, in the end you only have a complex weighted sum (actually a weighted average):
Quote: //units to deploy as a response:
nDeploy = ( mLow * 10 + mMedium * 30 + mHigh * 50) / (mLow + mMedium + mHigh);
By using responses curve that ramps upwards as the values approach one end or the other, you can increase the magnitude of the importance. For example, by using an exponential curve applied to the threat distance, you can create a similar effect as what you arrived at in the above equation. The point of the formula was that as the threat level progressed from the lower ranges into the higher ones, you deployed more units at a rapidly increasing rate (not just linearly). If you were to use something along the lines of:
nDeploy = (threat)^exponent
... you would get the same effect. What's more, it is tuneable with one value (the exponent) rather than many overlapping ones. (Of course, you would have to do similar juggling to arrive at the value of "threat" in the first place.)
Anyway, you can proceed ahead with your method, although I think your original question should be answered far better in the book you are reading. You've actually danced around the answer in this thread already. I still think you are possibly using the wrong tool for the problem. The saying goes "when all you have is a hammer, everything looks like a nail". In your case, it seems that you are trying to use a really expensive cordless power drill when all you need to do is hammer a nail.
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit
Author of the book, Behavioral Mathematics for Game AI
Blogs I write:
IA News - What's happening at IA | IA on AI - AI news and notes | Post-Play'em - Observations on AI of games I play
"Reducing the world to mathematical equations!"