bulanik.type2
type2 ¶
Interval type-2 fuzzy sets, type reduction and inference.
An interval type-2 membership function (IT2MF) maps
\(x\) to an interval \([\underline{\mu}(x), \overline{\mu}(x)]\) of membership
degrees, written (lower, upper): the area between the two bounds is the
footprint of uncertainty (FOU). The module has
- set builders:
IT2MFfrom two type-1 functions, and the helpersgaussian_uncertain_mean,gaussian_uncertain_sigmaandscaled_triangle; IT2LinguisticVariable, a variable with interval type-2 terms;- type reduction:
type_reduceturns points with interval weights into an interval \([y_l, y_r]\) of crisp outputs (result typeTypeReduced), with the Karnik-Mendel (km), enhanced KM (ekm), Nie-Tan (nie_tan) and Begian-Melek-Mendel (bmm) methods; - systems:
IT2MamdaniFISandIT2SugenoFIS. Rules (same syntax as type-1, seeparse_rule) fire with an interval \([\underline{f}, \overline{f}]\), and the output is the midpoint of the type-reduced interval.
Rules use bulanik.inference for parsing and share its options; a system built
from IT2LinguisticVariable.from_type1
variables (no uncertainty) reproduces the type-1 result.
NoLowerFiringError ¶
Bases: ValueError
bmm type reduction needs a positive lower weight and every one is 0.
A ValueError raised by type_reduce and by
the interval type-2 systems' evaluate / evaluate_interval / explain
when type_reduction="bmm" and no rule fires with certainty (every lower
firing is 0). Use "km", "ekm" or "nie_tan" instead.
Examples:
>>> from bulanik.type2 import type_reduce
>>> type_reduce([1, 2], [0, 0], [1, 1], "bmm")
Traceback (most recent call last):
...
bulanik.type2.NoLowerFiringError: bmm needs a positive lower weight somewhere (every lower weight is 0); use 'km', 'ekm' or 'nie_tan' instead
IT2MF
dataclass
¶
IT2MF(upper: MembershipFunction, lower: MembershipFunction)
Interval type-2 membership function bounded by two type-1 functions.
Calling mf(x) returns the pair (lower, upper) of membership degrees at
x, so \(\underline{\mu}(x) \le \overline{\mu}(x)\). The region between
the two bounds is the footprint of uncertainty. A lower above the upper by
more than \(10^{-12}\) at some x raises ValueError when that x is
evaluated; float noise within that tolerance is clamped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
upper
|
MembershipFunction
|
The upper membership function \(\overline{\mu}\). |
required |
lower
|
MembershipFunction
|
The lower membership function \(\underline{\mu}\). |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Attributes:
| Name | Type | Description |
|---|---|---|
upper |
MembershipFunction
|
The upper membership function. |
lower |
MembershipFunction
|
The lower membership function. |
Examples:
>>> from bulanik.sets import triangular
>>> from bulanik.type2 import IT2MF
>>> mf = IT2MF(upper=triangular(0, 5, 10), lower=triangular(2, 5, 8))
>>> mf(5), mf(3)
((1.0, 1.0), (0.3333333333333333, 0.6))
>>> IT2MF(upper=triangular(2, 5, 8), lower=triangular(0, 5, 10))(1)
Traceback (most recent call last):
...
ValueError: lower membership 0.2 exceeds upper membership 0 at x=1
IT2LinguisticVariable ¶
IT2LinguisticVariable(name: str, universe: tuple[float, float], terms: Mapping[str, IT2MF])
A named variable on a universe (lo, hi) with interval type-2 terms.
The type-2 counterpart of LinguisticVariable;
variable["term"] returns the IT2MF.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The variable name, used in rule text. |
required |
universe
|
tuple[float, float]
|
The pair |
required |
terms
|
Mapping[str, IT2MF]
|
Mapping from term name to |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TypeError
|
If a term is not an |
Attributes:
| Name | Type | Description |
|---|---|---|
name |
The variable name. |
|
universe |
The domain as a tuple of floats. |
|
term_names |
tuple[str, ...]
|
The term names, in insertion order. |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, scaled_triangle
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> x
IT2LinguisticVariable('x', (0.0, 10.0), terms=('lo', 'hi'))
>>> x.fuzzify(2)
{'lo': (0.4, 0.8), 'hi': (0.1, 0.2)}
fuzzify ¶
fuzzify(x: float) -> dict[str, Interval]
(lower, upper) membership of x in every term.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
A crisp input inside the universe. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Interval]
|
A dict from term name to the pair |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, scaled_triangle
>>> x = IT2LinguisticVariable("x", (0, 10), {"mid": scaled_triangle(0, 5, 10, 0.8)})
>>> x.fuzzify(5)
{'mid': (0.8, 1.0)}
>>> x.fuzzify(11)
Traceback (most recent call last):
...
ValueError: 'x' input 11 is outside its universe [0, 10]
from_type1
classmethod
¶
from_type1(lv: LinguisticVariable) -> IT2LinguisticVariable
The type-1 variable as a type-2 one with no uncertainty (lower = upper).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lv
|
LinguisticVariable
|
required |
Returns:
| Type | Description |
|---|---|
IT2LinguisticVariable
|
An |
IT2LinguisticVariable
|
each term's lower and upper bound being the type-1 function. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Examples:
>>> from bulanik.sets import LinguisticVariable, linear_decreasing
>>> from bulanik.type2 import IT2LinguisticVariable
>>> lv = LinguisticVariable("x", (0, 10), {"lo": linear_decreasing(0, 10)})
>>> IT2LinguisticVariable.from_type1(lv).fuzzify(2.5)
{'lo': (0.75, 0.75)}
TypeReduced
dataclass
¶
TypeReduced(left: float, right: float, output: float, left_switch: int | None, right_switch: int | None)
Type-reduced interval [left, right] and the crisp output.
Returned by type_reduce and, per output
variable, by evaluate_interval of the interval type-2 systems.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
float
|
Left end \(y_l\) of the interval. |
required |
right
|
float
|
Right end \(y_r\). |
required |
output
|
float
|
The crisp output, the interval midpoint (for |
required |
left_switch
|
int | None
|
KM / EKM switch point of the left end, or |
required |
right_switch
|
int | None
|
KM / EKM switch point of the right end, or |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
left |
float
|
Left end of the interval. |
right |
float
|
Right end of the interval. |
output |
float
|
The crisp output. |
left_switch |
int | None
|
The 1-based position in the |
right_switch |
int | None
|
The same for the right end, where the weights switch from lower to upper instead. |
Examples:
>>> from bulanik.type2 import type_reduce
>>> r = type_reduce([1, 2, 3], [0.2, 0.3, 0.1], [0.6, 0.8, 0.5])
>>> (r.left, r.right, r.output, r.left_switch, r.right_switch)
(1.5, 2.3, 1.9, 1, 2)
IT2MamdaniFIS ¶
IT2MamdaniFIS(inputs: Sequence[IT2LinguisticVariable], outputs: Sequence[IT2LinguisticVariable], rules: Sequence[Rule | str], *, and_method: str = 'min', or_method: str = 'max', implication: str = 'min', aggregation: str = 'max', type_reduction: str = 'km', resolution: int = 1001, default: Mapping[str, float | tuple[float, float]] | None = None)
Bases: _IT2Base
Interval type-2 Mamdani system with the centroid type reducer.
Each rule fires with an interval \([\underline{f}_k, \overline{f}_k]\) (the
rule weight times the antecedent firing, computed with the lower and upper
membership bounds separately; NOT maps \([a, b]\) to \([1 - b, 1 - a]\)).
Each output universe is sampled at resolution points \(x_i\). At each
sample the upper and lower aggregated sets are
and type_reduce turns the pair into the
interval \([y_l, y_r]\) whose midpoint is the output. With lower = upper
everywhere it gives exactly the type-1 centroid. If the upper set is zero
everywhere no rule fired, and the default is returned or
NoRuleFiredError is raised. A
default value is a number or a (left, right) pair (the type-reduced
interval to report; the output is its midpoint). type_reduction="bmm"
additionally needs some rule with a positive lower firing; without one,
evaluation raises NoLowerFiringError
naming the output.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Sequence[IT2LinguisticVariable]
|
Input |
required |
outputs
|
Sequence[IT2LinguisticVariable]
|
Output interval type-2 variables (at least one; names distinct from the inputs). |
required |
rules
|
Sequence[Rule | str]
|
|
required |
and_method
|
str
|
|
'min'
|
or_method
|
str
|
|
'max'
|
implication
|
str
|
|
'min'
|
aggregation
|
str
|
|
'max'
|
type_reduction
|
str
|
|
'km'
|
resolution
|
int
|
Samples per output universe, an integer of at least 2. |
1001
|
default
|
Mapping[str, float | tuple[float, float]] | None
|
Output value, or |
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If a variable is not an |
ValueError
|
If an option name is unknown, |
Attributes:
| Name | Type | Description |
|---|---|---|
inputs |
The input variables (read-only). |
|
outputs |
The output variables (read-only). |
|
rules |
The parsed rules (read-only). |
|
and_method |
The t-norm name. |
|
or_method |
The t-conorm name. |
|
implication |
The implication name. |
|
aggregation |
The aggregation name. |
|
type_reduction |
The type reduction method. |
|
resolution |
Samples per output universe. |
|
default |
A copy of the no-fire defaults, or |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, IT2MamdaniFIS, scaled_triangle
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> tip = IT2LinguisticVariable("tip", (0, 20), {
... "low": scaled_triangle(0, 0, 10, 0.6), "high": scaled_triangle(10, 20, 20, 0.6)})
>>> fis = IT2MamdaniFIS([x], [tip], [
... "IF x IS lo THEN tip IS low", "IF x IS hi THEN tip IS high"], resolution=201)
>>> fis.evaluate({"x": 7})
{'tip': 12.01...}
>>> r = fis.evaluate_interval({"x": 7})["tip"]
>>> round(r.left, 2), round(r.right, 2)
(10.2, 13.83)
Without uncertainty the system gives the type-1 answer:
>>> from bulanik.sets import LinguisticVariable, triangular
>>> from bulanik.inference import MamdaniFIS
>>> t1x = LinguisticVariable("x", (0, 10), {"lo": triangular(0, 0, 10), "hi": triangular(0, 10, 10)})
>>> t1y = LinguisticVariable("tip", (0, 20), {"low": triangular(0, 0, 10), "high": triangular(10, 20, 20)})
>>> rules = ["IF x IS lo THEN tip IS low", "IF x IS hi THEN tip IS high"]
>>> type1 = MamdaniFIS([t1x], [t1y], rules, resolution=201).evaluate({"x": 7})
>>> type2 = IT2MamdaniFIS([IT2LinguisticVariable.from_type1(t1x)],
... [IT2LinguisticVariable.from_type1(t1y)], rules,
... resolution=201).evaluate({"x": 7})
>>> abs(type1["tip"] - type2["tip"]) < 1e-9
True
References
Mendel (2001): Uncertain Rule-Based Fuzzy Logic Systems: Introduction and New Directions.
evaluate_interval ¶
evaluate_interval(inputs: Mapping[str, float]) -> dict[str, TypeReduced]
Type-reduced interval and crisp output of every output variable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Mapping[str, float]
|
Crisp value of every input variable, by name. The keys must be exactly the input names and each value inside its universe. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, TypeReduced]
|
A dict from output variable name to its |
dict[str, TypeReduced]
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If a value is a |
ValueError
|
If an input is missing, unexpected, not finite or outside its universe. |
NoRuleFiredError
|
If no rule fires for an output and there is no
|
NoLowerFiringError
|
If |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, IT2SugenoFIS, scaled_triangle
>>> from bulanik.inference import SugenoOutput
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> y = SugenoOutput("y", {"a": 0.0, "b": 10.0})
>>> fis = IT2SugenoFIS([x], [y], ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"])
>>> r = fis.evaluate_interval({"x": 7})["y"]
>>> round(r.left, 3), round(r.right, 3), round(r.output, 3)
(5.385, 8.235, 6.81)
evaluate ¶
evaluate(inputs: Mapping[str, float]) -> dict[str, float]
Crisp outputs (the type-reduced output) for crisp inputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Mapping[str, float]
|
Crisp value of every input variable, by name. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
A dict from output variable name to its crisp value. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a value is a |
ValueError
|
If an input is missing, unexpected, not finite or outside its universe. |
NoRuleFiredError
|
If no rule fires for an output and there is no
|
NoLowerFiringError
|
If |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, IT2SugenoFIS, scaled_triangle
>>> from bulanik.inference import SugenoOutput
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> y = SugenoOutput("y", {"a": 0.0, "b": 10.0})
>>> rules = ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"]
>>> IT2SugenoFIS([x], [y], rules, type_reduction="nie_tan").evaluate({"x": 7})
{'y': 7.0}
explain ¶
explain(inputs: Mapping[str, float]) -> Explanation
Degrees (lower, upper), rule firing intervals and crisp outputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Mapping[str, float]
|
Crisp value of every input variable, by name. |
required |
Returns:
| Type | Description |
|---|---|
Explanation
|
An |
Explanation
|
|
Explanation
|
whose |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a value is a |
ValueError
|
If an input is missing, unexpected, not finite or outside its universe. |
NoRuleFiredError
|
If no rule fires for an output and there is no
|
NoLowerFiringError
|
If |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, IT2SugenoFIS, scaled_triangle
>>> from bulanik.inference import SugenoOutput
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> y = SugenoOutput("y", {"a": 0.0, "b": 10.0})
>>> fis = IT2SugenoFIS([x], [y], ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"])
>>> info = fis.explain({"x": 7})
>>> info.degrees["x"]
{'lo': (0.15, 0.3), 'hi': (0.35, 0.7)}
>>> info.activations[1].strength
(0.35, 0.7)
IT2SugenoFIS ¶
IT2SugenoFIS(inputs: Sequence[IT2LinguisticVariable], outputs: Sequence[SugenoOutput], rules: Sequence[Rule | str], *, and_method: str = 'min', or_method: str = 'max', type_reduction: str = 'km', default: Mapping[str, float | tuple[float, float]] | None = None)
Bases: _IT2Base
Interval type-2 Sugeno system with the centre-of-sets type reducer.
Each fired rule \(k\) gives \(z_k\) (a constant or a
Linear of the inputs) with firing
interval \([\underline{f}_k, \overline{f}_k]\); the type-reduced interval is
type_reduce([z_k], [f_lower_k], [f_upper_k]) and the output its midpoint.
When no rule fires for an output (all upper firings are 0) the default
(a number or a (left, right) pair) is returned or
NoRuleFiredError is raised.
type_reduction="bmm" needs some positive lower firing, else
NoLowerFiringError is raised.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Sequence[IT2LinguisticVariable]
|
Input |
required |
outputs
|
Sequence[SugenoOutput]
|
|
required |
rules
|
Sequence[Rule | str]
|
|
required |
and_method
|
str
|
|
'min'
|
or_method
|
str
|
|
'max'
|
type_reduction
|
str
|
|
'km'
|
default
|
Mapping[str, float | tuple[float, float]] | None
|
Output value, or |
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If a variable has the wrong class or a rule is neither a
|
ValueError
|
If an option name is unknown, there are no inputs, outputs
or rules, a variable name is duplicated, a rule names an unknown
variable or term, a |
Attributes:
| Name | Type | Description |
|---|---|---|
inputs |
The input variables (read-only). |
|
outputs |
The output variables (read-only). |
|
rules |
The parsed rules (read-only). |
|
and_method |
The t-norm name. |
|
or_method |
The t-conorm name. |
|
type_reduction |
The type reduction method. |
|
default |
A copy of the no-fire defaults, or |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, IT2SugenoFIS, scaled_triangle
>>> from bulanik.inference import SugenoOutput
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> y = SugenoOutput("y", {"a": 0.0, "b": 10.0})
>>> fis = IT2SugenoFIS([x], [y], ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"])
>>> fis.evaluate({"x": 7})
{'y': 6.809...}
>>> fis.evaluate_interval({"x": 7})["y"].left_switch
1
evaluate_interval ¶
evaluate_interval(inputs: Mapping[str, float]) -> dict[str, TypeReduced]
Type-reduced interval and crisp output of every output variable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Mapping[str, float]
|
Crisp value of every input variable, by name. The keys must be exactly the input names and each value inside its universe. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, TypeReduced]
|
A dict from output variable name to its |
dict[str, TypeReduced]
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If a value is a |
ValueError
|
If an input is missing, unexpected, not finite or outside its universe. |
NoRuleFiredError
|
If no rule fires for an output and there is no
|
NoLowerFiringError
|
If |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, IT2SugenoFIS, scaled_triangle
>>> from bulanik.inference import SugenoOutput
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> y = SugenoOutput("y", {"a": 0.0, "b": 10.0})
>>> fis = IT2SugenoFIS([x], [y], ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"])
>>> r = fis.evaluate_interval({"x": 7})["y"]
>>> round(r.left, 3), round(r.right, 3), round(r.output, 3)
(5.385, 8.235, 6.81)
evaluate ¶
evaluate(inputs: Mapping[str, float]) -> dict[str, float]
Crisp outputs (the type-reduced output) for crisp inputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Mapping[str, float]
|
Crisp value of every input variable, by name. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
A dict from output variable name to its crisp value. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a value is a |
ValueError
|
If an input is missing, unexpected, not finite or outside its universe. |
NoRuleFiredError
|
If no rule fires for an output and there is no
|
NoLowerFiringError
|
If |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, IT2SugenoFIS, scaled_triangle
>>> from bulanik.inference import SugenoOutput
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> y = SugenoOutput("y", {"a": 0.0, "b": 10.0})
>>> rules = ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"]
>>> IT2SugenoFIS([x], [y], rules, type_reduction="nie_tan").evaluate({"x": 7})
{'y': 7.0}
explain ¶
explain(inputs: Mapping[str, float]) -> Explanation
Degrees (lower, upper), rule firing intervals and crisp outputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Mapping[str, float]
|
Crisp value of every input variable, by name. |
required |
Returns:
| Type | Description |
|---|---|
Explanation
|
An |
Explanation
|
|
Explanation
|
whose |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a value is a |
ValueError
|
If an input is missing, unexpected, not finite or outside its universe. |
NoRuleFiredError
|
If no rule fires for an output and there is no
|
NoLowerFiringError
|
If |
Examples:
>>> from bulanik.type2 import IT2LinguisticVariable, IT2SugenoFIS, scaled_triangle
>>> from bulanik.inference import SugenoOutput
>>> x = IT2LinguisticVariable("x", (0, 10), {
... "lo": scaled_triangle(0, 0, 10, 0.5), "hi": scaled_triangle(0, 10, 10, 0.5)})
>>> y = SugenoOutput("y", {"a": 0.0, "b": 10.0})
>>> fis = IT2SugenoFIS([x], [y], ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"])
>>> info = fis.explain({"x": 7})
>>> info.degrees["x"]
{'lo': (0.15, 0.3), 'hi': (0.35, 0.7)}
>>> info.activations[1].strength
(0.35, 0.7)
gaussian_uncertain_mean ¶
gaussian_uncertain_mean(mean_low: float, mean_high: float, sigma: float) -> IT2MF
Gaussian with a mean anywhere in \([m_1, m_2]\) (Mendel 2001).
With \(g(x; m) = \exp\bigl(-(x - m)^2 / (2\sigma^2)\bigr)\), the upper bound is 1 on \([m_1, m_2]\) and the Gaussian of the nearer mean outside it; the lower bound is \(\min\bigl(g(x; m_1), g(x; m_2)\bigr)\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mean_low
|
float
|
Left end \(m_1\) of the mean interval. |
required |
mean_high
|
float
|
Right end \(m_2\), with \(m_1 \le m_2\). |
required |
sigma
|
float
|
Common standard deviation, positive. |
required |
Returns:
| Type | Description |
|---|---|
IT2MF
|
The interval type-2 membership function. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
>>> from bulanik.type2 import gaussian_uncertain_mean
>>> mf = gaussian_uncertain_mean(4, 6, 1.5)
>>> mf(5)
(0.800..., 1.0)
>>> mf(8)
(0.0285..., 0.411...)
References
Mendel (2001): Uncertain Rule-Based Fuzzy Logic Systems: Introduction and New Directions.
gaussian_uncertain_sigma ¶
gaussian_uncertain_sigma(mean: float, sigma_low: float, sigma_high: float) -> IT2MF
Gaussian with a width anywhere in \([\sigma_1, \sigma_2]\).
The upper bound is the Gaussian with \(\sigma_2\) and the lower bound the Gaussian with \(\sigma_1\), both with the same mean.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mean
|
float
|
The centre. |
required |
sigma_low
|
float
|
Smallest width \(\sigma_1\), positive. |
required |
sigma_high
|
float
|
Largest width \(\sigma_2\), with \(\sigma_1 \le \sigma_2\). |
required |
Returns:
| Type | Description |
|---|---|
IT2MF
|
The interval type-2 membership function. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
>>> from bulanik.type2 import gaussian_uncertain_sigma
>>> mf = gaussian_uncertain_sigma(5, 1, 2)
>>> mf(6)
(0.606..., 0.882...)
>>> gaussian_uncertain_sigma(5, 2, 1)
Traceback (most recent call last):
...
ValueError: gaussian_uncertain_sigma needs 0 < sigma_low <= sigma_high, got 2, 1
scaled_triangle ¶
scaled_triangle(a: float, b: float, c: float, height: float) -> IT2MF
Triangle \(\operatorname{tri}(a, b, c)\) over a lower triangle \(h \cdot \operatorname{tri}(a, b, c)\).
The upper bound is the triangular function with feet a, c and peak b;
the lower bound is the same triangle scaled to height \(h\), \(0 < h \le 1\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
float
|
Left foot. |
required |
b
|
float
|
Peak. |
required |
c
|
float
|
Right foot, with |
required |
height
|
float
|
Height \(h\) of the lower triangle, in \((0, 1]\). |
required |
Returns:
| Type | Description |
|---|---|
IT2MF
|
The interval type-2 membership function. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the points are not ordered or |
Examples:
>>> from bulanik.type2 import scaled_triangle
>>> mf = scaled_triangle(0, 5, 10, 0.6)
>>> mf(5), mf(2.5)
((0.6, 1.0), (0.3, 0.5))
type_reduce ¶
type_reduce(ys: Sequence[float], lower: Sequence[float], upper: Sequence[float], method: str = 'km', *, bmm_m: float = 0.5, bmm_n: float = 0.5) -> TypeReduced
Reduce points ys with interval weights [lower, upper] to a crisp value.
Each point \(y_i\) may carry any weight \(w_i \in [\underline{w}_i, \overline{w}_i]\). The centroid interval is
and the methods are
"km"(Karnik and Mendel 2001) and"ekm"(enhanced KM, Wu and Mendel 2009) find the exact \([y_l, y_r]\); the output is its midpoint. Both converge to the same endpoints, but only up to rounding (about 1 ulp), and on plateaus (equalysor equal weights) they may stop at different, equally optimal switch indices."nie_tan"(Nie and Tan 2008) is the closed form \(\sum_i y_i (\underline{w}_i + \overline{w}_i) / \sum_i (\underline{w}_i + \overline{w}_i)\), withleft == right == output."bmm"(Begian, Melek and Mendel 2008) is \(m\,\bar y_{\text{lower}} + n\,\bar y_{\text{upper}}\), the combination of the weighted averages with the lower and with the upper weights;left/rightare the two averages, sorted.bmm_mandbmm_nonly have to be finite: they are deliberately unconstrained (the usual choice is \(m = n = 0.5\), but neither sign nor \(m + n = 1\) is enforced, so the output may fall outside[left, right]). It needs some positive lower weight.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ys
|
Sequence[float]
|
The points. |
required |
lower
|
Sequence[float]
|
Lower weight of each point. |
required |
upper
|
Sequence[float]
|
Upper weight of each point. |
required |
method
|
str
|
|
'km'
|
bmm_m
|
float
|
Factor \(m\) of the lower average ( |
0.5
|
bmm_n
|
float
|
Factor \(n\) of the upper average ( |
0.5
|
Returns:
| Type | Description |
|---|---|
TypeReduced
|
A |
TypeReduced
|
crisp output. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a point or weight is a |
ValueError
|
If |
NoLowerFiringError
|
If |
Examples:
>>> from bulanik.type2 import type_reduce
>>> ys, lo, hi = [1, 2, 3], [0.2, 0.3, 0.1], [0.6, 0.8, 0.5]
>>> r = type_reduce(ys, lo, hi)
>>> (r.left, r.right, r.output)
(1.5, 2.3, 1.9)
>>> type_reduce(ys, lo, hi, "nie_tan").output
1.92
>>> type_reduce(ys, [0.5] * 3, [0.5] * 3).output
2.0
References
Karnik and Mendel (2001): "Centroid of a type-2 fuzzy set", Information Sciences. Wu and Mendel (2009): "Enhanced Karnik-Mendel algorithms", IEEE Transactions on Fuzzy Systems. Nie and Tan (2008): "Towards an efficient type-reduction method for interval type-2 fuzzy logic systems", FUZZ-IEEE. Begian, Melek and Mendel (2008): "Stability analysis of type-2 fuzzy systems", IEEE International Conference on Fuzzy Systems (FUZZ-IEEE), 947-953 (the BMM reducer).