Skip to content

Repository files navigation

Fuzzy Inference Library

A comprehensive Python library for designing and implementing fuzzy logic inference systems with support for both Mamdani and Sugeno methods.

Features

  • Multiple Membership Functions: Triangular, trapezoidal, Gaussian, and sigmoid functions for defining fuzzy sets
  • Fuzzy Sets with Logical Operations: Support for AND, OR, and NOT operations on fuzzy sets
  • Linguistic Variables: Define fuzzy variables with multiple fuzzy sets and automatic fuzzification
  • Flexible Rule System: IF-THEN rules with support for multiple antecedents and consequents
  • Dual Inference Engines:
    • Mamdani: Traditional fuzzy logic with fuzzy consequents and full defuzzification
    • Sugeno: Efficient inference with crisp consequents (constants or linear functions)
  • Multiple Defuzzification Methods: Centroid, bisector, mean/smallest/largest of maximum (for Mamdani)
  • Sugeno System Support: Both Order-0 (constant) and Order-1 (linear) consequent functions
  • NumPy Integration: Efficient computation using NumPy arrays

Installation

pip install numpy

Then copy the fuzzy_inference/ directory to your project.

Quick Start

Mamdani System (Traditional Fuzzy Logic)

from fuzzy_inference import FuzzyVariable, FuzzySet, FuzzyRule, FuzzySystem
from fuzzy_inference import triangular

# Create input variable
temperature = FuzzyVariable("temperature", 0, 100)
temperature.add_set(FuzzySet("cold", lambda x: triangular(x, 0, 0, 50)))
temperature.add_set(FuzzySet("hot", lambda x: triangular(x, 50, 100, 100)))

# Create output variable
fan_speed = FuzzyVariable("fan_speed", 0, 100)
fan_speed.add_set(FuzzySet("slow", lambda x: triangular(x, 0, 0, 50)))
fan_speed.add_set(FuzzySet("fast", lambda x: triangular(x, 50, 100, 100)))

# Create Mamdani system and add rules
system = FuzzySystem(system_type="mamdani")  # or just FuzzySystem() - mamdani is default
system.add_input_variable(temperature)
system.add_output_variable(fan_speed)

system.add_rule(FuzzyRule(
    {"temperature": temperature["cold"]},
    {"fan_speed": fan_speed["slow"]}
))

system.add_rule(FuzzyRule(
    {"temperature": temperature["hot"]},
    {"fan_speed": fan_speed["fast"]}
))

# Perform inference
result = system.infer({"temperature": 75})
print(f"Fan speed: {result['fan_speed']:.2f}")

Sugeno System (Efficient Alternative)

from fuzzy_inference import FuzzyVariable, FuzzySet, SugenoRule, FuzzySystem
from fuzzy_inference import triangular

# Create input variable (same as Mamdani)
temperature = FuzzyVariable("temperature", 0, 100)
temperature.add_set(FuzzySet("cold", lambda x: triangular(x, 0, 0, 50)))
temperature.add_set(FuzzySet("hot", lambda x: triangular(x, 50, 100, 100)))

# Create output variable (only universe range needed)
fan_speed = FuzzyVariable("fan_speed", 0, 100)

# Create Sugeno system
system = FuzzySystem(system_type="sugeno")
system.add_input_variable(temperature)
system.add_output_variable(fan_speed)

# Order-0 Sugeno (constant consequents)
system.add_rule(SugenoRule(
    {"temperature": temperature["cold"]},
    {"fan_speed": 20}  # Constant value
))

# Order-1 Sugeno (linear consequents)
system.add_rule(SugenoRule(
    {"temperature": temperature["hot"]},
    {"fan_speed": lambda inputs: 0.8 * inputs["temperature"] + 10}  # Linear function
))

# Perform inference (uses weighted average, no defuzzification method needed)
result = system.infer({"temperature": 75})
print(f"Fan speed: {result['fan_speed']:.2f}")

Core Components

The fuzzy_inference library is organized into several key modules:

1. Membership Functions (membership.py)

Membership functions define the degree to which a value belongs to a fuzzy set. All functions return values between 0 and 1.

triangular(x, a, b, c)

