Skip to content

Commit 7852121

Browse files
committed
added tests for combinators
1 parent bd920b9 commit 7852121

File tree

5 files changed

+169
-70
lines changed

5 files changed

+169
-70
lines changed

Showcase.ipynb

Lines changed: 14 additions & 23 deletions
Large diffs are not rendered by default.

TODO-fuzzy

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
do: build a #testcase suite
22
---
3-
do: MUST review #functions
4-
---
53
do: #Set.plot SHOULD always plot between 0 and 1
64
---
75
do: #Set.plot SHOULD always plot the full set range
86
---
9-
do: MUST fix #Domain._sets (should be either set OR dict)
10-
until: 2017-3-1
11-
requires: Set.plot testcase
12-
---
137
do: check tests
148
after: 2017-3-1
159
repeat: dayly
1610
until: end of year
1711
---
1812
do: SHOULD find examples for truth functions
19-
---
13+
---
14+
15+
---
16+
do: MUST review #functions
17+
done: yes
18+
---
19+
do: MUST fix #Domain._sets (should be either set OR dict)
20+
until: 2017-3-1
21+
requires: Set.plot testcase
22+
done: yes
23+
---

fuzzy/combinators.py

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,37 +69,55 @@ def f(x):
6969
return f
7070

7171
def hamacher_product(a, b):
72-
"""AND variant."""
73-
def f(x):
74-
a_x, b_x = a(x), b(x)
75-
return (a_x * b_x) / (a_x + b_x - a_x * b_x)
72+
"""AND variant.
73+
(xy) / (x + y - xy) for x, y != 0
74+
0 otherwise
75+
"""
76+
def f(z):
77+
x, y = a(z), b(z)
78+
return (x * y) / (x + y - x * y) if x != 0 and y != 0 else 0
79+
return f
7680

7781
def hamacher_sum(a, b):
78-
"""OR variant."""
79-
def f(x):
80-
a_x, b_x = a(x), b(x)
81-
return (a_x + b_x - 2 * a_x * b_x) / (1 - a_x * b_x)
82+
"""OR variant.
83+
(x + y - 2xy) / (1 - xy) for x,y != 1
84+
1 otherwise
85+
"""
86+
def f(z):
87+
x, y = a(z), b(z)
88+
return (x + y - 2 * x * y) / (1 - x * y) if x != 1 or y != 1 else 1
8289
return f
8390

84-
def lambda_op(a, b, l):
91+
92+
def lambda_op(l):
8593
"""A 'compensatoric' operator, combining AND with OR by a weighing factor l.
94+
95+
This complicates matters a little, since all combinators promise to just take
96+
2 functions as arguments, so we parametrize this with l.
8697
"""
87-
def f(x):
88-
a_x, b_x = a(x), b(x)
89-
return l * (a_x * b_x) + (1 - l) * (a_x + b_x - a_x * b_x)
90-
return f
98+
assert (0 <= l <= 1)
99+
100+
def e(a, b):
101+
def f(x):
102+
a_x, b_x = a(x), b(x)
103+
return l * (a_x * b_x) + (1 - l) * (a_x + b_x - a_x * b_x)
104+
return f
105+
return e
91106

92107

93-
def gamma_op(a, b, g):
108+
def gamma_op(g):
94109
"""A 'compensatoric' operator, combining AND with OR by a weighing factor g.
95110
g (gamma-factor)
96111
0 < g < 1 (g == 0 -> AND; g == 1 -> OR)
112+
113+
Same problem as with lambda_op, since all combinators promise to just take
114+
2 functions as arguments, so we parametrize this with g.
97115
"""
98-
if not(0 <= g <= 1):
99-
raise ValueError
100-
101-
def f(x):
102-
a_x, b_x = a(x), b(x)
103-
return (a_x * b_x) ** (1 - g) * ((1 - a_x) * (1 - b_x)) ** g
104-
105-
return f
116+
assert (0 <= g <= 1)
117+
118+
def e(a, b):
119+
def f(z):
120+
x, y = a(z), b(z)
121+
return (x * y) ** (1 - g) * ((1 - x) * (1 - y)) ** g
122+
return f
123+
return e

test_fuzzy_functionality.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ def setUp(self):
1515
self.temp = Domain('temperature', -100, 100, 1) # in Celsius
1616
self.temp.cold = Set(S(0, 15))
1717
self.temp.hot = Set(R(10, 30))
18-
self.temp.warm = ~self.cold & ~self.hot
19-
assert(temp(6) == {'cold': 0.6, 'hot': 0, 'warm': 0.4})
18+
self.temp.warm = ~self.temp.cold & ~self.temp.hot
2019

2120
def test_temp(self):
22-
# we need to define a dictionary-aggregation func here
23-
pass
21+
assert(self.temp(6) == {'cold': 0.6, 'hot': 0, 'warm': 0.4})
2422

2523

2624
if __name__ == '__main__':

test_fuzzy_units.py

Lines changed: 102 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from fuzzy.classes import Domain, Set, Rule
77
from fuzzy import functions as fun
88
from fuzzy import hedges
9+
from fuzzy import combinators as combi
910

