1import numpy as np
2import skfuzzy as fuzz
3from numpy.testing import assert_allclose, assert_raises
4
5
6def test_bisector():
7    x = np.arange(6)
8    mfx = fuzz.trimf(x, [0, 5, 5])
9    expected = 3.53553390593274
10
11    # Test both triangle code paths
12    assert_allclose(expected, fuzz.defuzz(x, mfx, 'bisector'))
13    assert_allclose(5 - expected, fuzz.defuzz(x, 1 - mfx, 'bisector'))
14
15    # Test singleton input
16    y = np.r_[2]
17    mfy = np.r_[0.33]
18    assert_allclose(y, fuzz.defuzz(y, mfy, 'bisector'))
19
20    # Test rectangle code path
21    mfx = fuzz.trapmf(x, [2, 2, 4, 4])
22    assert_allclose(3., fuzz.defuzz(x, mfx, 'bisector'))
23
24
25def test_centroid():
26
27    def helper_centroid(mean=0, sigma=1):
28        x = np.arange(21) - 10
29        gmf = fuzz.gaussmf(x, mean, sigma)
30        assert_allclose(mean, fuzz.centroid(x, gmf), atol=1e-1)
31        return None
32
33    def helper_dcentroid(mean=0, sigma=1, dc=0):
34        x = np.arange(21) - 10
35        gmf = fuzz.gaussmf(x, mean, sigma)
36        assert_allclose(mean, fuzz.dcentroid(x, gmf, dc), atol=1e-1)
37        assert_allclose(fuzz.centroid(x, gmf),
38                        fuzz.dcentroid(x, gmf, 0))
39        return None
40
41    for mean in np.arange(-5, 5, 2):
42        for sigma in range(1, 3):
43            helper_centroid(mean, sigma)
44            for differential_centroid in 42 * (np.arange(11) - 5):
45                helper_dcentroid(mean, sigma, differential_centroid)
46
47    # Test with ends @ zero, to evaluate special cases in new defuzz method
48    x = np.arange(21) - 10
49    gmf = fuzz.gaussmf(x, 0, np.pi)
50    gmf[0] = 0
51    gmf[-1] = 0
52    assert_allclose(0, fuzz.centroid(x, gmf), atol=1e-8)
53
54
55def test_centroid_singleton():
56    x = np.r_[0]
57    mfx = np.r_[0]
58    assert_allclose(np.r_[0], fuzz.centroid(x, mfx))
59
60    x = np.r_[3]
61    mfx = np.r_[0.5]
62    assert_allclose(x, fuzz.centroid(x, mfx))
63
64
65def test_defuzz():
66    x = np.arange(21) - 10
67    gmf = fuzz.gaussmf(x, 0, 2)
68
69    assert_allclose(0, fuzz.defuzz(x, gmf, 'centroid'), atol=1e-9)
70    assert_allclose(0, fuzz.defuzz(x, gmf, 'bisector'), atol=1e-9)
71    assert_allclose(0, fuzz.defuzz(x, gmf, 'mom'))
72    assert_allclose(0, fuzz.defuzz(x, gmf, 'som'))
73    assert_allclose(0, fuzz.defuzz(x, gmf, 'lom'))
74
75    # Fuzzy plateau to differentiate mom, som, lom
76    trapmf = fuzz.trapmf(x, [-1, 3, 7, 8])
77
78    assert_allclose(3, fuzz.defuzz(x, trapmf, 'som'))
79    assert_allclose(5, fuzz.defuzz(x, trapmf, 'mom'))
80    assert_allclose(7, fuzz.defuzz(x, trapmf, 'lom'))
81
82
83    # Make sure som/lom work for all-negative universes:
84    x_neg = x-20
85    assert_allclose(-17, fuzz.defuzz(x_neg, trapmf, 'som'))
86    assert_allclose(-13, fuzz.defuzz(x_neg, trapmf, 'lom'))
87
88    # Bad string argument
89    assert_raises(ValueError, fuzz.defuzz, x, trapmf, 'bad string')
90
91
92def test_lambda_cut():
93    x = np.arange(21) - 10
94    mfx = fuzz.trimf(x, [-2, 3, 5])
95
96    # fuzz.lambda_cut test
97    expected = np.r_[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98                     1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
99    result = fuzz.lambda_cut(mfx, 0.33)
100    assert_allclose(expected, result)
101
102    # fuzz.arglcut test
103    expected = np.r_[10, 11, 12, 13, 14]
104    result = fuzz.arglcut(mfx, 0.33)
105
106    assert len(result) == 1
107    assert_allclose(expected, result[0])
108
109
110def test_lambda_cut_series():
111    x = np.arange(21) - 10
112    mfx = fuzz.trimf(x, [-2, 3, 5])
113
114    expected = np.array([[0.  , -2.,  5.],
115                         [0.25,  0.,  4.],
116                         [0.5 ,  1.,  4.],
117                         [0.75,  2.,  3.],
118                         [1.  ,  3.,  3.]])
119
120    assert_allclose(expected, fuzz.lambda_cut_series(x, mfx, 5))
121
122
123def test_lambda_cut_boundaries():
124    x = np.arange(10)
125    mfx = fuzz.trapmf(x, [0, 6, 7, 10])
126
127    assert_allclose(fuzz.lambda_cut_boundaries(x, mfx, 0.2), np.r_[1.2])
128
129    x = np.arange(11)
130    mfx = fuzz.trapmf(x, [0, 6, 7, 10])
131    assert_allclose(fuzz.lambda_cut_boundaries(x, mfx, 0.2), np.r_[1.2, 9.4])
132
133
134def test_lambda_cut_boundaries_degenerate():
135    x = np.arange(11)
136    mfx = fuzz.trimf(x, [0, 7, 10])
137    assert_allclose(fuzz.lambda_cut_boundaries(x, mfx, 1), np.r_[7])
138
139
140if __name__ == '__main__':
141    np.testing.run_module_suite()
142