Skip to content

bulanik.numbers

numbers

Fuzzy number types.

Every type implements the common interface of FuzzyNumber: the operations add, mul, scale and power, and score, accuracy and distance. Operations are selected by name (ops="algebraic", plus "einstein" for orthopair numbers), and combining numbers of different types raises TypeError.

Triangular and trapezoidal numbers (TFN, TrFN)
Ordered points on the real line; closed under the operators of interval arithmetic on alpha-cuts.
Orthopair numbers (QROFN, IFN, PFN, FFN)
A pair \((\mu, \nu)\) with \(\mu^q + \nu^q \le 1\) for rung \(q\) (\(q = 1\) intuitionistic, \(q = 2\) Pythagorean, \(q = 3\) Fermatean).
Interval-valued orthopair numbers (IVQROFN, IVIFN, IVPFN, IVFFN)
A membership interval and a non-membership interval with \(\mu_U^q + \nu_U^q \le 1\); the point laws of the orthopair numbers act on the lower and the upper pair.
Three-part numbers (SphericalFN, PictureFN, NeutrosophicFN)
A triple of membership, neutral/hesitant and non-membership parts.
Interval neutrosophic numbers (IVNeutrosophicFN)
Intervals of truth, indeterminacy and falsity; the laws of NeutrosophicFN act on the lower and the upper bounds.
Interval type-2 trapezoids (IT2TrFN)
An upper and a lower generalised trapezoid (the footprint of uncertainty); the type-1 rules act on both and the heights combine with min.

Examples:

>>> from bulanik.numbers import TFN, IFN
>>> TFN(1, 2, 3) + TFN(2, 3, 4)
TFN(l=3.0, m=5.0, u=7.0)
>>> IFN(0.6, 0.3).score()
0.3

FuzzyNumber

Bases: ABC

Common interface of fuzzy numbers.

The base assumes nothing about how many parts a number has, so interval-valued and type-2 numbers can implement it too. Subclasses declare which operator sets, scores, accuracy functions and distances they support in the class attributes below; the ops, method and score arguments of the methods are validated against them.

Operators +, * (number or scalar), ** (scalar) and, for triangular numbers, -, / and unary -, call the default ("algebraic") operator set.

Attributes:

Name Type Description
OPS tuple[str, ...]

Names of the supported operator sets; the first is the default.

SCORES tuple[str, ...]

Names of the supported score functions.

DEFAULT_SCORE str | None

Score used when score() gets no method.

ACCURACIES tuple[str, ...]

Names of the supported accuracy functions (may be empty).

DEFAULT_ACCURACY str | None

Accuracy used when accuracy() gets no method.

DISTANCES tuple[str, ...]

Names of the supported distance measures.

DEFAULT_DISTANCE str | None

Distance used when distance() gets no method.

Examples:

>>> from bulanik import TFN, IFN
>>> TFN.OPS
('algebraic',)
>>> IFN.OPS
('algebraic', 'einstein')
>>> TFN(1, 2, 3) + IFN(0.5, 0.4)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'TFN' and 'IFN'

add abstractmethod

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type.

Parameters:

Name Type Description Default
other Any

A number of the same type (and the same q, if any).

required
ops str

Operator set name, one of OPS.

'algebraic'

Returns:

Type Description
Any

The sum, a number of the same type.

Raises:

Type Description
TypeError

If other is of a different type or rung.

ValueError

If ops is not a supported operator set.

mul abstractmethod

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type.

Parameters:

Name Type Description Default
other Any

A number of the same type (and the same q, if any).

required
ops str

Operator set name, one of OPS.

'algebraic'

Returns:

Type Description
Any

The product, a number of the same type.

Raises:

Type Description
TypeError

If other is of a different type or rung.

ValueError

If ops is not a supported operator set.

scale abstractmethod

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (repeated addition, extended to real k).

Parameters:

Name Type Description Default
k float

The scalar. Orthopair and three-part numbers need k >= 0.

required
ops str

Operator set name, one of OPS.

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same type.

Raises:

Type Description
ValueError

If k is not finite, is negative for a type that needs k >= 0, or ops is unsupported.

power abstractmethod

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (repeated multiplication, extended to real k).

Parameters:

Name Type Description Default
k float

The exponent. Orthopair and three-part numbers need k >= 0.

required
ops str

Operator set name, one of OPS.

'algebraic'

Returns:

Type Description
Any

The power, of the same type.

Raises:

Type Description
ValueError

If k is not finite, is out of range for the type, or ops is unsupported.

score abstractmethod

score(method: str | None = None) -> float

Crisp score used for ranking.

Parameters:

Name Type Description Default
method str | None

One of SCORES; None selects DEFAULT_SCORE.

None

Returns:

Type Description
float

The score as a float.

Raises:

Type Description
ValueError

If method is not one of SCORES.

accuracy abstractmethod

accuracy(method: str | None = None) -> float

Accuracy (certainty) function, used to break ties between equal scores.

Parameters:

Name Type Description Default
method str | None

One of ACCURACIES; None selects DEFAULT_ACCURACY.

None

Returns:

Type Description
float

The accuracy as a float.

Raises:

Type Description
ValueError

If method is not one of ACCURACIES, or the type has no accuracy function (triangular and trapezoidal numbers).

distance abstractmethod

distance(other: Any, method: str | None = None) -> float

Distance to another number of the same type.

Parameters:

Name Type Description Default
other Any

A number of the same type (and the same q, if any).

required
method str | None

One of DISTANCES; None selects DEFAULT_DISTANCE.

None

Returns:

Type Description
float

A non-negative float.

Raises:

Type Description
TypeError

If other is of a different type or rung.

ValueError

If method is not one of DISTANCES.

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

IT2TrFN dataclass

IT2TrFN(upper: _Six, lower: _Six)

Bases: FuzzyNumber

Interval type-2 trapezoidal fuzzy number \((\tilde A^U, \tilde A^L)\).

Each of upper and lower holds \((a_1, a_2, a_3, a_4, h_1, h_2)\) with \(a_1 \le a_2 \le a_3 \le a_4\); \(h_1\) is the membership at \(a_2\) and \(h_2\) the membership at \(a_3\). Following Chen and Lee (2010a) every operation applies the type-1 rule to the upper and to the lower trapezoid, and the heights combine with min:

  • sum: points add; difference: \((a_1 - b_4, a_2 - b_3, a_3 - b_2, a_4 - b_1)\);
  • product: componentwise, for non-negative points;
  • scalar \(k\): points times \(k\), heights unchanged (for \(k < 0\) the points reverse and \(h_1, h_2\) swap);
  • power \(k\): points to the power \(k\), heights unchanged (for \(k < 0\) the points reverse and the heights swap). The product and power give the geometric mean \((\prod \tilde a_i)^{1/n}\) of Kahraman et al. (2014).

Scores (default "dtrat"):

  • "dtrat", the defuzzification DTraT of Kahraman et al. (2014), \(\tfrac12 \sum_{X \in \{U, L\}} \Big[\dfrac{(a^X_4 - a^X_1) + (h^X_1 a^X_2 - a^X_1) + (h^X_2 a^X_3 - a^X_1)}{4} + a^X_1\Big]\); for a type-1 trapezoid (heights 1, upper = lower) it is the mean of the four points.
  • "centroid": the mean of the x-centroids of the upper and the lower polygon \((a_1, 0), (a_2, h_1), (a_3, h_2), (a_4, 0)\) (shoelace formula; the mean of the points if the polygon has zero area). This is bulanik's own choice and not the Karnik-Mendel centroid of the type-2 set.
  • "chen_lee", the ranking value of Chen and Lee (2010a), \(\sum_{X \in \{U, L\}} \Big[\sum_{p=1}^{3} M_p(X) - \tfrac14 \sum_{q=1}^{4} S_q(X) + h_1(X) + h_2(X)\Big]\) with \(M_p = (a_p + a_{p+1})/2\), \(S_q\) (\(q \le 3\)) the population standard deviation of \(\{a_q, a_{q+1}\}\) and \(S_4\) that of \(\{a_1, \dots, a_4\}\).

There is no accuracy function. The only distance is "vertex", \(\sqrt{\tfrac18 \sum (\Delta a)^2}\) over the 8 points of the two trapezoids; heights are ignored.

Validation: points are finite and ordered, heights lie in \([0, 1]\) (out by at most \(10^{-12}\) they are projected) and the upper trapezoid has \(\max(h_1, h_2) > 0\). The lower trapezoid must be nested in the upper one (up to \(10^{-12}\)): \(a^U_1 \le a^L_1 \le a^L_2 \le a^L_3 \le a^L_4 \le a^U_4\), \(a^U_2 \le a^L_2\), \(a^L_3 \le a^U_3\) and \(h^L_1, h^L_2 \le \min(h^U_1, h^U_2)\). The violated inequality is named in the ValueError. Nesting implies that the lower membership never exceeds the upper one (on each rising or falling edge both curves are linear up to the upper core, where the upper membership is at least \(\min(h^U_1, h^U_2) \ge h^L\)), and it is preserved by the sum, difference, non-negative product, scalar and power (each acts monotonically on the reference points, and the heights take min), so arithmetic never leaves the class. General containment is slightly weaker, but the sum of two merely contained numbers can leave the footprint constraint, so it is not enough for a closed arithmetic. The nesting is the usual assumption of the interval type-2 MCDM literature (the linguistic scales of Chen and Lee 2010b and Kahraman et al. 2014 satisfy it). The lower heights are compared with \(\min(h^U_1, h^U_2)\) and not point by point, because the upper membership between the two inner points is only known to be at least that minimum.

Parameters:

Name Type Description Default
upper _Six

The six values of the upper trapezoid.

required
lower _Six

The six values of the lower trapezoid.

required

Raises:

Type Description
ValueError

If a sequence does not have six values, a value is NaN or infinite, the points are unordered, a height is outside \([0, 1]\), the upper heights are both 0, or the lower membership exceeds the upper.

TypeError

If a value is a bool or a string.

Attributes:

Name Type Description
upper _Six

The upper trapezoid \((a_1, a_2, a_3, a_4, h_1, h_2)\).

lower _Six

The lower trapezoid.

References

Chen and Lee (2010a), Expert Systems with Applications 37(1), 824-833, doi:10.1016/j.eswa.2009.06.094 (arithmetic and ranking value). Chen and Lee (2010b), Expert Systems with Applications 37(4), 2790-2798, doi:10.1016/j.eswa.2009.09.012 (IT2 TOPSIS, linguistic scale). Kahraman, Oztaysi, Ucal Sari and Turanoglu (2014), Knowledge-Based Systems 59, 48-57, doi:10.1016/j.knosys.2014.02.001 (DTraT, IT2 AHP). Mendel, John and Liu (2006), IEEE Transactions on Fuzzy Systems 14(6), 808-821 (terminology).

Examples:

>>> from bulanik import IT2TrFN
>>> low = IT2TrFN((0, 0.1, 0.1, 0.3, 1, 1), (0.05, 0.1, 0.1, 0.2, 0.9, 0.9))
>>> (low + low).upper
(0.0, 0.2, 0.2, 0.6, 1.0, 1.0)
>>> round(low.score(), 5)
0.11625
>>> IT2TrFN((0, 1, 2, 3, 0.5, 0.5), (0.5, 1, 2, 2.5, 0.9, 0.9))
Traceback (most recent call last):
...
ValueError: IT2TrFN needs nested reference points: h1L <= min(h1U, h2U), got 0.9 > 0.5

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

from_trfn classmethod

from_trfn(x: 'TrFN | TFN') -> 'IT2TrFN'

The type-1 number \(x\) as an IT2 number: upper = lower = \((\text{points}; 1, 1)\).

Parameters:

Name Type Description Default
x 'TrFN | TFN'

A TrFN or TFN.

required

Returns:

Type Description
'IT2TrFN'

The IT2 number with a zero-width footprint.

Raises:

Type Description
TypeError

If x is neither a TrFN nor a TFN.

Examples:

>>> from bulanik import IT2TrFN, TrFN
>>> IT2TrFN.from_trfn(TrFN(1, 2, 3, 5)).upper
(1.0, 2.0, 3.0, 5.0, 1.0, 1.0)

add

add(other: Any, ops: str = 'algebraic') -> 'IT2TrFN'

Sum: points add, heights take the minimum (Chen and Lee 2010a).

Parameters:

Name Type Description Default
other Any

An IT2TrFN.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IT2TrFN'

The sum.

Raises:

Type Description
TypeError

If other is not an IT2TrFN.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IT2TrFN
>>> a = IT2TrFN((0, 1, 2, 3, 1, 1), (0.5, 1, 2, 2.5, 0.8, 0.8))
>>> (a + a).lower
(1.0, 2.0, 4.0, 5.0, 0.8, 0.8)

sub

sub(other: Any, ops: str = 'algebraic') -> 'IT2TrFN'

Difference \((a_1 - b_4, a_2 - b_3, a_3 - b_2, a_4 - b_1)\) per trapezoid; A - B calls it.

Parameters:

Name Type Description Default
other Any

An IT2TrFN.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IT2TrFN'

The difference; heights take the minimum.

Raises:

Type Description
TypeError

