Skip to content

Commit bd920b9

Browse files
committed
added hedge tests.
1 parent 1dd044f commit bd920b9

File tree

6 files changed

+111
-97
lines changed

6 files changed

+111
-97
lines changed

Showcase.ipynb

Lines changed: 57 additions & 65 deletions
Large diffs are not rendered by default.

fuzzy/classes.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ def __init__(self, name, low, high, res=1):
6161
def __call__(self, x):
6262
if not(self.low <= x <= self.high):
6363
warn(f"{x} is outside of domain!")
64-
set_memberships = {}
65-
for setname, s in self._sets.items():
66-
set_memberships["{0}.{1}".format(self.name, setname)] = s(x)
67-
return set_memberships
64+
memberships = {name: s.func(x) for
65+
name, s, in self._sets.items()}
66+
return memberships
6867

6968
def __str__(self):
7069
return self.name

fuzzy/combinators.py

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,26 @@
33
-----------
44
COMBINATORS
55
-----------
6-
Linguistic terms (membership functions of two different FuzzySets)
7-
are combined with these functions to implement rules.
6+
Linguistic terms (membership functions of two different FuzzySets of the same domain)
7+
are combined.
88
99
a and b are functions.
10+
11+
Since these combinators are used directly in the Set class to implement logic operations,
12+
the most obvious use of this module is when subclassing Set to make use of specific combinators
13+
for special circumstances.
1014
"""
1115

1216

1317
def MIN(a, b):
14-
"""Simple AND of two functions a and b."""
18+
"""Classic AND variant."""
1519
def f(x):
1620
return min(a(x), b(x))
1721
return f
1822

1923

2024
def MAX(a, b):
21-
"""Simple OR of two functions a and x."""
25+
"""Classic OR variant."""
2226
def f(x):
2327
return max(a(x), b(x))
2428
return f
@@ -38,51 +42,44 @@ def f(x):
3842
return a_x + b_x - a_x * b_x
3943
return f
4044

41-
42-
def lukasiewicz_OR(a, b):
43-
"""OR variant."""
44-
def f(x):
45-
return max(0, a(x) + b(x) - 1)
46-
return f
47-
48-
4945
def lukasiewicz_AND(a, b):
5046
"""AND variant."""
5147
def f(x):
5248
return min(1, a(x) + b(x))
5349
return f
5450

55-
56-
def einstein_sum(a, b):
51+
def lukasiewicz_OR(a, b):
5752
"""OR variant."""
5853
def f(x):
59-
a_x, b_x = a(x), b(x)
60-
return (a_x + b_x) / (1 + a_x * b_x)
54+
return max(0, a(x) + b(x) - 1)
6155
return f
6256

63-
6457
def einstein_product(a, b):
6558
"""AND variant."""
6659
def f(x):
6760
a_x, b_x = a(x), b(x)
6861
return (a_x * b_x) / (2 - (a_x + b_x - a_x * b_x))
6962
return f
7063

71-
72-
def hamacher_sum(a, b):
64+
def einstein_sum(a, b):
7365
"""OR variant."""
7466
def f(x):
7567
a_x, b_x = a(x), b(x)
76-
return (a_x + b_x - 2 * a_x * b_x) / (1 - a_x * b_x)
68+
return (a_x + b_x) / (1 + a_x * b_x)
7769
return f
7870

79-
8071
def hamacher_product(a, b):
8172
"""AND variant."""
8273
def f(x):
8374
a_x, b_x = a(x), b(x)
8475
return (a_x * b_x) / (a_x + b_x - a_x * b_x)
8576

77+
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+
return f
8683

8784
def lambda_op(a, b, l):
8885
"""A 'compensatoric' operator, combining AND with OR by a weighing factor l.
@@ -105,4 +102,4 @@ def f(x):
105102
a_x, b_x = a(x), b(x)
106103
return (a_x * b_x) ** (1 - g) * ((1 - a_x) * (1 - b_x)) ** g
107104

108-
return f
105+
return f

fuzzy/truth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
-------------------
66
Functions that transform a given membership value to a truth value.
77
8-
How this can be useful? Well..
8+
How this can be useful? Beats me. Found it somewhere on the internet, never needed it.
99
"""
1010

1111

test_fuzzy_functionality.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ def setUp(self):
1414
Lucy tells her robot that it is good to heat when it's cold and not when it's hot."""
1515
self.temp = Domain('temperature', -100, 100, 1) # in Celsius
1616
self.temp.cold = Set(S(0, 15))
17-
self.temp.hot = Set(R(10, 20))
17+
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})
1820

1921
def test_temp(self):
2022
# we need to define a dictionary-aggregation func here

test_fuzzy_units.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
from math import isclose
44
from unittest import TestCase
55

6+
from fuzzy.classes import Domain, Set, Rule
67
from fuzzy import functions as fun
8+
from fuzzy import hedges
79

810
class Test_Functions(TestCase):
911
@given(st.floats(allow_nan=False))
@@ -108,7 +110,7 @@ def test_triangular(self, x, low, high, c, c_m, no_m):
108110
st.floats(allow_nan=False, allow_infinity=False),
109111
st.floats(allow_nan=False, allow_infinity=False),
110112
st.floats(allow_nan=False, allow_infinity=False),
111-
st.floats(min_value=0, max_value=1),
113+
st.floats(allow_nan=False, allow_infinity=False),
112114
st.floats(min_value=0, max_value=1),
113115
st.floats(min_value=0, max_value=1))
114116
def test_trapezoid(self, x, low, c_low, c_high, high, c_m, no_m):
@@ -152,9 +154,31 @@ def test_triangular_sigmoid(self, x, low, high, c):
152154
@given(st.floats(allow_nan=False),
153155
st.floats(allow_nan=False, allow_infinity=False),
154156
st.floats(allow_nan=False, allow_infinity=False),
155-
st.floats(allow_nan=False, allow_infinity=False))
157+
st.floats(min_value=0, max_value=1))
156158
def test_gauss(self, x, b, c, c_m):
157-
assume(0 < c_m < 1)
159+
assume(0 < c_m <= 1)
158160
assume(0 < b)
159161
f = fun.gauss(c, b, c_m=c_m)
160-
assert (0 <= f(x) <= 1)
162+
assert (0 <= f(x) <= 1)
163+
164+
class Test_Hedges(TestCase):
165+
@given(st.floats(allow_nan=False))
166+
def test_very(self, x):
167+
assume(0 <= x <= 1)
168+
s = Set(fun.noop())
169+
h = hedges.very(s)
170+
assert (0 <= h(x) <= 1)
171+
172+
@given(st.floats(allow_nan=False))
173+
def test_minus(self, x):
174+
assume(0 <= x <= 1)
175+
s = Set(fun.noop())
176+
h = hedges.minus(s)
177+
assert (0 <= h(x) <= 1)
178+
179+
@given(st.floats(allow_nan=False))
180+
def test_plus(self, x):
181+
assume(0 <= x <= 1)
182+
s = Set(fun.noop())
183+
h = hedges.plus(s)
184+
assert (0 <= h(x) <= 1)

0 commit comments

Comments
 (0)