Triangular membership function with linear slopes.

  • Parameters:
    • x: Input value or NumPy array
    • a: Left foot (membership = 0)
    • b: Peak (membership = 1)
    • c: Right foot (membership = 0)
  • Use case: General-purpose fuzzy sets, simple and intuitive

trapezoidal(x, a, b, c, d)

Trapezoidal membership function with a flat top region.

  • Parameters:
    • x: Input value or NumPy array
    • a: Left foot (membership = 0)
    • b: Left shoulder (membership = 1 starts)
    • c: Right shoulder (membership = 1 ends)
    • d: Right foot (membership = 0)
  • Use case: Representing ranges where membership is fully true across a region

gaussian(x, mean, sigma)

Gaussian (bell-shaped) membership function.

  • Parameters:
    • x: Input value or NumPy array
    • mean: Center of the curve
    • sigma: Standard deviation (controls width)
  • Use case: Smooth, continuous membership with natural uncertainty representation

sigmoid(x, a, c)

S-shaped sigmoid membership function.

  • Parameters:
    • x: Input value or NumPy array
    • a: Slope parameter (positive for rising, negative for falling)
    • c: Center point (inflection point)
  • Use case: Representing gradual transitions, often used for "high" or "low" concepts

2. FuzzySet (fuzzyset.py)

A FuzzySet represents a fuzzy set with a name and a membership function. It encapsulates the concept of partial membership.

Creating Fuzzy Sets

from fuzzy_inference import FuzzySet, triangular

# Create a fuzzy set with a membership function
cold = FuzzySet("cold", lambda x: triangular(x, 0, 0, 50))

Evaluating Membership

# Get membership degree for a single value
degree = cold.membership(25)  # Returns a value between 0 and 1

# Get membership for an array of values
import numpy as np
values = np.array([0, 10, 25, 40, 50])
degrees = cold.membership(values)

Logical Operations

Fuzzy sets support standard fuzzy logic operations:

cold = FuzzySet("cold", lambda x: triangular(x, 0, 0, 50))
warm = FuzzySet("warm", lambda x: triangular(x, 25, 50, 75))

# NOT operation (fuzzy complement)
not_cold = ~cold           # membership(x) = 1 - cold.membership(x)

# OR operation (fuzzy union, uses max)
cold_or_warm = cold | warm # membership(x) = max(cold.membership(x), warm.membership(x))

# AND operation (fuzzy intersection, uses min)
# Note: Typically used implicitly in rule antecedents

3. FuzzyVariable (variable.py)

A FuzzyVariable represents a linguistic variable—a variable that can take on fuzzy values described by linguistic terms (e.g., "cold", "warm", "hot" for temperature).

Creating Linguistic Variables

from fuzzy_inference import FuzzyVariable, FuzzySet, triangular

# Define the universe of discourse (min and max values)
temperature = FuzzyVariable("temperature", universe_min=0, universe_max=100)

# Add fuzzy sets (linguistic terms) to the variable
temperature.add_set(FuzzySet("cold", lambda x: triangular(x, 0, 0, 50)))
temperature.add_set(FuzzySet("warm", lambda x: triangular(x, 25, 50, 75)))
temperature.add_set(FuzzySet("hot", lambda x: triangular(x, 50, 100, 100)))

Fuzzification

Fuzzification converts a crisp (numeric) value into fuzzy membership degrees:

# Fuzzify a crisp value
memberships = temperature.fuzzify(60)
# Returns: {"cold": 0.0, "warm": 0.4, "hot": 0.6}
# Interpretation: The value 60 is 0% cold, 40% warm, and 60% hot

Accessing Fuzzy Sets

# Access a specific fuzzy set by name
hot_set = temperature["hot"]

# Get the universe of discourse (array of values)
universe = temperature.universe  # NumPy array from 0 to 100

4. FuzzyRule & SugenoRule (rule.py)

Rules define the IF-THEN logic of the fuzzy system. The antecedent (IF part) is always fuzzy, but the consequent (THEN part) differs between Mamdani and Sugeno systems.

FuzzyRule (for Mamdani systems)

Mamdani rules have fuzzy consequents:

from fuzzy_inference import FuzzyRule