If other is not an IT2TrFN.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IT2TrFN
>>> a = IT2TrFN((1, 2, 3, 4, 1, 1), (1, 2, 3, 4, 1, 1))
>>> (a - a).upper
(-3.0, -1.0, 1.0, 3.0, 1.0, 1.0)

mul

mul(other: Any, ops: str = 'algebraic') -> 'IT2TrFN'

Product: componentwise on the points, heights take the minimum (Chen and Lee 2010a).

Parameters:

Name Type Description Default
other Any

An IT2TrFN with all points \(\ge 0\) (as self).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IT2TrFN'

The product.

Raises:

Type Description
TypeError

If other is not an IT2TrFN.

ValueError

If ops is unknown, a point of either operand is negative.

Examples:

>>> from bulanik import IT2TrFN
>>> a = IT2TrFN((1, 2, 3, 4, 1, 1), (1.5, 2, 3, 3.5, 0.8, 0.8))
>>> (a * a).upper
(1.0, 4.0, 9.0, 16.0, 1.0, 1.0)

scale

scale(k: float, ops: str = 'algebraic') -> 'IT2TrFN'

Multiply the points by the real k; heights stay, and swap for \(k < 0\).

Parameters:

Name Type Description Default
k float

The scalar.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IT2TrFN'

The scaled number.

Raises:

Type Description
TypeError

If k is a bool or a string.

ValueError

If k is not finite or ops is unknown.

Examples:

>>> from bulanik import IT2TrFN
>>> a = IT2TrFN((0, 1, 2, 3, 1, 0.5), (0.5, 1, 2, 2.5, 0.5, 0.4))
>>> a.scale(-1).upper
(-3.0, -2.0, -1.0, -0.0, 0.5, 1.0)

power

power(k: float, ops: str = 'algebraic') -> 'IT2TrFN'

Raise the points to the real power k; heights stay (swap for \(k < 0\)); A ** k calls it.

Parameters:

Name Type Description Default
k float

The exponent.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IT2TrFN'

The power.

Raises:

Type Description
TypeError

If k is a bool or a string.

ValueError

If k is not finite, ops is unknown, the lowest point is negative (zero for \(k < 0\)) or the power overflows.

Examples:

>>> from bulanik import IT2TrFN
>>> a = IT2TrFN((1, 2, 3, 4, 1, 1), (1.5, 2, 3, 3.5, 0.8, 0.8))
>>> (a ** 2).upper
(1.0, 4.0, 9.0, 16.0, 1.0, 1.0)

score

score(method: str | None = None) -> float

Crisp score: "dtrat" (default), "centroid" or "chen_lee"; see the class docstring.

Parameters:

Name Type Description Default
method str | None

One of "dtrat", "centroid", "chen_lee"; None means "dtrat".

None

Returns:

Type Description
float

The score. "dtrat" and "centroid" are on the scale of the points;

float

"chen_lee" also adds the heights and is only meaningful for ranking.

Raises:

Type Description
ValueError

If method is not one of the three names.

Examples:

>>> from bulanik import IT2TrFN
>>> a = IT2TrFN((1, 2, 3, 5, 1, 1), (1, 2, 3, 5, 1, 1))
>>> a.score()
2.75
>>> round(a.score("chen_lee"), 4)
18.2605

accuracy

accuracy(method: str | None = None) -> float

Not defined for IT2TrFN.

Parameters:

Name Type Description Default
method str | None

Ignored.

None

Raises:

Type Description
ValueError

Always.

Examples:

>>> from bulanik import IT2TrFN
>>> IT2TrFN((0, 1, 2, 3, 1, 1), (0, 1, 2, 3, 1, 1)).accuracy()
Traceback (most recent call last):
...
ValueError: IT2TrFN has no accuracy function

distance

distance(other: Any, method: str | None = None) -> float

Vertex distance \(\sqrt{\tfrac18 \sum (\Delta a)^2}\) over the eight points; heights are ignored.

Parameters:

Name Type Description Default
other Any

An IT2TrFN.

required
method str | None

Only "vertex" exists.

None

Returns:

Type Description
float

The distance.

Raises:

Type Description
TypeError

If other is not an IT2TrFN.

ValueError

If method is not "vertex".

Examples:

>>> from bulanik import IT2TrFN
>>> a = IT2TrFN((0, 1, 2, 3, 1, 1), (0, 1, 2, 3, 1, 1))
>>> b = IT2TrFN((1, 2, 3, 4, 1, 1), (1, 2, 3, 4, 1, 1))
>>> a.distance(b)
1.0

IVNeutrosophicFN dataclass

IVNeutrosophicFN(t_l: float, t_u: float, i_l: float, i_u: float, f_l: float, f_u: float)

Bases: FuzzyNumber

Interval neutrosophic number \(\langle [t_L, t_U], [i_L, i_U], [f_L, f_U] \rangle\).

With \(\oplus\), \(\otimes\) the laws of NeutrosophicFN applied to the lower and to the upper triple separately:

operation \(T\) \(I\) \(F\)
add \([t^L_1 + t^L_2 - t^L_1 t^L_2,\ t^U_1 + t^U_2 - t^U_1 t^U_2]\) \([i^L_1 i^L_2,\ i^U_1 i^U_2]\) \([f^L_1 f^L_2,\ f^U_1 f^U_2]\)
mul \([t^L_1 t^L_2,\ t^U_1 t^U_2]\) \([i^L_1 + i^L_2 - i^L_1 i^L_2,\ \dots]\) \([f^L_1 + f^L_2 - f^L_1 f^L_2,\ \dots]\)
scale by \(k\) \([1 - (1 - t_L)^k,\ 1 - (1 - t_U)^k]\) \([i_L^k,\ i_U^k]\) \([f_L^k,\ f_U^k]\)
power by \(k\) \([t_L^k,\ t_U^k]\) \([1 - (1 - i_L)^k,\ \dots]\) \([1 - (1 - f_L)^k,\ \dots]\)

Score ("average", the only one, default): \(S = \tfrac16\left(4 + t_L + t_U - i_L - i_U - f_L - f_U\right)\), the NeutrosophicFN score \((2 + t - i - f)/3\) on the interval midpoints. Zhang et al. (2014, Definition 18) define an interval-valued score \([t_L + 2 - i_U - f_U,\ t_U + 2 - i_L - f_L]\); its midpoint is \(3S\), so "average" ranks exactly as the midpoint of that interval does.

Accuracy: "difference" (default) \(\tfrac12(t_L + t_U - f_L - f_U)\) or "certainty" \(\tfrac12(t_L + t_U)\) (midpoints of the accuracy and certainty intervals of Zhang et al. 2014). Distances (default "hamming") work on the six bounds: Hamming \(= \tfrac16 \sum |\Delta|\) and Euclidean \(= \sqrt{\tfrac16 \sum \Delta^2}\). For degenerate intervals all of these equal the NeutrosophicFN values.

Inversions \(t_L > t_U\) (likewise \(i\), \(f\)) of up to \(10^{-12}\) are clamped (lower := upper); larger ones raise ValueError.

Parameters:

Name Type Description Default
t_l float

Lower truth bound in \([0, 1]\).

required
t_u float

Upper truth bound in \([0, 1]\).

required
i_l float

Lower indeterminacy bound in \([0, 1]\).

required
i_u float

Upper indeterminacy bound in \([0, 1]\).

required
f_l float

Lower falsity bound in \([0, 1]\).

required
f_u float

Upper falsity bound in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a bound is outside \([0, 1]\) or not finite, or a lower bound exceeds its upper bound beyond rounding.

TypeError

If a bound is a bool or a string.

Attributes:

Name Type Description
t_l float

Lower truth bound.

t_u float

Upper truth bound.

i_l float

Lower indeterminacy bound.

i_u float

Upper indeterminacy bound.

f_l float

Lower falsity bound.

f_u float

Upper falsity bound.

References

Wang, Smarandache, Zhang and Sunderraman (2005), Interval Neutrosophic Sets and Logic: Theory and Applications in Computing, Hexis, Phoenix (definition, complement). Zhang, Wang and Chen (2014), The Scientific World Journal 2014, article 645953, doi:10.1155/2014/645953 (operations, score, INNWA and INNWG operators). The paper prints the addition and product with two typos (a \(T\) in place of an \(I\) index); the code follows the general t-norm forms of the same paper.

Examples:

>>> from bulanik import IVNeutrosophicFN
>>> a = IVNeutrosophicFN(0.6, 0.7, 0.1, 0.2, 0.2, 0.3)
>>> round(a.score(), 4), round(a.accuracy(), 4), round(a.accuracy("certainty"), 4)
(0.75, 0.4, 0.65)
>>> a.complement()
IVNeutrosophicFN(t_l=0.2, t_u=0.3, i_l=0.8, i_u=0.9, f_l=0.6, f_u=0.7)
>>> IVNeutrosophicFN(0.8, 0.7, 0.1, 0.2, 0.2, 0.3)
Traceback (most recent call last):
...
ValueError: need t_l <= t_u, got t_l=0.8, t_u=0.7

bounds property

bounds: tuple[float, float, float, float, float, float]

The six bounds \((t_L, t_U, i_L, i_U, f_L, f_U)\).

Examples:

>>> from bulanik import IVNeutrosophicFN
>>> IVNeutrosophicFN(0.6, 0.7, 0.1, 0.2, 0.2, 0.3).bounds
(0.6, 0.7, 0.1, 0.2, 0.2, 0.3)

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

from_neutrosophic classmethod

from_neutrosophic(x: NeutrosophicFN) -> 'IVNeutrosophicFN'

Degenerate interval \(\langle [t, t], [i, i], [f, f] \rangle\) of a NeutrosophicFN.

Parameters:

Name Type Description Default
x NeutrosophicFN

A single-valued neutrosophic number.

required

Returns:

Type Description
'IVNeutrosophicFN'

The interval number with equal lower and upper bounds.

Raises:

Type Description
TypeError

If x is not a NeutrosophicFN.

Examples:

>>> from bulanik import IVNeutrosophicFN, NeutrosophicFN
>>> IVNeutrosophicFN.from_neutrosophic(NeutrosophicFN(0.7, 0.2, 0.1))
IVNeutrosophicFN(t_l=0.7, t_u=0.7, i_l=0.2, i_u=0.2, f_l=0.1, f_u=0.1)

complement

complement() -> 'IVNeutrosophicFN'

Complement \(([f_L, f_U], [1 - i_U, 1 - i_L], [t_L, t_U])\).

Returns:

Type Description
'IVNeutrosophicFN'

The complement (Wang et al. 2005).

Examples:

>>> from bulanik import IVNeutrosophicFN
>>> IVNeutrosophicFN(0.6, 0.7, 0.1, 0.2, 0.2, 0.3).complement().i_l
0.8

add

add(other: Any, ops: str = 'algebraic') -> 'IVNeutrosophicFN'

Sum of two interval neutrosophic numbers (law of NeutrosophicFN on both ends).

A + B calls this method.

Parameters:

Name Type Description Default
other Any

An IVNeutrosophicFN.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IVNeutrosophicFN'

The sum.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If ops is unknown.

References

Zhang, Wang and Chen (2014), The Scientific World Journal 2014, 645953.

Examples:

>>> from bulanik import IVNeutrosophicFN as N
>>> s = N(0.6, 0.7, 0.1, 0.2, 0.2, 0.3) + N(0.5, 0.6, 0.2, 0.3, 0.1, 0.2)
>>> tuple(round(x, 4) for x in s.bounds)
(0.8, 0.88, 0.02, 0.06, 0.02, 0.06)

mul

mul(other: Any, ops: str = 'algebraic') -> 'IVNeutrosophicFN'

Product of two interval neutrosophic numbers (law of NeutrosophicFN on both ends).

A * B calls this method.

Parameters:

Name Type Description Default
other Any

An IVNeutrosophicFN.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IVNeutrosophicFN'

The product.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IVNeutrosophicFN as N
>>> p = N(0.6, 0.7, 0.1, 0.2, 0.2, 0.3) * N(0.5, 0.6, 0.2, 0.3, 0.1, 0.2)
>>> tuple(round(x, 4) for x in p.bounds)
(0.3, 0.42, 0.28, 0.44, 0.28, 0.44)

scale

scale(k: float, ops: str = 'algebraic') -> 'IVNeutrosophicFN'

Scalar multiple k * A (law of NeutrosophicFN on both ends).

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IVNeutrosophicFN'

The scaled number.

Raises:

Type Description
ValueError

If k is negative or not finite, or ops is unknown.

Examples:

>>> from bulanik import IVNeutrosophicFN as N
>>> tuple(round(x, 4) for x in N(0.6, 0.7, 0.1, 0.2, 0.2, 0.3).scale(2).bounds)
(0.84, 0.91, 0.01, 0.04, 0.04, 0.09)

power

power(k: float, ops: str = 'algebraic') -> 'IVNeutrosophicFN'

Power A ** k (law of NeutrosophicFN on both ends).

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
'IVNeutrosophicFN'

The power.

Raises:

Type Description
ValueError

If k is negative or not finite, or ops is unknown.

Examples:

