Source code for fuzzy_set.trapezoidal_fuzzy_number

# © 2025 Nokia
# Licensed under the BSD 3-Clause License
# SPDX-License-Identifier: BSD-3-Clause

from .fuzzy_number import FuzzyNumber


[docs] class TrapezoidalFuzzyNumber(FuzzyNumber): """ A *Trapezoidal Fuzzy Number (TFN)* is a Fuzzy Number (FN) which is piecewise linear and continuous. Thus, it has a trapezoidal shape. As a consequence, a TFN is fully characterized by a quadruple of real numbers, denoted by :math:`[x_1, x_2, x_3, x_4]`, where: - :math:`x_1 \\le ... \\le x_4`; - :math:`[x_1, x_4]` is the support of the TFN; - :math:`[x_2, x_3]` is the core of the TFN. Trapezoidal Fuzzy Numbers support arithmetic operators, i.e., +, -, \\*, /. See `Reliability Range Through Upgraded Operation with TFN <https://www.tandfonline.com/doi/full/10.1080/16168658.2021.1918039#d1e133>`__. **Example:** >>> from fuzzy_set import TrapezoidalFuzzyNumber >>> t1 = TrapezoidalFuzzyNumber(1, 3, 8, 10) >>> t2 = TrapezoidalFuzzyNumber(2, 5, 7, 8) >>> t1 + t2 TrapezoidalFuzzyNumber<(3, 8, 15, 18)> >>> t1 - t2 TrapezoidalFuzzyNumber<(-7, -4, 3, 8)> >>> t1 * t2 TrapezoidalFuzzyNumber<(2, 15, 56, 80)> >>> t1 / t2 TrapezoidalFuzzyNumber<(0.125, 0.42857142857142855, 1.6, 5.0)> **Example:** .. code-block:: python import matplotlib.pyplot as plt from operator import __add__, __sub__, __mul__, __truediv__ (fig, axs) = plt.subplots(2, 2) for (ij, (op, opname)) in { (0, 0): (__add__, "+"), (0, 1): (__sub__, "-"), (1, 0): (__mul__, "\\cdot"), (1, 1): (__truediv__, "/"), }.items(): ax = axs[ij] title = f"$a_1 {opname} a_2$" ax.set_title(title) t1.plot(ax=ax, label="$a_1$") t2.plot(ax=ax, label="$a_2$") op(t1, t2).plot(ax=axs[ij], label=title) ax.grid() ax.legend() ax.legend(bbox_to_anchor=(1, 0.5), loc="center left") plt.tight_layout() """ def __init__(self, x1: float, x2: float, x3: float, x4: float): """ Constructor. Makes a _Trapezoidal Fuzzy Number (TFN)_ from four real numbers :math:`x_1 \\le x_2 \\le x_3 \\le x_4``. Args: x1 (float): The value of :math:`x_1`. x2 (float): The value of :math:`x_2`. x3 (float): The value of :math:`x_3`. x4 (float): The value of :math:`x_4`. """ assert x1 <= x2 <= x3 <= x4, (x1, x2, x3, x4) super().__init__({x1: 0, x2: 1, x3: 1, x4: 0}) self.x1 = x1 self.x2 = x2 self.x3 = x3 self.x4 = x4 def _init_xis(self): pass def _check_convexity(self, points: dict[float, float]): pass def __add__( self, other: "TrapezoidalFuzzyNumber" ) -> "TrapezoidalFuzzyNumber": """ Adds this :math:`[a_1, a_2, a_3, a_4]` TFN and another :math:`[b_1, b_2, b_3, b_4]` TFN. Args: other (TrapezoidalFuzzyNumber): The other TFN. Returns: The resulting :math:`[a_1 + b_1, a_2 + b_2, a_3 + b_3, a_4 + b_4]` TFN. """ return self.__class__( self.x1 + other.x1, self.x2 + other.x2, self.x3 + other.x3, self.x4 + other.x4 ) def __sub__( self, other: "TrapezoidalFuzzyNumber" ) -> "TrapezoidalFuzzyNumber": """ Subtracts this :math:`[a_1, a_2, a_3, a_4]` TFN and another :math:`[b_1, b_2, b_3, b_4]` TFN. Args: other (TrapezoidalFuzzyNumber): The other TFN. Returns: The resulting :math:`[a_1 - b_4, a_2 - b_3, a_3 - b_2, a_4 - b_1]` TFN. """ return self.__class__( self.x1 - other.x4, self.x2 - other.x3, self.x3 - other.x2, self.x4 - other.x1 ) def __mul__( self, other: "TrapezoidalFuzzyNumber" ) -> "TrapezoidalFuzzyNumber": """ Approximates the multiplication of this :math:`[a_1, a_2, a_3, a_4]` TFN and another :math:`[b_1, b_2, b_3, b_4]` TFN. Args: other (TrapezoidalFuzzyNumber): The other TFN. Returns: The resulting approximated :math:`[a_1 \\cdot b_1, a_2 \\cdot b_2, a_3 \\cdot b_3, a_4 \\cdot b_4]` TFN. """ return self.__class__( self.x1 * other.x1, self.x2 * other.x2, self.x3 * other.x3, self.x4 * other.x4 ) def __truediv__( self, other: "TrapezoidalFuzzyNumber" ) -> "TrapezoidalFuzzyNumber": """ Approximates the division of this :math:`[a_1, a_2, a_3, a_4]` TFN and another :math:`[b_1, b_2, b_3, b_4]` TFN. Args: other (TrapezoidalFuzzyNumber): The other TFN. Returns: The resulting approximated :math:`[a_1 / b_4, a_2 / b_3, a_3 / b_2, a_4 / b_1]` TFN. """ return self.__class__( self.x1 / other.x4, self.x2 / other.x3, self.x3 / other.x2, self.x4 / other.x1 ) def __repr__(self) -> str: return ( f"{self.__class__.__name__}" f"<{self.x1, self.x2, self.x3, self.x4}>" ) def __str__(self) -> str: return self.__repr__()