Skip to content

Commit eaee0e4

Browse files
authored
add karnik-mendel defuzzification algorithm (#19)
* add karnik-mendel defuzzification algorithm * more tests and remove unneeded code * fix bug in karnik-mendel and add enhanced karnik-mendel * fix bug in ekm and add docs and tests * more defuzzifiers and tests * add tutorial about type-2 * Update docs/src/literate/tutorials/type2.jl
1 parent 3e67555 commit eaee0e4

18 files changed

+444
-27
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ using FuzzyLogic
2424

2525
## Features
2626

27-
- **Rich!** Mamdani and Sugeno Type-1 inference systems, several membership functions and algoritms options available.
27+
- **Rich!** Mamdani and Sugeno inference systems, both Type-1 and Type-2, several [membership functions](https://lucaferranti.github.io/FuzzyLogic.jl/stable/api/memberships) and [algoritms options](https://lucaferranti.github.io/FuzzyLogic.jl/stable/api/fis) available.
28+
- **Compatible!** Read your models from [IEC 61131-7 Fuzzy Control Language](https://ffll.sourceforge.net/fcl.htm) and Matlab Fuzzy toolbox `.fis` files.
2829
- **Expressive!** Clear Domain Specific Language to write your model as human readable Julia code
2930
- **Productive!** Several visualization tools to help debug and tune your model.
30-
3131
## Quickstart example
3232

3333
```julia

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ makedocs(;
154154
"Tutorials" => [
155155
"Build a Mamdani inference system" => "tutorials/mamdani.md",
156156
"Build a Sugeno inference system" => "tutorials/sugeno.md",
157+
"Build a type-2 inference system" => "tutorials/type2.md",
157158
],
158159
"Applications" => [
159160
"Edge detection" => "applications/edge_detector.md",

docs/src/api/defuzzification.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# Defuzzification methods
22

3+
## Type-1 defuzzifiers
34
```@autodocs
45
Modules = [FuzzyLogic]
5-
Filter = t -> typeof(t) === DataType && t <: FuzzyLogic.AbstractDefuzzifier
6-
```
6+
Filter = t -> typeof(t) === DataType && t <: FuzzyLogic.AbstractDefuzzifier && !(t <: FuzzyLogic.Type2Defuzzifier)
7+
```
8+
9+
## Type-2 defuzzifiers
10+
11+
```@autodocs
12+
Modules = [FuzzyLogic]
13+
Filter = t -> typeof(t) === DataType && t <: FuzzyLogic.Type2Defuzzifier
14+
```

docs/src/api/fis.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,10 @@ MamdaniFuzzySystem
1212
SugenoFuzzySystem
1313
ConstantSugenoOutput
1414
LinearSugenoOutput
15+
```
16+
17+
## General functions
18+
19+
```@docs
20+
set
1521
```

docs/src/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
- ![](https://img.shields.io/badge/new%20feature-green.svg) support for weighted rules.
88
- ![](https://img.shields.io/badge/new%20feature-green.svg) allow to specify input and output variables as vectors (e.g. `x[1:10]`) and support for loops to avoid repetitive code.
9+
- ![](https://img.shields.io/badge/new%20feature-green.svg) added support for type-2 membership functions and type-2 systems.
910

1011
## v0.1.1 -- 2023-02-25
1112

docs/src/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ using FuzzyLogic
2424

2525
## Features
2626

27-
- **Rich!** Mamdani and Sugeno Type-1 inference systems, several membership functions and algoritms options available.
27+
- **Rich!** Mamdani and Sugeno inference systems, both Type-1 and Type-2, several [membership functions](https://lucaferranti.github.io/FuzzyLogic.jl/stable/api/memberships) and [algoritms options](https://lucaferranti.github.io/FuzzyLogic.jl/stable/api/fis) available.
28+
- **Compatible!** Read your models from [IEC 61131-7 Fuzzy Control Language](https://ffll.sourceforge.net/fcl.htm) and Matlab Fuzzy toolbox `.fis` files.
2829
- **Expressive!** Clear Domain Specific Language to write your model as human readable Julia code
2930
- **Productive!** Several visualization tools to help debug and tune your model.
3031

docs/src/literate/tutorials/type2.jl

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#=
2+
3+
# Build a type-2 inference system
4+
5+
This tutorial explains how to build a type-2 inference system.
6+
The reader is assumed to be familiar with the basic syntax to build a fuzzy system, which
7+
is described in the [Build a Mamdani inference system](@ref) tutorial.
8+
9+
DOWNLOAD_NOTE
10+
11+
## Interval membership function
12+
13+
While a normal membership function associates each element of a fuzzy set ot a membership
14+
degree $\mu \in [0, 1]$, an interval membership function associates each element to an
15+
*interval membership degeee* $\overline{\mu}\subseteq[0, 1]$.
16+
17+
The following example shows how to contruct an interval membership function in the library
18+
and displays the result.
19+
=#
20+
21+
using FuzzyLogic, Plots
22+
23+
mf = 0.7 * TriangularMF(1, 2, 3) .. TriangularMF(0, 2, 4)
24+
25+
plot(mf, -1, 5)
26+
27+
#=
28+
An interval membership function can be constructed using the `..` operator. The left input
29+
is the lower bound and the right input is the upper bound. The expression `0.5 * TriangularMF(1, 2, 3)`
30+
constructs a scaled membership.
31+
32+
## Type-2 inference systems
33+
34+
A type-2 Mamdani system can be built with the [`@mamfis`](@ref) macro, just like type-1, with two differences
35+
36+
- membership functions can be interval membership funcions
37+
- the defuzzifier should be one of the [Type-2 defuzzifiers](@ref)
38+
39+
The following code shows an example of building a type-2 system and performing inference with it.
40+
41+
=#
42+
43+
fis = @mamfis function tipper(service, food)::tip
44+
service := begin
45+
domain = 0:10
46+
poor = 0.8 * GaussianMF(0.0, 1.2) .. GaussianMF(0.0, 1.5)
47+
good = 0.8 * GaussianMF(5.0, 1.2) .. GaussianMF(5.0, 1.5)
48+
excellent = 0.8 * GaussianMF(10.0, 1.2) .. GaussianMF(10.0, 1.5)
49+
end
50+
51+
food := begin
52+
domain = 0:10
53+
rancid = 0.9 * TrapezoidalMF(-1.8, 0.0, 1.0, 2.8) .. TrapezoidalMF(-2, 0, 1, 3)
54+
delicious = 0.9 * TrapezoidalMF(8, 9, 10, 12) .. TrapezoidalMF(7, 9, 10, 12)
55+
end
56+
57+
tip := begin
58+
domain = 0:30
59+
cheap = 0.8 * TriangularMF(1, 5, 9) .. TriangularMF(0, 5, 10)
60+
average = 0.8 * TriangularMF(11, 15, 19) .. TriangularMF(10, 15, 20)
61+
generous = 0.8 * TriangularMF(22, 25, 29) .. TriangularMF(20, 25, 30)
62+
end
63+
64+
service == poor || food == rancid --> tip == cheap
65+
service == good --> tip == average
66+
service == excellent || food == delicious --> tip == generous
67+
68+
defuzzifier = KarnikMendelDefuzzifier()
69+
end
70+
71+
plot(fis)
72+
73+
#-
74+
75+
fis(service = 2, food = 3)

src/FuzzyLogic.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export DifferenceSigmoidMF, LinearMF, GeneralizedBellMF, GaussianMF, ProductSigm
2222
ProbSumOr, MaxOr, BoundedSumOr, DrasticOr, NilpotentOr, EinsteinOr,
2323
MinImplication, ProdImplication,
2424
MaxAggregator, ProbSumAggregator, CentroidDefuzzifier, BisectorDefuzzifier,
25-
@mamfis, MamdaniFuzzySystem, @sugfis, SugenoFuzzySystem,
25+
KarnikMendelDefuzzifier, EKMDefuzzifier, IASCDefuzzifier, EIASCDefuzzifier,
26+
@mamfis, MamdaniFuzzySystem, @sugfis, SugenoFuzzySystem, set,
2627
LinearSugenoOutput, ConstantSugenoOutput,
2728
fuzzy_cmeans,
2829
readfis

src/InferenceSystem.jl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22

33
abstract type AbstractFuzzySystem end
44

5+
"""
6+
Create a copy of the given fuzzy systems, but with the new settings as specified in the
7+
keyword arguments.
8+
9+
### Inputs
10+
11+
- `fis::AbstractFuzzySystem` -- input fuzzy system
12+
13+
### Keyword arguments
14+
15+
- `kwargs...` -- new settings of the inference system to be tuned
16+
17+
"""
18+
function set(fis::AbstractFuzzySystem; kwargs...)
19+
typeof(fis).name.wrapper(NamedTuple(f => get(kwargs, f, getproperty(fis, f))
20+
for f in fieldnames(typeof(fis)))...)
21+
end
22+
523
###########
624
# Mamdani #
725
###########
@@ -154,8 +172,6 @@ const SETTINGS = (MamdaniFuzzySystem = (:and, :or, :implication, :aggregator,
154172
:defuzzifier),
155173
SugenoFuzzySystem = (:and, :or))
156174

157-
implication(::SugenoFuzzySystem) = ProdImplication()
158-
159175
# sugeno output functions
160176

161177
abstract type AbstractSugenoOutputFunction <: AbstractPredicate end

src/evaluation.jl

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,6 @@ 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;
22-
N = 100)
23-
map(fr.consequent) do c
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
28-
end
29-
3021
function (fis::MamdaniFuzzySystem)(inputs::T) where {T <: NamedTuple}
3122
Npoints = fis.defuzzifier.N + 1
3223
S = outputtype(typeof(fis.defuzzifier), T)
@@ -38,7 +29,7 @@ function (fis::MamdaniFuzzySystem)(inputs::T) where {T <: NamedTuple}
3829
var = fis.outputs[con.subj]
3930
l, h = low(var.domain), high(var.domain)
4031
mf = map(var.mfs[con.prop], LinRange(l, h, Npoints))
41-
ruleres = scale(broadcast(implication(fis), w, mf), rule)
32+
ruleres = scale(map(Base.Fix1(implication(fis), w), mf), rule)
4233
res[con.subj] = broadcast(fis.aggregator, res[con.subj], ruleres)
4334
end
4435
end

0 commit comments

Comments
 (0)