>>> from bulanik import IVNeutrosophicFN as N
>>> tuple(round(x, 4) for x in (N(0.6, 0.7, 0.1, 0.2, 0.2, 0.3) ** 2).bounds)
(0.36, 0.49, 0.19, 0.36, 0.36, 0.51)

score

score(method: str | None = None) -> float

Score \(\tfrac16(4 + t_L + t_U - i_L - i_U - f_L - f_U)\) ("average", the only method).

Parameters:

Name Type Description Default
method str | None

"average" or None.

None

Returns:

Type Description
float

The score in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IVNeutrosophicFN
>>> round(IVNeutrosophicFN(0.6, 0.7, 0.1, 0.2, 0.2, 0.3).score(), 4)
0.75

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\tfrac12(t_L + t_U - f_L - f_U)\) ("difference", default) or \(\tfrac12(t_L + t_U)\) ("certainty").

Parameters:

Name Type Description Default
method str | None

"difference", "certainty" or None.

None

Returns:

Type Description
float

The accuracy.

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IVNeutrosophicFN
>>> a = IVNeutrosophicFN(0.6, 0.7, 0.1, 0.2, 0.2, 0.3)
>>> round(a.accuracy(), 4), round(a.accuracy("certainty"), 4)
(0.4, 0.65)

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) \(\tfrac16 \sum |\Delta|\) or Euclidean \(\sqrt{\tfrac16 \sum \Delta^2}\) over the six bounds.

Parameters:

Name Type Description Default
other Any

An IVNeutrosophicFN.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IVNeutrosophicFN as N
>>> a, b = N(0.6, 0.7, 0.1, 0.2, 0.2, 0.3), N(0.5, 0.6, 0.2, 0.3, 0.1, 0.2)
>>> round(a.distance(b), 4)
0.1

IVFFN dataclass

IVFFN(mu_l: float, mu_u: float, nu_l: float, nu_u: float, q: int | None = None)

Bases: _FixedIV

Interval-valued Fermatean fuzzy number with \(\mu_U^3 + \nu_U^3 \le 1\) (q = 3, Jeevaraj 2021).

An IVQROFN with q = 3, constructed as IVFFN(mu_l, mu_u, nu_l, nu_u).

Parameters:

Name Type Description Default
mu_l float

Lower membership bound in \([0, 1]\).

required
mu_u float

Upper membership bound in \([0, 1]\).

required
nu_l float

Lower non-membership bound in \([0, 1]\).

required
nu_u float

Upper non-membership bound in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a bound is outside \([0, 1]\), a lower bound exceeds its upper bound, or \(\mu_U^3 + \nu_U^3 > 1\).

References

Jeevaraj (2021), Expert Systems with Applications 185, 115613.

Examples:

>>> from bulanik import IVFFN
>>> IVFFN(0.6, 0.8, 0.5, 0.6)
IVFFN(mu_l=0.6, mu_u=0.8, nu_l=0.5, nu_u=0.6)

hesitancy property

hesitancy: tuple[float, float]

Hesitancy interval \(\left((1 - \mu_U^q - \nu_U^q)^{1/q},\, (1 - \mu_L^q - \nu_L^q)^{1/q}\right)\).

Examples:

>>> from bulanik import IVIFN
>>> tuple(round(x, 4) for x in IVIFN(0.4, 0.5, 0.3, 0.4).hesitancy)
(0.1, 0.3)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type and rung (point law on both ends).

A + B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

References

Xu (2007), Control and Decision 22(2), 215-219 (IIFWA, q = 1). Wang and Liu (2013), Journal of Intelligent & Fuzzy Systems 25(2), 279-290 (Einstein operations).

Examples:

>>> from bulanik import IVIFN
>>> a, b = IVIFN(0.4, 0.5, 0.3, 0.4), IVIFN(0.5, 0.6, 0.2, 0.3)
>>> a + b
IVIFN(mu_l=0.7, mu_u=0.8, nu_l=0.06, nu_u=0.12)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type and rung (point law on both ends).

A * B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4) * IVIFN(0.5, 0.6, 0.2, 0.3)
IVIFN(mu_l=0.2, mu_u=0.3, nu_l=0.44, nu_u=0.58)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (point law on both ends).

k * A and A * k call this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4).scale(2)
IVIFN(mu_l=0.64, mu_u=0.75, nu_l=0.09, nu_u=0.16)

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (point law on both ends).

A ** k calls this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4) ** 2
IVIFN(mu_l=0.16, mu_u=0.25, nu_l=0.51, nu_u=0.64)

score

score(method: str | None = None) -> float

Score \(\tfrac12(\mu_L^q + \mu_U^q - \nu_L^q - \nu_U^q)\) ("difference", default), \((1 + S)/2\) ("normalized") or a defuzzified value ("defuzzified").

"defuzzified" is defined for intuitionistic numbers (\(q = 1\)) only:

\[D = \frac{\mu_L + \mu_U + (1 - \nu_L) + (1 - \nu_U) + \mu_L \mu_U - \sqrt{(1 - \nu_L)(1 - \nu_U)}}{4},\]

which lies in \([0, 1]\).

Parameters:

Name Type Description Default
method str | None

"difference", "normalized" or "defuzzified"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown, or it is "defuzzified" and \(q \ne 1\).

References

Xu (2007), Control and Decision 22(2), 215-219 (q = 1); Peng and Yang (2016), International Journal of Intelligent Systems 31(5), 444-487 (q = 2). "defuzzified": Bolturk and Kahraman (2022), Informatica 33(4), 693-711, Definition 4, doi:10.15388/22-INFOR478.

Examples:

>>> from bulanik import IVIFN
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score(), 4)
0.1
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score("normalized"), 4)
0.55
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score("defuzzified"), 4)
0.438

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\tfrac12(\mu_L^q + \mu_U^q + \nu_L^q + \nu_U^q)\) ("sum", the only method).

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IVIFN
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).accuracy(), 4)
0.8

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance on the powers of both ends and the hesitancy.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IVIFN
>>> a, b = IVIFN(0.4, 0.5, 0.3, 0.4), IVIFN(0.5, 0.6, 0.2, 0.3)
>>> round(a.distance(b), 4), round(a.distance(b, "euclidean"), 4)
(0.1, 0.1)

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

from_qrofn classmethod

from_qrofn(x: QROFN) -> Any

Degenerate interval \(([\mu, \mu], [\nu, \nu])\) of a QROFN.

On a fixed-rung subclass the rung of x must equal the class rung.

Parameters:

Name Type Description Default
x QROFN

A QROFN, IFN, PFN or FFN.

required

Returns:

Type Description
Any

The interval-valued number with equal lower and upper bounds.

Raises:

Type Description
TypeError

If x is not a QROFN.

ValueError

If the class has a fixed rung that differs from x.q.

Examples:

>>> from bulanik import IFN, IVIFN
>>> IVIFN.from_qrofn(IFN(0.6, 0.3))
IVIFN(mu_l=0.6, mu_u=0.6, nu_l=0.3, nu_u=0.3)

complement

complement() -> Any

Complement: membership and non-membership intervals swapped.

Returns:

Type Description
Any

The number \(([\nu_L, \nu_U], [\mu_L, \mu_U])\) of the same type.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4).complement()
IVIFN(mu_l=0.3, mu_u=0.4, nu_l=0.4, nu_u=0.5)

IVIFN dataclass

IVIFN(mu_l: float, mu_u: float, nu_l: float, nu_u: float, q: int | None = None)

Bases: _FixedIV

Interval-valued intuitionistic fuzzy number with \(\mu_U + \nu_U \le 1\) (q = 1, Atanassov and Gargov 1989).

An IVQROFN with q = 1, constructed as IVIFN(mu_l, mu_u, nu_l, nu_u). All methods are those of IVQROFN.

Parameters:

Name Type Description Default
mu_l float

Lower membership bound in \([0, 1]\).

required
mu_u float

Upper membership bound in \([0, 1]\).

required
nu_l float

Lower non-membership bound in \([0, 1]\).

required
nu_u float

Upper non-membership bound in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a bound is outside \([0, 1]\), a lower bound exceeds its upper bound, or \(\mu_U + \nu_U > 1\).

References

Atanassov and Gargov (1989), Fuzzy Sets and Systems 31(3), 343-349.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4)
IVIFN(mu_l=0.4, mu_u=0.5, nu_l=0.3, nu_u=0.4)
>>> IVIFN(0.5, 0.4, 0.1, 0.2)
Traceback (most recent call last):
...
ValueError: need mu_l <= mu_u, got mu_l=0.5, mu_u=0.4

hesitancy property

hesitancy: tuple[float, float]

Hesitancy interval \(\left((1 - \mu_U^q - \nu_U^q)^{1/q},\, (1 - \mu_L^q - \nu_L^q)^{1/q}\right)\).

Examples:

>>> from bulanik import IVIFN
>>> tuple(round(x, 4) for x in IVIFN(0.4, 0.5, 0.3, 0.4).hesitancy)
(0.1, 0.3)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type and rung (point law on both ends).

A + B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

References

Xu (2007), Control and Decision 22(2), 215-219 (IIFWA, q = 1). Wang and Liu (2013), Journal of Intelligent & Fuzzy Systems 25(2), 279-290 (Einstein operations).

Examples:

>>> from bulanik import IVIFN
>>> a, b = IVIFN(0.4, 0.5, 0.3, 0.4), IVIFN(0.5, 0.6, 0.2, 0.3)
>>> a + b
IVIFN(mu_l=0.7, mu_u=0.8, nu_l=0.06, nu_u=0.12)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type and rung (point law on both ends).

A * B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4) * IVIFN(0.5, 0.6, 0.2, 0.3)
IVIFN(mu_l=0.2, mu_u=0.3, nu_l=0.44, nu_u=0.58)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (point law on both ends).

k * A and A * k call this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4).scale(2)
IVIFN(mu_l=0.64, mu_u=0.75, nu_l=0.09, nu_u=0.16)

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (point law on both ends).

A ** k calls this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4) ** 2
IVIFN(mu_l=0.16, mu_u=0.25, nu_l=0.51, nu_u=0.64)

score

score(method: str | None = None) -> float

Score \(\tfrac12(\mu_L^q + \mu_U^q - \nu_L^q - \nu_U^q)\) ("difference", default), \((1 + S)/2\) ("normalized") or a defuzzified value ("defuzzified").

"defuzzified" is defined for intuitionistic numbers (\(q = 1\)) only:

\[D = \frac{\mu_L + \mu_U + (1 - \nu_L) + (1 - \nu_U) + \mu_L \mu_U - \sqrt{(1 - \nu_L)(1 - \nu_U)}}{4},\]

which lies in \([0, 1]\).

Parameters:

Name Type Description Default
method str | None

"difference", "normalized" or "defuzzified"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown, or it is "defuzzified" and \(q \ne 1\).

References

Xu (2007), Control and Decision 22(2), 215-219 (q = 1); Peng and Yang (2016), International Journal of Intelligent Systems 31(5), 444-487 (q = 2). "defuzzified": Bolturk and Kahraman (2022), Informatica 33(4), 693-711, Definition 4, doi:10.15388/22-INFOR478.

Examples:

>>> from bulanik import IVIFN
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score(), 4)
0.1
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score("normalized"), 4)
0.55
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score("defuzzified"), 4)
0.438

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\tfrac12(\mu_L^q + \mu_U^q + \nu_L^q + \nu_U^q)\) ("sum", the only method).

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IVIFN
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).accuracy(), 4)
0.8

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance on the powers of both ends and the hesitancy.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IVIFN
>>> a, b = IVIFN(0.4, 0.5, 0.3, 0.4), IVIFN(0.5, 0.6, 0.2, 0.3)
>>> round(a.distance(b), 4), round(a.distance(b, "euclidean"), 4)
(0.1, 0.1)

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

from_qrofn classmethod

from_qrofn(x: QROFN) -> Any

Degenerate interval \(([\mu, \mu], [\nu, \nu])\) of a QROFN.

On a fixed-rung subclass the rung of x must equal the class rung.

Parameters:

Name Type Description Default
x QROFN

A QROFN, IFN, PFN or FFN.

required

Returns:

Type Description
Any

The interval-valued number with equal lower and upper bounds.

Raises:

Type Description
TypeError

If x is not a QROFN.

ValueError

If the class has a fixed rung that differs from x.q.

Examples:

>>> from bulanik import IFN, IVIFN
>>> IVIFN.from_qrofn(IFN(0.6, 0.3))
IVIFN(mu_l=0.6, mu_u=0.6, nu_l=0.3, nu_u=0.3)

complement

complement() -> Any

Complement: membership and non-membership intervals swapped.

Returns:

Type Description
Any

The number \(([\nu_L, \nu_U], [\mu_L, \mu_U])\) of the same type.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4).complement()
IVIFN(mu_l=0.3, mu_u=0.4, nu_l=0.4, nu_u=0.5)

IVPFN dataclass

IVPFN(mu_l: float, mu_u: float, nu_l: float, nu_u: float, q: int | None = None)

Bases: _FixedIV

Interval-valued Pythagorean fuzzy number with \(\mu_U^2 + \nu_U^2 \le 1\) (q = 2, Peng and Yang 2016).

