Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
junzis
GitHub Repository: junzis/openap
Path: blob/master/openap/extra/fuzzy.py
592 views
1
"""Fuzzy logic membership functions.
2
3
Extracted from scikit-fuzzy library to prevent conda breaking:
4
https://github.com/scikit-fuzzy/scikit-fuzzy
5
"""
6
7
import numpy as np
8
9
10
def gaussmf(x, mean: float, sigma: float):
11
"""Gaussian fuzzy membership function.
12
13
Args:
14
x: Independent variable (1d array or iterable).
15
mean: Gaussian parameter for center (mean) value.
16
sigma: Gaussian parameter for standard deviation.
17
18
Returns:
19
Gaussian membership function for x.
20
21
"""
22
return np.exp(-((x - mean) ** 2) / (2 * sigma**2))
23
24
25
def zmf(x, a: float, b: float):
26
"""Z-function fuzzy membership generator.
27
28
Named for its Z-like shape.
29
30
Args:
31
x: Independent variable (1d array).
32
a: Ceiling, where the function begins falling from 1.
33
b: Foot, where the function reattains zero.
34
35
Returns:
36
Z-function membership values.
37
38
"""
39
assert a <= b, "a <= b is required."
40
41
y = np.ones(len(x))
42
43
idx = np.logical_and(a <= x, x < (a + b) / 2)
44
y[idx] = 1 - 2 * ((x[idx] - a) / (b - a)) ** 2
45
46
idx = np.logical_and((a + b) / 2 <= x, x <= b)
47
y[idx] = 2 * ((x[idx] - b) / (b - a)) ** 2
48
49
idx = x >= b
50
y[idx] = 0
51
52
return y
53
54
55
def smf(x, a: float, b: float):
56
"""S-function fuzzy membership generator.
57
58
Named for its S-like shape.
59
60
Args:
61
x: Independent variable (1d array).
62
a: Foot, where the function begins to climb from zero.
63
b: Ceiling, where the function levels off at 1.
64
65
Returns:
66
S-function membership values.
67
68
"""
69
assert a <= b, "a <= b is required."
70
71
y = np.ones(len(x))
72
idx = x <= a
73
y[idx] = 0
74
75
idx = np.logical_and(a <= x, x <= (a + b) / 2)
76
y[idx] = 2 * ((x[idx] - a) / (b - a)) ** 2
77
78
idx = np.logical_and((a + b) / 2 <= x, x <= b)
79
y[idx] = 1 - 2 * ((x[idx] - b) / (b - a)) ** 2
80
81
return y
82
83
84
def interp_membership(x, xmf, xx, zero_outside_x: bool = True):
85
"""Find the degree of membership u(xx) for a given value of x = xx.
86
87
For use in Fuzzy Logic, where an interpolated discrete membership function
88
u(x) for discrete values of x on the universe of x is given. This function
89
computes the membership value u(xx) using linear interpolation.
90
91
Args:
92
x: Independent discrete variable vector (1d array).
93
xmf: Fuzzy membership function for x. Same length as x.
94
xx: Value(s) on universe x where the interpolated membership is desired.
95
zero_outside_x: If True, extrapolated values will be zero. If False,
96
the first or last value in x will be returned. Defaults to True.
97
98
Returns:
99
Membership function value at xx, u(xx).
100
101
"""
102
if not zero_outside_x:
103
kwargs = (None, None)
104
else:
105
kwargs = (0, 0)
106
return np.interp(xx, x, xmf, left=kwargs[0], right=kwargs[1])
107
108
109
def defuzz(x, mfx, mode: str):
110
"""Defuzzification of a membership function.
111
112
Args:
113
x: Independent variable (1d array, length N).
114
mfx: Fuzzy membership function (1d array, length N).
115
mode: Defuzzification method ('mom': mean of maximum,
116
'som': min of maximum, 'lom': max of maximum).
117
118
Returns:
119
Defuzzified result.
120
121
Raises:
122
ValueError: When membership function data is inconsistent or mode invalid.
123
124
"""
125
mode = mode.lower()
126
x = x.ravel()
127
mfx = mfx.ravel()
128
n = len(x)
129
if n != len(mfx):
130
raise ValueError("inconsistent membership function")
131
132
elif "mom" in mode:
133
return np.mean(x[mfx == mfx.max()])
134
135
elif "som" in mode:
136
return np.min(x[mfx == mfx.max()])
137
138
elif "lom" in mode:
139
return np.max(x[mfx == mfx.max()])
140
141
else:
142
raise ValueError(f"The mode: {mode} was incorrect.")
143
144