Skip to content

Commit

Permalink
refactor Fuzzy.jl package
Browse files Browse the repository at this point in the history
this commit do a refactor and solve some bugs
  • Loading branch information
phelipe committed Sep 5, 2021
1 parent df1eef9 commit 23a93d7
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 171 deletions.
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name = "Fuzzy"
uuid = "a9166f1b-85e5-4df0-9c26-e06b441f12e8"
authors = ["Phelipe Wesley <[email protected]> and contributors"]
version = "0.2.1"
version = "0.3.0"

[compat]
julia = "1"
julia = "1.6"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
18 changes: 11 additions & 7 deletions src/Eval.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function eval_fis(fis::FISMamdani, input_values::Vector{<:AbstractFloat}, defuzz
tmp_strengths = AbstractFloat[]
for i in 1:length(rule.input_mf_names)
if (rule.input_mf_names[i] !== "")
push!(tmp_strengths, fis.input_mfs_dicts[i][rule.input_mf_names[i]].eval(input_values[i]))
push!(tmp_strengths, eval(fis.input_mfs_dicts[i][rule.input_mf_names[i]], input_values[i]))
end
end
push!(firing_strengths, firing(tmp_strengths, rule.firing_method))
Expand All @@ -46,7 +46,7 @@ function eval_fis(fis::FISSugeno, input_values::Vector{<:AbstractFloat})
tmp_strengths = AbstractFloat[]
for i in 1:length(rule.input_mf_names)
if (rule.input_mf_names[i] !== "")
push!(tmp_strengths, fis.input_mfs_dicts[i][rule.input_mf_names[i]].eval(input_values[i]))
push!(tmp_strengths, eval(fis.input_mfs_dicts[i][rule.input_mf_names[i]], input_values[i]))
end
end
push!(firing_strengths, firing(tmp_strengths, rule.firing_method))
Expand Down Expand Up @@ -80,17 +80,21 @@ end
"""
function defuzz(firing_strengths::Vector{AbstractFloat}, rules::Vector{Rule}, output_mfs_dict::Dict{AbstractString,MF}, defuzz_method::AbstractString)


if defuzz_method == "MOM"
max_firing_index = indmax(firing_strengths)
max_firing_index = argmax(firing_strengths)
max_fired_mf_name = rules[max_firing_index].output_mf
output_mfs_dict[max_fired_mf_name].mean_at(maximum(firing_strengths))
mean_at(output_mfs_dict[max_fired_mf_name], maximum(firing_strengths))
elseif defuzz_method == "WTAV"
mean_vec = AbstractFloat[]
for i in 1:length(rules)
push!(mean_vec, output_mfs_dict[rules[i].output_mf].mean_at(firing_strengths[i]))
push!(mean_vec, mean_at(output_mfs_dict[rules[i].output_mf], firing_strengths[i]))
end
sumfire = sum(firing_strengths)
if sumfire != 0
(mean_vec' * firing_strengths)[1] / sum(firing_strengths)
else
mean_vec
end
(mean_vec' * firing_strengths)[1] / sum(firing_strengths)
end

end
Expand Down
59 changes: 59 additions & 0 deletions src/EvalMF.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
function eval(membership_function::TriangularMF, x::T) where {T <: Number}
return maximum([minimum([((x - membership_function.l_vertex) / (membership_function.center - membership_function.l_vertex)), ((membership_function.r_vertex - x) / (membership_function.r_vertex - membership_function.center))]), 0])
end

function mean_at(membership_function::TriangularMF, firing_strength::T) where {T <: Number}
if firing_strength != 1
p1 = (membership_function.center - membership_function.l_vertex) * firing_strength + membership_function.l_vertex
p2 = (membership_function.center - membership_function.r_vertex) * firing_strength + membership_function.r_vertex
(p1 + p2) / 2
elseif firing_strength == 1
return membership_function.center
end
end

function eval(menbership_function::GaussianMF, x::T) where {T <: Number}
return exp(- 0.5 * ((x - menbership_function.center) / menbership_function.sigma)^2)
end

function mean_at(membership_function::GaussianMF, firing_strength::T) where {T <: Number}
return membership_function.center
end


function eval(membership_function::BellMF, x::T) where {T <: Number}
return (1 / (1 + abs((x - membership_function.c) / membership_function.a)^(2 * membership_function.b)))
end

function mean_at(membership_function::BellMF, firing_strength::T) where {T <: Number}
return membership_function.c
end

function eval(membership_function::TrapezoidalMF, x::T) where {T <: Number}
return maximum([minimum([((x - membership_function.l_bottom_vertex) / (membership_function.l_top_vertex - membership_function.l_bottom_vertex)), 1, ((membership_function.r_bottom_vertex - x) / (membership_function.r_bottom_vertex - membership_function.r_top_vertex))]), 0])
end

function mean_at(membership_function::TrapezoidalMF, firing_strength::T) where {T <: Number}
p1 = (membership_function.l_top_vertex - membership_function.l_bottom_vertex) * firing_strength + membership_function.l_bottom_vertex
p2 = (membership_function.r_top_vertex - membership_function.r_bottom_vertex) * firing_strength + membership_function.r_bottom_vertex
(p1 + p2) / 2
end


function eval(membership_function::SigmoidMF, x::T) where {T <: Number}
return 1 / (1 + exp(-membership_function.a * (x - membership_function.c)))
end

function mean_at(membership_function::SigmoidMF, firing_strength::T) where {T <: Number}
if firing_strength == 1
p_firing_strength = 0.999
elseif firing_strength == 0
p_firing_strength = 0.001
else
p_firing_strength = firing_strength
end

p1 = -log((1 / p_firing_strength) - 1) / membership_function.a + membership_function.c
p2 = membership_function.limit
(p1 + p2) / 2
end
5 changes: 4 additions & 1 deletion src/Fuzzy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Fuzzy

export Rule, FISMamdani, FISSugeno

export eval_fis
export mean_at, eval_fis

export minimum_value, algebraic_product, bounded_difference, drastic_product, einstein_product, hamacher_product

Expand All @@ -19,6 +19,9 @@ module Fuzzy
# Membership functions
include("MF.jl")

# Membership functions evaluations
include("EvalMF.jl")

# FIS
include("FIS.jl")

Expand Down
166 changes: 5 additions & 161 deletions src/MF.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,55 +13,19 @@ abstract type MF end
Properties
----------
`l_vertex`, `center` and `r_vertex` are the vertices of the triangle, in order
`eval` function returns membership value at a point
`mean_at` function returns mean value at line clipped by given firing strength
"""
mutable struct TriangularMF <: MF

l_vertex::Real
center::Real
r_vertex::Real

eval::Function
mean_at::Function

function TriangularMF(l_vertex::Real, center::Real, r_vertex::Real)

if l_vertex <= center <= r_vertex

this = new()

this.l_vertex = l_vertex
this.center = center
this.r_vertex = r_vertex

this.eval = function eval(x)
maximum([minimum([((x - this.l_vertex) / (this.center - this.l_vertex)), ((this.r_vertex - x) / (this.r_vertex - this.center))]), 0])
end

this.mean_at = function mean_at(firing_strength)

if firing_strength != 1
p1 = (this.center - this.l_vertex) * firing_strength + this.l_vertex
p2 = (this.center - this.r_vertex) * firing_strength + this.r_vertex
(p1 + p2) / 2
elseif firing_strength == 1
return this.center
end

end

this

new(l_vertex::Real, center::Real, r_vertex::Real)
else

error("invalid vertices")

end

end

end


Expand All @@ -75,37 +39,14 @@ Gaussian membership function type
`center` is the center of the distribution
`sigma` determines width of the distribution
`eval` function returns membership value at a point
`mean_at` function returns mean value at line clipped by given firing strength
"""
mutable struct GaussianMF <: MF

center::Real
sigma::Real

eval::Function
mean_at::Function

function GaussianMF(center::Real, sigma::Real)

this = new()

this.center = center
this.sigma = sigma

this.eval = function eval(x)
exp(- 0.5 * ((x - this.center) / this.sigma)^2)
end

this.mean_at = function mean_at(firing_strength)
this.center
end

this

new(center::Real, sigma::Real)
end

end

"""
Expand All @@ -117,39 +58,15 @@ end
----------
`a`, `b` and `c` the usual bell parameters with `c` being the center
`eval` function returns membership value at a point
`mean_at` function returns mean value at line clipped by given firing strength
"""
mutable struct BellMF <: MF

a::Real
b::Real
c::Real

eval::Function
mean_at::Function

function BellMF(a::Real, b::Real, c::Real)

this = new()

this.a = a
this.b = b
this.c = c

this.eval = function eval(x)
1 / (1 + abs((x - this.c) / this.a)^(2 * this.b))
end

this.mean_at = function mean_at(firing_strength)
this.c
end

this

new(a::Real, b::Real, c::Real)
end

end

"""
Expand All @@ -160,52 +77,20 @@ end
Properties
----------
`l_bottom_vertex`, `l_top_vertex`, `r_top_vertex` and `r_bottom_vertex` are the vertices of the trapezoid, in order
`eval` function returns membership value at a point
`mean_at` function returns mean value at line clipped by given firing strength
"""
mutable struct TrapezoidalMF <: MF

l_bottom_vertex::Real
l_top_vertex::Real
r_top_vertex::Real
r_bottom_vertex::Real

eval::Function
mean_at::Function

function TrapezoidalMF(l_bottom_vertex::Real, l_top_vertex::Real, r_top_vertex::Real, r_bottom_vertex::Real)

if l_bottom_vertex <= l_top_vertex <= r_top_vertex <= r_bottom_vertex

this = new()

this.l_bottom_vertex = l_bottom_vertex
this.l_top_vertex = l_top_vertex
this.r_top_vertex = r_top_vertex
this.r_bottom_vertex = r_bottom_vertex

this.eval = function eval(x)
maximum([minimum([((x - this.l_bottom_vertex) / (this.l_top_vertex - this.l_bottom_vertex)), 1, ((this.r_bottom_vertex - x) / (this.r_bottom_vertex - this.r_top_vertex))]), 0])
end

this.mean_at = function mean_at(firing_strength)
p1 = (this.l_top_vertex - this.l_bottom_vertex) * firing_strength + this.l_bottom_vertex
p2 = (this.r_top_vertex - this.r_bottom_vertex) * firing_strength + this.r_bottom_vertex
(p1 + p2) / 2
end

this

new(l_bottom_vertex::Real, l_top_vertex::Real, r_top_vertex::Real, r_bottom_vertex::Real)
else

error("invalid vertices")

end

end

end

"""
Expand All @@ -218,58 +103,17 @@ end
`a` controls slope
`c` is the crossover point
`limit` sets the extreme limit
`eval` function returns membership value at a point
`mean_at` function returns mean value at line clipped by given firing strength
"""
mutable struct SigmoidMF <: MF

a::Real
c::Real
limit::Real

eval::Function
mean_at::Function

function SigmoidMF(a::Real, c::Real, limit::Real)

if (a > 0 && limit > c) || (a < 0 && limit < c)

this = new()

this.a = a
this.c = c
this.limit = limit

this.eval = function eval(x)
1 / (1 + exp(-this.a * (x - this.c)))
end

this.mean_at = function mean_at(firing_strength)

if firing_strength == 1
p_firing_strength = 0.999
elseif firing_strength == 0
p_firing_strength = 0.001
else
p_firing_strength = firing_strength
end

p1 = -log((1 / p_firing_strength) - 1) / this.a + this.c
p2 = this.limit
(p1 + p2) / 2

end

this

new(a::Real, c::Real, limit::Real)
else

error("invalid parameters")

end

end

end

0 comments on commit 23a93d7

Please sign in to comment.