1011
class Test_Functions(TestCase):
1112
@given(st.floats(allow_nan=False))
@@ -156,29 +157,116 @@ def test_triangular_sigmoid(self, x, low, high, c):
156157
st.floats(allow_nan=False, allow_infinity=False),
157158
st.floats(min_value=0, max_value=1))
158159
def test_gauss(self, x, b, c, c_m):
159-
assume(0 < c_m <= 1)
160160
assume(0 < b)
161+
assume(0 < c_m)
161162
f = fun.gauss(c, b, c_m=c_m)
162163
assert (0 <= f(x) <= 1)
163164

164165
class Test_Hedges(TestCase):
165-
@given(st.floats(allow_nan=False))
166+
@given(st.floats(min_value=0, max_value=1))
166167
def test_very(self, x):
167-
assume(0 <= x <= 1)
168168
s = Set(fun.noop())
169-
h = hedges.very(s)
170-
assert (0 <= h(x) <= 1)
171-
172-
@given(st.floats(allow_nan=False))
169+
f = hedges.very(s)
170+
assert (0 <= f(x) <= 1)
171+
172+
@given(st.floats(min_value=0, max_value=1))
173173
def test_minus(self, x):
174-
assume(0 <= x <= 1)
175174
s = Set(fun.noop())
176-
h = hedges.minus(s)
177-
assert (0 <= h(x) <= 1)
175+
f = hedges.minus(s)
176+
assert (0 <= f(x) <= 1)
178177

179-
@given(st.floats(allow_nan=False))
178+
@given(st.floats(min_value=0, max_value=1))
180179
def test_plus(self, x):
181-
assume(0 <= x <= 1)
182180
s = Set(fun.noop())
183-
h = hedges.plus(s)
184-
assert (0 <= h(x) <= 1)
181+
f = hedges.plus(s)
182+
assert (0 <= f(x) <= 1)
183+
184+
185+
class Test_Combinators(TestCase):
186+
@given(st.floats(min_value=0, max_value=1))
187+
def test_MIN(self, x):
188+
a = fun.noop()
189+
b = fun.noop()
190+
f = combi.MIN(a, b)
191+
assert (0 <= f(x) <= 1)
192+
193+
@given(st.floats(min_value=0, max_value=1))
194+
def test_MAX(self, x):
195+
a = fun.noop()
196+
b = fun.noop()
197+
f = combi.MAX(a, b)
198+
assert (0 <= f(x) <= 1)
199+
200+
@given(st.floats(min_value=0, max_value=1))
201+
def test_product(self, x):
202+
a = fun.noop()
203+
b = fun.noop()
204+
f = combi.product(a, b)
205+
assert (0 <= f(x) <= 1)
206+
207+
@given(st.floats(min_value=0, max_value=1))
208+
def test_bounded_sum(self, x):
209+
a = fun.noop()
210+
b = fun.noop()
211+
f = combi.bounded_sum(a, b)
212+
assert (0 <= f(x) <= 1)
213+
214+
@given(st.floats(min_value=0, max_value=1))
215+
def test_lukasiewicz_AND(self, x):
216+
a = fun.noop()
217+
b = fun.noop()
218+
f = combi.lukasiewicz_AND(a, b)
219+
assert (0 <= f(x) <= 1)
220+
221+
@given(st.floats(min_value=0, max_value=1))
222+
def test_lukasiewicz_OR(self, x):
223+
a = fun.noop()
224+
b = fun.noop()
225+
f = combi.lukasiewicz_OR(a, b)
226+
assert (0 <= f(x) <= 1)
227+
228+
@given(st.floats(min_value=0, max_value=1))
229+
def test_einstein_product(self, x):
230+
a = fun.noop()
231+
b = fun.noop()
232+
f = combi.einstein_product(a, b)
233+
assert (0 <= f(x) <= 1)
234+
235+
@given(st.floats(min_value=0, max_value=1))
236+
def test_einstein_sum(self, x):
237+
a = fun.noop()
238+
b = fun.noop()
239+
f = combi.einstein_sum(a, b)
240+
assert (0 <= f(x) <= 1)
241+
242+
@given(st.floats(min_value=0, max_value=1))
243+
def test_hamacher_product(self, x):
244+
a = fun.noop()
245+
b = fun.noop()
246+
f = combi.hamacher_product(a, b)
247+
assert (0 <= f(x) <= 1)
248+
249+
@given(st.floats(min_value=0, max_value=1))
250+
def test_hamacher_sum(self, x):
251+
a = fun.noop()
252+
b = fun.noop()
253+
f = combi.hamacher_sum(a, b)
254+
assert (0 <= f(x) <= 1)
255+
256+
@given(st.floats(min_value=0, max_value=1),
257+
st.floats(min_value=0, max_value=1))
258+
def test_lambda_op(self, x, l):
259+
a = fun.noop()
260+
b = fun.noop()
261+
g = combi.lambda_op(l)
262+
f = g(a, b)
263+
assert (0 <= f(x) <= 1)
264+
265+
@given(st.floats(min_value=0, max_value=1),
266+
st.floats(min_value=0, max_value=1))
267+
def test_gamma_op(self, x, g):
268+
a = fun.noop()
269+
b = fun.noop()
270+
g = combi.gamma_op(g)
271+
f = g(a, b)
272+
assert (0 <= f(x) <= 1)

0 commit comments

Comments
 (0)