# Single input, single output
rule = FuzzyRule(
    antecedent={"temperature": temp["hot"]},
    consequent={"fan_speed": speed["fast"]}  # FuzzySet
)

# Multiple inputs (uses min for AND operation)
rule = FuzzyRule(
    antecedent={"temperature": temp["hot"], "humidity": humid["high"]},
    consequent={"fan_speed": speed["fast"]}
)

Rule Evaluation Process:

  1. Fuzzification: Crisp inputs are converted to membership degrees
  2. Antecedent evaluation: Multiple antecedents are combined using min (AND)
  3. Implication: The output fuzzy set is clipped at the activation level
  4. Aggregation: Multiple rules are combined using max (OR)
  5. Defuzzification: The aggregated fuzzy output is converted to a crisp value

SugenoRule (for Sugeno systems)

Sugeno rules have crisp function consequents (constants or linear functions):

from fuzzy_inference import SugenoRule

# Order-0 Sugeno (constant consequent)
rule = SugenoRule(
    antecedent={"temperature": temp["hot"]},
    consequent={"fan_speed": 80}  # Constant value
)

# Order-1 Sugeno (linear function consequent)
rule = SugenoRule(
    antecedent={"temperature": temp["hot"], "humidity": humid["high"]},
    consequent={"fan_speed": lambda inputs: 0.5 * inputs["temperature"] + 0.3 * inputs["humidity"] + 10}
)

Rule Evaluation Process:

  1. Fuzzification: Crisp inputs are converted to membership degrees
  2. Antecedent evaluation: Multiple antecedents are combined using min (AND)
  3. Consequent evaluation: The crisp function is evaluated with the inputs
  4. Weighted average: Output is the weighted average of all consequents, weighted by activation strengths

5. FuzzySystem (system.py)

The FuzzySystem class is the main inference engine that coordinates the entire fuzzy logic process. It supports both Mamdani and Sugeno inference methods.

Creating a Fuzzy System

from fuzzy_inference import FuzzySystem

# Create a Mamdani system (default)
system = FuzzySystem(system_type="mamdani")

# Or create a Sugeno system
system = FuzzySystem(system_type="sugeno")

Building the System

# Add input variables
system.add_input_variable(temperature)
system.add_input_variable(humidity)

# Add output variables
system.add_output_variable(fan_speed)

# Add rules
system.add_rule(rule1)
system.add_rule(rule2)
# ... more rules

# Method chaining is supported
system.add_input_variable(temperature)\
      .add_output_variable(fan_speed)\
      .add_rule(rule1)\
      .add_rule(rule2)

Performing Inference

Mamdani Inference:

# Perform inference with defuzzification method
output = system.infer(
    inputs={"temperature": 75, "humidity": 60},
    method="centroid"  # or "bisector", "mom", "som", "lom"
)
# Returns: {"fan_speed": 65.3}

Sugeno Inference:

# Perform inference (weighted average automatically used)
output = system.infer(
    inputs={"temperature": 75, "humidity": 60}
)
# Returns: {"fan_speed": 67.8}

System Information

# Get system representation
print(system)
# Output:
# FuzzySystem(
#   type='mamdani',
#   inputs=['temperature', 'humidity'],
#   outputs=['fan_speed'],
#   rules=9
# )

Defuzzification Methods

Defuzzification converts the fuzzy output of a Mamdani system back into a crisp value. Different methods can produce different results depending on the shape of the aggregated output.

Mamdani Defuzzification Methods

centroid (Center of Gravity) - Default

Calculates the center of area under the membership function curve.

  • Formula: Σ(x * μ(x)) / Σ(μ(x))
  • Best for: Most applications; provides smooth, balanced output
  • Characteristics: Computationally moderate, intuitive results

bisector (Area Bisector)

Finds the value that divides the area under the curve into two equal parts.

  • Best for: When you need the median value
  • Characteristics: Computationally moderate, less common

mom (Mean of Maximum)

Returns the average of all values with maximum membership.

  • Best for: When multiple peaks exist and you want a compromise
  • Characteristics: Fast computation, can be unstable with flat tops

som (Smallest of Maximum)

Returns the smallest value among those with maximum membership.

  • Best for: Conservative control (prefer lower values)
  • Characteristics: Very fast, biased toward lower values

lom (Largest of Maximum)

Returns the largest value among those with maximum membership.

  • Best for: Aggressive control (prefer higher values)
  • Characteristics: Very fast, biased toward higher values

Sugeno Defuzzification

For Sugeno systems, defuzzification uses a weighted average of rule consequents:

  • Formula: Σ(activation_i * consequent_i) / Σ(activation_i)
  • Automatic: No method parameter needed
  • Advantages: Computationally efficient, guaranteed continuity, well-suited for optimization

Mamdani vs Sugeno: When to Use Each?

Understanding the differences between these two inference methods helps you choose the right approach for your application.

Comparison Table

Aspect Mamdani Sugeno
Consequent Type Fuzzy sets (linguistic) Constants (Order-0) or linear functions (Order-1)
Defuzzification Required (centroid, bisector, etc.) Weighted average (automatic)
Computational Cost Higher (more operations) Lower (simpler calculations)
Interpretability Highly intuitive, human-readable More mathematical, less intuitive
Output Surface Complex, non-linear surfaces Piecewise constant (Order-0) or linear (Order-1)
Rule Consequents {"output": fuzzy_set} {"output": constant} or {"output": lambda ...}
Memory Usage Higher (stores membership functions) Lower (stores numbers/functions)
Best For Expert systems, control, decision support Optimization, adaptive learning, ANFIS
Learning Capability Difficult to optimize Easy to optimize (linear parameters)

Decision Guide

Choose Mamdani when:

  • You need intuitive, human-interpretable rules ("IF temp is HOT THEN fan is FAST")
  • Working with expert knowledge from domain experts
  • Output requires complex, non-linear surfaces
  • Interpretability is more important than computational speed
  • Building control systems where operators need to understand the logic

Choose Sugeno when:

  • Computational efficiency is critical (real-time systems)
  • Working with mathematical models or data-driven approaches
  • Using adaptive techniques (ANFIS, neuro-fuzzy, optimization)
  • Need guaranteed continuity and smoothness in output
  • Integrating with machine learning or optimization algorithms
  • Working with embedded systems or resource-constrained environments

Hybrid Approach

You can also combine both methods in a single application:

  • Use Mamdani for high-level decision making (interpretability)
  • Use Sugeno for low-level control (efficiency)

How Fuzzy Inference Works

Understanding the inference process helps you design better fuzzy systems.

Mamdani Inference Process

The Mamdani method follows these steps:

  1. Fuzzification

    • Convert crisp inputs to fuzzy membership degrees
    • Example: Temperature 75°C → {cold: 0.0, warm: 0.5, hot: 0.5}
  2. Rule Evaluation

    • For each rule, evaluate the antecedent (IF part)
    • Multiple antecedents are combined using min (AND operation)
    • Example: IF temp is HOT (0.5) AND humidity is HIGH (0.7) → activation = min(0.5, 0.7) = 0.5
  3. Implication

    • Apply the activation strength to the consequent fuzzy set
    • Uses clipping: membership is limited to the activation level
    • Example: If activation = 0.5, "fan is FAST" membership is clipped at 0.5
  4. Aggregation

    • Combine outputs from all rules using max (OR operation)
    • Creates a single aggregated fuzzy set for each output variable
    • Example: max(rule1_output, rule2_output, rule3_output)
  5. Defuzzification

    • Convert the aggregated fuzzy output to a crisp value
    • Uses methods like centroid, bisector, etc.
    • Example: Aggregated fuzzy set → crisp value 65.3%

Sugeno Inference Process

The Sugeno method is more streamlined:

  1. Fuzzification

    • Same as Mamdani: convert crisp inputs to membership degrees
  2. Rule Evaluation

    • Same as Mamdani: evaluate antecedents using min for AND
  3. Consequent Evaluation

    • Evaluate the crisp consequent function
    • Order-0: Use constant value
    • Order-1: Evaluate linear function with inputs
    • Example: consequent = 0.5 * temp + 0.3 * humidity + 10
  4. Weighted Average

    • Combine all rule outputs using weighted average
    • Weights are the rule activation strengths
    • Formula: output = Σ(activation_i * consequent_i) / Σ(activation_i)
    • Example: (0.5 * 80 + 0.7 * 65 + 0.3 * 50) / (0.5 + 0.7 + 0.3) = 67.8

