Packages

A toolkit for fuzzy logic, this library includes functions for creating fuzzy variables, sets, rules to create a Fuzzy Logic System (FLS).

Current section

Files

Jump to
flex lib variable.ex
Raw

lib/variable.ex

defmodule Flex.Variable do
alias Flex.Variable
@moduledoc """
An interface to create Fuzzy Variables.
"""
defstruct tag: nil,
fuzzy_sets: nil,
mf_values: %{},
range: nil,
tmp: nil,
type: nil
@typedoc """
Fuzzy Variable struct.
- `:tag` - (string) Defines the linguistic name of the fuzzy variable (e.g., "error").
- `:fuzzy_sets` - (list) Defines which all the fuzzy sets related to the variable.
- `:mf_values` - (map) The current values of each of the membership functions of the fuzzy sets.
- `:range` - (range) The range in which the variable exists.
- `:type` - (atom) :antecedent if the variable is an input or consequent for outputs.
"""
@type t :: %__MODULE__{
tag: String.t(),
fuzzy_sets: [Flex.Set.t(), ...],
mf_values: %{},
range: any(),
type: :antecedent | :consequent
}
@doc """
Creates a Fuzzy Variable.
The following options are require:
* `:tag` - (string) Defines the linguistic name of the fuzzy variable (e.g., "error"),
* `:fuzzy_sets` - (list) Defines which type of membership function use the set (e.g., "triangle").
* `:type` - (atom) Defines the type of variable (e.g., :antecedent or :consequent),
* `:range` - (range) The range in which the variable exists.
"""
@spec new(keyword) :: Flex.Variable.t()
def new(params) do
tag = Keyword.fetch!(params, :tag)
range = Keyword.fetch!(params, :range)
fuzzy_sets = Keyword.fetch!(params, :fuzzy_sets)
type = Keyword.fetch!(params, :type)
%Variable{range: range, fuzzy_sets: fuzzy_sets, type: type, tag: tag}
end
@doc """
Turns an antecedent fuzzy variable (input) from a crisp value to a fuzzy value.
"""
@spec fuzzification(Flex.Variable.t(), any()) :: :error | Flex.Variable.t()
def fuzzification(%Variable{type: type} = fuzzy_var, input) when type == :antecedent do
res = map_all_mf(fuzzy_var.fuzzy_sets, input, %{})
%{fuzzy_var | mf_values: res}
end
def fuzzification(_fuzzy_var, _input), do: :error
defp map_all_mf([], _input, acc), do: acc
defp map_all_mf([fs | tail], input, acc) do
mu = fs.mf.(input)
key = fs.tag
acc = Map.put(acc, key, mu)
map_all_mf(tail, input, acc)
end
@doc """
Turns an consequent fuzzy variable (output) from a fuzzy value to a crisp value (centroid method).
"""
@spec defuzzification(Flex.Variable.t()) :: float
def defuzzification(%Variable{type: type} = fuzzy_var) when type == :consequent do
fuzzy_to_crisp(fuzzy_var.fuzzy_sets, fuzzy_var.tmp, 0, 0)
end
defp fuzzy_to_crisp([], _input, nom, den), do: nom / den
defp fuzzy_to_crisp([fs | f_tail], [input | i_tail], nom, den) do
nom = nom + fs.mf_center * input
den = den + input
fuzzy_to_crisp(f_tail, i_tail, nom, den)
end
end