An IVQROFN with q = 2, constructed as IVPFN(mu_l, mu_u, nu_l, nu_u).

Parameters:

Name Type Description Default
mu_l float

Lower membership bound in \([0, 1]\).

required
mu_u float

Upper membership bound in \([0, 1]\).

required
nu_l float

Lower non-membership bound in \([0, 1]\).

required
nu_u float

Upper non-membership bound in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a bound is outside \([0, 1]\), a lower bound exceeds its upper bound, or \(\mu_U^2 + \nu_U^2 > 1\).

References

Peng and Yang (2016), International Journal of Intelligent Systems 31(5), 444-487.

Examples:

>>> from bulanik import IVPFN
>>> IVPFN(0.6, 0.8, 0.5, 0.6)
IVPFN(mu_l=0.6, mu_u=0.8, nu_l=0.5, nu_u=0.6)

hesitancy property

hesitancy: tuple[float, float]

Hesitancy interval \(\left((1 - \mu_U^q - \nu_U^q)^{1/q},\, (1 - \mu_L^q - \nu_L^q)^{1/q}\right)\).

Examples:

>>> from bulanik import IVIFN
>>> tuple(round(x, 4) for x in IVIFN(0.4, 0.5, 0.3, 0.4).hesitancy)
(0.1, 0.3)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type and rung (point law on both ends).

A + B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

References

Xu (2007), Control and Decision 22(2), 215-219 (IIFWA, q = 1). Wang and Liu (2013), Journal of Intelligent & Fuzzy Systems 25(2), 279-290 (Einstein operations).

Examples:

>>> from bulanik import IVIFN
>>> a, b = IVIFN(0.4, 0.5, 0.3, 0.4), IVIFN(0.5, 0.6, 0.2, 0.3)
>>> a + b
IVIFN(mu_l=0.7, mu_u=0.8, nu_l=0.06, nu_u=0.12)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type and rung (point law on both ends).

A * B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4) * IVIFN(0.5, 0.6, 0.2, 0.3)
IVIFN(mu_l=0.2, mu_u=0.3, nu_l=0.44, nu_u=0.58)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (point law on both ends).

k * A and A * k call this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4).scale(2)
IVIFN(mu_l=0.64, mu_u=0.75, nu_l=0.09, nu_u=0.16)

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (point law on both ends).

A ** k calls this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4) ** 2
IVIFN(mu_l=0.16, mu_u=0.25, nu_l=0.51, nu_u=0.64)

score

score(method: str | None = None) -> float

Score \(\tfrac12(\mu_L^q + \mu_U^q - \nu_L^q - \nu_U^q)\) ("difference", default), \((1 + S)/2\) ("normalized") or a defuzzified value ("defuzzified").

"defuzzified" is defined for intuitionistic numbers (\(q = 1\)) only:

\[D = \frac{\mu_L + \mu_U + (1 - \nu_L) + (1 - \nu_U) + \mu_L \mu_U - \sqrt{(1 - \nu_L)(1 - \nu_U)}}{4},\]

which lies in \([0, 1]\).

Parameters:

Name Type Description Default
method str | None

"difference", "normalized" or "defuzzified"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown, or it is "defuzzified" and \(q \ne 1\).

References

Xu (2007), Control and Decision 22(2), 215-219 (q = 1); Peng and Yang (2016), International Journal of Intelligent Systems 31(5), 444-487 (q = 2). "defuzzified": Bolturk and Kahraman (2022), Informatica 33(4), 693-711, Definition 4, doi:10.15388/22-INFOR478.

Examples:

>>> from bulanik import IVIFN
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score(), 4)
0.1
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score("normalized"), 4)
0.55
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score("defuzzified"), 4)
0.438

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\tfrac12(\mu_L^q + \mu_U^q + \nu_L^q + \nu_U^q)\) ("sum", the only method).

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IVIFN
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).accuracy(), 4)
0.8

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance on the powers of both ends and the hesitancy.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IVIFN
>>> a, b = IVIFN(0.4, 0.5, 0.3, 0.4), IVIFN(0.5, 0.6, 0.2, 0.3)
>>> round(a.distance(b), 4), round(a.distance(b, "euclidean"), 4)
(0.1, 0.1)

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

from_qrofn classmethod

from_qrofn(x: QROFN) -> Any

Degenerate interval \(([\mu, \mu], [\nu, \nu])\) of a QROFN.

On a fixed-rung subclass the rung of x must equal the class rung.

Parameters:

Name Type Description Default
x QROFN

A QROFN, IFN, PFN or FFN.

required

Returns:

Type Description
Any

The interval-valued number with equal lower and upper bounds.

Raises:

Type Description
TypeError

If x is not a QROFN.

ValueError

If the class has a fixed rung that differs from x.q.

Examples:

>>> from bulanik import IFN, IVIFN
>>> IVIFN.from_qrofn(IFN(0.6, 0.3))
IVIFN(mu_l=0.6, mu_u=0.6, nu_l=0.3, nu_u=0.3)

complement

complement() -> Any

Complement: membership and non-membership intervals swapped.

Returns:

Type Description
Any

The number \(([\nu_L, \nu_U], [\mu_L, \mu_U])\) of the same type.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4).complement()
IVIFN(mu_l=0.3, mu_u=0.4, nu_l=0.4, nu_u=0.5)

IVQROFN dataclass

IVQROFN(mu_l: float, mu_u: float, nu_l: float, nu_u: float, q: int)

Bases: FuzzyNumber

Interval-valued q-rung orthopair fuzzy number \(([\mu_L, \mu_U], [\nu_L, \nu_U])\).

With \(a = \mu^q\) and \(b = \nu^q\), every operation is the point law of QROFN (see its table of operators, both "algebraic" and "einstein") applied to \((a_L, b_L)\) and to \((a_U, b_U)\) separately; the result is \(\mu\) = [first part of the lower result, first part of the upper result] to the power \(1/q\), and likewise for \(\nu\). For \(q = 1\) and the algebraic operators this is Xu's (2007) arithmetic, e.g. \(\tilde a \oplus \tilde b = ([a^L + b^L - a^L b^L,\, a^U + b^U - a^U b^U], [c^L d^L,\, c^U d^U])\).

Scores: "difference" (default) \(S = \tfrac12(\mu_L^q + \mu_U^q - \nu_L^q - \nu_U^q)\) (Xu 2007 for \(q = 1\), Peng and Yang 2016 for \(q = 2\)), "normalized" \((1 + S)/2\) and, for \(q = 1\) only, "defuzzified" (see score). Accuracy "sum" \(H = \tfrac12(\mu_L^q + \mu_U^q + \nu_L^q + \nu_U^q)\). Distances (default "hamming") work on \((a_L, a_U, b_L, b_U, \pi_L, \pi_U)\) with \(\pi_L = 1 - a_U - b_U\) and \(\pi_U = 1 - a_L - b_L\): Hamming \(= \tfrac14 \sum |\Delta|\) and Euclidean \(= \sqrt{\tfrac14 \sum \Delta^2}\). For degenerate intervals all of these equal the QROFN values, except "defuzzified", which QROFN does not have.

Inversions \(\mu_L > \mu_U\) or \(\nu_L > \nu_U\) of up to \(10^{-12}\) are clamped (lower := upper); larger ones raise ValueError. The constraint is checked and projected on the upper pair exactly as QROFN does, and the lower bounds are then clamped to at most the upper ones.

Parameters:

Name Type Description Default
mu_l float

Lower membership bound in \([0, 1]\).

required
mu_u float

Upper membership bound in \([0, 1]\).

required
nu_l float

Lower non-membership bound in \([0, 1]\).

required
nu_u float

Upper non-membership bound in \([0, 1]\).

required
q int

The rung, an integer \(\ge 1\).

required

Raises:

Type Description
ValueError

If q is not an integer \(\ge 1\), a bound is outside \([0, 1]\) or not finite, a lower bound exceeds its upper bound, or \(\mu_U^q + \nu_U^q > 1\) (beyond rounding).

TypeError

If a bound is a bool or a string.

Attributes:

Name Type Description
mu_l float

Lower membership bound.

mu_u float

Upper membership bound.

nu_l float

Lower non-membership bound.

nu_u float

Upper non-membership bound.

q int

The rung.

References

Atanassov and Gargov (1989), Fuzzy Sets and Systems 31(3), 343-349 (interval-valued intuitionistic fuzzy sets). Xu (2007), Control and Decision 22(2), 215-219 (arithmetic, score and accuracy). Wang and Liu (2013), Journal of Intelligent & Fuzzy Systems 25(2), 279-290 (Einstein operations). Peng and Yang (2016), International Journal of Intelligent Systems 31(5), 444-487. Joshi, Singh, Bhatt and Vaisla (2018), Journal of Intelligent & Fuzzy Systems 35(5), 5225-5230 (interval-valued q-rung orthopair sets). Garg (2016), Journal of Intelligent & Fuzzy Systems 31(1), 529-540, doi:10.3233/IFS-162165, gives an accuracy function for \(q = 2\) that is not implemented; the scores above are the ones of Xu (2007) and Peng and Yang (2016).

Examples:

>>> from bulanik import IVQROFN
>>> IVQROFN(0.6, 0.8, 0.3, 0.5, 3)
IVQROFN(mu_l=0.6, mu_u=0.8, nu_l=0.3, nu_u=0.5, q=3)
>>> IVQROFN(0.6, 0.9, 0.3, 0.7, 3)
Traceback (most recent call last):
...
ValueError: need mu_u^3 + nu_u^3 <= 1, got mu_u=0.9, nu_u=0.7 (sum 1.072)

hesitancy property

hesitancy: tuple[float, float]

Hesitancy interval \(\left((1 - \mu_U^q - \nu_U^q)^{1/q},\, (1 - \mu_L^q - \nu_L^q)^{1/q}\right)\).

Examples:

>>> from bulanik import IVIFN
>>> tuple(round(x, 4) for x in IVIFN(0.4, 0.5, 0.3, 0.4).hesitancy)
(0.1, 0.3)

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

from_qrofn classmethod

from_qrofn(x: QROFN) -> Any

Degenerate interval \(([\mu, \mu], [\nu, \nu])\) of a QROFN.

On a fixed-rung subclass the rung of x must equal the class rung.

Parameters:

Name Type Description Default
x QROFN

A QROFN, IFN, PFN or FFN.

required

Returns:

Type Description
Any

The interval-valued number with equal lower and upper bounds.

Raises:

Type Description
TypeError

If x is not a QROFN.

ValueError

If the class has a fixed rung that differs from x.q.

Examples:

>>> from bulanik import IFN, IVIFN
>>> IVIFN.from_qrofn(IFN(0.6, 0.3))
IVIFN(mu_l=0.6, mu_u=0.6, nu_l=0.3, nu_u=0.3)

complement

complement() -> Any

Complement: membership and non-membership intervals swapped.

Returns:

Type Description
Any

The number \(([\nu_L, \nu_U], [\mu_L, \mu_U])\) of the same type.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4).complement()
IVIFN(mu_l=0.3, mu_u=0.4, nu_l=0.4, nu_u=0.5)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type and rung (point law on both ends).

A + B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

References

Xu (2007), Control and Decision 22(2), 215-219 (IIFWA, q = 1). Wang and Liu (2013), Journal of Intelligent & Fuzzy Systems 25(2), 279-290 (Einstein operations).

Examples:

>>> from bulanik import IVIFN
>>> a, b = IVIFN(0.4, 0.5, 0.3, 0.4), IVIFN(0.5, 0.6, 0.2, 0.3)
>>> a + b
IVIFN(mu_l=0.7, mu_u=0.8, nu_l=0.06, nu_u=0.12)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type and rung (point law on both ends).

A * B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4) * IVIFN(0.5, 0.6, 0.2, 0.3)
IVIFN(mu_l=0.2, mu_u=0.3, nu_l=0.44, nu_u=0.58)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (point law on both ends).

k * A and A * k call this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4).scale(2)
IVIFN(mu_l=0.64, mu_u=0.75, nu_l=0.09, nu_u=0.16)

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (point law on both ends).

A ** k calls this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IVIFN
>>> IVIFN(0.4, 0.5, 0.3, 0.4) ** 2
IVIFN(mu_l=0.16, mu_u=0.25, nu_l=0.51, nu_u=0.64)

score

score(method: str | None = None) -> float

Score \(\tfrac12(\mu_L^q + \mu_U^q - \nu_L^q - \nu_U^q)\) ("difference", default), \((1 + S)/2\) ("normalized") or a defuzzified value ("defuzzified").

"defuzzified" is defined for intuitionistic numbers (\(q = 1\)) only:

\[D = \frac{\mu_L + \mu_U + (1 - \nu_L) + (1 - \nu_U) + \mu_L \mu_U - \sqrt{(1 - \nu_L)(1 - \nu_U)}}{4},\]

which lies in \([0, 1]\).

Parameters:

Name Type Description Default
method str | None

"difference", "normalized" or "defuzzified"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown, or it is "defuzzified" and \(q \ne 1\).

References

Xu (2007), Control and Decision 22(2), 215-219 (q = 1); Peng and Yang (2016), International Journal of Intelligent Systems 31(5), 444-487 (q = 2). "defuzzified": Bolturk and Kahraman (2022), Informatica 33(4), 693-711, Definition 4, doi:10.15388/22-INFOR478.

