Current section
Files
Jump to
Current section
Files
test/rule_test.exs
defmodule RuleTest do
use ExUnit.Case
import Flex.Rule
alias Flex.{Rule, Set, Variable}
doctest Flex
setup do
t_h = Set.new(tag: "too hot", mf_type: "saturation", mf_params: [-2, 0, -4])
j_r = Set.new(tag: "just right", mf_type: "triangle", mf_params: [-2, 0, 2])
t_c = Set.new(tag: "too cold", mf_type: "shoulder", mf_params: [0, 2, 4])
fuzzy_sets = [t_h, j_r, t_c]
error = Variable.new(tag: "error", fuzzy_sets: fuzzy_sets, type: :antecedent, range: -4..4)
t_h = Set.new(tag: "getting hotter", mf_type: "saturation", mf_params: [-5, 0, -10])
j_r = Set.new(tag: "no change", mf_type: "triangle", mf_params: [-5, 0, 5])
t_c = Set.new(tag: "getting colder", mf_type: "shoulder", mf_params: [0, 5, 10])
fuzzy_sets = [t_h, j_r, t_c]
dt_error =
Variable.new(tag: "dt_error", fuzzy_sets: fuzzy_sets, type: :antecedent, range: -10..10)
t_h = Set.new(tag: "cool", mf_type: "saturation", mf_params: [-50, 0, -100])
j_r = Set.new(tag: "do nothing", mf_type: "triangle", mf_params: [-50, 0, 50])
t_c = Set.new(tag: "heat", mf_type: "shoulder", mf_params: [0, 50, 100])
fuzzy_sets = [t_h, j_r, t_c]
output =
Variable.new(tag: "output", fuzzy_sets: fuzzy_sets, type: :consequent, range: -100..100)
%{ant: [error, dt_error], cons: output}
end
test "tau 'fuzzy and (product)' operator", %{ant: [error, _dt_error], cons: _output} do
n_error = Variable.fuzzification(error, -1)
assert n_error ~> "just right" == 0.5
assert tau(n_error ~> "just right", 0.3) == 0.15
end
test "&&& 'fuzzy and' operator", %{ant: [error, _dt_error], cons: _output} do
n_error = Variable.fuzzification(error, -1)
assert n_error ~> "just right" &&& 0.3 == 0.3
end
test "||| 'fuzzy or' operator", %{ant: [error, _dt_error], cons: _output} do
n_error = Variable.fuzzification(error, -1)
assert (n_error ~> "just right" ||| 0.3) == 0.5
end
test " ~> 'is' operator for antecedent var", %{ant: [error, _dt_error], cons: _output} do
n_error = Variable.fuzzification(error, -1)
assert n_error ~> "just right" == 0.5
end
test " ~> 'is' operator for consequent vars", %{ant: [_error, _dt_error], cons: output} do
output = %{output | rule_output: 0.75}
n_output = output ~> "just right"
assert n_output.mf_values["just right"] == [0.75]
n_output = n_output ~> "just right"
assert n_output.mf_values["just right"] == [0.75, 0.75]
end
test " >>> 'then' operator for antecedent vars", %{ant: [error, _dt_error], cons: _output} do
assert_raise RuntimeError, ~r/^only the consequent variable can use the THEN operation/, fn ->
1 >>> error
end
end
test " >>> 'then' operator for consequent vars", %{ant: [_error, _dt_error], cons: output} do
d_output = %{output | rule_output: 0.75}
assert 0.75 >>> output == d_output
end
test "fuzzy operators with lambdas", %{ant: [error, dt_error], cons: output} do
n_error = Variable.fuzzification(error, -1)
n_dt_error = Variable.fuzzification(dt_error, -2.5)
r1 = fn [at1, at2, con] ->
(at1 ~> "too hot" &&& at2 ~> "getting colder") >>> con ~> "cool"
end
r2 = fn [at1, at2, con] ->
(at1 ~> "too hot" &&& at2 ~> "no change") >>> con ~> "cool"
end
r3 = fn [at1, at2, con] ->
(at1 ~> "too hot" &&& at2 ~> "no change") >>> con ~> "heat"
end
output = r1.([n_error, n_dt_error, output])
assert output.mf_values["cool"] == [0]
output = r2.([n_error, n_dt_error, output])
assert output.mf_values["cool"] == [0, 0.5]
output = r3.([n_error, n_dt_error, output])
assert output.mf_values["heat"] == [0.5]
end
test "new Rule", %{ant: [error, dt_error], cons: output} do
n_error = Variable.fuzzification(error, -1)
n_dt_error = Variable.fuzzification(dt_error, -2.5)
r1 = fn [at1, at2, con] ->
(at1 ~> "too hot" &&& at2 ~> "getting colder") >>> con ~> "cool"
end
rule1 =
Rule.new(statement: r1, consequent: output.tag, antecedent: [n_error.tag, n_dt_error.tag])
assert rule1.antecedent == ["error", "dt_error"]
assert rule1.consequent == "output"
output = rule1.statement.([n_error, n_dt_error, output])
assert output.mf_values["cool"] == [0]
end
end