Key Implementation Details

  • AND operation: Uses min() for combining antecedents
  • OR operation: Uses max() for aggregating rules (Mamdani only)
  • Universe of discourse: Automatically discretized to 1000 points for Mamdani
  • No rule fires: Returns midpoint of output universe range
  • NumPy arrays: All computations vectorized for performance

Examples

See the example files for complete demonstrations:

  • example.py: Mamdani system for a tipping calculator
  • example_sugeno.py: Sugeno systems (both Order-0 and Order-1) for fan speed control
  • example_comparison.py: Side-by-side comparison of Mamdani and Sugeno systems

Run them with:

python example.py
python example_sugeno.py
python example_comparison.py

Architecture

fuzzy_inference/
├── __init__.py          # Package initialization
├── membership.py        # Membership functions
├── fuzzyset.py         # FuzzySet class
├── variable.py         # FuzzyVariable class
├── rule.py             # FuzzyRule and SugenoRule classes
└── system.py           # FuzzySystem (Mamdani & Sugeno inference engines)

Use Cases and Applications

The fuzzy_inference library is suitable for a wide range of applications:

Control Systems

  • HVAC control: Temperature and humidity regulation
  • Motor speed control: Adaptive speed based on load and conditions
  • Traffic light control: Dynamic timing based on traffic flow
  • Home automation: Smart lighting, climate control

Decision Support Systems

  • Credit risk assessment: Evaluating loan applications
  • Medical diagnosis: Assisting in disease identification
  • Investment analysis: Portfolio management recommendations
  • Tipping calculators: Service quality evaluation

Industrial Applications

  • Quality control: Product classification and grading
  • Process optimization: Manufacturing parameter tuning
  • Fault diagnosis: Equipment health monitoring
  • Energy management: Power distribution optimization

Robotics and AI

  • Robot navigation: Obstacle avoidance and path planning
  • Behavior arbitration: Multi-objective decision making
  • Sensor fusion: Combining multiple sensor inputs
  • Autonomous vehicles: Adaptive cruise control

Other Applications

  • Pattern recognition: Image and signal classification
  • Natural language processing: Sentiment analysis
  • Game AI: Adaptive difficulty and NPC behavior
  • Financial trading: Market analysis and strategy selection

Best Practices

Designing Membership Functions

  1. Overlap is good: Adjacent fuzzy sets should overlap (typically 25-50%)

    • Provides smooth transitions between linguistic terms
    • Prevents discontinuities in the output
  2. Cover the universe: Ensure the entire input range is covered

    • Every possible input should have non-zero membership in at least one set
    • Gaps can lead to unexpected behavior
  3. Keep it simple: Start with 3-7 fuzzy sets per variable

    • Too few: Loss of granularity
    • Too many: Complexity without significant benefit
  4. Use appropriate shapes:

    • Triangular: General purpose, fast computation
    • Trapezoidal: When a range should be "fully true"
    • Gaussian: Smooth, natural uncertainty
    • Sigmoid: Monotonic transitions (e.g., "low" to "high")

Designing Rules

  1. Completeness: Cover all important input combinations

    • Missing rules can lead to poor performance
    • Use domain knowledge to identify critical scenarios
  2. Consistency: Avoid contradictory rules

    • Rules with same antecedent should have compatible consequents
    • Test edge cases to verify behavior
  3. Start simple: Begin with a minimal rule set

    • Add rules incrementally based on testing
    • Every rule should serve a clear purpose

System Design

  1. Choose the right inference method:

    • Mamdani: When interpretability matters
    • Sugeno: When efficiency and optimization matter
  2. Normalize inputs: Keep inputs in reasonable ranges (e.g., 0-100)

    • Makes rule design more intuitive
    • Improves numerical stability
  3. Test thoroughly: Validate with:

    • Edge cases (min/max values)
    • Typical operating conditions
    • Boundary regions between fuzzy sets
  4. Iterate and refine:

    • Start with expert knowledge
    • Refine based on real-world testing
    • Consider tuning with data if available

