Skip to content

Variables & rules

Linguistic variables

import fuzzytool as fz

# Auto-generate evenly-spaced terms ("triangular" default, or "gauss"):
temp = fz.Variable("temp", (0, 40), terms=["cold", "warm", "hot"], kind="gauss")

# Or assign terms explicitly:
temp["freezing"] = fz.trap(-10, -10, 0, 5)

Rules with operators

Indexing a variable yields a proposition (temp["hot"]). Compose propositions:

Operator Meaning Default
& AND t-norm min
\| OR s-norm max
~ NOT complement 1 - μ
fan = fz.Variable("fan", (0, 100), terms=["off", "low", "high"])

sys = fz.Mamdani()
sys.rule(temp["hot"] & ~temp["cold"], fan["high"])
sys.rule(temp["warm"], fan["low"])

Each rule may carry a weight in [0, 1]:

sys.rule(temp["cold"], fan["off"], weight=0.5)

Choosing connectives

Pass them to the engine by name (or supply your own callable):

sys = fz.Mamdani(tnorm="prod", snorm="probor")

All three connectives are pluggable, NOT included:

Argument Options
tnorm min, prod, lukasiewicz, einstein, hamacher, drastic, nilpotent
snorm max, probor, lukasiewicz, einstein, hamacher, drastic, nilpotent
complement standard (1 - μ), or any callable
from fuzzytool import norms

fz.Mamdani(tnorm="einstein", complement=norms.sugeno_complement(2.0))
fz.Mamdani(tnorm=norms.yager_tnorm(2.0))      # parametric families

The Yager, Dombi and Frank families are exposed as factories returning a callable, which every engine accepts wherever it accepts a name. See fuzzytool.norms for the full list.

Reading a rule base back

Every engine shares the same introspection API:

sys.summary()                 # variables, terms and rules, as text
sys.firing(temp=32)           # firing strength of each rule
sys.explain(temp=32)          # the output plus which rules produced it
sys.input_variables()         # {name: Variable} the antecedents reference

explain is the one to reach for when someone asks why:

{'output': 78.4,
 'fired_rules': [{'index': 0, 'rule': 'IF (temp is hot and (not temp is cold)) THEN fan is high',
                  'firing': 0.8, 'share': 0.73}, ...]}

Rules can also be written as text rather than as Python expressions — see Rules as text — and a whole rule base can be checked for contradictions and gaps with audit.