Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Rebuild the example of skfuzzy with fuzzylogic: #47

Unanswered
born2bwater asked this question in Q&A
Discussion options

Hi,
I am familiarizing myself with your super nice package. Thanks for making it publicly available.
During my search I came across this example: Tipping Problem
The example has the result 20% tip.
With the code below I get: 2%

image

I would expect that it is the combination of the rules that makes the difference. What would you recommend to do?

from fuzzylogic.classes import Domain, Set, Rule
from fuzzylogic.functions import R, S, alpha, trapezoid
res = 0.1
food = Domain("food_quality", 0, 10, res = res)
serv = Domain("service_quality", 0, 10, res = res)
tipa = Domain("tip_amount", 0, 25, res = res)
food.lo = S(0, 5)
food.md = alpha(floor = 0, ceiling = 1, func = trapezoid(0, 5, 5, 10))
food.hi = R(5, 10)
serv.lo = S(0, 5)
serv.md = alpha(floor = 0, ceiling = 1, func = trapezoid(0, 5, 5, 10))
serv.hi = R(5, 10)
tipa.lo = S(0, 13)
tipa.md = alpha(floor = 0, ceiling = 1, func = trapezoid(0, 13, 13, 25))
tipa.hi = R(13, 25)
rules = Rule({
 (food.hi, serv.hi): tipa.hi,
 (food.lo, serv.lo): tipa.lo,
 (serv.md, ): tipa.md,
})
values = {food: 6.5, serv: 9.8}
print(R1(values), R2(values), R3(values), rules(values))
You must be logged in to vote

Replies: 3 comments 21 replies

Comment options

Hi and thanks you!

The first thing I'm noticing is their use of trimf, which is the triangular function which should correspond to fuzzylogic.functions.triangular (at least one would rightfully expect so!).

You must be logged in to vote
0 replies
Comment options

The next thing I'm noticing is x_qual = np.arange(0, 11, 1) which corresponds to your food = Domain("food_quality", 0, 10, res = res) (changing resolution and domain may change the end result quite a bit since weights are shifted)

You must be logged in to vote
7 replies
Comment options

Next step would be to visually check if the plots match your expectations...

Comment options

Ah, interesting. They have an fuzz.interp_membership function - smart. Let's steal that 😁 (probably just a wrapper for a np interpolation, but still)

Comment options

You're using the Rule class to map the use of OR in their code? I'd immediately think of fuzzylogic.combinators.MAX when I read OR... or the | operator between fuzzy-functions, which maps to MAX.

Comment options

Next step would be to visually check if the plots match your expectations...

Food:
image

Service
image

Tip:
image

Comment options

I find it a bit hard to read their mix of rules, plots and functions, tbh.. but here we go

Comment options

I think I found the issue.

from fuzzylogic.classes import Domain, Rule
from fuzzylogic.functions import R, S, triangular
res = 1
food = Domain("food_quality", 0, 10, res=res)
serv = Domain("service_quality", 0, 10, res=res)
tip = Domain("tip_amount", 0, 25, res=res)
food.lo = S(0, 5)
food.md = triangular(0, 10)
food.hi = R(5, 10)
serv.lo = S(0, 5)
serv.md = triangular(0, 10)
serv.hi = R(5, 10)
tip.lo = S(0, 13)
tip.md = triangular(0, 25)
tip.hi = R(13, 25)
rules = Rule({
 (food.lo, serv.lo): tip.lo,
 (food.md, serv.md): tip.md,
 (food.hi, serv.hi): tip.hi,
})
values = {food: 6.5, serv: 9.8}
print(rules(values))

Returns 19.513574660633484 which is close to the expected 20% - it seems the resolution indeed was the culprit - which means the interpolation actually makes all the difference.

(Now looking at my code and comparing it to the original makes me wonder if I missed anything, it's so much more concise.. 🤔)

You must be logged in to vote
14 replies
Comment options

While, of course, I hope that my code is correct, it's possible that I made a mistake. That's why I rewrote it - to better scrutinize and improve.

My code does the following:

  1. for every domain:value in the input calculate the membership values for all relevant fuzzy sets
  2. for every IF-THEN rule take the min (AND) of the membership values and associate the THEN fuzzy set with the result as weight
  3. calculate the weighted average for the cog of all THEN fuzzy sets as dimensionless index on the domain array
  4. adjust for the limits and resolution of the domain to translate the index to the actual end value.

I guess it shows I never really cared much for defuzzification and put my emphasis on correctness and efficiency of the membership functions and combinators... 🤔

Comment options

Hey,

thanks for the explanation. I cannot claim to being able to evaluate your code, but it is read-, and understandable. How it works in the bigger picture is yet beyond my scope. But I will look further into the options your package offers for me =D

Comment options

Heya,

hope you're doing great.

I played around with your fuzzylogic package in a separate python environment (called fuzzy). Now that my main project is far enough to add fuzzy logic to it, i re-installed your package in a different env (called gis). The same example we posted above is not working in the gis environment. Neither does the new one. But it still works in the fuzzy.
Thus either there is a bad interaction betwenn different packages in the gis environment or you changed something in your code that causes that error (code see below). What do you think?
(PS: does github not offer to have collabseable sections in posts?)

from fuzzylogic.classes import Domain, Rule
from fuzzylogic.functions import R, S, triangular
res = 1
food = Domain("food_quality", 0, 10, res=res)
serv = Domain("service_quality", 0, 10, res=res)
tip = Domain("tip_amount", 0, 25, res=res)
food.lo = S(0, 5)
food.md = triangular(0, 10)
food.hi = R(5, 10)
serv.lo = S(0, 5)
serv.md = triangular(0, 10)
serv.hi = R(5, 10)
tip.lo = S(0, 13)
tip.md = triangular(0, 25)
tip.hi = R(13, 25)
rules = Rule({
 (food.lo, serv.lo): tip.lo,
 (food.md, serv.md): tip.md,
 (food.hi, serv.hi): tip.hi,
})
values = {food: 6.5, serv: 9.8}
print(rules(values))
ohalala
Traceback (most recent call last):
 Cell In[13], line 30
 print(rules(values))
 File ~\AppData\Local\miniconda3\envs\gis\Lib\site-packages\fuzzylogic\classes.py:447 in __call__
 index = sum(v.center_of_gravity * x for v, x in weights) / sum(x for v, x in weights)
 File ~\AppData\Local\miniconda3\envs\gis\Lib\site-packages\fuzzylogic\classes.py:447 in <genexpr>
 index = sum(v.center_of_gravity * x for v, x in weights) / sum(x for v, x in weights)
TypeError: unsupported operand type(s) for *: 'method' and 'float'
Comment options

That's the old (fixed, but not released) bug. It's just missing a () at v.center_of_gravity(). I really should push a release. Possibly later today.

Comment options

Oh nos. I am sorry I should have known... I once corrected it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /