API reference¶
Generated from docstrings with mkdocstrings.
Membership functions¶
fuzzytool.membership ¶
Membership functions.
Every membership function (MF) is a callable mapping a crisp value (scalar or
NumPy array) to a membership degree in [0, 1]. The :class:MembershipFunction
Protocol is the only contract the rest of the library relies on: the inference
engine never inspects a concrete MF type, so a new shape = a new callable, with
no changes to the core (mirroring the "one variant = one impl" design of the
sibling project turboswarm).
The lowercase factory functions (:func:tri, :func:trap, :func:gauss,
:func:gbell, :func:sigmoid) are the public API; they return small classes so
the parameters stay introspectable for visualization and serialization.
MembershipFunction ¶
Bases: Protocol
A callable x -> degree with membership degrees in [0, 1].
Triangular ¶
Triangular MF with feet at a/c and peak at b.
Trapezoidal ¶
Trapezoidal MF; flat top between b and c.
Gaussian ¶
Gaussian MF centered at c with spread sigma.
GeneralizedBell ¶
Generalized bell MF: 1 / (1 + |(x - c) / a|^(2b)).
Sigmoid ¶
Sigmoidal MF: 1 / (1 + exp(-a (x - c))). Monotonic (invertible).
RampUp ¶
Monotonically increasing ramp: 0 below a, 1 above b.
RampDown ¶
Monotonically decreasing ramp: 1 below a, 0 above b.
trap ¶
Trapezoidal MF: shoulders a/d, flat top b..c.
gbell ¶
Generalized bell MF: width a, slope b, center c.
ramp_up ¶
Increasing ramp MF from 0 at a to 1 at b (monotonic).
ramp_down ¶
Decreasing ramp MF from 1 at a to 0 at b (monotonic).
Connectives (t-norms / s-norms)¶
fuzzytool.norms ¶
Fuzzy connectives: t-norms (AND) and s-norms / t-conorms (OR).
Connectives are plain vectorized callables (a, b) -> result operating
elementwise on membership degrees. They are pluggable: the inference engines
look them up by name through :func:get_tnorm / :func:get_snorm, so adding a
connective means registering one function — the engine never changes.
Sets, variables, and rule antecedents¶
fuzzytool.sets ¶
Fuzzy sets, linguistic variables, and the rule-antecedent expression tree.
A :class:Variable is a linguistic variable: a named universe of discourse plus
a dictionary of terms (named membership functions). Indexing a variable with a
term name (score["good"]) returns a :class:Proposition, the atom of a
rule antecedent. Propositions compose with Python operators:
score["poor"] | dti["high"] # OR (s-norm)
score["good"] & dti["low"] # AND (t-norm)
~dti["high"] # NOT (complement)
The result is a small expression tree that the inference engine evaluates
against crisp inputs to get a firing strength. The same atom doubles as a rule
consequent (premium["high"]), so there is a single concept to learn.
Antecedent ¶
Base node of a rule-antecedent expression tree.
Proposition ¶
Variable ¶
A linguistic variable: a named universe with named fuzzy-set terms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
identifier; rule inputs are matched to variables by this name. |
required |
universe
|
tuple[float, float]
|
|
required |
terms
|
Iterable[str] | Mapping[str, MembershipFunction] | None
|
optional list of term names to auto-generate evenly across the
universe, or a mapping |
None
|
kind
|
str
|
shape used by auto-generation ( |
'triangular'
|
resolution
|
int
|
number of samples used to discretize the universe for Mamdani defuzzification. |
501
|
auto_terms ¶
Generate evenly-spaced terms named names across the universe.
to_dict ¶
Serialize this variable (universe + terms) to a JSON-ready dict.
Only built-in membership functions can be serialized (see
:func:fuzzytool.membership.to_dict).
from_dict
classmethod
¶
Rebuild a variable from :meth:to_dict output.
antecedent_from_dict ¶
Rebuild an antecedent tree from :meth:Antecedent.to_dict output.
variables maps variable names to the :class:Variable instances the
propositions should reference.
Rules¶
fuzzytool.rules ¶
Fuzzy rules shared by the inference engines.
A :class:Rule pairs an antecedent expression with a consequent and an optional
weight. The consequent is interpreted by the engine: Mamdani expects a
:class:~fuzzytool.sets.Proposition (output is term); TSK expects a
constant or a linear coefficient vector.
Rule
dataclass
¶
IF antecedent THEN consequent with an optional firing weight.
Defuzzification¶
fuzzytool.defuzz ¶
Defuzzification: collapse an aggregated output set into a crisp value.
Each defuzzifier takes the discretized universe x and the aggregated
membership y (same shape) and returns a scalar. They are looked up by name
through :func:get_defuzzifier, so adding a method = registering a function.
Inference — Mamdani¶
fuzzytool.inference.mamdani ¶
Mamdani fuzzy inference.
The engine knows nothing about specific membership functions, connectives, or
defuzzifiers: t-norm, s-norm, implication, aggregation and defuzzification are
all resolved by name (or supplied as callables) and applied uniformly. Adding a
behavior means registering a function in :mod:fuzzytool.norms or
:mod:fuzzytool.defuzz, never editing this loop.
Pipeline per call: evaluate each rule's antecedent to a firing strength → shape its consequent term over the output universe via the implication operator → aggregate the shaped sets per output variable → defuzzify.
Mamdani ¶
A Mamdani inference system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tnorm
|
str | Callable
|
t-norm for AND in antecedents (default |
'min'
|
snorm
|
str | Callable
|
s-norm for OR in antecedents (default |
'max'
|
implication
|
str
|
how a firing strength shapes its consequent set —
|
'min'
|
aggregation
|
str | Callable
|
s-norm combining shaped sets per output (default |
'max'
|
defuzz
|
str | Callable
|
defuzzification method (default |
'centroid'
|
rule ¶
Add IF antecedent THEN output is term and return self.
__call__ ¶
Run inference. Returns a float for one output, else a dict by name.
predict ¶
Vectorized inference over array-valued inputs.
Each keyword is an array of n samples. Returns an array of length
n for a single output, else a dict of arrays. Equivalent to calling
the system once per sample, but evaluated in batch.
Inference — Takagi-Sugeno (TSK)¶
fuzzytool.inference.tsk ¶
Takagi-Sugeno-Kang (TSK) fuzzy inference.
Consequents are crisp functions of the inputs rather than fuzzy sets, so there is no defuzzification: the output is the firing-weighted average of the rule consequents. A consequent may be
- a number — zero-order (Sugeno constant), e.g.
5.0; - a mapping
{"const": b0, "x": b1, ...}— first-order linear in the inputs; - any callable
f(**inputs) -> float— arbitrary.
TSK ¶
A (zero- or first-order) Takagi-Sugeno inference system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tnorm
|
str | Callable
|
t-norm for AND in antecedents (default |
'min'
|
snorm
|
str | Callable
|
s-norm for OR in antecedents (default |
'max'
|
Inference — Tsukamoto¶
fuzzytool.inference.tsukamoto ¶
Tsukamoto fuzzy inference.
In a Tsukamoto system every rule's consequent is a monotonic membership
function. A rule firing with strength w produces the crisp value at which
its consequent reaches w (the inverse of the monotonic MF). The system
output is the firing-weighted average of those crisp values — so, like TSK,
there is no defuzzification step.
Consequents must expose inverse(degree) -> value; the built-in
:func:~fuzzytool.membership.ramp_up, :func:~fuzzytool.membership.ramp_down
and :func:~fuzzytool.membership.sigmoid do.
Tsukamoto ¶
A Tsukamoto inference system (monotonic consequents).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tnorm
|
str | Callable
|
t-norm for AND in antecedents (default |
'min'
|
snorm
|
str | Callable
|
s-norm for OR in antecedents (default |
'max'
|
Rule learning (Wang-Mendel)¶
fuzzytool.learn ¶
Learning fuzzy rule bases from data.
:func:wang_mendel implements the classic Wang-Mendel (1992) method: it turns
each training sample into one fuzzy rule (picking, per variable, the term with
the highest membership), assigns the rule a degree equal to the product of those
memberships, and resolves antecedent conflicts by keeping the highest-degree
consequent. The result is a ready-to-use :class:~fuzzytool.inference.Mamdani.
wang_mendel ¶
Generate a Mamdani rule base from data with the Wang-Mendel method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
inputs, shape |
required |
y
|
ndarray
|
targets, shape |
required |
inputs
|
list[Variable]
|
the input linguistic variables (each pre-populated with terms);
column |
required |
output
|
Variable
|
the output linguistic variable (pre-populated with terms). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
A |
Mamdani
|
class: |
Mamdani
|
antecedent (conflicts resolved by rule degree). |
Fuzzy numbers¶
fuzzytool.fuzzynum ¶
Fuzzy numbers and their arithmetic.
A fuzzy number is a convex, normal fuzzy set on the reals. This module provides
the two most used shapes — triangular (TFN) and trapezoidal (TrFN) — with
standard fuzzy arithmetic (+ - * / and scalar scaling), alpha-cuts, a crisp
(centroid) value, and a vertex distance used by fuzzy MCDM (see
:mod:fuzzytool.mcdm).
Multiplication and division use the common positive-support approximation
(operate on the ordered defining points), which is exact for +/- and a
good approximation for *// when supports are positive.
FuzzyNumber ¶
Base class for fuzzy numbers defined by ordered points p.
distance ¶
Vertex distance to another fuzzy number of the same shape.
TriangularFuzzyNumber ¶
TrapezoidalFuzzyNumber ¶
tfn ¶
Shortcut for :class:TriangularFuzzyNumber.
trfn ¶
Shortcut for :class:TrapezoidalFuzzyNumber.
rank ¶
Indices that sort numbers from largest to smallest by centroid.
Fuzzy MCDM¶
fuzzytool.mcdm ¶
Fuzzy multi-criteria decision making (MCDM).
- :func:
fuzzy_topsis— Chen's (2000) fuzzy TOPSIS: rank alternatives by their closeness to the fuzzy positive-ideal solution. - :func:
fuzzy_ahp— Chang's (1996) extent-analysis AHP: derive crisp criterion weights from a triangular-fuzzy pairwise-comparison matrix.
Inputs are triangular fuzzy numbers (:class:~fuzzytool.fuzzynum.TriangularFuzzyNumber).
TopsisResult
dataclass
¶
Result of :func:fuzzy_topsis.
Attributes:
| Name | Type | Description |
|---|---|---|
closeness |
ndarray
|
closeness coefficient |
ranking |
list[int]
|
alternative indices ordered best-to-worst. |
d_plus |
ndarray
|
distance to the fuzzy positive-ideal solution per alternative. |
d_minus |
ndarray
|
distance to the fuzzy negative-ideal solution per alternative. |
fuzzy_topsis ¶
Rank alternatives with Chen's fuzzy TOPSIS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
matrix
|
list
|
|
required |
weights
|
list
|
|
required |
benefit
|
list
|
length- |
required |
Returns:
| Name | Type | Description |
|---|---|---|
A |
TopsisResult
|
class: |
fuzzy_ahp ¶
Crisp criterion weights from a fuzzy pairwise matrix (Chang's method).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
matrix
|
list
|
|
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
A length- |
Serialization¶
fuzzytool.serialize ¶
Save and load fuzzy inference systems as JSON.
Supports :class:~fuzzytool.inference.Mamdani and
:class:~fuzzytool.inference.TSK systems whose connectives/defuzzifier were
given by name and whose variables use built-in membership functions.
TSK consequents must be numbers or coefficient mappings (callable consequents
cannot be serialized).
fz.save(system, "system.json")
system = fz.load("system.json")
Interval type-2 — sets¶
fuzzytool.type2.sets ¶
Interval type-2 (IT2) membership functions.
An :class:IntervalType2MF carries a lower (LMF) and an upper (UMF) type-1
membership function. Calling it returns the membership interval
(lower, upper); the engines also call .lower(x) / .upper(x) directly.
The constructors cover the standard ways of building an FOU from a type-1 set:
- :func:
it2— explicit LMF/UMF; - :func:
it2_scale— height uncertainty (LMF is a scaled-down UMF); - :func:
it2_gauss_uncertain_mean— a Gaussian with mean in[c1, c2]; - :func:
it2_gauss_uncertain_std— a Gaussian with uncertain spread.
IntervalType2MF ¶
An IT2 set defined by a lower (LMF) and an upper (UMF) type-1 MF.
The UMF must dominate the LMF everywhere (LMF(x) <= UMF(x)); this is not
enforced at construction (it would require sampling the universe) but holds
for every set built through the constructors below.
it2 ¶
An IT2 set from explicit lower and upper type-1 membership functions.
it2_scale ¶
Height-uncertainty FOU: UMF is mf, LMF is scale * mf (0 < scale ≤ 1).
it2_gauss_uncertain_mean ¶
Gaussian with an uncertain mean spanning [c1, c2] (c1 < c2).
The UMF is the upper envelope of all Gaussians with mean in [c1, c2]
(flat-topped at 1 between the means); the LMF is their lower envelope.
it2_gauss_uncertain_std ¶
Gaussian with an uncertain spread: UMF uses the wider σ, LMF the narrower.
Interval type-2 — inference¶
fuzzytool.type2.inference ¶
Interval type-2 inference engines.
Both engines evaluate each rule's antecedent to a firing interval
[f_low, f_high] (via :meth:Antecedent.eval_interval) and then collapse the
rule base with Karnik-Mendel type reduction, returning the midpoint of the
type-reduced interval [y_l, y_r].
- :class:
IT2Mamdaniuses center-of-sets type reduction: each consequent IT2 set is summarized by its centroid interval (computed once and cached), and KM combines those centroids weighted by the firing intervals. - :class:
IT2TSKhas crisp consequents (numbers, coefficient mappings, or callables) and applies KM directly to them.
IT2Mamdani ¶
Interval type-2 Mamdani inference (center-of-sets type reduction).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tnorm
|
str | Callable
|
t-norm for AND in antecedents (default |
'min'
|
snorm
|
str | Callable
|
s-norm for OR in antecedents (default |
'max'
|
IT2TSK ¶
Interval type-2 Takagi-Sugeno inference (KM over crisp consequents).
Consequents follow the same convention as the type-1 :class:~fuzzytool.inference.tsk.TSK
engine: a number, a coefficient mapping {"const": b0, "x": b1, ...}, or a
callable f(**inputs) -> float.
Interval type-2 — type reduction¶
fuzzytool.type2.reduction ¶
Karnik-Mendel type reduction.
Type reduction turns the interval-valued output of an IT2 system into a crisp
interval [y_l, y_r] (typically defuzzified as its midpoint). The
Karnik-Mendel (KM) algorithm finds each endpoint by locating the switch point
where the per-point weight flips between its lower and upper bound.
The single primitive :func:km_endpoint is reused everywhere: for an IT2 set's
centroid (points = universe samples, weights = the FOU) and for an IT2 rule base
(points = consequent centroids, weights = rule firing intervals).
km_endpoint ¶
km_endpoint(points: ndarray, lower: ndarray, upper: ndarray, side: str = 'l', max_iter: int = 100) -> float
One endpoint of the type-reduced interval via Karnik-Mendel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
ndarray
|
the y-values (e.g. consequent centroids or universe samples). |
required |
lower
|
ndarray
|
per-point weight lower bounds (same shape as |
required |
upper
|
ndarray
|
per-point weight upper bounds (same shape as |
required |
side
|
str
|
|
'l'
|
max_iter
|
int
|
safeguard on the Karnik-Mendel iteration count. |
100
|
Left endpoint uses the upper weights to the left of the switch and the lower weights to its right; the right endpoint mirrors this.
karnik_mendel ¶
Type-reduce to the interval (y_l, y_r) over a shared set of points.
centroid_it2 ¶
Centroid interval (c_l, c_r) of an IT2 set over universe.
Fuzzy clustering¶
fuzzytool.cluster ¶
Fuzzy clustering.
Unlike crisp k-means, fuzzy clustering lets each sample belong to several
clusters with graded membership. This module provides three algorithms and a
small set of validity metrics, all on plain NumPy arrays of shape
(n_samples, n_features):
- :func:
fuzzy_cmeans— Bezdek's FCM (spherical clusters, Euclidean norm). - :func:
gustafson_kessel— GK, an adaptive norm per cluster that captures ellipsoidal shapes. - :func:
possibilistic_cmeans— PCM, which drops the "memberships sum to 1" constraint so outliers get low typicality in every cluster.
Each returns a :class:ClusterResult. Every algorithm accepts a seed for
reproducibility.
ClusterResult
dataclass
¶
Outcome of a fuzzy clustering run.
Attributes:
| Name | Type | Description |
|---|---|---|
centers |
ndarray
|
cluster prototypes, shape |
u |
ndarray
|
membership/typicality matrix, shape |
n_iter |
int
|
iterations run until convergence. |
objective |
float
|
final value of the algorithm's objective function. |
labels |
ndarray
|
hard assignment |
fuzzy_cmeans ¶
fuzzy_cmeans(X: ndarray, c: int, m: float = 2.0, max_iter: int = 150, tol: float = 1e-05, seed: int | None = None) -> ClusterResult
Bezdek's fuzzy c-means.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
data, shape |
required |
c
|
int
|
number of clusters. |
required |
m
|
float
|
fuzziness exponent ( |
2.0
|
max_iter
|
int
|
maximum iterations. |
150
|
tol
|
float
|
stop when the membership matrix changes by less than this (max-norm). |
1e-05
|
seed
|
int | None
|
RNG seed for the membership initialization. |
None
|
gustafson_kessel ¶
gustafson_kessel(X: ndarray, c: int, m: float = 2.0, max_iter: int = 150, tol: float = 1e-05, seed: int | None = None, reg: float = 1e-10) -> ClusterResult
Gustafson-Kessel clustering (adaptive per-cluster Mahalanobis norm).
Each cluster learns a covariance-shaped, unit-determinant norm, so GK fits ellipsoidal clusters that FCM (fixed spherical norm) cannot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
data, shape |
required |
c
|
int
|
number of clusters. |
required |
m
|
float
|
fuzziness exponent ( |
2.0
|
max_iter
|
int
|
maximum iterations. |
150
|
tol
|
float
|
convergence threshold on the membership matrix (max-norm). |
1e-05
|
seed
|
int | None
|
RNG seed for initialization. |
None
|
reg
|
float
|
ridge added to each fuzzy covariance for numerical stability. |
1e-10
|
possibilistic_cmeans ¶
possibilistic_cmeans(X: ndarray, c: int, m: float = 2.0, max_iter: int = 150, tol: float = 1e-05, seed: int | None = None, k: float = 1.0) -> ClusterResult
Possibilistic c-means (Krishnapuram-Keller).
PCM drops the probabilistic constraint that memberships sum to 1: each value
is a typicality in [0, 1], so noise points score low everywhere. It is
initialized from an FCM run, which also fixes each cluster's scale eta.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
data, shape |
required |
c
|
int
|
number of clusters. |
required |
m
|
float
|
fuzziness exponent ( |
2.0
|
max_iter
|
int
|
maximum iterations. |
150
|
tol
|
float
|
convergence threshold on the typicality matrix (max-norm). |
1e-05
|
seed
|
int | None
|
RNG seed (passed to the initializing FCM). |
None
|
k
|
float
|
scale multiplier for the bandwidth |
1.0
|
partition_coefficient ¶
Bezdek's partition coefficient in (1/c, 1]; higher = crisper.
partition_entropy ¶
Partition entropy in [0, log c); lower = crisper.
xie_beni ¶
Xie-Beni index (compactness / separation); lower is better.
ANFIS¶
fuzzytool.anfis ¶
ANFIS — an adaptive network-based fuzzy inference system (Jang, 1993).
ANFIS is a first-order Takagi-Sugeno system whose parameters are learned from
data. With a grid partition, each of the p inputs carries n_mf Gaussian
membership functions, giving n_mf ** p rules; rule i fires with the
product of its inputs' memberships and emits an affine function of the inputs.
Training uses Jang's hybrid scheme, one pass per epoch:
- with the premise (Gaussian) parameters fixed, the consequent (affine) parameters are solved in closed form by least squares — the output is linear in them;
- with the consequents fixed, the premise centers and widths take a gradient-descent step on the mean squared error.
Pure NumPy; intended for low-dimensional problems (the rule count grows as
n_mf ** p).
ANFIS ¶
A trainable first-order Sugeno system over a grid partition.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_inputs
|
int
|
number of input features |
required |
n_mf
|
int
|
Gaussian membership functions per input (rules = |
3
|
learning_rate
|
float
|
step size for the premise gradient updates. |
0.05
|
F-transform¶
fuzzytool.ftransform ¶
F-transform — the fuzzy transform of Perfilieva.
The F-transform projects a function onto a fuzzy partition of its domain. Over
a uniform partition by triangular basis functions A_1..A_n that satisfy the
Ruspini condition (they sum to 1 everywhere on [a, b]):
- the direct transform reduces the data to
ncomponents, each a membership-weighted average of the samples falling under one basis function; - the inverse transform reconstructs an approximation
f̂(x) = Σ_k F_k · A_k(x).
With few components the round trip smooths/denoises a signal; with many it approximates it closely. Pure NumPy.
FTransform ¶
A triangular F-transform over a uniform fuzzy partition of [a, b].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
float
|
left end of the domain. |
required |
b
|
float
|
right end of the domain ( |
required |
n_basis
|
int
|
number of basis functions / components ( |
required |
Visualization¶
fuzzytool.viz ¶
Matplotlib visualization helpers.
Importing this module requires matplotlib (an optional dependency; install
with pip install fuzzytool[viz]). Visualization is a first-class priority of
the project, mirroring its sibling turboswarm.
plot_variable ¶
Plot every term's membership function over the variable's universe.
plot_it2_variable ¶
Plot an IT2 variable: each term's lower/upper MF with a shaded FOU.
Type-1 terms (if any are mixed in) are drawn as a single line.
control_surface ¶
Plot a system's output as a surface over two input variables.
system must be callable as system(**{x_var.name: x, y_var.name: y})
and return a scalar (single-output Mamdani or TSK).
plot_clusters ¶
Scatter 2-D data colored by hard label, with cluster centers marked.
result is a :class:~fuzzytool.cluster.ClusterResult. Point opacity
encodes the top membership, so fuzzy/boundary points appear fainter.
Integrations — pandas¶
fuzzytool.integrations.pandas ¶
pandas integration: DataFrame in/out and tabular views of fuzzy objects.
Install with pip install fuzzytool[pandas]. Nothing here imports pandas at
module load beyond a guarded check, so the rest of the toolkit stays dependency
-free.
- :func:
predict_df— batch inference straight from a DataFrame. - :func:
rules_dataframe— a readable table of a system's rule base. - :func:
memberships_dataframe— a clustering result's membership matrix. - :func:
components_dataframe— an F-transform's components.
predict_df ¶
predict_df(system: Mamdani | TSK, df: DataFrame, columns: list[str] | None = None) -> pd.Series | pd.DataFrame
Run vectorized inference over a DataFrame.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
Mamdani | TSK
|
a :class: |
required |
df
|
DataFrame
|
a DataFrame whose columns include the system's input variables. |
required |
columns
|
list[str] | None
|
input column names to use, in order. Defaults to the variables
the system's rules reference (see
:func: |
None
|
Returns:
| Type | Description |
|---|---|
Series | DataFrame
|
A |
Series | DataFrame
|
|
rules_dataframe ¶
Return the system's rule base as a DataFrame (one row per rule).
Columns: antecedent (the IF part as text), consequent (the
THEN part) and weight.
memberships_dataframe ¶
Return a clustering result's membership matrix as a DataFrame.
One row per sample, one column {prefix}_{k} per cluster, plus a label
column holding the hard (argmax) assignment.
components_dataframe ¶
Return an :class:~fuzzytool.ftransform.FTransform's components as a DataFrame.
Columns: node (the basis-function center) and component (its value).
Integrations — scikit-learn¶
fuzzytool.integrations.sklearn ¶
scikit-learn integration: fuzzy systems as estimators and transformers.
These objects follow the scikit-learn estimator protocol (fit returns
self, plus predict/transform, get_params/set_params and a
score/fit_transform), so they slot into a Pipeline, GridSearchCV
or cross_val_score — yet, like :class:~fuzzytool.anfis.ANFIS, they do not
import scikit-learn. The [sklearn] extra simply installs scikit-learn so
you have those tools available:
pip install fuzzytool[sklearn]
- :class:
Fuzzifier— a transformer turning crisp features into fuzzy membership-degree features (one column per term). - :class:
WangMendelRegressor— learns a Mamdani rule base from data (Wang-Mendel) and predicts with it. - :class:
FuzzySystemRegressor— wraps an already-built Mamdani/TSK system so it can be scored or pipelined.
Fuzzifier ¶
Bases: _Estimator
Expand crisp features into fuzzy membership-degree features.
Column j of X is interpreted through variables[j]: each of that
variable's terms becomes one output column holding the membership degree.
The result is a soft, interpretable encoding that downstream linear or tree
models can consume.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
list[Variable]
|
one :class: |
required |
WangMendelRegressor ¶
Bases: _Estimator
A regressor that learns a Mamdani rule base from data (Wang-Mendel).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
list[Variable]
|
input linguistic variables (pre-populated with terms), one per
column of |
required |
output
|
Variable
|
the output linguistic variable (pre-populated with terms). |
required |
FuzzySystemRegressor ¶
Bases: _Estimator
Wrap an already-built single-output fuzzy system as an sklearn regressor.
fit does not change the system (it is already defined); it only records
the input column order. Use this to cross-validate, score, or pipeline a
hand-written Mamdani/TSK system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
Mamdani | TSK
|
a single-output Mamdani or TSK system. |
required |
columns
|
list[str] | None
|
input variable names matching |
None
|
Integrations — SciPy¶
fuzzytool.integrations.scipy ¶
SciPy integration: tune a fuzzy system's membership functions to data.
Install with pip install fuzzytool[scipy]. :func:tune adjusts the
parameters of a system's built-in membership functions so its output fits a
dataset, using :func:scipy.optimize.least_squares. It mutates the system in
place and returns SciPy's OptimizeResult (.x, .cost, .nfev,
.success …) — a drop-in way to refine a hand-written Mamdani/TSK system.
Only built-in membership shapes (tri, trap, gauss, gbell,
sigmoid, ramp_up, ramp_down) are tunable; custom callables are left
untouched. Shape validity is preserved every iteration (breakpoints are kept
ordered, widths kept positive), so the optimizer explores freely without
producing degenerate sets.
tune ¶
tune(system: Mamdani | TSK, X: ndarray, y: ndarray, columns: list[str] | None = None, tune_outputs: bool = True, **least_squares_kwargs) -> OptimizeResult
Fit a system's membership-function parameters to data.
Any extra keyword arguments are forwarded to
:func:scipy.optimize.least_squares (e.g. max_nfev).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
Mamdani | TSK
|
a Mamdani or TSK system (mutated in place with the best params). |
required |
X
|
ndarray
|
inputs, shape |
required |
y
|
ndarray
|
targets, shape |
required |
columns
|
list[str] | None
|
input variable names matching |
None
|
tune_outputs
|
bool
|
also tune the output variables' MFs (Mamdani only). |
True
|
Returns:
| Type | Description |
|---|---|
OptimizeResult
|
The SciPy |
Integrations — Optuna¶
fuzzytool.integrations.optuna ¶
Optuna integration: search fuzzy-system structure and hyperparameters.
Install with pip install fuzzytool[optuna]. Fuzzy systems have plenty of
discrete/continuous knobs — which t-norm, which defuzzifier, how many membership
functions, what learning rate — that are awkward to grid-search by hand. These
helpers turn an Optuna trial into a configured system, plus a ready-made
:func:tune_anfis study.
- :func:
suggest_inference_spec— sample the connectives/implication/defuzz of a Mamdani system from a trial. - :func:
suggest_anfis— build an :class:~fuzzytool.anfis.ANFISwith a trial-suggestedn_mfandlearning_rate. - :func:
tune_anfis— run a full study that minimizes training RMSE and returns the best (refit) model.
suggest_inference_spec ¶
Sample a Mamdani spec {tnorm, snorm, implication, defuzz} from a trial.
prefix namespaces the parameter names so several specs can coexist in one
study. Pass the result straight to :class:~fuzzytool.inference.Mamdani.
suggest_anfis ¶
suggest_anfis(trial, n_inputs: int, n_mf_range: tuple[int, int] = (2, 5), lr_range: tuple[float, float] = (0.001, 0.2)) -> ANFIS
Build an ANFIS with a trial-suggested n_mf and learning_rate.
tune_anfis ¶
tune_anfis(X: ndarray, y: ndarray, n_trials: int = 20, n_mf_range: tuple[int, int] = (2, 5), lr_range: tuple[float, float] = (0.001, 0.2), epochs: int = 100, seed: int | None = None) -> tuple
Tune an ANFIS's n_mf/learning_rate with an Optuna study.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
inputs, shape |
required |
y
|
ndarray
|
targets, shape |
required |
n_trials
|
int
|
number of Optuna trials. |
20
|
n_mf_range
|
tuple[int, int]
|
|
(2, 5)
|
lr_range
|
tuple[float, float]
|
|
(0.001, 0.2)
|
epochs
|
int
|
training epochs per trial. |
100
|
seed
|
int | None
|
seed for Optuna's sampler (reproducible search). |
None
|
Returns:
| Type | Description |
|---|---|
tuple
|
A |
tuple
|
hyperparameters, and the Optuna study. |
Integrations — Joblib / Dask¶
fuzzytool.integrations.parallel ¶
Parallel execution helpers (Joblib and Dask).
Install with pip install fuzzytool[parallel] (Joblib) or
fuzzytool[dask] (Dask). These spread embarrassingly-parallel fuzzy workloads
across cores or a Dask cluster:
- :func:
parallel_predict— chunked batch inference with Joblib. - :func:
multi_start_cmeans— run fuzzy c-means from many seeds in parallel and keep the best (FCM is sensitive to initialization). - :func:
dask_predict— the same chunked inference on a Dask scheduler.
.. note::
The process backends pickle the system. A hand-written Mamdani/TSK built from
the built-in shapes pickles fine; a TSK with lambda consequents does not —
pass backend="threading" for those.
parallel_predict ¶
parallel_predict(system: Mamdani | TSK, X: ndarray, columns: list[str] | None = None, n_jobs: int = -1, n_chunks: int | None = None, backend: str = 'loky') -> np.ndarray | dict
Run batch inference over X in parallel chunks with Joblib.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
Mamdani | TSK
|
a Mamdani or TSK system. |
required |
X
|
ndarray
|
inputs, shape |
required |
columns
|
list[str] | None
|
input variable names matching |
None
|
n_jobs
|
int
|
Joblib worker count ( |
-1
|
n_chunks
|
int | None
|
number of row chunks (defaults to |
None
|
backend
|
str
|
Joblib backend ( |
'loky'
|
Returns:
| Type | Description |
|---|---|
ndarray | dict
|
The stacked predictions — an array (single output) or a dict of arrays. |
multi_start_cmeans ¶
multi_start_cmeans(X: ndarray, c: int, n_starts: int = 8, n_jobs: int = -1, backend: str = 'loky', **kwargs) -> ClusterResult
Run :func:~fuzzytool.cluster.fuzzy_cmeans from many seeds; keep the best.
Fuzzy c-means converges to a local optimum that depends on initialization;
running several seeds and keeping the lowest-objective result is a standard
safeguard. The runs are independent, so they parallelize cleanly. Extra
keyword arguments are forwarded to :func:~fuzzytool.cluster.fuzzy_cmeans.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
data, shape |
required |
c
|
int
|
number of clusters. |
required |
n_starts
|
int
|
number of random restarts (seeds |
8
|
n_jobs
|
int
|
Joblib worker count ( |
-1
|
backend
|
str
|
Joblib backend. |
'loky'
|
Returns:
| Type | Description |
|---|---|
ClusterResult
|
The best :class: |
dask_predict ¶
dask_predict(system: Mamdani | TSK, X: ndarray, columns: list[str] | None = None, n_chunks: int | None = None) -> np.ndarray | dict
Run chunked batch inference on a Dask scheduler.
Mirrors :func:parallel_predict but builds a Dask graph (dask.delayed)
and computes it, so it scales to a distributed cluster.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
Mamdani | TSK
|
a Mamdani or TSK system. |
required |
X
|
ndarray
|
inputs, shape |
required |
columns
|
list[str] | None
|
input variable names matching |
None
|
n_chunks
|
int | None
|
number of row chunks (default 8). |
None
|
Returns:
| Type | Description |
|---|---|
ndarray | dict
|
The stacked predictions — an array or a dict of arrays. |
Integrations — LLM agents¶
fuzzytool.integrations.agents ¶
LLM-agent integration: expose a fuzzy system as an explainable tool.
Install with pip install fuzzytool[agents]. A fuzzy inference system is an
unusually good citizen for tool-using LLMs: it is deterministic, bounded, and —
unlike a black-box model — it can say why it produced an answer by reporting
which rules fired and how strongly.
- :func:
explain— run a system and return its crisp output plus the fired rules (no third-party dependency; useful on its own). - :func:
inference_tool— wrap a system as a LangChainStructuredToolan agent can call.
explain ¶
Run system on inputs and explain the result.
Returns a dict with the crisp output (a float, or a dict for a
multi-output Mamdani) and fired_rules: the rules whose firing strength is
positive, each {"rule", "firing"}, sorted strongest-first. This is the
payload an agent (or a human) needs to trust the answer.
inference_tool ¶
inference_tool(system: Mamdani | TSK, columns: list[str] | None = None, name: str = 'fuzzy_inference', description: str | None = None) -> StructuredTool
Wrap a fuzzy system as a LangChain StructuredTool.
The tool takes one float argument per input variable and returns the crisp output together with the rules that fired — so the agent can both use and explain the system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
Mamdani | TSK
|
a Mamdani or TSK system. |
required |
columns
|
list[str] | None
|
input variable names (the tool's arguments). Defaults to the variables the rules reference. |
None
|
name
|
str
|
tool name exposed to the agent. |
'fuzzy_inference'
|
description
|
str | None
|
tool description; a sensible default is generated. |
None
|
Returns:
| Type | Description |
|---|---|
StructuredTool
|
A |
Datasets¶
fuzzytool.datasets ¶
Ready-made example systems.
credit_risk ¶
A credit-risk-premium Mamdani system.
Given a borrower's credit score (300-850) and dti (debt-to-income
ratio, 0-50%), recommend the premium (risk points, 0-12) a lender should
add on top of its base interest rate. Returns (system, score, dti,
premium) so callers can inspect the variables (e.g. for plotting).
sys, score, dti, premium = credit_risk() safe = sys(score=800, dti=10) # great score, low leverage risky = sys(score=520, dti=42) # poor score, high leverage safe < risky True
credit_risk_it2 ¶
An interval type-2 version of :func:credit_risk.
The score and premium terms carry a footprint of uncertainty (uncertain
Gaussian means), modeling vagueness in how a "good" score or a "low" premium
is defined. Returns (system, score, dti, premium).
sys, score, dti, premium = credit_risk_it2() sys(score=800, dti=10) < sys(score=520, dti=42) True
make_blobs ¶
make_blobs(centers=((0.0, 0.0), (6.0, 6.0), (0.0, 6.0)), n_per: int = 60, spread: float = 0.7, seed: int | None = 0) -> np.ndarray
Synthetic isotropic Gaussian blobs for clustering demos and tests.
Returns the stacked data X of shape (len(centers) * n_per, n_features).
X = make_blobs(seed=0) X.shape (180, 2)