Examples:

>>> from bulanik import IVIFN
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score(), 4)
0.1
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score("normalized"), 4)
0.55
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).score("defuzzified"), 4)
0.438

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\tfrac12(\mu_L^q + \mu_U^q + \nu_L^q + \nu_U^q)\) ("sum", the only method).

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IVIFN
>>> round(IVIFN(0.4, 0.5, 0.3, 0.4).accuracy(), 4)
0.8

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance on the powers of both ends and the hesitancy.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IVIFN
>>> a, b = IVIFN(0.4, 0.5, 0.3, 0.4), IVIFN(0.5, 0.6, 0.2, 0.3)
>>> round(a.distance(b), 4), round(a.distance(b, "euclidean"), 4)
(0.1, 0.1)

FFN dataclass

FFN(mu: float, nu: float, q: int | None = None)

Bases: _Fixed

Fermatean fuzzy number \((\mu, \nu)\) with \(\mu^3 + \nu^3 \le 1\) (q = 3, Senapati and Yager 2020).

A QROFN with q = 3, constructed as FFN(mu, nu).

Parameters:

Name Type Description Default
mu float

Membership degree in \([0, 1]\).

required
nu float

Non-membership degree in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a degree is outside \([0, 1]\) or \(\mu^3 + \nu^3 > 1\).

References

Senapati and Yager (2020), Fermatean fuzzy sets, Journal of Ambient Intelligence and Humanized Computing 11(2), 663-674.

Examples:

>>> from bulanik import FFN
>>> FFN(0.8, 0.6)
FFN(mu=0.8, nu=0.6)

hesitancy property

hesitancy: float

Hesitancy degree \(\pi = (1 - \mu^q - \nu^q)^{1/q}\).

Examples:

>>> from bulanik import PFN
>>> round(PFN(0.7, 0.5).hesitancy, 4)
0.5099

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type and rung (see the table of operators above).

A + B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

References

Wang and Liu (2011), International Journal of Intelligent Systems 26 (Einstein operations, intuitionistic case).

Examples:

>>> from bulanik import IFN
>>> a, b = IFN(0.6, 0.3), IFN(0.5, 0.4)
>>> a + b
IFN(mu=0.8, nu=0.12)
>>> e = a.add(b, ops="einstein")
>>> round(e.mu, 4), round(e.nu, 4)
(0.8462, 0.0845)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type and rung (see the table of operators above).

A * B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3) * IFN(0.5, 0.4)
IFN(mu=0.3, nu=0.58)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (see the table of operators above).

k * A and A * k call this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3).scale(2)
IFN(mu=0.84, nu=0.09)
>>> IFN(0.6, 0.3).scale(-1)
Traceback (most recent call last):
...
ValueError: scale needs k >= 0, got -1.0

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (see the table of operators above).

A ** k calls this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3) ** 2
IFN(mu=0.36, nu=0.51)

score

score(method: str | None = None) -> float

Score for ranking: \(\mu^q - \nu^q\) ("difference", default) or \((1 + \mu^q - \nu^q)/2\) ("normalized").

Parameters:

Name Type Description Default
method str | None

"difference" or "normalized"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.3).score(), 4)
0.3
>>> round(IFN(0.6, 0.3).score("normalized"), 4)
0.65

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\mu^q + \nu^q\) ("sum", the only method); the complement of the hesitancy power.

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.3).accuracy(), 4)
0.9

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance on (mu^q, nu^q, pi^q).

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.2).distance(IFN(0.3, 0.3)), 4)
0.3
>>> round(IFN(0.6, 0.2).distance(IFN(0.3, 0.3), "euclidean"), 4)
0.2646

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

complement

complement() -> Any

Complement: membership and non-membership swapped.

Returns:

Type Description
Any

The number \((\nu, \mu)\) of the same type.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3).complement()
IFN(mu=0.3, nu=0.6)

IFN dataclass

IFN(mu: float, nu: float, q: int | None = None)

Bases: _Fixed

Intuitionistic fuzzy number \((\mu, \nu)\) with \(\mu + \nu \le 1\) (q = 1, Atanassov 1986).

A QROFN with q = 1, constructed as IFN(mu, nu). All methods are those of QROFN.

Parameters:

Name Type Description Default
mu float

Membership degree in \([0, 1]\).

required
nu float

Non-membership degree in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a degree is outside \([0, 1]\) or \(\mu + \nu > 1\).

References

Atanassov (1986), Fuzzy Sets and Systems 20(1): intuitionistic fuzzy sets.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3)
IFN(mu=0.6, nu=0.3)
>>> IFN(0.8, 0.5)
Traceback (most recent call last):
...
ValueError: need mu^1 + nu^1 <= 1, got mu=0.8, nu=0.5 (sum 1.3)

hesitancy property

hesitancy: float

Hesitancy degree \(\pi = (1 - \mu^q - \nu^q)^{1/q}\).

Examples:

>>> from bulanik import PFN
>>> round(PFN(0.7, 0.5).hesitancy, 4)
0.5099

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type and rung (see the table of operators above).

A + B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

References

Wang and Liu (2011), International Journal of Intelligent Systems 26 (Einstein operations, intuitionistic case).

Examples:

>>> from bulanik import IFN
>>> a, b = IFN(0.6, 0.3), IFN(0.5, 0.4)
>>> a + b
IFN(mu=0.8, nu=0.12)
>>> e = a.add(b, ops="einstein")
>>> round(e.mu, 4), round(e.nu, 4)
(0.8462, 0.0845)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type and rung (see the table of operators above).

A * B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3) * IFN(0.5, 0.4)
IFN(mu=0.3, nu=0.58)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (see the table of operators above).

k * A and A * k call this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3).scale(2)
IFN(mu=0.84, nu=0.09)
>>> IFN(0.6, 0.3).scale(-1)
Traceback (most recent call last):
...
ValueError: scale needs k >= 0, got -1.0

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (see the table of operators above).

A ** k calls this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3) ** 2
IFN(mu=0.36, nu=0.51)

score

score(method: str | None = None) -> float

Score for ranking: \(\mu^q - \nu^q\) ("difference", default) or \((1 + \mu^q - \nu^q)/2\) ("normalized").

Parameters:

Name Type Description Default
method str | None

"difference" or "normalized"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.3).score(), 4)
0.3
>>> round(IFN(0.6, 0.3).score("normalized"), 4)
0.65

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\mu^q + \nu^q\) ("sum", the only method); the complement of the hesitancy power.

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.3).accuracy(), 4)
0.9

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance on (mu^q, nu^q, pi^q).

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.2).distance(IFN(0.3, 0.3)), 4)
0.3
>>> round(IFN(0.6, 0.2).distance(IFN(0.3, 0.3), "euclidean"), 4)
0.2646

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

complement

complement() -> Any

Complement: membership and non-membership swapped.

Returns:

Type Description
Any

The number \((\nu, \mu)\) of the same type.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3).complement()
IFN(mu=0.3, nu=0.6)

PFN dataclass

PFN(mu: float, nu: float, q: int | None = None)

Bases: _Fixed

Pythagorean fuzzy number \((\mu, \nu)\) with \(\mu^2 + \nu^2 \le 1\) (q = 2, Yager 2013).

A QROFN with q = 2, constructed as PFN(mu, nu).

Parameters:

Name Type Description Default
mu float

Membership degree in \([0, 1]\).

required
nu float

Non-membership degree in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a degree is outside \([0, 1]\) or \(\mu^2 + \nu^2 > 1\).

References

Yager (2013), Pythagorean fuzzy subsets, Joint IFSA World Congress and NAFIPS Annual Meeting, 57-61.

Examples:

>>> from bulanik import PFN
>>> PFN(0.8, 0.5)
PFN(mu=0.8, nu=0.5)
>>> PFN(0.8, 0.5).q
2

hesitancy property

hesitancy: float

Hesitancy degree \(\pi = (1 - \mu^q - \nu^q)^{1/q}\).

Examples:

>>> from bulanik import PFN
>>> round(PFN(0.7, 0.5).hesitancy, 4)
0.5099

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type and rung (see the table of operators above).

A + B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

References

Wang and Liu (2011), International Journal of Intelligent Systems 26 (Einstein operations, intuitionistic case).

Examples:

>>> from bulanik import IFN
>>> a, b = IFN(0.6, 0.3), IFN(0.5, 0.4)
>>> a + b
IFN(mu=0.8, nu=0.12)
>>> e = a.add(b, ops="einstein")
>>> round(e.mu, 4), round(e.nu, 4)
(0.8462, 0.0845)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type and rung (see the table of operators above).

A * B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3) * IFN(0.5, 0.4)
IFN(mu=0.3, nu=0.58)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (see the table of operators above).

k * A and A * k call this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3).scale(2)
IFN(mu=0.84, nu=0.09)
>>> IFN(0.6, 0.3).scale(-1)
Traceback (most recent call last):
...
ValueError: scale needs k >= 0, got -1.0

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (see the table of operators above).

A ** k calls this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3) ** 2
IFN(mu=0.36, nu=0.51)

score

score(method: str | None = None) -> float

Score for ranking: \(\mu^q - \nu^q\) ("difference", default) or \((1 + \mu^q - \nu^q)/2\) ("normalized").

Parameters:

Name Type Description Default
method str | None

"difference" or "normalized"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.3).score(), 4)
0.3
>>> round(IFN(0.6, 0.3).score("normalized"), 4)
0.65

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\mu^q + \nu^q\) ("sum", the only method); the complement of the hesitancy power.

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.3).accuracy(), 4)
0.9

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance on (mu^q, nu^q, pi^q).

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.2).distance(IFN(0.3, 0.3)), 4)
0.3
>>> round(IFN(0.6, 0.2).distance(IFN(0.3, 0.3), "euclidean"), 4)
0.2646

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

complement

complement() -> Any

Complement: membership and non-membership swapped.

Returns:

Type Description
Any

The number \((\nu, \mu)\) of the same type.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3).complement()
IFN(mu=0.3, nu=0.6)

QROFN dataclass

QROFN(mu: float, nu: float, q: int)

Bases: FuzzyNumber

q-rung orthopair fuzzy number \((\mu, \nu)\) with \(\mu^q + \nu^q \le 1\).

Every operation is the intuitionistic one applied to \((a, b) = (\mu^q, \nu^q)\), followed by the q-th root of each part. For two numbers with powers \((a_1, b_1)\) and \((a_2, b_2)\) the result powers are:

operation "algebraic" "einstein"
add \((a_1 + a_2 - a_1 a_2,\; b_1 b_2)\) \(\left(\frac{a_1 + a_2}{1 + a_1 a_2},\; \frac{b_1 b_2}{1 + (1 - b_1)(1 - b_2)}\right)\)
mul \((a_1 a_2,\; b_1 + b_2 - b_1 b_2)\) \(\left(\frac{a_1 a_2}{1 + (1 - a_1)(1 - a_2)},\; \frac{b_1 + b_2}{1 + b_1 b_2}\right)\)
scale by \(k\) \((1 - (1 - a)^k,\; b^k)\) \(\left(\frac{(1+a)^k - (1-a)^k}{(1+a)^k + (1-a)^k},\; \frac{2 b^k}{(2-b)^k + b^k}\right)\)
power by \(k\) \((a^k,\; 1 - (1 - b)^k)\) \(\left(\frac{2 a^k}{(2-a)^k + a^k},\; \frac{(1+b)^k - (1-b)^k}{(1+b)^k + (1-b)^k}\right)\)

Scores: "difference" (default) \(= \mu^q - \nu^q\) and "normalized" \(= (1 + \mu^q - \nu^q)/2\). Accuracy: "sum" \(= \mu^q + \nu^q\). Distances (default "hamming") work on \((a, b, \pi)\) with the hesitancy power \(\pi = 1 - a - b\): Hamming \(= (|\Delta a| + |\Delta b| + |\Delta \pi|)/2\) and Euclidean \(= \sqrt{(\Delta a^2 + \Delta b^2 + \Delta \pi^2)/2}\).

Inputs that exceed the constraint by no more than \(10^{-12}\) are accepted as rounding and put back on the boundary \(\mu^q + \nu^q = 1\); results that violate it by more than rounding raise ValueError.

Parameters:

Name Type Description Default
mu float

Membership degree in \([0, 1]\).

required
nu float

Non-membership degree in \([0, 1]\).

required
q int

The rung, an integer \(\ge 1\).

required

Raises:

Type Description
ValueError

If q is not an integer \(\ge 1\), a degree is outside \([0, 1]\) or not finite, or \(\mu^q + \nu^q > 1\) (beyond rounding).

TypeError

If a degree is a bool or a string.

Attributes:

Name Type Description
mu float

Membership degree.

nu float

Non-membership degree.

q int

The rung.

References

Yager (2017), IEEE Transactions on Fuzzy Systems 25(5): q-rung orthopair fuzzy sets. Einstein operations: Wang and Liu (2011), International Journal of Intelligent Systems 26(11), 1049-1075.

Examples:

