Skip to content

Commit b24d4f4

Browse files
authored
remove anonymous functions (#12)
* remove anonymous functions * update bisector defuzzifier and add tests
1 parent cc2499f commit b24d4f4

File tree

3 files changed

+44
-24
lines changed

3 files changed

+44
-24
lines changed

src/evaluation.jl

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,34 @@ function (fo::FuzzyOr)(fis::AbstractFuzzySystem, inputs)
1818
fis.or(fo.left(fis, inputs), fo.right(fis, inputs))
1919
end
2020

21-
function (fr::FuzzyRule)(fis::AbstractFuzzySystem, inputs)::Dictionary{Symbol, Function}
21+
function (fr::FuzzyRule)(fis::AbstractFuzzySystem, inputs;
22+
N = 100)
2223
map(fr.consequent) do c
23-
mf = memberships(fis.outputs[c.subj])[c.prop]
24-
c.subj => Base.Fix1(implication(fis), fr.antecedent(fis, inputs)) mf
25-
end |> dictionary
24+
l, h = low(fis.outputs[c.sub].domain), high(fis.outputs[c.sub].domain)
25+
mf = broadcast(memberships(fis.outputs[c.subj])[c.prop], LinRange(l, h, N))
26+
broadcast(implication(fis), fr.antecedent(fis, inputs), mf)
27+
end
2628
end
2729

28-
function (fis::MamdaniFuzzySystem)(inputs::T)::Dictionary{Symbol,
29-
float(eltype(T))
30-
} where {T <: NamedTuple}
31-
rules = [rule(fis, inputs) for rule in fis.rules]
32-
map(pairs(fis.outputs)) do (y, var)
33-
fis.defuzzifier(domain(var)) do x
34-
reduce(fis.aggregator, rule[y](x) for rule in rules if haskey(rule, y))
30+
function (fis::MamdaniFuzzySystem)(inputs::T) where {T <: NamedTuple}
31+
Npoints = fis.defuzzifier.N + 1
32+
S = float(eltype(T))
33+
res = Dictionary{Symbol, Vector{S}}(keys(fis.outputs),
34+
[zeros(S, Npoints) for _ in 1:length(fis.outputs)])
35+
@inbounds for rule in fis.rules
36+
w = rule.antecedent(fis, inputs)::S
37+
for con in rule.consequent
38+
var = fis.outputs[con.subj]
39+
l, h = low(var.domain), high(var.domain)
40+
mf = map(var.mfs[con.prop], LinRange(l, h, Npoints))
41+
ruleres = broadcast(implication(fis), w, mf)
42+
res[con.subj] = broadcast(fis.aggregator, res[con.subj], ruleres)
3543
end
3644
end
45+
46+
Dictionary(keys(fis.outputs), map(zip(res, fis.outputs)) do (y, var)
47+
fis.defuzzifier(y, var.domain)
48+
end)
3749
end
3850

3951
(fis::MamdaniFuzzySystem)(; inputs...) = fis(values(inputs))

src/options.jl

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,13 @@ variable domain ``[a, b]`` the defuzzified output is the centroid computed as
156156
The integrals are computed numerically using the trapezoidal rule.
157157
"""
158158
struct CentroidDefuzzifier <: AbstractDefuzzifier
159-
"number of subintegrals for integration, default 100."
159+
"number of subintervals for integration, default 100."
160160
N::Int
161161
end
162162
CentroidDefuzzifier() = CentroidDefuzzifier(100)
163-
function (cd::CentroidDefuzzifier)(f::Function, dom::Domain{T})::float(T) where {T}
164-
l, h = low(dom), high(dom)
165-
(_trapz(x -> x * f(x), l, h, cd.N) / _trapz(f, l, h, cd.N))
163+
function (cd::CentroidDefuzzifier)(y, dom::Domain{T})::float(T) where {T}
164+
dx = (high(dom) - low(dom)) / cd.N
165+
_trapz(dx, LinRange(low(dom), high(dom), cd.N + 1) .* y) / _trapz(dx, y)
166166
end
167167

168168
@doc raw"""
@@ -186,20 +186,19 @@ struct BisectorDefuzzifier <: AbstractDefuzzifier
186186
N::Int
187187
end
188188
BisectorDefuzzifier() = BisectorDefuzzifier(100)
189-
function (bd::BisectorDefuzzifier)(f::Function, dom::Domain{T})::float(T) where {T}
189+
function (bd::BisectorDefuzzifier)(y, dom::Domain{T})::float(T) where {T}
190190
area_left = zero(T)
191-
area_right = _trapz(f, low(dom), high(dom), bd.N)
192-
cand = low(dom)
193191
h = (high(dom) - low(dom)) / bd.N
192+
area_right = _trapz(h, y)
193+
cand = LinRange(low(dom), high(dom), bd.N + 1)
194+
i = firstindex(y)
194195
while area_left < area_right
195-
trap = (f(cand) + f(cand + h)) * h / 2
196+
trap = (y[i] + y[i + 1]) * h / 2
196197
area_left += trap
197198
area_right -= trap
198-
cand += h
199+
i += 1
199200
end
200-
(f(cand - h) + f(cand)) * h / 2 >= area_left - area_right ? cand : cand - h
201+
(y[i - 1] + y[i]) * h / 2 >= area_left - area_right ? cand[i] : cand[i - 1]
201202
end
202203

203-
function _trapz(f, a, b, N)
204-
(b - a) / N * (sum(f(xi) for xi in LinRange(a, b, N + 1)) + (f(a) + f(b)) / 2)
205-
end
204+
_trapz(dx, y) = (2sum(y) - first(y) - last(y)) * dx / 2

test/test_settings.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,12 @@ end
5252
@test EinsteinOr()(0.5, 0.5) == 0.8
5353
@test EinsteinOr()(1.0, 1.0) == 1.0
5454
end
55+
56+
@testset "test defuzzifiers" begin
57+
N = 800
58+
mf = TrapezoidalMF(1, 2, 5, 7)
59+
x = LinRange(0, 8, N + 1)
60+
y = mf.(x)
61+
@test BisectorDefuzzifier(N)(y, FuzzyLogic.Domain(0, 8)) 3.75
62+
@test CentroidDefuzzifier(N)(y, FuzzyLogic.Domain(0, 8)) 3.7777777777777772
63+
end

0 commit comments

Comments
 (0)