gale.ai.fuzzy module
This file contains a small fuzzy logic toolkit: fuzzy sets (membership functions), FuzzyVariable (a named collection of linguistic values over a domain), FuzzyRule/FuzzyRuleSet (antecedent/consequent rules and their evaluation), and defuzzify (turning an aggregated fuzzy output back into a single crisp number). Useful for AI decisions that should change gradually instead of snapping between states – for instance, a guard’s alertness rising smoothly as a player gets closer and stays visible longer, instead of jumping straight from “unaware” to “alerted”.
Author: Alejandro Mujica (aledrums@gmail.com)
- class gale.ai.fuzzy.FuzzySet[source]
Bases:
objectBase class for a fuzzy set: a function from a crisp value to a degree of membership between 0 (not in the set at all) and 1 (fully in the set).
- class gale.ai.fuzzy.TriangularSet(left, peak, right)[source]
Bases:
FuzzySetA fuzzy set shaped like a triangle: membership is 0 at and beyond left/right, rises linearly to 1 at peak, then falls linearly back to 0.
- Parameters:
left (float)
peak (float)
right (float)
- class gale.ai.fuzzy.TrapezoidalSet(left, left_peak, right_peak, right)[source]
Bases:
FuzzySetA fuzzy set shaped like a trapezoid: membership is 0 at and beyond left/right, rises linearly to 1 at left_peak, stays 1 until right_peak, then falls linearly back to 0.
- Parameters:
left (float)
left_peak (float)
right_peak (float)
right (float)
- class gale.ai.fuzzy.LeftShoulderSet(peak, right)[source]
Bases:
FuzzySetA fuzzy set that is fully true (1) at and below peak, then falls linearly to 0 at and beyond right. Useful for the lowest linguistic value of a variable (e.g. “near”), where anything below the interesting range should be fully in the set.
- Parameters:
peak (float)
right (float)
- class gale.ai.fuzzy.RightShoulderSet(left, peak)[source]
Bases:
FuzzySetA fuzzy set that is 0 at and below left, rises linearly to 1 at peak, and stays fully true (1) beyond it. Useful for the highest linguistic value of a variable (e.g. “far”), where anything beyond the interesting range should be fully in the set.
- Parameters:
left (float)
peak (float)
- gale.ai.fuzzy.fuzzy_and(*degrees)[source]
- Parameters:
degrees (float) – Membership degrees to combine.
- Returns:
The fuzzy AND (minimum) of degrees.
- Return type:
float
- gale.ai.fuzzy.fuzzy_or(*degrees)[source]
- Parameters:
degrees (float) – Membership degrees to combine.
- Returns:
The fuzzy OR (maximum) of degrees.
- Return type:
float
- class gale.ai.fuzzy.FuzzyVariable(name, domain, sets, resolution=100)[source]
Bases:
objectA named collection of fuzzy sets (linguistic values, such as “near”/”medium”/”far”) sharing a single domain. Used both to fuzzify a crisp input (turn a number into a dict of membership degrees, one per linguistic value) and, as a consequent, to defuzzify a rule set’s aggregated output back into a single crisp number.
Usage example:
- distance = FuzzyVariable(
“distance”, domain=(0, 100), sets={
“near”: LeftShoulderSet(10, 30), “medium”: TriangularSet(10, 40, 70), “far”: RightShoulderSet(50, 90),
},
) distance.fuzzify(25) # {“near”: 0.25, “medium”: 0.5, “far”: 0.0}
- Parameters:
name (str)
domain (Tuple[float, float])
sets (Dict[str, FuzzySet])
resolution (int)
- fuzzify(x)[source]
- Parameters:
x (float) – The crisp value to fuzzify.
- Returns:
The membership degree of x in each of this variable’s linguistic values.
- Return type:
Dict[str, float]
- defuzzify(degrees)[source]
Turn an aggregated set of output degrees (one per linguistic value of this variable, as produced by FuzzyRuleSet.evaluate) back into a single crisp number, using the centroid method: sample the domain, clip each linguistic value’s membership at its degree, and average the samples weighted by their clipped membership.
- Parameters:
degrees (Dict[str, float]) – Aggregated membership degree of each of this variable’s linguistic values.
- Returns:
The crisp value at the centroid of the aggregated, clipped membership curve, or the midpoint of domain if every sample has zero membership.
- Return type:
float
- class gale.ai.fuzzy.FuzzyRule(antecedent, consequent_variable, consequent_set)[source]
Bases:
objectA single fuzzy rule: an antecedent that computes a firing degree from a dict of fuzzified inputs (build it with fuzzy_and/fuzzy_or over the values fuzzify() produced), and a consequent – the linguistic value of an output FuzzyVariable that this rule votes for, weighted by how strongly it fires.
- Parameters:
antecedent (Callable[[Dict[str, float]], float])
consequent_variable (str)
consequent_set (str)
- class gale.ai.fuzzy.FuzzyRuleSet(rules)[source]
Bases:
objectA collection of FuzzyRule evaluated together: each rule’s firing degree is computed from the fuzzified inputs, then rules voting for the same (variable, linguistic value) pair are aggregated by fuzzy_or (max), producing one degree per output linguistic value per variable – ready to hand to FuzzyVariable.defuzzify.
Usage example:
- alertness = FuzzyVariable(“alertness”, (0, 1), {
“low”: LeftShoulderSet(0.2, 0.5), “high”: RightShoulderSet(0.5, 0.8),
}) rules = FuzzyRuleSet([
- FuzzyRule(
lambda d: fuzzy_and(d[“distance”][“near”], d[“visible”][“yes”]), “alertness”, “high”,
), FuzzyRule(lambda d: d[“distance”][“far”], “alertness”, “low”),
]) fuzzified = {
“distance”: distance.fuzzify(25), “visible”: visible.fuzzify(1),
} output_degrees = rules.evaluate(fuzzified) alertness.defuzzify(output_degrees[“alertness”])
- Parameters:
rules (List[FuzzyRule])
- evaluate(fuzzified_inputs)[source]
- Parameters:
fuzzified_inputs (Dict[str, Dict[str, float]]) – Fuzzified input variables, as name -> FuzzyVariable.fuzzify(x) result.
- Returns:
For each consequent variable name affected by at least one rule, a dict of linguistic_value -> aggregated firing degree.
- Return type:
Dict[str, Dict[str, float]]