>>> from bulanik import QROFN
>>> QROFN(0.9, 0.5, 3)
QROFN(mu=0.9, nu=0.5, q=3)
>>> QROFN(0.9, 0.8, 3)
Traceback (most recent call last):
...
ValueError: need mu^3 + nu^3 <= 1, got mu=0.9, nu=0.8 (sum 1.241)

hesitancy property

hesitancy: float

Hesitancy degree \(\pi = (1 - \mu^q - \nu^q)^{1/q}\).

Examples:

>>> from bulanik import PFN
>>> round(PFN(0.7, 0.5).hesitancy, 4)
0.5099

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

complement

complement() -> Any

Complement: membership and non-membership swapped.

Returns:

Type Description
Any

The number \((\nu, \mu)\) of the same type.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3).complement()
IFN(mu=0.3, nu=0.6)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type and rung (see the table of operators above).

A + B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

References

Wang and Liu (2011), International Journal of Intelligent Systems 26 (Einstein operations, intuitionistic case).

Examples:

>>> from bulanik import IFN
>>> a, b = IFN(0.6, 0.3), IFN(0.5, 0.4)
>>> a + b
IFN(mu=0.8, nu=0.12)
>>> e = a.add(b, ops="einstein")
>>> round(e.mu, 4), round(e.nu, 4)
(0.8462, 0.0845)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type and rung (see the table of operators above).

A * B calls this method with the algebraic operators.

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If ops is unknown.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3) * IFN(0.5, 0.4)
IFN(mu=0.3, nu=0.58)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A (see the table of operators above).

k * A and A * k call this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3).scale(2)
IFN(mu=0.84, nu=0.09)
>>> IFN(0.6, 0.3).scale(-1)
Traceback (most recent call last):
...
ValueError: scale needs k >= 0, got -1.0

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k (see the table of operators above).

A ** k calls this method with the algebraic operators.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

"algebraic" (default) or "einstein".

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint beyond rounding.

Examples:

>>> from bulanik import IFN
>>> IFN(0.6, 0.3) ** 2
IFN(mu=0.36, nu=0.51)

score

score(method: str | None = None) -> float

Score for ranking: \(\mu^q - \nu^q\) ("difference", default) or \((1 + \mu^q - \nu^q)/2\) ("normalized").

Parameters:

Name Type Description Default
method str | None

"difference" or "normalized"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.3).score(), 4)
0.3
>>> round(IFN(0.6, 0.3).score("normalized"), 4)
0.65

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\mu^q + \nu^q\) ("sum", the only method); the complement of the hesitancy power.

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.3).accuracy(), 4)
0.9

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance on (mu^q, nu^q, pi^q).

Parameters:

Name Type Description Default
other Any

A number of the same class and the same q.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance, in \([0, 1]\).

Raises:

Type Description
TypeError

If other differs in class or rung.

ValueError

If method is unknown.

Examples:

>>> from bulanik import IFN
>>> round(IFN(0.6, 0.2).distance(IFN(0.3, 0.3)), 4)
0.3
>>> round(IFN(0.6, 0.2).distance(IFN(0.3, 0.3), "euclidean"), 4)
0.2646

NeutrosophicFN dataclass

NeutrosophicFN(t: float, i: float, f: float)

Bases: _ThreePart

Single-valued neutrosophic number \((t, i, f)\), each part in \([0, 1]\).

The parts are truth, indeterminacy and falsity; they are independent (no joint constraint). Operations as the code evaluates them:

operation \(t\) \(i\) \(f\)
add \(t_1 + t_2 - t_1 t_2\) \(i_1 i_2\) \(f_1 f_2\)
mul \(t_1 t_2\) \(i_1 + i_2 - i_1 i_2\) \(f_1 + f_2 - f_1 f_2\)
scale by \(k\) \(1 - (1 - t)^k\) \(i^k\) \(f^k\)
power by \(k\) \(t^k\) \(1 - (1 - i)^k\) \(1 - (1 - f)^k\)

Score (the only one, "average"): \((2 + t - i - f)/3\). Accuracy: "difference" (default) \(= t - f\) or "certainty" \(= t\). Distances divide by 3 instead of 2.

Parameters:

Name Type Description Default
t float

Truth degree in \([0, 1]\).

required
i float

Indeterminacy degree in \([0, 1]\).

required
f float

Falsity degree in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a part is outside \([0, 1]\) or not finite.

TypeError

If a part is a bool or a string.

Attributes:

Name Type Description
t float

Truth degree.

i float

Indeterminacy degree.

f float

Falsity degree.

References

Wang, Smarandache, Zhang and Sunderraman (2010), Single valued neutrosophic sets, Multispace and Multistructure 4.

Examples:

>>> from bulanik import NeutrosophicFN
>>> a = NeutrosophicFN(0.7, 0.2, 0.1)
>>> round(a.score(), 4), a.accuracy(), a.accuracy("certainty")
(0.8, 0.6, 0.7)
>>> a.complement()
NeutrosophicFN(t=0.1, i=0.8, f=0.7)

parts property

parts: tuple[float, float, float]

The three parts as a tuple, in the order of the constructor arguments.

Examples:

>>> from bulanik import PictureFN
>>> PictureFN(0.5, 0.2, 0.1).parts
(0.5, 0.2, 0.1)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type; the formulas are on each class.

A + B calls this method.

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import NeutrosophicFN
>>> s = NeutrosophicFN(0.7, 0.2, 0.1) + NeutrosophicFN(0.5, 0.3, 0.2)
>>> [round(p, 4) for p in s.parts]
[0.85, 0.06, 0.02]

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type; the formulas are on each class.

A * B calls this method.

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import PictureFN
>>> p = PictureFN(0.5, 0.2, 0.1) * PictureFN(0.4, 0.3, 0.2)
>>> [round(x, 4) for x in p.parts]
[0.43, 0.06, 0.28]

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A; the formulas are on each class.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint of the type (see PictureFN for k < 1).

Examples:

>>> from bulanik import NeutrosophicFN
>>> [round(p, 4) for p in NeutrosophicFN(0.7, 0.2, 0.1).scale(2).parts]
[0.91, 0.04, 0.01]

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k; the formulas are on each class.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import PictureFN
>>> [round(p, 4) for p in (PictureFN(0.5, 0.2, 0.1) ** 2).parts]
[0.45, 0.04, 0.19]

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance between two numbers.

With \(d_i\) the differences of the "simplex parts" of the two numbers (spherical: the squares plus the refusal \(1 - \mu^2 - \nu^2 - \pi^2\); picture: \(\mu, \eta, \nu\) and the refusal \(1 - \mu - \eta - \nu\); neutrosophic: \(t, i, f\)) the Hamming distance is \(\sum |d_i| / D\) and the Euclidean one \(\sqrt{\sum d_i^2 / D}\), with \(D = 2\) (spherical, picture) or \(D = 3\) (neutrosophic).

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If method is unknown.

Examples:

>>> from bulanik import NeutrosophicFN
>>> a, b = NeutrosophicFN(0.7, 0.2, 0.1), NeutrosophicFN(0.5, 0.3, 0.2)
>>> round(a.distance(b), 4)
0.1333

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

complement

complement() -> 'NeutrosophicFN'

Complement \((f, 1 - i, t)\).

Examples:

>>> from bulanik import NeutrosophicFN
>>> NeutrosophicFN(0.7, 0.2, 0.1).complement()
NeutrosophicFN(t=0.1, i=0.8, f=0.7)

score

score(method: str | None = None) -> float

Score \((2 + t - i - f)/3\) ("average", the only method).

Parameters:

Name Type Description Default
method str | None

"average" or None.

None

Returns:

Type Description
float

The score in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import NeutrosophicFN
>>> round(NeutrosophicFN(0.7, 0.2, 0.1).score(), 4)
0.8

accuracy

accuracy(method: str | None = None) -> float

Accuracy: \(t - f\) ("difference", default) or \(t\) ("certainty").

Parameters:

Name Type Description Default
method str | None

"difference", "certainty" or None.

None

Returns:

Type Description
float

The accuracy.

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import NeutrosophicFN
>>> a = NeutrosophicFN(0.7, 0.2, 0.1)
>>> round(a.accuracy(), 4), a.accuracy("certainty")
(0.6, 0.7)

PictureFN dataclass

PictureFN(mu: float, eta: float, nu: float)

Bases: _ThreePart

Picture fuzzy number \((\mu, \eta, \nu)\) with \(\mu + \eta + \nu \le 1\).

The parts are the degrees of positive membership, neutral membership and negative membership. Operations of Wei (2017), as the code evaluates them:

operation \(\mu\) \(\eta\) \(\nu\)
add \(\mu_1 + \mu_2 - \mu_1 \mu_2\) \(\eta_1 \eta_2\) \(\nu_1 \nu_2\)
mul \((\mu_1 + \eta_1)(\mu_2 + \eta_2) - \eta_1 \eta_2\) \(\eta_1 \eta_2\) \(\nu_1 + \nu_2 - \nu_1 \nu_2\)
scale by \(k\) \(1 - (1 - \mu)^k\) \(\eta^k\) \(\nu^k\)
power by \(k\) \((\mu + \eta)^k - \eta^k\) \(\eta^k\) \(1 - (1 - \nu)^k\)

Multiplication and power are closed; addition is too. Scaling by \(k < 1\) can leave the constraint set (\(\eta^k + \nu^k\) may exceed \((1 - \mu)^k\)) and then raises ValueError, as does \(k = 0\), because the additive identity \((0, 1, 1)\) is not itself a valid number. The weighted aggregations wa and wg use closed forms that avoid this.

Scores: "difference" (default) \(= \mu - \nu\) and "normalized" \(= (1 + \mu - \nu)/2\). Accuracy "sum" \(= \mu + \eta + \nu\).

Parameters:

Name Type Description Default
mu float

Positive membership degree in \([0, 1]\).

required
eta float

Neutral membership degree in \([0, 1]\).

required
nu float

Negative membership degree in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a part is outside \([0, 1]\) or not finite, or \(\mu + \eta + \nu > 1\) beyond rounding.

TypeError

If a part is a bool or a string.

Attributes:

Name Type Description
mu float

Positive membership degree.

eta float

Neutral membership degree.

nu float

Negative membership degree.

References

Wei (2017), Journal of Intelligent & Fuzzy Systems 33(2): "Picture fuzzy aggregation operators and their application to multiple attribute decision making". Cuong (2014), Journal of Computer Science and Cybernetics 30(4), 409-420: picture fuzzy sets. Note: Wei (2017) was retracted by the publisher in 2025; the closed forms are kept as documented and are tested against the code, not the paper.

Examples:

>>> from bulanik import PictureFN
>>> a = PictureFN(0.5, 0.2, 0.1)
>>> round(a.score(), 4), round(a.accuracy(), 4)
(0.4, 0.8)
>>> a.scale(0.5)
Traceback (most recent call last):
...
ValueError: result violates mu + eta + nu <= 1 (sum 1.0...)

parts property

parts: tuple[float, float, float]

The three parts as a tuple, in the order of the constructor arguments.

Examples:

>>> from bulanik import PictureFN
>>> PictureFN(0.5, 0.2, 0.1).parts
(0.5, 0.2, 0.1)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type; the formulas are on each class.

A + B calls this method.

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import NeutrosophicFN
>>> s = NeutrosophicFN(0.7, 0.2, 0.1) + NeutrosophicFN(0.5, 0.3, 0.2)
>>> [round(p, 4) for p in s.parts]
[0.85, 0.06, 0.02]

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type; the formulas are on each class.

A * B calls this method.

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import PictureFN
>>> p = PictureFN(0.5, 0.2, 0.1) * PictureFN(0.4, 0.3, 0.2)
>>> [round(x, 4) for x in p.parts]
[0.43, 0.06, 0.28]

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A; the formulas are on each class.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint of the type (see PictureFN for k < 1).

Examples:

>>> from bulanik import NeutrosophicFN
>>> [round(p, 4) for p in NeutrosophicFN(0.7, 0.2, 0.1).scale(2).parts]
[0.91, 0.04, 0.01]

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k; the formulas are on each class.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import PictureFN
>>> [round(p, 4) for p in (PictureFN(0.5, 0.2, 0.1) ** 2).parts]
[0.45, 0.04, 0.19]

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance between two numbers.

With \(d_i\) the differences of the "simplex parts" of the two numbers (spherical: the squares plus the refusal \(1 - \mu^2 - \nu^2 - \pi^2\); picture: \(\mu, \eta, \nu\) and the refusal \(1 - \mu - \eta - \nu\); neutrosophic: \(t, i, f\)) the Hamming distance is \(\sum |d_i| / D\) and the Euclidean one \(\sqrt{\sum d_i^2 / D}\), with \(D = 2\) (spherical, picture) or \(D = 3\) (neutrosophic).

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If method is unknown.

Examples:

>>> from bulanik import NeutrosophicFN
>>> a, b = NeutrosophicFN(0.7, 0.2, 0.1), NeutrosophicFN(0.5, 0.3, 0.2)
>>> round(a.distance(b), 4)
0.1333

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

complement

complement() -> 'PictureFN'

Complement \((\nu, \eta, \mu)\): positive and negative degrees swapped.

