Skip to content

Commit f37e5b5

Browse files
committed
completed weighted_sum roundtrip
1 parent 8635ca1 commit f37e5b5

File tree

4 files changed

+35
-18
lines changed

4 files changed

+35
-18
lines changed

fuzzy/classes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def range(self):
113113
"""
114114
return arange(self.low, self.high, self.res)
115115

116-
def MIN(self, x):
116+
def min(self, x):
117117
"""Standard way to get the min over all membership funcs.
118118
119119
It's not just more convenient but also faster than
@@ -122,7 +122,7 @@ def MIN(self, x):
122122
"""
123123
return min(f(x) for f in self._sets.values())
124124

125-
def MAX(self, x):
125+
def max(self, x):
126126
"""Standard way to get the max over all membership funcs.
127127
"""
128128
return max(f(x) for f in self._sets.values())

fuzzy/rules.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def round_partial(value, res):
2626
return value
2727
return round(value / res) * res
2828

29-
def scale(out_min, out_max, *, in_min=0, in_max=1):
29+
def rescale(out_min, out_max, *, in_min=0, in_max=1):
3030
"""Scale from one domain to another.
3131
3232
Tests only cover scaling from [0,1] (with default in_min, in_max!)
@@ -66,9 +66,10 @@ def weighted_sum(*, weights:dict, target:Domain) -> float:
6666
there MUST be at least as many items in weights as factors.
6767
"""
6868
assert sum(w for w in weights.values()) == 1
69-
S = scale(target.low, target.high)
69+
70+
rsc = rescale(target.low, target.high)
7071

71-
def f(factors):
72-
RES = sum(r * weights[n] for n, r in factors.items())
73-
return S(round_partial(RES, target.res))
72+
def f(memberships):
73+
result = sum(r * weights[n] for n, r in memberships.items())
74+
return round_partial(rsc(result), target.res)
7475
return f

test_fuzzy_functionality.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from unittest import TestCase, skip
77

88
from fuzzy.classes import Domain, Set
9-
from fuzzy.rules import scale
9+
from fuzzy.rules import rescale, weighted_sum
1010
from fuzzy.functions import R, S, bounded_linear
1111

1212
class TestTop(TestCase):
@@ -20,22 +20,38 @@ def setUp(self):
2020
def test_temp(self):
2121
assert(self.temp(6) == {'cold': 0.6, 'hot': 0, 'warm': 0.4})
2222

23-
class Test_Meal(TestCase):
23+
class Test_Weighted(TestCase):
2424
def setUp(self):
2525
"""Tom is surveying restaurants.
26-
He doesn't need fancy logic but rather uses a simple approach with weights.
27-
He went into a small, dirty bar that served some delicious drink and food.
26+
He doesn't need fancy logic but rather uses a simple approach
27+
with weights.
28+
He went into a small, dirty bar that served some
29+
really good drink and food that wasn't nicely arranged but still
30+
yummmy. He rates the different factors on a scale from 1 to 10,
31+
uses a bounded_linear function to normalize over [0,1] and
32+
passes both the weights (how much each aspect should weigh in total)
33+
and the domain as parameters into weighted_sum.
34+
However, he can't just use Domain(value) because that would return
35+
a dict of memberships, instead he uses Domain.min(value) which
36+
returns the minimum of all memberships no matter how many sets
37+
there are. He creates a dict of membership values corresponding to
38+
the weights and passes that into the parametrized weighted_sum func
39+
as argument to get the final rating for this restaurant.
2840
"""
2941
self.R = Domain("rating", 1, 10, res=0.1)
3042
self.R.norm = Set(bounded_linear(1, 10))
3143
self.weights = weights = {"beverage": 0.3,
3244
"atmosphere": 0.2,
33-
"arrangement":0.2,
45+
"looks":0.2,
3446
"taste": 0.3}
35-
self.ratings = {"beverage": self.R.MIN(7),
36-
"atmosphere": self.R.MIN(3),
37-
"arrangement": self.R.MIN(2),
38-
"taste": self.R.MIN(9)}
47+
self.w_func = weighted_sum(weights=self.weights, target=self.R)
48+
49+
def test_rating(self):
50+
ratings = {"beverage": self.R.min(9),
51+
"atmosphere": self.R.min(5),
52+
"looks": self.R.min(4),
53+
"taste": self.R.min(8)}
54+
assert (self.w_func(ratings) == 6.9)
3955

4056
if __name__ == '__main__':
4157
unittest.main()

test_fuzzy_units.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,11 +356,11 @@ class Test_Rules(TestCase):
356356
st.floats(allow_infinity=False, allow_nan=False),
357357
st.floats(min_value=0, max_value=1),
358358
st.floats(min_value=0, max_value=1))
359-
def test_scale(self, x, out_min, out_max, in_min, in_max):
359+
def test_rescale(self, x, out_min, out_max, in_min, in_max):
360360
assume(in_min < in_max)
361361
assume(in_min <= x <= in_max)
362362
assume(out_min < out_max)
363-
f = ru.scale(out_min, out_max)
363+
f = ru.rescale(out_min, out_max)
364364
assert (out_min <= f(x) <= out_max)
365365

366366
@given(st.floats(allow_nan=False),

0 commit comments

Comments
 (0)