Performance Optimization

  1. For Mamdani systems:

    • Use fewer universe discretization points if precision allows
    • Prefer centroid defuzzification for most applications
    • Consider Sugeno if speed is critical
  2. For Sugeno systems:

    • Use Order-0 (constants) when linear functions aren't needed
    • Order-1 provides better approximation but is slightly slower
  3. Rule optimization:

    • Minimize the number of rules while maintaining performance
    • Group similar rules when possible

API Quick Reference

Imports

from fuzzy_inference import (
    # Membership functions
    triangular, trapezoidal, gaussian, sigmoid,
    # Core classes
    FuzzySet, FuzzyVariable, FuzzyRule, SugenoRule, FuzzySystem
)

Creating Components

# Membership function
mf = lambda x: triangular(x, 0, 50, 100)

# Fuzzy set
fs = FuzzySet("hot", lambda x: triangular(x, 50, 100, 100))

# Fuzzy variable
temp = FuzzyVariable("temperature", 0, 100)
temp.add_set(FuzzySet("cold", lambda x: triangular(x, 0, 0, 50)))

# Mamdani rule
rule = FuzzyRule(
    {"temperature": temp["hot"]},
    {"fan_speed": speed["fast"]}
)

# Sugeno rule (Order-0)
rule = SugenoRule(
    {"temperature": temp["hot"]},
    {"fan_speed": 80}
)

# Sugeno rule (Order-1)
rule = SugenoRule(
    {"temperature": temp["hot"]},
    {"fan_speed": lambda inputs: 0.8 * inputs["temperature"] + 10}
)

# Fuzzy system
system = FuzzySystem(system_type="mamdani")  # or "sugeno"
system.add_input_variable(temp)
system.add_output_variable(speed)
system.add_rule(rule)

# Inference
result = system.infer({"temperature": 75}, method="centroid")

Common Operations

# Fuzzify a value
memberships = temperature.fuzzify(65)  # Returns dict of memberships

# Get membership degree
degree = fuzzy_set.membership(50)  # Returns float

# Logical operations on sets
not_cold = ~cold_set
cold_or_warm = cold_set | warm_set

# Access fuzzy set by name
hot_set = temperature["hot"]

Troubleshooting

Common Issues and Solutions

Issue: System returns unexpected values

  • Check: Ensure all input ranges are covered by fuzzy sets
  • Check: Verify rules are complete and consistent
  • Check: Test fuzzification: variable.fuzzify(test_value)

Issue: Output always returns the midpoint

  • Cause: No rules are firing (all activations are 0)
  • Solution: Check that input values are within variable universe ranges
  • Solution: Verify fuzzy sets overlap and cover the input range

Issue: Sugeno system gives different results than Mamdani

  • This is normal: The two methods use different inference approaches
  • Tip: Sugeno outputs are typically smoother and more continuous
  • Tip: You can tune Sugeno consequents to approximate Mamdani behavior

Issue: Performance is slow with Mamdani

  • Solution: Reduce the number of rules if possible
  • Solution: Use simpler membership functions (triangular vs gaussian)
  • Solution: Consider switching to Sugeno for better performance
  • Solution: Cache repeated calculations if using the same inputs

Issue: TypeError when creating membership functions

  • Check: Ensure you're passing a callable (lambda or function)
  • Example: FuzzySet("hot", lambda x: triangular(x, 50, 100, 100))
  • Not: FuzzySet("hot", triangular(x, 50, 100, 100))

Issue: Output is too sensitive to small input changes

  • Solution: Increase overlap between fuzzy sets
  • Solution: Use smoother membership functions (gaussian instead of triangular)
  • Solution: For Mamdani, try different defuzzification methods

Contributing

Contributions are welcome! Areas for enhancement:

  • Additional membership functions (generalized bell, trapezoidal variants)
  • Visualization tools for membership functions and inference
  • Type-2 fuzzy logic support
  • Additional defuzzification methods
  • Performance optimizations
  • More example applications

Version History

v0.1.0 - Initial release

  • Mamdani and Sugeno inference engines
  • Four membership functions
  • Five defuzzification methods
  • Complete rule system

License

MIT License

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages