TheAlgorithms/Python · error · ValueError

Invalid value {x} for fuzzy set {self}

Error message

Invalid value {x} for fuzzy set {self}

What it means

Raised by FuzzySet.membership() in fuzzy_logic/fuzzy_operations.py with the message 'Invalid value {x} for fuzzy set {self}'. The method returns 0.0 outside [left, right], a rising slope up to the peak, and a falling slope after — those branches cover every real number, so this raise is effectively dead code for ordinary inputs. The only realistic way to reach it is NaN, which fails all comparisons and falls through every branch.

Source

Thrown at fuzzy_logic/fuzzy_operations.py:139

        >>> 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 U b', left_boundary=0.1, peak=0.6, right_boundary=0.35)
        """
        return FuzzySet(
            f"{self.name} U {other.name}",
            min(self.left_boundary, other.left_boundary),
            max(self.right_boundary, other.right_boundary),
            (self.peak + other.peak) / 2,
        )

View on GitHub (pinned to f5988cc097)

Solutions

  1. Sanitize inputs: reject or replace NaN before calling membership().
  2. Check upstream math for 0/0 or log of non-positives that generate NaN.
  3. If maintaining this module, consider an explicit math.isnan check with a clearer error message.

Example fix

# before
deg = FuzzySet('warm', 15, 22, 30).membership(sensor_temp)  # sensor_temp = nan

# after
import math
if math.isnan(sensor_temp):
    degree = 0.0  # or raise a clear error
else:
    degree = FuzzySet('warm', 15, 22, 30).membership(sensor_temp)
Defensive patterns

Strategy: validation

Validate before calling

import math
if math.isnan(x):
    raise ValueError('NaN has no membership degree')
FuzzySet('warm', 15, 22, 30).membership(x)

Type guard

def is_finite_number(v: object) -> bool:
    return isinstance(v, (int, float)) and not isinstance(v, bool) and math.isfinite(v)

Try / catch

try:
    deg = fs.membership(x)
except ValueError as exc:
    if 'Invalid value' in str(exc):
        deg = 0.0  # out-of-domain / NaN treated as no membership
    else:
        raise

Prevention

When it happens

Trigger: Calling membership(float('nan')) on any FuzzySet — NaN fails x <= left, x >= right, and both slope conditions, falling through to the raise. Any finite float returns 0.0 or a slope value instead.

Common situations: Feeding fuzzy controllers data from sensors or pipelines that produce NaN (missing readings, 0/0 features), numpy NaN leaking from array math, or un-sanitized user input parsed with float().

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/1d89dd4e160909a1. Report an issue: GitHub.