Mamdani FIS Quick Start Guide
Overview
MamdaniSystem is a fuzzy inference system that uses linguistic rules with fuzzy outputs for decision-making and control applications.
Key Features:
- Flexible input/output variable creation
- Manual or automatic membership function generation
- Intuitive rule creation
- Multiple visualization tools
- Rule export/import capabilities
- System persistence (save/load)
1. Creating a Mamdani FIS
Basic Instantiation
from fuzzy_systems import MamdaniSystem
from fuzzy_systems.core.membership_functions import TNorm, SNorm, DefuzzMethod
# Create Mamdani system
fis = MamdaniSystem(
name="My FIS",
and_method=TNorm.MIN, # T-norm for AND operator
or_method=SNorm.MAX, # S-norm for OR operator
implication_method='min', # Implication: 'min' or 'product'
aggregation_method='max', # Aggregation: 'max', 'sum', 'probabilistic'
defuzzification_method=DefuzzMethod.CENTROID # Defuzzification method
)
Key Parameters
name: System identifier
and_method: T-norm for AND operations
TNorm.MIN: Minimum (default, most common)
TNorm.PRODUCT: Product
TNorm.LUKASIEWICZ: Lukasiewicz
or_method: S-norm for OR operations
SNorm.MAX: Maximum (default)
SNorm.PROBOR: Probabilistic OR
SNorm.LUKASIEWICZ: Lukasiewicz
implication_method: Rule implication
'min': Minimum (default, Mamdani)
'product': Product (Larsen)
aggregation_method: Aggregate multiple rules
'max': Maximum (default)
'sum': Bounded sum
'probabilistic': Probabilistic OR
defuzzification_method: Convert fuzzy output to crisp
DefuzzMethod.CENTROID: Center of area (most common)
DefuzzMethod.BISECTOR: Bisector of area
DefuzzMethod.MOM: Mean of maximum
DefuzzMethod.SOM: Smallest of maximum
DefuzzMethod.LOM: Largest of maximum
2. Adding Variables
# Add input variable with universe of discourse
fis.add_input('temperature', (0, 100)) # Temperature from 0 to 100
fis.add_input('humidity', (0, 100)) # Humidity from 0 to 100
Output Variables
# Add output variable
fis.add_output('fan_speed', (0, 100)) # Fan speed from 0 to 100
3. Adding Membership Functions (Manual)
Method 1: Using add_term()
# Add membership functions manually
# Syntax: add_term(variable_name, term_name, mf_type, parameters)
# Temperature: cold, warm, hot
fis.add_term('temperature', 'cold', 'triangular', (0, 0, 50))
fis.add_term('temperature', 'warm', 'triangular', (0, 50, 100))
fis.add_term('temperature', 'hot', 'triangular', (50, 100, 100))
# Humidity: low, medium, high
fis.add_term('humidity', 'low', 'trapezoidal', (0, 0, 30, 50))
fis.add_term('humidity', 'medium', 'triangular', (30, 50, 70))
fis.add_term('humidity', 'high', 'trapezoidal', (50, 70, 100, 100))
# Fan speed: slow, medium, fast
fis.add_term('fan_speed', 'slow', 'gaussian', (25, 10))
fis.add_term('fan_speed', 'medium', 'gaussian', (50, 10))
fis.add_term('fan_speed', 'fast', 'gaussian', (75, 10))
Available Membership Function Types
| Type |
Parameters |
Example |
'triangular' |
(a, b, c) |
(0, 50, 100) |
'trapezoidal' |
(a, b, c, d) |
(0, 20, 80, 100) |
'gaussian' |
(center, sigma) |
(50, 15) |
'bell' |
(center, width, slope) |
(50, 20, 2) |
'sigmoid' |
(center, slope) |
(50, 0.1) |
4. Adding Membership Functions (Automatic)
Using add_auto_mfs() - Quick Setup
# Automatically generate evenly spaced membership functions
fis.add_input('temperature', (0, 100))
fis.add_auto_mfs(
variable_name='temperature',
n_mfs=3, # Number of MFs (minimum 2)
mf_type='triangular', # MF type
label_prefix=None, # Custom labels (None = linguistic)
overlap_strategy='standard' # 'standard' or 'perfect'
)
# This creates 3 triangular MFs with linguistic labels:
# - 'very low' at left
# - 'medium' at center
# - 'very high' at right
Key Parameters
n_mfs: Number of membership functions (≥ 2)
mf_type: Type of membership function
'triangular': Triangle-shaped (default)
'gaussian': Gaussian/bell-shaped
'trapezoidal': Trapezoid-shaped
'bell': Generalized bell
label_prefix: Custom label prefix
None: Uses linguistic labels (very low, low, medium, high, very high, etc.)
'temp_': Creates labels like temp_1, temp_2, temp_3
overlap_strategy: How MFs overlap
'standard': Standard overlap (default)
'perfect': Perfect overlap (sum of memberships = 1.0 at any point)
Linguistic Labels (when label_prefix=None)
For different n_mfs, automatic linguistic labels are generated:
- n_mfs=2: very low, very high
- n_mfs=3: very low, medium, very high
- n_mfs=4: very low, low, high, very high
- n_mfs=5: very low, low, medium, high, very high
- n_mfs=7: very low, low, somewhat low, medium, somewhat high, high, very high
Example: Complete System with Auto MFs
from fuzzy_systems import MamdaniSystem
# Create system
fis = MamdaniSystem(name="Temperature Controller")
# Add variables
fis.add_input('temperature', (0, 100))
fis.add_input('humidity', (0, 100))
fis.add_output('fan_speed', (0, 100))
# Generate MFs automatically
fis.add_auto_mfs('temperature', n_mfs=3, mf_type='triangular')
fis.add_auto_mfs('humidity', n_mfs=3, mf_type='triangular')
fis.add_auto_mfs('fan_speed', n_mfs=3, mf_type='triangular')
# Now you have:
# temperature: very low, medium, very high
# humidity: very low, medium, very high
# fan_speed: very low, medium, very high
5. Adding Rules
Method 1: Using Dictionaries (Most Readable)
# Add rules using variable and term names
fis.add_rule({
'temperature': 'cold',
'humidity': 'high',
'fan_speed': 'slow',
'operator': 'AND',
'weight': 1.0
})
# Operator and weight are optional
fis.add_rule({
'temperature': 'hot',
'humidity': 'high',
'fan_speed': 'fast'
})
Method 2: Using Lists (Ordered by Variable)
# Rules as lists: [input1_term, input2_term, ..., output1_term, ...]
# Order follows the order variables were added
fis.add_rule(['cold', 'low', 'slow'])
fis.add_rule(['warm', 'medium', 'medium'])
fis.add_rule(['hot', 'high', 'fast'])
Method 3: Batch Adding with add_rules()
# Add multiple rules at once
fis.add_rules([
{'temperature': 'cold', 'humidity': 'low', 'fan_speed': 'slow'},
{'temperature': 'cold', 'humidity': 'high', 'fan_speed': 'medium'},
{'temperature': 'warm', 'humidity': 'low', 'fan_speed': 'medium'},
{'temperature': 'warm', 'humidity': 'high', 'fan_speed': 'medium'},
{'temperature': 'hot', 'humidity': 'low', 'fan_speed': 'medium'},
{'temperature': 'hot', 'humidity': 'high', 'fan_speed': 'fast'}
])
Rule Parameters
operator: Rule connector
'AND': All conditions must be true (default)
'OR': At least one condition must be true
weight: Rule importance (0.0 to 1.0, default: 1.0)
- Used to reduce rule influence without removing it
- Example:
weight=0.5 reduces rule firing strength by half
6. Evaluating the System
Basic Evaluation
# Evaluate with dictionary
output = fis.evaluate({'temperature': 75, 'humidity': 80})
print(f"Fan speed: {output['fan_speed']:.2f}")
# Evaluate with keyword arguments
output = fis.evaluate(temperature=75, humidity=80)
# Evaluate with positional arguments (follows variable order)
output = fis.evaluate(75, 80)
Detailed Evaluation (Debugging)
# Get detailed information about inference process
result = fis.evaluate_detailed(temperature=75, humidity=80)
print(f"Inputs: {result['inputs']}")
print(f"Fuzzified: {result['fuzzified']}")
print(f"Outputs: {result['outputs']}")
print(f"Rule activations: {result['rule_activations']}")
7. Visualization
# Plot all variables (inputs and outputs)
fis.plot_variables()
# Plot specific variable
fis.plot_variables(variables=['temperature'])
# Customize plot
fis.plot_variables(
variables=['temperature', 'humidity'],
figsize=(12, 6),
grid=True
)
# Plot 3D surface for 2-input, 1-output systems
fis.plot_output(
output_var='fan_speed',
resolution=50, # Points per dimension
figsize=(10, 8),
colormap='viridis'
)
Plot Rule Matrix
# Visualize rule firing strength matrix (2D systems)
fis.plot_rule_matrix(
input1='temperature',
input2='humidity',
output='fan_speed',
resolution=30
)
# Alternative 2D visualization
fis.plot_rule_matrix_2d(
output_var='fan_speed',
resolution=30
)
8. Rule Management
Export Rules
# Export rules to JSON format
rules_json = fis.export_rules()
print(rules_json)
# Save rules to file
import json
with open('rules.json', 'w') as f:
json.dump(rules_json, f, indent=2)
Import Rules
# Import rules from JSON
rules_json = [
{
"antecedents": {"temperature": "cold", "humidity": "low"},
"consequents": {"fan_speed": "slow"},
"operator": "AND",
"weight": 1.0
},
{
"antecedents": {"temperature": "hot", "humidity": "high"},
"consequents": {"fan_speed": "fast"},
"operator": "AND",
"weight": 1.0
}
]
fis.import_rules(rules_json)
Clear Rules
# Remove all rules
fis.rule_base.rules.clear()
9. System Persistence
Save System to File
# Save entire system (variables, MFs, rules)
fis.save('temperature_controller.fis')
Load System from File
from fuzzy_systems import MamdaniSystem
# Load saved system
fis = MamdaniSystem.load('temperature_controller.fis')
# Use immediately
output = fis.evaluate(temperature=75, humidity=80)
Export to JSON
# Export system to JSON format
fis_json = fis.to_json()
# Save JSON to file
with open('fis.json', 'w') as f:
json.dump(fis_json, f, indent=2)
Import from JSON
# Load from JSON
with open('fis.json', 'r') as f:
fis_json = json.load(f)
fis = MamdaniSystem.from_json(fis_json)
10. Complete Example
import numpy as np
import matplotlib.pyplot as plt
from fuzzy_systems import MamdaniSystem
from fuzzy_systems.core.membership_functions import DefuzzMethod
# ============================================================================
# Step 1: Create System
# ============================================================================
fis = MamdaniSystem(
name="Temperature Controller",
defuzzification_method=DefuzzMethod.CENTROID
)
# ============================================================================
# Step 2: Add Variables
# ============================================================================
fis.add_input('temperature', (0, 100))
fis.add_input('humidity', (0, 100))
fis.add_output('fan_speed', (0, 100))
# ============================================================================
# Step 3: Generate Membership Functions Automatically
# ============================================================================
fis.add_auto_mfs('temperature', n_mfs=3, mf_type='triangular')
fis.add_auto_mfs('humidity', n_mfs=3, mf_type='triangular')
fis.add_auto_mfs('fan_speed', n_mfs=3, mf_type='triangular')
# ============================================================================
# Step 4: Add Rules
# ============================================================================
fis.add_rules([
{'temperature': 'very low', 'humidity': 'very low', 'fan_speed': 'very low'},
{'temperature': 'very low', 'humidity': 'medium', 'fan_speed': 'very low'},
{'temperature': 'very low', 'humidity': 'very high', 'fan_speed': 'medium'},
{'temperature': 'medium', 'humidity': 'very low', 'fan_speed': 'very low'},
{'temperature': 'medium', 'humidity': 'medium', 'fan_speed': 'medium'},
{'temperature': 'medium', 'humidity': 'very high', 'fan_speed': 'medium'},
{'temperature': 'very high', 'humidity': 'very low', 'fan_speed': 'medium'},
{'temperature': 'very high', 'humidity': 'medium', 'fan_speed': 'very high'},
{'temperature': 'very high', 'humidity': 'very high', 'fan_speed': 'very high'}
])
# ============================================================================
# Step 5: Evaluate System
# ============================================================================
# Single evaluation
output = fis.evaluate(temperature=75, humidity=60)
print(f"Temperature: 75°C, Humidity: 60%")
print(f"Fan Speed: {output['fan_speed']:.2f}%")
print()
# Multiple evaluations
print("System Response Table:")
print(f"{'Temperature':<12} {'Humidity':<12} {'Fan Speed':<12}")
print("-" * 40)
for temp in [20, 40, 60, 80]:
for hum in [30, 60, 90]:
result = fis.evaluate(temperature=temp, humidity=hum)
print(f"{temp:<12} {hum:<12} {result['fan_speed']:<12.2f}")
# ============================================================================
# Step 6: Visualize
# ============================================================================
# Plot membership functions
fis.plot_variables()
# Plot control surface
fis.plot_output('fan_speed', resolution=50)
# Plot rule matrix
fis.plot_rule_matrix('temperature', 'humidity', 'fan_speed')
# ============================================================================
# Step 7: Save System
# ============================================================================
fis.save('temperature_controller.fis')
print("System saved successfully!")
# Export rules
rules = fis.export_rules()
with open('rules.json', 'w') as f:
json.dump(rules, f, indent=2)
print("Rules exported successfully!")
11. Tips and Best Practices
System Design
- Start simple: Begin with 2-3 membership functions per variable
- Use
add_auto_mfs(): Faster than manual definition for symmetric distributions
- Triangular MFs: Good default choice (simple, efficient)
- Gaussian MFs: Better for smooth control surfaces
- Rule coverage: Ensure rules cover all important input combinations
Membership Function Selection
| MF Type |
Best For |
Advantages |
Disadvantages |
| Triangular |
General-purpose, control |
Simple, fast, interpretable |
Sharp peaks |
| Gaussian |
Smooth control, modeling |
Smooth, differentiable |
More parameters |
| Trapezoidal |
Flat regions, classification |
Stable plateau |
More parameters |
| Bell |
Smooth transitions |
Very smooth |
Computationally expensive |
Defuzzification Methods
- Centroid: Most common, balanced (default choice)
- Bisector: Similar to centroid but may be faster
- MOM/SOM/LOM: Use when you need extreme values
- For control: Use centroid or bisector
- For classification: Consider MOM (mean of maximum)
- Reduce
num_points: Use 100-500 for evaluation (default: 1000)
- Minimize rules: More rules = slower inference
- Use triangular MFs: Fastest computation
- Cache evaluations: Store results if inputs repeat
Rule Design
- Complete rule base: Cover all critical regions
- Avoid contradictions: Don't assign different outputs to same inputs
- Use weights: Instead of removing rules, reduce weight (0.1-0.5)
- Test edge cases: Verify behavior at universe boundaries
Visualization Best Practices
- Plot early: Visualize MFs before adding rules
- Check surface: Use
plot_output() to verify system behavior
- Rule matrix: Useful for debugging 2-input systems
- Document decisions: Save plots with system versions
Debugging
# Use detailed evaluation to debug
result = fis.evaluate_detailed(temperature=50, humidity=50)
# Check which rules fired
for i, activation in enumerate(result['rule_activations']):
if activation > 0.01:
rule = fis.rule_base.rules[i]
print(f"Rule {i}: activation = {activation:.3f}")
print(f" {rule}")
12. Common Issues and Solutions
| Problem |
Cause |
Solution |
| Output always constant |
Only one rule fires |
Add more rules, check MF overlap |
| Output at universe boundary |
Defuzzification issue |
Check rule consequents, verify MF coverage |
| Slow evaluation |
Too many points |
Reduce num_points parameter |
| Unexpected behavior |
Rule contradictions |
Review rule base with export_rules() |
| NaN output |
No rules fire |
Check input ranges, MF coverage |
| Jerky control surface |
Sharp MF transitions |
Use Gaussian instead of triangular |
13. Comparison with Sugeno Systems
| Aspect |
Mamdani |
Sugeno |
| Output |
Fuzzy sets |
Mathematical functions |
| Interpretability |
High (linguistic) |
Medium (numeric) |
| Computation |
Slower (defuzzification) |
Faster (weighted average) |
| Learning |
Harder to optimize |
Easier (linear consequents) |
| Control |
Better for complex |
Better for simple |
| Best for |
Human interpretation |
Mathematical optimization |
14. Advanced Features
Custom T-norms and S-norms
from fuzzy_systems.core.membership_functions import TNorm, SNorm
# Use different operators
fis = MamdaniSystem(
and_method=TNorm.PRODUCT, # Product T-norm
or_method=SNorm.PROBOR # Probabilistic OR
)
Custom Defuzzification Points
# Use more points for smoother defuzzification
output = fis.evaluate(temperature=75, humidity=60, num_points=2000)
Weighted Rules
# Add rules with different importance
fis.add_rule({
'temperature': 'very high',
'humidity': 'very high',
'fan_speed': 'very high',
'weight': 1.0 # Critical rule
})
fis.add_rule({
'temperature': 'medium',
'humidity': 'medium',
'fan_speed': 'medium',
'weight': 0.5 # Less important
})
References
- Mamdani, E. H., & Assilian, S. (1975). "An experiment in linguistic synthesis with a fuzzy logic controller." International Journal of Man-Machine Studies, 7(1), 1-13.
- Zadeh, L. A. (1965). "Fuzzy sets." Information and Control, 8(3), 338-353.