Examples:

>>> from bulanik import PictureFN
>>> PictureFN(0.5, 0.2, 0.1).complement()
PictureFN(mu=0.1, eta=0.2, nu=0.5)

score

score(method: str | None = None) -> float

Score \(\mu - \nu\) ("difference", default) or \((1 + \mu - \nu)/2\) ("normalized").

Parameters:

Name Type Description Default
method str | None

"difference" or "normalized"; None means "difference".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import PictureFN
>>> round(PictureFN(0.5, 0.2, 0.1).score("normalized"), 4)
0.7

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\mu + \eta + \nu\) ("sum", the only method).

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import PictureFN
>>> round(PictureFN(0.5, 0.2, 0.1).accuracy(), 4)
0.8

SphericalFN dataclass

SphericalFN(mu: float, nu: float, pi: float)

Bases: _ThreePart

Spherical fuzzy number \((\mu, \nu, \pi)\) with \(\mu^2 + \nu^2 + \pi^2 \le 1\).

Operations of Kutlu Gundogdu and Kahraman (2019), evaluated on the squares \((a, b, c) = (\mu^2, \nu^2, \pi^2)\) and the exact refusal \(r = 1 - a - b - c\) (squares of the results are taken back with a square root):

operation \(\mu^2\) \(\nu^2\) \(\pi^2\)
add \(1 - (1 - a_1)(1 - a_2)\) \(b_1 b_2\) \((1 - a_1)(1 - a_2) - (b_1 + r_1)(b_2 + r_2)\)
mul \(a_1 a_2\) \(1 - (1 - b_1)(1 - b_2)\) \((1 - b_1)(1 - b_2) - (a_1 + r_1)(a_2 + r_2)\)
scale by \(k\) \(1 - (1 - a)^k\) \(b^k\) \((1 - a)^k - (1 - a - c)^k\)
power by \(k\) \(a^k\) \(1 - (1 - b)^k\) \((1 - b)^k - (1 - b - c)^k\)

Scores: "pi_adjusted" (default) \(= (\mu - \pi)^2 - (\nu - \pi)^2\) and "normalized" \(= (1 + \text{pi_adjusted})/2\). Accuracy "sum" \(= \mu^2 + \nu^2 + \pi^2\).

Limit: a part below about 1.5e-154 squares to 0.0 in a double, so it behaves as 0 in the operations (absolute error < 1.5e-154; the sqrt of a result part is likewise exact only down to that scale). Parts that small carry no information at double precision, so no log-domain arithmetic is used.

Parameters:

Name Type Description Default
mu float

Membership degree in \([0, 1]\).

required
nu float

Non-membership degree in \([0, 1]\).

required
pi float

Hesitancy degree in \([0, 1]\).

required

Raises:

Type Description
ValueError

If a part is outside \([0, 1]\) or not finite, or \(\mu^2 + \nu^2 + \pi^2 > 1\) beyond rounding.

TypeError

If a part is a bool or a string.

Attributes:

Name Type Description
mu float

Membership degree.

nu float

Non-membership degree.

pi float

Hesitancy degree.

References

Kutlu Gundogdu and Kahraman (2019), Journal of Intelligent & Fuzzy Systems 36(1), 337-352: "Spherical fuzzy sets and spherical fuzzy TOPSIS method".

Examples:

>>> from bulanik import SphericalFN
>>> a = SphericalFN(0.5, 0.4, 0.3)
>>> round(a.score(), 4), round(a.accuracy(), 4)
(0.03, 0.5)
>>> s = a + SphericalFN(0.4, 0.3, 0.2)
>>> [round(p, 4) for p in s.parts]
[0.6083, 0.12, 0.3194]
>>> SphericalFN(0.8, 0.5, 0.5)
Traceback (most recent call last):
...
ValueError: need mu^2 + nu^2 + pi^2 <= 1, got mu=0.8, nu=0.5, pi=0.5 (sum 1.14)

parts property

parts: tuple[float, float, float]

The three parts as a tuple, in the order of the constructor arguments.

Examples:

>>> from bulanik import PictureFN
>>> PictureFN(0.5, 0.2, 0.1).parts
(0.5, 0.2, 0.1)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum of two numbers of the same type; the formulas are on each class.

A + B calls this method.

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The sum, of the same class.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import NeutrosophicFN
>>> s = NeutrosophicFN(0.7, 0.2, 0.1) + NeutrosophicFN(0.5, 0.3, 0.2)
>>> [round(p, 4) for p in s.parts]
[0.85, 0.06, 0.02]

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product of two numbers of the same type; the formulas are on each class.

A * B calls this method.

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The product, of the same class.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import PictureFN
>>> p = PictureFN(0.5, 0.2, 0.1) * PictureFN(0.4, 0.3, 0.2)
>>> [round(x, 4) for x in p.parts]
[0.43, 0.06, 0.28]

scale

scale(k: float, ops: str = 'algebraic') -> Any

Scalar multiple k * A; the formulas are on each class.

Parameters:

Name Type Description Default
k float

A finite scalar \(\ge 0\).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint of the type (see PictureFN for k < 1).

Examples:

>>> from bulanik import NeutrosophicFN
>>> [round(p, 4) for p in NeutrosophicFN(0.7, 0.2, 0.1).scale(2).parts]
[0.91, 0.04, 0.01]

power

power(k: float, ops: str = 'algebraic') -> Any

Power A ** k; the formulas are on each class.

Parameters:

Name Type Description Default
k float

A finite exponent \(\ge 0\).

required
ops str

Only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The power, of the same class.

Raises:

Type Description
ValueError

If k is negative or not finite, ops is unknown, or the result violates the constraint of the type beyond rounding.

Examples:

>>> from bulanik import PictureFN
>>> [round(p, 4) for p in (PictureFN(0.5, 0.2, 0.1) ** 2).parts]
[0.45, 0.04, 0.19]

distance

distance(other: Any, method: str | None = None) -> float

Normalized Hamming (default) or Euclidean distance between two numbers.

With \(d_i\) the differences of the "simplex parts" of the two numbers (spherical: the squares plus the refusal \(1 - \mu^2 - \nu^2 - \pi^2\); picture: \(\mu, \eta, \nu\) and the refusal \(1 - \mu - \eta - \nu\); neutrosophic: \(t, i, f\)) the Hamming distance is \(\sum |d_i| / D\) and the Euclidean one \(\sqrt{\sum d_i^2 / D}\), with \(D = 2\) (spherical, picture) or \(D = 3\) (neutrosophic).

Parameters:

Name Type Description Default
other Any

A number of the same class.

required
method str | None

"hamming" or "euclidean"; None means "hamming".

None

Returns:

Type Description
float

The distance.

Raises:

Type Description
TypeError

If other is of a different class.

ValueError

If method is unknown.

Examples:

>>> from bulanik import NeutrosophicFN
>>> a, b = NeutrosophicFN(0.7, 0.2, 0.1), NeutrosophicFN(0.5, 0.3, 0.2)
>>> round(a.distance(b), 4)
0.1333

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

complement

complement() -> 'SphericalFN'

Complement \((\nu, \mu, \pi)\): membership and non-membership swapped.

Examples:

>>> from bulanik import SphericalFN
>>> SphericalFN(0.5, 0.4, 0.3).complement()
SphericalFN(mu=0.4, nu=0.5, pi=0.3)

score

score(method: str | None = None) -> float

Score \((\mu - \pi)^2 - (\nu - \pi)^2\) ("pi_adjusted", default) or its "normalized" form \((1 + s)/2\).

Parameters:

Name Type Description Default
method str | None

"pi_adjusted" or "normalized"; None means "pi_adjusted".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import SphericalFN
>>> round(SphericalFN(0.5, 0.4, 0.3).score("normalized"), 4)
0.515

accuracy

accuracy(method: str | None = None) -> float

Accuracy \(\mu^2 + \nu^2 + \pi^2\) ("sum", the only method).

Parameters:

Name Type Description Default
method str | None

"sum" or None.

None

Returns:

Type Description
float

The accuracy in \([0, 1]\).

Raises:

Type Description
ValueError

If method is unknown.

Examples:

>>> from bulanik import SphericalFN
>>> round(SphericalFN(0.5, 0.4, 0.3).accuracy(), 4)
0.5

TFN dataclass

TFN(l: float, m: float, u: float)

Bases: _Piecewise

Triangular fuzzy number \((l, m, u)\) with \(l \le m \le u\).

The membership rises linearly from 0 at l to 1 at m and falls to 0 at u. Points are converted to floats. Arithmetic, scores and membership are documented on the shared methods (add, sub, mul, scale, power, reciprocal, alpha_cut, mu, score, defuzzify, distance); the operators + - * / and ** and unary - call them.

Parameters:

Name Type Description Default
l float

Lower foot.

required
m float

Peak (core).

required
u float

Upper foot.

required

Raises:

Type Description
ValueError

If a point is NaN or infinite, or the points are not ordered l <= m <= u.

TypeError

If a point is a bool or a string.

Attributes:

Name Type Description
l float

Lower foot.

m float

Peak.

u float

Upper foot.

Examples:

>>> from bulanik import TFN
>>> a = TFN(1, 2, 4)
>>> a
TFN(l=1.0, m=2.0, u=4.0)
>>> a / TFN(2, 3, 5)
TFN(l=0.2, m=0.6666666666666666, u=2.0)
>>> TFN(3, 2, 1)
Traceback (most recent call last):
...
ValueError: TFN needs l <= m <= u, got (3.0, 2.0, 1.0)

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum, pointwise: \((x_1, \dots, x_n) + (y_1, \dots, y_n) = (x_i + y_i)\).

Parameters:

Name Type Description Default
other Any

A number of the same type.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The sum, of the same type.

Raises:

Type Description
TypeError

If other is not the same type.

ValueError

If ops is not "algebraic".

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).add(TFN(2, 3, 5))
TFN(l=3.0, m=5.0, u=9.0)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product, the standard approximate (point-based) multiplication.

The outer points are the smallest and largest of the four products of the two outer points of each operand, and the inner points are the products of the inner points (sorted). For non-negative numbers this is the componentwise product \((l_1 l_2,\; m_1 m_2,\; u_1 u_2)\).

Parameters:

Name Type Description Default
other Any

A number of the same type.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The product, of the same type.

Raises:

Type Description
TypeError

If other is not the same type.

ValueError

If ops is not "algebraic".

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4) * TFN(2, 3, 5)
TFN(l=2.0, m=6.0, u=20.0)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Multiply every point by the real number k.

A negative k also reverses the order of the points, so the result stays ordered. k * A, A * k and A / k call this method.

Parameters:

Name Type Description Default
k float

The scalar.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same type.

Raises:

Type Description
TypeError

If k is not a real number (bool and str are rejected).

ValueError

If k is not finite, or ops is not "algebraic".

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).scale(2)
TFN(l=2.0, m=4.0, u=8.0)
>>> TFN(1, 2, 4).scale(-1)
TFN(l=-4.0, m=-2.0, u=-1.0)

power

power(k: float, ops: str = 'algebraic') -> Any

Raise every point to the real power k; A ** k calls this method.

For a negative k the order of the points is reversed. The lowest point must be non-negative (strictly positive when k < 0).

Parameters:

Name Type Description Default
k float

The exponent.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The power, of the same type.

Raises:

Type Description
TypeError

If k is not a real number (bool and str are rejected).

ValueError

If k is not finite, ops is not "algebraic", or the lowest point is negative (or zero with k < 0).

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4) ** 2
TFN(l=1.0, m=4.0, u=16.0)
>>> TFN(-1, 2, 4).power(2)
Traceback (most recent call last):
...
ValueError: power 2.0 needs the lowest point >= 0, got -1.0

score

score(method: str | None = None) -> float

Crisp score for ranking; same as defuzzify, default "centroid".

For a triangle \((l, m, u)\): centroid \(= (l + m + u)/3\) (also the mean), graded mean \(= (l + 4m + u)/6\). For a trapezoid \((a, b, c, d)\): graded mean \(= (a + 2b + 2c + d)/6\), mean \(= (a + b + c + d)/4\) and centroid \(= \dfrac{d^2 + c^2 + cd - a^2 - b^2 - ab}{3\,(d + c - a - b)}\) (the common point a if all four points coincide).

Parameters:

Name Type Description Default
method str | None

One of "centroid", "graded_mean", "mean"; None means "centroid".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is not one of the three names.

Examples:

>>> from bulanik import TFN, TrFN
>>> round(TFN(1, 2, 4).score(), 4)
2.3333
>>> TrFN(1, 2, 3, 5).score("mean")
2.75

accuracy

accuracy(method: str | None = None) -> float

Not defined for triangular and trapezoidal numbers.

Parameters:

Name Type Description Default
method str | None

Ignored.

None

Raises:

Type Description
ValueError

Always.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).accuracy()
Traceback (most recent call last):
...
ValueError: TFN has no accuracy function

distance

distance(other: Any, method: str | None = None) -> float

Vertex distance (Chen 2000): \(\sqrt{\tfrac{1}{n}\sum_i (x_i - y_i)^2}\) over the \(n\) points.

Parameters:

Name Type Description Default
other Any

A number of the same type.

required
method str | None

Only "vertex" exists (the default).

None

Returns:

Type Description
float

The distance.

Raises:

Type Description
TypeError

If other is not the same type.

ValueError

If method is not "vertex".

References

Chen (2000), Fuzzy Sets and Systems 114: the vertex method.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).distance(TFN(2, 3, 5))
1.0

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

sub

sub(other: Any, ops: str = 'algebraic') -> Any

Difference \(A - B\), pairing each point of \(A\) with the opposite point of \(B\).

For a triangle, \((l_1, m_1, u_1) - (l_2, m_2, u_2) = (l_1 - u_2,\; m_1 - m_2,\; u_1 - l_2)\). The operator A - B calls this method.

Parameters:

Name Type Description Default
other Any

A number of the same type.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The difference, of the same type.

Raises:

Type Description
TypeError

If other is not the same type.

ValueError

If ops is not "algebraic".

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4) - TFN(2, 3, 5)
TFN(l=-4.0, m=-1.0, u=2.0)

reciprocal

reciprocal() -> Any

Reciprocal \(1 / A\), taking \(1/x\) of every point in reversed order.

A / B computes A * B.reciprocal().

Returns:

Type Description
Any

The reciprocal, of the same type.

Raises:

Type Description
ValueError

If the support \([\text{lowest}, \text{highest}]\) contains 0.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).reciprocal()
TFN(l=0.25, m=0.5, u=1.0)
>>> TFN(-1, 0, 1).reciprocal()
Traceback (most recent call last):
...
ValueError: cannot take the reciprocal of TFN(l=-1.0, m=0.0, u=1.0): its support contains 0

alpha_cut

alpha_cut(alpha: float) -> tuple[float, float]

The alpha-cut \(\{x : \mu(x) \ge \alpha\}\) as an interval.

With support \([p_0, p_n]\) and core \([c_\text{lo}, c_\text{hi}]\) the cut is \([p_0 + \alpha (c_\text{lo} - p_0),\; p_n - \alpha (p_n - c_\text{hi})]\).

Parameters:

Name Type Description Default
alpha float

Membership level in \([0, 1]\).

required

Returns:

Type Description
tuple[float, float]

The pair (lower, upper).

Raises:

Type Description
ValueError

If alpha is outside [0, 1] or not finite.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).alpha_cut(0.5)
(1.5, 3.0)
>>> TFN(1, 2, 4).alpha_cut(1)
(2.0, 2.0)

mu

mu(x: float) -> float

Membership degree \(\mu(x)\): piecewise linear, 1 on the core, 0 outside the support.

Parameters:

Name Type Description Default
x float

A real number.

required

Returns:

Type Description
float

The membership degree in \([0, 1]\).

Raises:

Type Description
ValueError

If x is NaN or infinite.

Examples:

>>> from bulanik import TFN, TrFN
>>> TFN(1, 2, 4).mu(1.5)
0.5
>>> TrFN(0, 1, 2, 4).mu(1.5)
1.0

defuzzify

defuzzify(method: str = 'centroid') -> float

Crisp value of the number (the same functions as score).

Methods: "centroid" (centre of gravity), "graded_mean" (graded mean integration) and "mean" (arithmetic mean of the points; equal to the centroid for a triangle).

Parameters:

Name Type Description Default
method str

One of "centroid", "graded_mean", "mean".

'centroid'

Returns:

Type Description
float

The crisp value.

Raises:

Type Description
ValueError

If method is not one of the three names.

Examples:

>>> from bulanik import TFN
>>> round(TFN(1, 2, 4).defuzzify("graded_mean"), 4)
2.1667

to_trfn

to_trfn() -> 'TrFN'

Convert to the equivalent trapezoid \((l, m, m, u)\).

Returns:

Type Description
'TrFN'

A TrFN with a one-point core.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).to_trfn()
TrFN(a=1.0, b=2.0, c=2.0, d=4.0)

TrFN dataclass

TrFN(a: float, b: float, c: float, d: float)

Bases: _Piecewise

Trapezoidal fuzzy number \((a, b, c, d)\) with \(a \le b \le c \le d\).

The membership rises from 0 at a to 1 at b, stays 1 up to c and falls to 0 at d. It offers the same methods and operators as TFN.

Parameters:

Name Type Description Default
a float

Lower foot.

required
b float

Start of the core.

required
c float

End of the core.

required
d float

Upper foot.

required

Raises:

Type Description
ValueError

If a point is NaN or infinite, or the points are not ordered.

TypeError

If a point is a bool or a string.

Attributes:

Name Type Description
a float

Lower foot.

b float

Start of the core.

c float

End of the core.

d float

Upper foot.

Examples:

>>> from bulanik import TrFN
>>> t = TrFN(1, 2, 3, 5)
>>> t.alpha_cut(0.5)
(1.5, 4.0)
>>> round(t.score(), 4)
2.8
>>> t.accuracy()
Traceback (most recent call last):
...
ValueError: TrFN has no accuracy function

add

add(other: Any, ops: str = 'algebraic') -> Any

Sum, pointwise: \((x_1, \dots, x_n) + (y_1, \dots, y_n) = (x_i + y_i)\).

Parameters:

Name Type Description Default
other Any

A number of the same type.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The sum, of the same type.

Raises:

Type Description
TypeError

If other is not the same type.

ValueError

If ops is not "algebraic".

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).add(TFN(2, 3, 5))
TFN(l=3.0, m=5.0, u=9.0)

mul

mul(other: Any, ops: str = 'algebraic') -> Any

Product, the standard approximate (point-based) multiplication.

The outer points are the smallest and largest of the four products of the two outer points of each operand, and the inner points are the products of the inner points (sorted). For non-negative numbers this is the componentwise product \((l_1 l_2,\; m_1 m_2,\; u_1 u_2)\).

Parameters:

Name Type Description Default
other Any

A number of the same type.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The product, of the same type.

Raises:

Type Description
TypeError

If other is not the same type.

ValueError

If ops is not "algebraic".

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4) * TFN(2, 3, 5)
TFN(l=2.0, m=6.0, u=20.0)

scale

scale(k: float, ops: str = 'algebraic') -> Any

Multiply every point by the real number k.

A negative k also reverses the order of the points, so the result stays ordered. k * A, A * k and A / k call this method.

Parameters:

Name Type Description Default
k float

The scalar.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The scaled number, of the same type.

Raises:

Type Description
TypeError

If k is not a real number (bool and str are rejected).

ValueError

If k is not finite, or ops is not "algebraic".

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).scale(2)
TFN(l=2.0, m=4.0, u=8.0)
>>> TFN(1, 2, 4).scale(-1)
TFN(l=-4.0, m=-2.0, u=-1.0)

power

power(k: float, ops: str = 'algebraic') -> Any

Raise every point to the real power k; A ** k calls this method.

For a negative k the order of the points is reversed. The lowest point must be non-negative (strictly positive when k < 0).

Parameters:

Name Type Description Default
k float

The exponent.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The power, of the same type.

Raises:

Type Description
TypeError

If k is not a real number (bool and str are rejected).

ValueError

If k is not finite, ops is not "algebraic", or the lowest point is negative (or zero with k < 0).

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4) ** 2
TFN(l=1.0, m=4.0, u=16.0)
>>> TFN(-1, 2, 4).power(2)
Traceback (most recent call last):
...
ValueError: power 2.0 needs the lowest point >= 0, got -1.0

score

score(method: str | None = None) -> float

Crisp score for ranking; same as defuzzify, default "centroid".

For a triangle \((l, m, u)\): centroid \(= (l + m + u)/3\) (also the mean), graded mean \(= (l + 4m + u)/6\). For a trapezoid \((a, b, c, d)\): graded mean \(= (a + 2b + 2c + d)/6\), mean \(= (a + b + c + d)/4\) and centroid \(= \dfrac{d^2 + c^2 + cd - a^2 - b^2 - ab}{3\,(d + c - a - b)}\) (the common point a if all four points coincide).

Parameters:

Name Type Description Default
method str | None

One of "centroid", "graded_mean", "mean"; None means "centroid".

None

Returns:

Type Description
float

The score.

Raises:

Type Description
ValueError

If method is not one of the three names.

Examples:

>>> from bulanik import TFN, TrFN
>>> round(TFN(1, 2, 4).score(), 4)
2.3333
>>> TrFN(1, 2, 3, 5).score("mean")
2.75

accuracy

accuracy(method: str | None = None) -> float

Not defined for triangular and trapezoidal numbers.

Parameters:

Name Type Description Default
method str | None

Ignored.

None

Raises:

Type Description
ValueError

Always.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).accuracy()
Traceback (most recent call last):
...
ValueError: TFN has no accuracy function

distance

distance(other: Any, method: str | None = None) -> float

Vertex distance (Chen 2000): \(\sqrt{\tfrac{1}{n}\sum_i (x_i - y_i)^2}\) over the \(n\) points.

Parameters:

Name Type Description Default
other Any

A number of the same type.

required
method str | None

Only "vertex" exists (the default).

None

Returns:

Type Description
float

The distance.

Raises:

Type Description
TypeError

If other is not the same type.

ValueError

If method is not "vertex".

References

Chen (2000), Fuzzy Sets and Systems 114: the vertex method.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).distance(TFN(2, 3, 5))
1.0

same_kind

same_kind(other: Any) -> None

Check that other has the same class (and q, when present) as self.

Parameters:

Name Type Description Default
other Any

The object to compare against.

required

Raises:

Type Description
TypeError

If the classes or the rungs differ.

Examples:

>>> from bulanik import PFN, FFN
>>> PFN(0.5, 0.5).same_kind(PFN(0.1, 0.2))
>>> PFN(0.5, 0.5).same_kind(FFN(0.1, 0.2))
Traceback (most recent call last):
...
TypeError: cannot combine PFN(q=2) with FFN(q=3)

sub

sub(other: Any, ops: str = 'algebraic') -> Any

Difference \(A - B\), pairing each point of \(A\) with the opposite point of \(B\).

For a triangle, \((l_1, m_1, u_1) - (l_2, m_2, u_2) = (l_1 - u_2,\; m_1 - m_2,\; u_1 - l_2)\). The operator A - B calls this method.

Parameters:

Name Type Description Default
other Any

A number of the same type.

required
ops str

Operator set; only "algebraic" exists.

'algebraic'

Returns:

Type Description
Any

The difference, of the same type.

Raises:

Type Description
TypeError

If other is not the same type.

ValueError

If ops is not "algebraic".

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4) - TFN(2, 3, 5)
TFN(l=-4.0, m=-1.0, u=2.0)

reciprocal

reciprocal() -> Any

Reciprocal \(1 / A\), taking \(1/x\) of every point in reversed order.

A / B computes A * B.reciprocal().

Returns:

Type Description
Any

The reciprocal, of the same type.

Raises:

Type Description
ValueError

If the support \([\text{lowest}, \text{highest}]\) contains 0.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).reciprocal()
TFN(l=0.25, m=0.5, u=1.0)
>>> TFN(-1, 0, 1).reciprocal()
Traceback (most recent call last):
...
ValueError: cannot take the reciprocal of TFN(l=-1.0, m=0.0, u=1.0): its support contains 0

alpha_cut

alpha_cut(alpha: float) -> tuple[float, float]

The alpha-cut \(\{x : \mu(x) \ge \alpha\}\) as an interval.

With support \([p_0, p_n]\) and core \([c_\text{lo}, c_\text{hi}]\) the cut is \([p_0 + \alpha (c_\text{lo} - p_0),\; p_n - \alpha (p_n - c_\text{hi})]\).

Parameters:

Name Type Description Default
alpha float

Membership level in \([0, 1]\).

required

Returns:

Type Description
tuple[float, float]

The pair (lower, upper).

Raises:

Type Description
ValueError

If alpha is outside [0, 1] or not finite.

Examples:

>>> from bulanik import TFN
>>> TFN(1, 2, 4).alpha_cut(0.5)
(1.5, 3.0)
>>> TFN(1, 2, 4).alpha_cut(1)
(2.0, 2.0)

mu

mu(x: float) -> float

Membership degree \(\mu(x)\): piecewise linear, 1 on the core, 0 outside the support.

Parameters:

Name Type Description Default
x float

A real number.

required

Returns:

Type Description
float

The membership degree in \([0, 1]\).

Raises:

Type Description
ValueError

If x is NaN or infinite.

Examples:

>>> from bulanik import TFN, TrFN
>>> TFN(1, 2, 4).mu(1.5)
0.5
>>> TrFN(0, 1, 2, 4).mu(1.5)
1.0

defuzzify

defuzzify(method: str = 'centroid') -> float

Crisp value of the number (the same functions as score).

Methods: "centroid" (centre of gravity), "graded_mean" (graded mean integration) and "mean" (arithmetic mean of the points; equal to the centroid for a triangle).

Parameters:

Name Type Description Default
method str

One of "centroid", "graded_mean", "mean".

'centroid'

Returns:

Type Description
float

The crisp value.

Raises:

Type Description
ValueError

If method is not one of the three names.

Examples:

>>> from bulanik import TFN
>>> round(TFN(1, 2, 4).defuzzify("graded_mean"), 4)
2.1667