By Shreya123714 https:en.wikipedia.orgwikiFuzzyset A class for representing and manipulating triangular fuzzy sets. Attributes: name: The name or label of the fuzzy set. leftboundary: The left boundary of the fuzzy set. peak: The peak central value of the fuzzy set. rightboundary: The right boundary of the fuzzy set. Methods: membershipx: Calculate the membership value of an input 'x' in the fuzzy set. unionother: Calculate the union of this fuzzy set with another fuzzy set. intersectionother: Calculate the intersection of this fuzzy set with another. complement: Calculate the complement negation of this fuzzy set. plot: Plot the membership function of the fuzzy set.  sheru  FuzzySetSheru, 0.4, 1, 0.6  sheru FuzzySetname'Sheru', leftboundary0.4, peak1, rightboundary0.6  strsheru 'Sheru: 0.4, 1, 0.6'  siya  FuzzySetSiya, 0.5, 1, 0.7  siya FuzzySetname'Siya', leftboundary0.5, peak1, rightboundary0.7 Complement Operation  sheru.complement FuzzySetname'Sheru', leftboundary0.4, peak0.6, rightboundary0  siya.complement   doctest: NORMALIZEWHITESPACE FuzzySetname'Siya', leftboundary0.30000000000000004, peak0.5, rightboundary0 Intersection Operation  siya.intersectionsheru FuzzySetname'Siya  Sheru', leftboundary0.5, peak0.6, rightboundary1.0 Membership Operation  sheru.membership0.5 0.16666666666666663  sheru.membership0.6 0.0 Union Operations  siya.unionsheru FuzzySetname'Siya  Sheru', leftboundary0.4, peak0.7, rightboundary1.0  FuzzySetfuzzyset, 0.1, 0.2, 0.3 FuzzySetname'fuzzyset', leftboundary0.1, peak0.2, rightboundary0.3 Calculate the complement negation of this fuzzy set. Returns: FuzzySet: A new fuzzy set representing the complement.  FuzzySetfuzzyset, 0.1, 0.2, 0.3.complement FuzzySetname'fuzzyset', leftboundary0.7, peak0.9, rightboundary0.8 Calculate the intersection of this fuzzy set with another fuzzy set. Args: other: Another fuzzy set to intersect with. Returns: A new fuzzy set representing the intersection.  FuzzySeta, 0.1, 0.2, 0.3.intersectionFuzzySetb, 0.4, 0.5, 0.6 FuzzySetname'a  b', leftboundary0.4, peak0.3, rightboundary0.35 Calculate the membership value of an input 'x' in the fuzzy set. Returns: The membership value of 'x' in the fuzzy set.  a  FuzzySeta, 0.1, 0.2, 0.3  a.membership0.09 0.0  a.membership0.1 0.0  a.membership0.11 0.09999999999999995  a.membership0.4 0.0  FuzzySetA, 0, 0.5, 1.membership0.1 0.2  FuzzySetB, 0.2, 0.7, 1.membership0.6 0.8 Calculate the union of this fuzzy set with another fuzzy set. Args: other FuzzySet: Another fuzzy set to union with. Returns: FuzzySet: A new fuzzy set representing the union.  FuzzySeta, 0.1, 0.2, 0.3.unionFuzzySetb, 0.4, 0.5, 0.6 FuzzySetname'a  b', leftboundary0.1, peak0.6, rightboundary0.35 Plot the membership function of the fuzzy set.
from __future__ import annotations

from dataclasses import dataclass

import matplotlib.pyplot as plt
import numpy as np


@dataclass
class FuzzySet:
    """
    A class for representing and manipulating triangular fuzzy sets.
    Attributes:
        name: The name or label of the fuzzy set.
        left_boundary: The left boundary of the fuzzy set.
        peak: The peak (central) value of the fuzzy set.
        right_boundary: The right boundary of the fuzzy set.
    Methods:
        membership(x): Calculate the membership value of an input 'x' in the fuzzy set.
        union(other): Calculate the union of this fuzzy set with another fuzzy set.
        intersection(other): Calculate the intersection of this fuzzy set with another.
        complement(): Calculate the complement (negation) of this fuzzy set.
        plot(): Plot the membership function of the fuzzy set.

    >>> sheru = FuzzySet("Sheru", 0.4, 1, 0.6)
    >>> sheru
    FuzzySet(name='Sheru', left_boundary=0.4, peak=1, right_boundary=0.6)
    >>> str(sheru)
    'Sheru: [0.4, 1, 0.6]'

    >>> siya = FuzzySet("Siya", 0.5, 1, 0.7)
    >>> siya
    FuzzySet(name='Siya', left_boundary=0.5, peak=1, right_boundary=0.7)

    # Complement Operation
    >>> sheru.complement()
    FuzzySet(name='¬Sheru', left_boundary=0.4, peak=0.6, right_boundary=0)
    >>> siya.complement()  # doctest: +NORMALIZE_WHITESPACE
    FuzzySet(name='¬Siya', left_boundary=0.30000000000000004, peak=0.5,
     right_boundary=0)

    # Intersection Operation
    >>> siya.intersection(sheru)
    FuzzySet(name='Siya ∩ Sheru', left_boundary=0.5, peak=0.6, right_boundary=1.0)

    # Membership Operation
    >>> sheru.membership(0.5)
    0.16666666666666663
    >>> sheru.membership(0.6)
    0.0

    # Union Operations
    >>> siya.union(sheru)
    FuzzySet(name='Siya ∪ Sheru', left_boundary=0.4, peak=0.7, right_boundary=1.0)
    """

    name: str
    left_boundary: float
    peak: float
    right_boundary: float

    def __str__(self) -> str:
        """
        >>> FuzzySet("fuzzy_set", 0.1, 0.2, 0.3)
        FuzzySet(name='fuzzy_set', left_boundary=0.1, peak=0.2, right_boundary=0.3)
        """
        return (
            f"{self.name}: [{self.left_boundary}, {self.peak}, {self.right_boundary}]"
        )

    def complement(self) -> FuzzySet:
        """
        Calculate the complement (negation) of this fuzzy set.
        Returns:
            FuzzySet: A new fuzzy set representing the complement.

        >>> FuzzySet("fuzzy_set", 0.1, 0.2, 0.3).complement()
        FuzzySet(name='¬fuzzy_set', left_boundary=0.7, peak=0.9, right_boundary=0.8)
        """
        return FuzzySet(
            f"¬{self.name}",
            1 - self.right_boundary,
            1 - self.left_boundary,
            1 - self.peak,
        )

    def intersection(self, other) -> FuzzySet:
        """
        Calculate the intersection of this fuzzy set
        with another fuzzy set.
        Args:
            other: Another fuzzy set to intersect with.
        Returns:
            A new fuzzy set representing the intersection.

        >>> FuzzySet("a", 0.1, 0.2, 0.3).intersection(FuzzySet("b", 0.4, 0.5, 0.6))
        FuzzySet(name='a ∩ b', left_boundary=0.4, peak=0.3, right_boundary=0.35)
        """
        return FuzzySet(
            f"{self.name} ∩ {other.name}",
            max(self.left_boundary, other.left_boundary),
            min(self.right_boundary, other.right_boundary),
            (self.peak + other.peak) / 2,
        )

    def membership(self, x: float) -> float:
        """
        Calculate the membership value of an input 'x' in the fuzzy set.
        Returns:
            The membership value of 'x' in the fuzzy set.

        >>> a = FuzzySet("a", 0.1, 0.2, 0.3)
        >>> a.membership(0.09)
        0.0
        >>> a.membership(0.1)
        0.0
        >>> a.membership(0.11)
        0.09999999999999995
        >>> a.membership(0.4)
        0.0
        >>> FuzzySet("A", 0, 0.5, 1).membership(0.1)
        0.2
        >>> FuzzySet("B", 0.2, 0.7, 1).membership(0.6)
        0.8
        """
        if x <= self.left_boundary or x >= self.right_boundary:
            return 0.0
        elif self.left_boundary < x <= self.peak:
            return (x - self.left_boundary) / (self.peak - self.left_boundary)
        elif self.peak < x < self.right_boundary:
            return (self.right_boundary - x) / (self.right_boundary - self.peak)
        msg = f"Invalid value {x} for fuzzy set {self}"
        raise ValueError(msg)

    def union(self, other) -> FuzzySet:
        """
        Calculate the union of this fuzzy set with another fuzzy set.
        Args:
            other (FuzzySet): Another fuzzy set to union with.
        Returns:
            FuzzySet: A new fuzzy set representing the union.

        >>> FuzzySet("a", 0.1, 0.2, 0.3).union(FuzzySet("b", 0.4, 0.5, 0.6))
        FuzzySet(name='a ∪ b', left_boundary=0.1, peak=0.6, right_boundary=0.35)
        """
        return FuzzySet(
            f"{self.name} ∪ {other.name}",
            min(self.left_boundary, other.left_boundary),
            max(self.right_boundary, other.right_boundary),
            (self.peak + other.peak) / 2,
        )

    def plot(self):
        """
        Plot the membership function of the fuzzy set.
        """
        x = np.linspace(0, 1, 1000)
        y = [self.membership(xi) for xi in x]

        plt.plot(x, y, label=self.name)


if __name__ == "__main__":
    from doctest import testmod

    testmod()
    a = FuzzySet("A", 0, 0.5, 1)
    b = FuzzySet("B", 0.2, 0.7, 1)

    a.plot()
    b.plot()

    plt.xlabel("x")
    plt.ylabel("Membership")
    plt.legend()
    plt.show()

    union_ab = a.union(b)
    intersection_ab = a.intersection(b)
    complement_a = a.complement()

    union_ab.plot()
    intersection_ab.plot()
    complement_a.plot()

    plt.xlabel("x")
    plt.ylabel("Membership")
    plt.legend()
    plt.show()
