Skip to content

Commit b605e43

Browse files
authored
add more defuzzifiers (#22)
* add more defuzzifiers * add defuzzifiers to parsers * typos in docs * add code generation for new defuzzifiers * update changelog
1 parent f45eb78 commit b605e43

File tree

8 files changed

+154
-1
lines changed

8 files changed

+154
-1
lines changed

docs/src/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
99
- ![](https://img.shields.io/badge/new%20feature-green.svg) added support for type-2 membership functions and type-2 systems.
1010
- ![](https://img.shields.io/badge/new%20feature-green.svg) added parser for Fuzzy Markup Language.
1111
- ![](https://img.shields.io/badge/new%20feature-green.svg) added generation of native Julia code.
12+
- ![](https://img.shields.io/badge/enhancement-blue.svg) added left maximum, right maximum and mean of maxima defuzzifiers.
1213

1314
## v0.1.1 -- 2023-02-25
1415

src/FuzzyLogic.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export DifferenceSigmoidMF, LinearMF, GeneralizedBellMF, GaussianMF, ProductSigm
2222
ProdAnd, MinAnd, LukasiewiczAnd, DrasticAnd, NilpotentAnd, HamacherAnd, EinsteinAnd,
2323
ProbSumOr, MaxOr, BoundedSumOr, DrasticOr, NilpotentOr, EinsteinOr, HamacherOr,
2424
MinImplication, ProdImplication,
25-
MaxAggregator, ProbSumAggregator, CentroidDefuzzifier, BisectorDefuzzifier,
25+
MaxAggregator, ProbSumAggregator,
26+
CentroidDefuzzifier, BisectorDefuzzifier, LeftMaximumDefuzzifier,
27+
RightMaximumDefuzzifier, MeanOfMaximaDefuzzifier,
2628
KarnikMendelDefuzzifier, EKMDefuzzifier, IASCDefuzzifier, EIASCDefuzzifier,
2729
@mamfis, MamdaniFuzzySystem, @sugfis, SugenoFuzzySystem, set,
2830
LinearSugenoOutput, ConstantSugenoOutput,

src/options.jl

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,91 @@ function (bd::BisectorDefuzzifier)(y, dom::Domain{T})::float(T) where {T}
225225
(y[i - 1] + y[i]) * h / 2 >= area_left - area_right ? cand[i] : cand[i - 1]
226226
end
227227

228+
"""
229+
Left maximum defuzzifier. Returns the smallest value in the domain for which the membership function
230+
reaches its maximum.
231+
232+
### Parameters
233+
234+
$(TYPEDFIELDS)
235+
236+
"""
237+
Base.@kwdef struct LeftMaximumDefuzzifier <: AbstractDefuzzifier
238+
"number of subintervals, default 100."
239+
N::Int = 100
240+
"absolute tolerance to determine if a value is maximum, default `eps(Float64)`."
241+
tol::Float64 = eps(Float64)
242+
end
243+
function (lmd::LeftMaximumDefuzzifier)(y, dom::Domain{T}) where {T}
244+
res = float(low(dom))
245+
maxval = first(y)
246+
for (xi, yi) in zip(LinRange(low(dom), high(dom), lmd.N + 1), y)
247+
if yi > maxval + lmd.tol
248+
res = xi
249+
maxval = yi
250+
end
251+
end
252+
res
253+
end
254+
255+
"""
256+
Right maximum defuzzifier. Returns the largest value in the domain for which the membership function
257+
reaches its maximum.
258+
259+
### Parameters
260+
261+
$(TYPEDFIELDS)
262+
263+
"""
264+
Base.@kwdef struct RightMaximumDefuzzifier <: AbstractDefuzzifier
265+
"number of subintervals, default 100."
266+
N::Int = 100
267+
"absolute tolerance to determine if a value is maximum, default `eps(Float64)`."
268+
tol::Float64 = eps(Float64)
269+
end
270+
function (lmd::RightMaximumDefuzzifier)(y, dom::Domain{T}) where {T}
271+
res = float(low(dom))
272+
maxval = first(y)
273+
for (xi, yi) in zip(LinRange(low(dom), high(dom), lmd.N + 1), y)
274+
if yi >= maxval - lmd.tol
275+
res = xi
276+
maxval = yi
277+
end
278+
end
279+
res
280+
end
281+
282+
"""
283+
Mean of maxima defuzzifier. Returns the mean of the values in the domain for which the
284+
membership function reaches its maximum.
285+
286+
### Parameters
287+
288+
$(TYPEDFIELDS)
289+
"""
290+
Base.@kwdef struct MeanOfMaximaDefuzzifier <: AbstractDefuzzifier
291+
"number of subintervals, default 100."
292+
N::Int = 100
293+
"absolute tolerance to determine if a value is maximum, default `eps(Float64)`."
294+
tol::Float64 = eps(Float64)
295+
end
296+
function (lmd::MeanOfMaximaDefuzzifier)(y, dom::Domain{T}) where {T}
297+
res = zero(float(T))
298+
maxcnt = 0
299+
maxval = first(y)
300+
for (xi, yi) in zip(LinRange(low(dom), high(dom), lmd.N + 1), y)
301+
if yi - maxval > lmd.tol # reset mean calculation
302+
res = xi
303+
maxval = yi
304+
maxcnt = 1
305+
elseif abs(yi - maxval) <= lmd.tol
306+
res += xi
307+
maxcnt += 1
308+
end
309+
end
310+
return res / maxcnt
311+
end
312+
228313
_trapz(dx, y) = (2sum(y) - first(y) - last(y)) * dx / 2
229314

230315
abstract type Type2Defuzzifier <: AbstractDefuzzifier end

src/parsers/fcl.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export parse_fcl, @fcl_str
1010
const FCL_JULIA = Dict("COG" => CentroidDefuzzifier(),
1111
"COGS" => "COGS", # dummy since hardcoded for sugeno
1212
"COA" => BisectorDefuzzifier(),
13+
"LM" => LeftMaximumDefuzzifier(),
14+
"RM" => RightMaximumDefuzzifier(),
15+
"MOM" => MeanOfMaximaDefuzzifier(),
1316
"ANDMIN" => MinAnd(),
1417
"ANDPROD" => ProdAnd(),
1518
"ANDBDIF" => LukasiewiczAnd(),

src/parsers/fml.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ XML_JULIA = Dict("mamdaniRuleBase" => MamdaniFuzzySystem,
2323
"rightLinearShape" => LinearMF,
2424
"COG" => CentroidDefuzzifier(),
2525
"COA" => BisectorDefuzzifier(),
26+
"MOM" => MeanOfMaximaDefuzzifier(),
27+
"LM" => LeftMaximumDefuzzifier(),
28+
"RM" => RightMaximumDefuzzifier(),
2629
"ACCMAX" => MaxAggregator(),
2730
"andMIN" => MinAnd(),
2831
"andPROD" => ProdAnd(),

src/parsers/matlab_fis.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ const MATLAB_JULIA = Dict("'mamdani'" => MamdaniFuzzySystem,
1616
"agg'probor'" => ProbSumAggregator(),
1717
"'centroid'" => CentroidDefuzzifier(),
1818
"'bisector'" => BisectorDefuzzifier(),
19+
"'mom'" => MeanOfMaximaDefuzzifier(),
20+
"'lom'" => RightMaximumDefuzzifier(),
21+
"'som'" => LeftMaximumDefuzzifier(),
1922
"'trapmf'" => TrapezoidalMF,
2023
"'trimf'" => TriangularMF,
2124
"'gaussmf'" => GaussianMF,

src/tojulia.jl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,53 @@ function to_expr(defuzz::BisectorDefuzzifier, mf, dom::Domain{T}) where {T <: Re
345345
(mf[i - 1] + mf[i]) * $(h / 2) >= area_left - area_right ? cand[i] : cand[i - 1]
346346
end)
347347
end
348+
349+
function to_expr(defuzz::LeftMaximumDefuzzifier, mf, dom::Domain{T}) where {T <: Real}
350+
:(let
351+
res = $(float(low(dom)))
352+
y = $mf
353+
maxval = first(y)
354+
for (xi, yi) in zip($(LinRange(low(dom), high(dom), defuzz.N + 1)), y)
355+
if yi > maxval + $(defuzz.tol)
356+
res = xi
357+
maxval = yi
358+
end
359+
end
360+
res
361+
end)
362+
end
363+
364+
function to_expr(defuzz::RightMaximumDefuzzifier, mf, dom::Domain{T}) where {T <: Real}
365+
:(let
366+
res = $(float(low(dom)))
367+
y = $mf
368+
maxval = first(y)
369+
for (xi, yi) in zip($(LinRange(low(dom), high(dom), defuzz.N + 1)), y)
370+
if yi >= maxval - $(defuzz.tol)
371+
res = xi
372+
maxval = yi
373+
end
374+
end
375+
res
376+
end)
377+
end
378+
379+
function to_expr(defuzz::MeanOfMaximaDefuzzifier, mf, dom::Domain{T}) where {T <: Real}
380+
:(let
381+
res = $(zero(float(T)))
382+
y = $mf
383+
maxval = first(y)
384+
maxcnt = 0
385+
for (xi, yi) in zip($(LinRange(low(dom), high(dom), defuzz.N + 1)), y)
386+
if yi - maxval > $(defuzz.tol) # reset mean calculation
387+
res = xi
388+
maxval = yi
389+
maxcnt = 1
390+
elseif abs(yi - maxval) <= $(defuzz.tol)
391+
res += xi
392+
maxcnt += 1
393+
end
394+
end
395+
res / maxcnt
396+
end)
397+
end

test/test_settings.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,10 @@ end
115115
3.75
116116
@test CentroidDefuzzifier(N)(y, dom) eval(to_expr(CentroidDefuzzifier(N), y, dom))
117117
3.7777777777777772
118+
@test LeftMaximumDefuzzifier(; N)(y, dom)
119+
eval(to_expr(LeftMaximumDefuzzifier(; N), y, dom)) 2
120+
@test RightMaximumDefuzzifier(; N)(y, dom)
121+
eval(to_expr(RightMaximumDefuzzifier(; N), y, dom)) 5
122+
@test MeanOfMaximaDefuzzifier(; N)(y, dom)
123+
eval(to_expr(MeanOfMaximaDefuzzifier(; N), y, dom)) 3.5
118124
end

0 commit comments

Comments
 (0)