fuzzytool 0.1.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/CHANGELOG.md +59 -20
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/CITATION.cff +3 -2
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/PKG-INFO +47 -4
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/README.md +24 -3
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/ROADMAP.md +37 -3
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/api/python.md +44 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/citing.md +4 -3
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/getting-started.md +6 -2
- fuzzytool-0.3.0/docs/guide/batch-and-io.md +51 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/clustering.md +2 -0
- fuzzytool-0.3.0/docs/guide/fraud-alert.md +65 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/ftransform.md +1 -1
- fuzzytool-0.3.0/docs/guide/mcdm.md +60 -0
- fuzzytool-0.3.0/docs/guide/rule-learning.md +48 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/tsk.md +1 -1
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/type2.md +12 -1
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/visualization.md +4 -0
- fuzzytool-0.3.0/docs/images/clusters.png +0 -0
- fuzzytool-0.3.0/docs/images/credit_control_surface.png +0 -0
- fuzzytool-0.3.0/docs/images/fraud_anomaly_terms.png +0 -0
- fuzzytool-0.3.0/docs/images/fraud_control_surface.png +0 -0
- fuzzytool-0.3.0/docs/images/gs_score_terms.png +0 -0
- fuzzytool-0.3.0/docs/images/it2_score.png +0 -0
- fuzzytool-0.3.0/docs/images/premium_terms.png +0 -0
- fuzzytool-0.3.0/docs/images/tut_advisor_surface.png +0 -0
- fuzzytool-0.3.0/docs/images/tut_advisor_volatility.png +0 -0
- fuzzytool-0.3.0/docs/images/tut_anfis.png +0 -0
- fuzzytool-0.3.0/docs/images/tut_clusters.png +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/index.md +6 -0
- fuzzytool-0.3.0/docs/integrations.md +293 -0
- fuzzytool-0.3.0/docs/javascripts/mathjax.js +12 -0
- fuzzytool-0.3.0/docs/tutorials/anfis-learning.md +69 -0
- fuzzytool-0.3.0/docs/tutorials/clustering-segmentation.md +76 -0
- fuzzytool-0.3.0/docs/tutorials/risk-advisor.md +97 -0
- fuzzytool-0.3.0/docs/tutorials/topsis-decision.md +66 -0
- fuzzytool-0.3.0/examples/fraud_alert.py +39 -0
- fuzzytool-0.3.0/examples/mcdm.py +39 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/__init__.py +13 -5
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/anfis.py +13 -0
- fuzzytool-0.3.0/fuzzytool/fuzzynum.py +161 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/inference/__init__.py +2 -1
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/inference/mamdani.py +32 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/inference/tsk.py +21 -0
- fuzzytool-0.3.0/fuzzytool/inference/tsukamoto.py +65 -0
- fuzzytool-0.3.0/fuzzytool/integrations/__init__.py +14 -0
- fuzzytool-0.3.0/fuzzytool/integrations/_util.py +39 -0
- fuzzytool-0.3.0/fuzzytool/integrations/agents.py +96 -0
- fuzzytool-0.3.0/fuzzytool/integrations/optuna.py +107 -0
- fuzzytool-0.3.0/fuzzytool/integrations/pandas.py +116 -0
- fuzzytool-0.3.0/fuzzytool/integrations/parallel.py +156 -0
- fuzzytool-0.3.0/fuzzytool/integrations/scipy.py +146 -0
- fuzzytool-0.3.0/fuzzytool/integrations/sklearn.py +178 -0
- fuzzytool-0.3.0/fuzzytool/integrations/torch.py +116 -0
- fuzzytool-0.3.0/fuzzytool/learn.py +73 -0
- fuzzytool-0.3.0/fuzzytool/mcdm.py +124 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/membership.py +92 -2
- fuzzytool-0.3.0/fuzzytool/serialize.py +97 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/sets.py +59 -1
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/mkdocs.yml +26 -1
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/pyproject.toml +11 -2
- fuzzytool-0.3.0/tests/test_engineering.py +78 -0
- fuzzytool-0.3.0/tests/test_integrations.py +281 -0
- fuzzytool-0.3.0/tests/test_learn.py +62 -0
- fuzzytool-0.3.0/tests/test_mcdm.py +77 -0
- fuzzytool-0.1.0/docs/comparison.md +0 -72
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.github/workflows/ci.yml +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.github/workflows/docs.yml +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.github/workflows/release-pypi.yml +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.gitignore +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.zenodo.json +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/CLAUDE.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/CONTRIBUTING.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/LICENSE +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/extending.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/anfis.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/defuzzification.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/mamdani.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/membership.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/rules.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/installation.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/anfis.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/clustering.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/credit_risk.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/credit_risk_it2.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/ftransform.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/cluster.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/datasets.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/defuzz.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/ftransform.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/norms.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/rules.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/type2/__init__.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/type2/inference.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/type2/reduction.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/type2/sets.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/viz.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/01_quickstart.ipynb +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/02_type2.ipynb +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/03_clustering.ipynb +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/04_learning.ipynb +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/README.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/paper.bib +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/paper.md +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_cluster.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_inference.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_learning.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_membership.py +0 -0
- {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_type2.py +0 -0
|
@@ -6,12 +6,68 @@ All notable changes to this project are documented here. The format is based on
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.3.0] - 2026-06-27
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Ecosystem integrations** under `fuzzytool.integrations.*` — each behind its
|
|
14
|
+
own extra and importing its dependency only on use, so the core stays pure
|
|
15
|
+
NumPy:
|
|
16
|
+
- **pandas** (`[pandas]`): `predict_df`, `rules_dataframe`,
|
|
17
|
+
`memberships_dataframe`, `components_dataframe`.
|
|
18
|
+
- **scikit-learn** (`[sklearn]`): `Fuzzifier` transformer (crisp →
|
|
19
|
+
membership-degree features), `WangMendelRegressor`, `FuzzySystemRegressor`.
|
|
20
|
+
- **PyTorch** (`[torch]`): `FuzzyLayer`, a differentiable first-order TSK
|
|
21
|
+
`nn.Module` trainable by autograd and composable into a network.
|
|
22
|
+
- **SciPy** (`[scipy]`): `tune`, fitting a system's membership-function
|
|
23
|
+
parameters to data via `scipy.optimize.least_squares`.
|
|
24
|
+
- **Optuna** (`[optuna]`): `suggest_inference_spec`, `suggest_anfis`, and a
|
|
25
|
+
ready-made `tune_anfis` study.
|
|
26
|
+
- **Joblib / Dask** (`[parallel]`, `[dask]`): `parallel_predict`,
|
|
27
|
+
`multi_start_cmeans`, `dask_predict`.
|
|
28
|
+
- **LLM agents** (`[agents]`): `explain` (crisp output + fired rules) and
|
|
29
|
+
`inference_tool` (a LangChain `StructuredTool`).
|
|
30
|
+
- Tutorials section (investment-risk advisor, ANFIS, Fuzzy TOPSIS, clustering)
|
|
31
|
+
and an Integrations guide page; rendered plots and computed results embedded
|
|
32
|
+
throughout the docs.
|
|
33
|
+
|
|
34
|
+
## [0.2.0] - 2026-06-24
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **Fuzzy numbers & MCDM**: `fuzzytool.fuzzynum` (triangular/trapezoidal numbers
|
|
39
|
+
with arithmetic, alpha-cuts, centroid, distance, ranking) and `fuzzytool.mcdm`
|
|
40
|
+
(`fuzzy_topsis`, `fuzzy_ahp`).
|
|
41
|
+
- **Rule learning**: `wang_mendel` generates a Mamdani rule base from data.
|
|
42
|
+
- **Tsukamoto** inference (`fuzzytool.inference.Tsukamoto`) with monotonic
|
|
43
|
+
consequents; added invertible `ramp_up` / `ramp_down` membership functions and
|
|
44
|
+
an `inverse` on `sigmoid`.
|
|
45
|
+
- **Batch inference**: `Mamdani.predict` / `TSK.predict` evaluate array-valued
|
|
46
|
+
inputs in a vectorized pass.
|
|
47
|
+
- **Serialization**: `fz.save` / `fz.load` (JSON) for Mamdani/TSK systems, plus
|
|
48
|
+
`to_dict`/`from_dict` on membership functions and variables.
|
|
49
|
+
- **scikit-learn compatibility**: `ANFIS.get_params` / `set_params`.
|
|
50
|
+
|
|
51
|
+
## [0.1.0] - 2026-06-24
|
|
52
|
+
|
|
9
53
|
### Added
|
|
10
54
|
|
|
55
|
+
- Core membership functions: triangular, trapezoidal, gaussian, generalized
|
|
56
|
+
bell, sigmoid (`fuzzytool.membership`).
|
|
57
|
+
- T-norms and s-norms (min/prod/Łukasiewicz, max/probor/Łukasiewicz), resolved
|
|
58
|
+
by name (`fuzzytool.norms`).
|
|
59
|
+
- `Variable` (linguistic variable) with auto-generated or explicit terms, and an
|
|
60
|
+
operator-based rule-antecedent expression tree (`&`, `|`, `~`).
|
|
61
|
+
- **Mamdani** inference with configurable implication/aggregation and
|
|
62
|
+
defuzzification (centroid, bisector, MOM/SOM/LOM).
|
|
63
|
+
- **Takagi-Sugeno (TSK)** inference (zero- and first-order, plus callable
|
|
64
|
+
consequents).
|
|
65
|
+
- `fuzzytool.viz`: membership-function plots and 2-input control surfaces.
|
|
66
|
+
- `fuzzytool.datasets.credit_risk`: the flagship example system.
|
|
11
67
|
- Example notebooks (`notebooks/`): quickstart, interval type-2, clustering, and
|
|
12
68
|
ANFIS/F-transform — committed executed.
|
|
13
|
-
- Documentation
|
|
14
|
-
`.zenodo.json` for DOI archival
|
|
69
|
+
- Documentation (MkDocs Material), CI, a comparison page vs scikit-fuzzy, a
|
|
70
|
+
citing/releasing page, and `.zenodo.json` for DOI archival.
|
|
15
71
|
- **ANFIS** (`fuzzytool.anfis.ANFIS`): a trainable first-order Sugeno system over
|
|
16
72
|
a grid partition, fit with Jang's hybrid scheme (least-squares consequents +
|
|
17
73
|
gradient-descent premises). `fit` / `predict` / `history_`.
|
|
@@ -32,21 +88,4 @@ All notable changes to this project are documented here. The format is based on
|
|
|
32
88
|
- `IT2Mamdani` (center-of-sets type reduction) and `IT2TSK` engines.
|
|
33
89
|
- Karnik-Mendel type reduction: `km_endpoint`, `karnik_mendel`, `centroid_it2`.
|
|
34
90
|
- `viz.plot_it2_variable` (shaded FOU); `datasets.credit_risk_it2`.
|
|
35
|
-
|
|
36
|
-
## [0.1.0] - 2026-06-24
|
|
37
|
-
|
|
38
|
-
### Added
|
|
39
|
-
|
|
40
|
-
- Core membership functions: triangular, trapezoidal, gaussian, generalized
|
|
41
|
-
bell, sigmoid (`fuzzytool.membership`).
|
|
42
|
-
- T-norms and s-norms (min/prod/Łukasiewicz, max/probor/Łukasiewicz), resolved
|
|
43
|
-
by name (`fuzzytool.norms`).
|
|
44
|
-
- `Variable` (linguistic variable) with auto-generated or explicit terms, and an
|
|
45
|
-
operator-based rule-antecedent expression tree (`&`, `|`, `~`).
|
|
46
|
-
- **Mamdani** inference with configurable implication/aggregation and
|
|
47
|
-
defuzzification (centroid, bisector, MOM/SOM/LOM).
|
|
48
|
-
- **Takagi-Sugeno (TSK)** inference (zero- and first-order, plus callable
|
|
49
|
-
consequents).
|
|
50
|
-
- `fuzzytool.viz`: membership-function plots and 2-input control surfaces.
|
|
51
|
-
- `fuzzytool.datasets.tipper`: the classic example system.
|
|
52
|
-
- Test suite, MkDocs Material documentation, and CI.
|
|
91
|
+
- Test suite covering every module.
|
|
@@ -5,8 +5,9 @@ type: software
|
|
|
5
5
|
authors:
|
|
6
6
|
- family-names: Salmeron
|
|
7
7
|
given-names: Jose L.
|
|
8
|
-
version: 0.
|
|
9
|
-
date-released: 2026-06-
|
|
8
|
+
version: 0.3.0
|
|
9
|
+
date-released: 2026-06-27
|
|
10
|
+
doi: 10.5281/zenodo.20836712
|
|
10
11
|
license: MIT
|
|
11
12
|
repository-code: "https://github.com/fuzzytool/fuzzytool.github.io"
|
|
12
13
|
url: "https://fuzzytool.github.io"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fuzzytool
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A clean, extensible fuzzy-logic toolkit in pure Python + NumPy
|
|
5
5
|
Project-URL: Homepage, https://fuzzytool.github.io
|
|
6
6
|
Project-URL: Documentation, https://fuzzytool.github.io
|
|
@@ -18,10 +18,20 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
18
18
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
19
19
|
Requires-Python: >=3.9
|
|
20
20
|
Requires-Dist: numpy>=1.21
|
|
21
|
+
Provides-Extra: agents
|
|
22
|
+
Requires-Dist: langchain-core>=0.1; extra == 'agents'
|
|
23
|
+
Provides-Extra: dask
|
|
24
|
+
Requires-Dist: dask>=2022.0; extra == 'dask'
|
|
21
25
|
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: joblib>=1.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: langchain-core>=0.1; extra == 'dev'
|
|
28
|
+
Requires-Dist: optuna>=3.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pandas>=1.3; extra == 'dev'
|
|
22
30
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
23
31
|
Requires-Dist: pytest>=7; extra == 'dev'
|
|
24
32
|
Requires-Dist: ruff; extra == 'dev'
|
|
33
|
+
Requires-Dist: scikit-learn>=1.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: scipy>=1.7; extra == 'dev'
|
|
25
35
|
Provides-Extra: docs
|
|
26
36
|
Requires-Dist: mkdocs-material; extra == 'docs'
|
|
27
37
|
Requires-Dist: mkdocstrings[python]; extra == 'docs'
|
|
@@ -31,6 +41,18 @@ Requires-Dist: jupyter; extra == 'notebooks'
|
|
|
31
41
|
Requires-Dist: matplotlib>=3.4; extra == 'notebooks'
|
|
32
42
|
Requires-Dist: nbconvert; extra == 'notebooks'
|
|
33
43
|
Requires-Dist: nbformat; extra == 'notebooks'
|
|
44
|
+
Provides-Extra: optuna
|
|
45
|
+
Requires-Dist: optuna>=3.0; extra == 'optuna'
|
|
46
|
+
Provides-Extra: pandas
|
|
47
|
+
Requires-Dist: pandas>=1.3; extra == 'pandas'
|
|
48
|
+
Provides-Extra: parallel
|
|
49
|
+
Requires-Dist: joblib>=1.0; extra == 'parallel'
|
|
50
|
+
Provides-Extra: scipy
|
|
51
|
+
Requires-Dist: scipy>=1.7; extra == 'scipy'
|
|
52
|
+
Provides-Extra: sklearn
|
|
53
|
+
Requires-Dist: scikit-learn>=1.0; extra == 'sklearn'
|
|
54
|
+
Provides-Extra: torch
|
|
55
|
+
Requires-Dist: torch>=1.12; extra == 'torch'
|
|
34
56
|
Provides-Extra: viz
|
|
35
57
|
Requires-Dist: matplotlib>=3.4; extra == 'viz'
|
|
36
58
|
Description-Content-Type: text/markdown
|
|
@@ -41,6 +63,7 @@ Description-Content-Type: text/markdown
|
|
|
41
63
|
<a href="https://fuzzytool.github.io/"><img src="https://img.shields.io/badge/docs-fuzzytool.github.io-3f51b5" alt="Docs"></a>
|
|
42
64
|
<img src="https://img.shields.io/pypi/pyversions/fuzzytool?logo=python&logoColor=white" alt="Python versions">
|
|
43
65
|
<img src="https://img.shields.io/badge/license-MIT-blue" alt="License: MIT">
|
|
66
|
+
<a href="https://doi.org/10.5281/zenodo.20836712"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.20836712.svg" alt="DOI"></a>
|
|
44
67
|
</p>
|
|
45
68
|
|
|
46
69
|
# fuzzytool
|
|
@@ -85,12 +108,32 @@ s-norm, `~` the complement.
|
|
|
85
108
|
|
|
86
109
|
| Phase | Content | Status |
|
|
87
110
|
|------|-----------|--------|
|
|
88
|
-
| 1 | Core: membership functions, t-/s-norms, `Variable`, operator rules, **Mamdani** + defuzzification,
|
|
111
|
+
| 1 | Core: membership functions, t-/s-norms, `Variable`, operator rules, **Mamdani** + defuzzification, fraud-alert example, tests | ✅ |
|
|
89
112
|
| 2 | **Takagi-Sugeno (TSK)** inference + `viz` (membership plots, control surface) | ✅ (TSK + viz) |
|
|
90
113
|
| 3 | **Type-2 / interval type-2** sets (footprint of uncertainty) + Karnik-Mendel type reduction | ✅ |
|
|
91
114
|
| 4 | **Fuzzy clustering**: fuzzy c-means, Gustafson-Kessel, possibilistic | ✅ |
|
|
92
115
|
| 5 | **ANFIS** (trainable TSK) + **F-transform** (direct/inverse) | ✅ |
|
|
93
|
-
| 6 | Notebooks, JOSS `paper.md`, Zenodo DOI, PyPI release |
|
|
116
|
+
| 6 | Notebooks, JOSS `paper.md`, Zenodo DOI, PyPI release | ✅ |
|
|
117
|
+
| 7 | **Ecosystem integrations**: pandas, scikit-learn, PyTorch, SciPy, Optuna, Joblib/Dask, LLM agents | ✅ |
|
|
118
|
+
|
|
119
|
+
### v0.3.0
|
|
120
|
+
|
|
121
|
+
- **Integrations** (`fuzzytool.integrations.*`, each behind its own extra):
|
|
122
|
+
**pandas** (DataFrame I/O), **scikit-learn** (`Fuzzifier`, regressors),
|
|
123
|
+
**PyTorch** (differentiable `FuzzyLayer`), **SciPy** (MF tuning), **Optuna**
|
|
124
|
+
(hyperparameter search), **Joblib/Dask** (parallel inference) and
|
|
125
|
+
**LLM agents** (explainable `inference_tool`).
|
|
126
|
+
- **Tutorials** and an **Integrations** guide page, with rendered plots and
|
|
127
|
+
computed outputs throughout the docs.
|
|
128
|
+
|
|
129
|
+
### v0.2.0
|
|
130
|
+
|
|
131
|
+
- **Fuzzy numbers & MCDM:** triangular/trapezoidal fuzzy-number arithmetic,
|
|
132
|
+
**Fuzzy TOPSIS** and **Fuzzy AHP**.
|
|
133
|
+
- **Rule learning:** **Wang-Mendel** rule-base generation from data; **Tsukamoto**
|
|
134
|
+
inference (monotonic consequents).
|
|
135
|
+
- **Engineering:** vectorized **batch inference** (`predict`), JSON
|
|
136
|
+
**save/load**, and a **scikit-learn** estimator interface for ANFIS.
|
|
94
137
|
|
|
95
138
|
See [`ROADMAP.md`](ROADMAP.md).
|
|
96
139
|
|
|
@@ -107,7 +150,7 @@ From source, for development:
|
|
|
107
150
|
python -m venv .venv && source .venv/bin/activate
|
|
108
151
|
pip install -e ".[dev,viz,docs]"
|
|
109
152
|
pytest -q
|
|
110
|
-
python examples/
|
|
153
|
+
python examples/fraud_alert.py
|
|
111
154
|
```
|
|
112
155
|
|
|
113
156
|
## Documentation
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<a href="https://fuzzytool.github.io/"><img src="https://img.shields.io/badge/docs-fuzzytool.github.io-3f51b5" alt="Docs"></a>
|
|
5
5
|
<img src="https://img.shields.io/pypi/pyversions/fuzzytool?logo=python&logoColor=white" alt="Python versions">
|
|
6
6
|
<img src="https://img.shields.io/badge/license-MIT-blue" alt="License: MIT">
|
|
7
|
+
<a href="https://doi.org/10.5281/zenodo.20836712"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.20836712.svg" alt="DOI"></a>
|
|
7
8
|
</p>
|
|
8
9
|
|
|
9
10
|
# fuzzytool
|
|
@@ -48,12 +49,32 @@ s-norm, `~` the complement.
|
|
|
48
49
|
|
|
49
50
|
| Phase | Content | Status |
|
|
50
51
|
|------|-----------|--------|
|
|
51
|
-
| 1 | Core: membership functions, t-/s-norms, `Variable`, operator rules, **Mamdani** + defuzzification,
|
|
52
|
+
| 1 | Core: membership functions, t-/s-norms, `Variable`, operator rules, **Mamdani** + defuzzification, fraud-alert example, tests | ✅ |
|
|
52
53
|
| 2 | **Takagi-Sugeno (TSK)** inference + `viz` (membership plots, control surface) | ✅ (TSK + viz) |
|
|
53
54
|
| 3 | **Type-2 / interval type-2** sets (footprint of uncertainty) + Karnik-Mendel type reduction | ✅ |
|
|
54
55
|
| 4 | **Fuzzy clustering**: fuzzy c-means, Gustafson-Kessel, possibilistic | ✅ |
|
|
55
56
|
| 5 | **ANFIS** (trainable TSK) + **F-transform** (direct/inverse) | ✅ |
|
|
56
|
-
| 6 | Notebooks, JOSS `paper.md`, Zenodo DOI, PyPI release |
|
|
57
|
+
| 6 | Notebooks, JOSS `paper.md`, Zenodo DOI, PyPI release | ✅ |
|
|
58
|
+
| 7 | **Ecosystem integrations**: pandas, scikit-learn, PyTorch, SciPy, Optuna, Joblib/Dask, LLM agents | ✅ |
|
|
59
|
+
|
|
60
|
+
### v0.3.0
|
|
61
|
+
|
|
62
|
+
- **Integrations** (`fuzzytool.integrations.*`, each behind its own extra):
|
|
63
|
+
**pandas** (DataFrame I/O), **scikit-learn** (`Fuzzifier`, regressors),
|
|
64
|
+
**PyTorch** (differentiable `FuzzyLayer`), **SciPy** (MF tuning), **Optuna**
|
|
65
|
+
(hyperparameter search), **Joblib/Dask** (parallel inference) and
|
|
66
|
+
**LLM agents** (explainable `inference_tool`).
|
|
67
|
+
- **Tutorials** and an **Integrations** guide page, with rendered plots and
|
|
68
|
+
computed outputs throughout the docs.
|
|
69
|
+
|
|
70
|
+
### v0.2.0
|
|
71
|
+
|
|
72
|
+
- **Fuzzy numbers & MCDM:** triangular/trapezoidal fuzzy-number arithmetic,
|
|
73
|
+
**Fuzzy TOPSIS** and **Fuzzy AHP**.
|
|
74
|
+
- **Rule learning:** **Wang-Mendel** rule-base generation from data; **Tsukamoto**
|
|
75
|
+
inference (monotonic consequents).
|
|
76
|
+
- **Engineering:** vectorized **batch inference** (`predict`), JSON
|
|
77
|
+
**save/load**, and a **scikit-learn** estimator interface for ANFIS.
|
|
57
78
|
|
|
58
79
|
See [`ROADMAP.md`](ROADMAP.md).
|
|
59
80
|
|
|
@@ -70,7 +91,7 @@ From source, for development:
|
|
|
70
91
|
python -m venv .venv && source .venv/bin/activate
|
|
71
92
|
pip install -e ".[dev,viz,docs]"
|
|
72
93
|
pytest -q
|
|
73
|
-
python examples/
|
|
94
|
+
python examples/fraud_alert.py
|
|
74
95
|
```
|
|
75
96
|
|
|
76
97
|
## Documentation
|
|
@@ -10,13 +10,13 @@ self-contained, testable increment.
|
|
|
10
10
|
- [x] T-norms / s-norms resolved by name; standard complement.
|
|
11
11
|
- [x] `Variable` + operator-based antecedent tree (`&`, `|`, `~`).
|
|
12
12
|
- [x] Mamdani inference + defuzzification (centroid, bisector, MOM/SOM/LOM).
|
|
13
|
-
- [x]
|
|
13
|
+
- [x] Fraud-alert example, test suite, packaging, docs, CI.
|
|
14
14
|
|
|
15
15
|
## ✅ Phase 2 — TSK + visualization
|
|
16
16
|
|
|
17
17
|
- [x] Takagi-Sugeno inference (zero/first-order + callable consequents).
|
|
18
18
|
- [x] `viz`: membership plots, 2-input control surface.
|
|
19
|
-
- [ ] Example notebooks (
|
|
19
|
+
- [ ] Example notebooks (fraud-alert, TSK).
|
|
20
20
|
|
|
21
21
|
## ✅ Phase 3 — Type-2 / interval type-2
|
|
22
22
|
|
|
@@ -42,7 +42,41 @@ self-contained, testable increment.
|
|
|
42
42
|
- [x] F-transform: direct and inverse over a triangular fuzzy partition
|
|
43
43
|
(partition of unity), with smoothing/denoising.
|
|
44
44
|
|
|
45
|
-
##
|
|
45
|
+
## ✅ v0.2.0 — Decision-making, rule learning, engineering
|
|
46
|
+
|
|
47
|
+
- [x] Fuzzy numbers (triangular/trapezoidal) + arithmetic; fuzzy MCDM
|
|
48
|
+
(`fuzzy_topsis`, `fuzzy_ahp`).
|
|
49
|
+
- [x] Rule learning from data (`wang_mendel`); Tsukamoto inference with
|
|
50
|
+
invertible ramp/sigmoid MFs.
|
|
51
|
+
- [x] Vectorized batch inference (`Mamdani.predict` / `TSK.predict`);
|
|
52
|
+
JSON serialization (`save`/`load`); scikit-learn estimator interface on ANFIS.
|
|
53
|
+
|
|
54
|
+
## 🔌 Ecosystem integrations (`fuzzytool.integrations.*`)
|
|
55
|
+
|
|
56
|
+
Each pulls its dependency in only on import, behind its own extra.
|
|
57
|
+
|
|
58
|
+
- [x] **pandas** (`[pandas]`): `predict_df`, `rules_dataframe`,
|
|
59
|
+
`memberships_dataframe`, `components_dataframe`.
|
|
60
|
+
- [x] **scikit-learn** (`[sklearn]`): `Fuzzifier` transformer,
|
|
61
|
+
`WangMendelRegressor`, `FuzzySystemRegressor` (ANFIS already compatible).
|
|
62
|
+
- [x] **PyTorch** (`[torch]`): `FuzzyLayer`, a differentiable first-order TSK
|
|
63
|
+
`nn.Module` trainable by autograd and composable into a network.
|
|
64
|
+
- [x] **SciPy** (`[scipy]`): `tune` MF parameters to data via
|
|
65
|
+
`scipy.optimize.least_squares` (returns the `OptimizeResult`).
|
|
66
|
+
- [x] **Optuna** (`[optuna]`): `suggest_inference_spec`, `suggest_anfis` and a
|
|
67
|
+
ready-made `tune_anfis` study.
|
|
68
|
+
- [x] **Joblib / Dask** (`[parallel]`, `[dask]`): `parallel_predict`,
|
|
69
|
+
`multi_start_cmeans`, `dask_predict`.
|
|
70
|
+
- [x] **Agents (LangChain/LangGraph)** (`[agents]`): `explain` plus an
|
|
71
|
+
`inference_tool` LangChain tool that reports which rules fired.
|
|
72
|
+
|
|
73
|
+
## Ideas for later
|
|
74
|
+
|
|
75
|
+
- Fuzzy cognitive maps (+ grey FCM).
|
|
76
|
+
- General (non-interval) type-2; more defuzzifiers.
|
|
77
|
+
- FIS tuning via metaheuristics (e.g. PSO).
|
|
78
|
+
|
|
79
|
+
## ⏳ Phase 6 — Release (v0.1.0)
|
|
46
80
|
|
|
47
81
|
- [x] Example notebooks (`notebooks/`) and a comparison page vs scikit-fuzzy.
|
|
48
82
|
- [x] JOSS `paper.md`; Zenodo metadata (`.zenodo.json`) and a citing/releasing page.
|
|
@@ -30,6 +30,26 @@ Generated from docstrings with `mkdocstrings`.
|
|
|
30
30
|
|
|
31
31
|
::: fuzzytool.inference.tsk
|
|
32
32
|
|
|
33
|
+
## Inference — Tsukamoto
|
|
34
|
+
|
|
35
|
+
::: fuzzytool.inference.tsukamoto
|
|
36
|
+
|
|
37
|
+
## Rule learning (Wang-Mendel)
|
|
38
|
+
|
|
39
|
+
::: fuzzytool.learn
|
|
40
|
+
|
|
41
|
+
## Fuzzy numbers
|
|
42
|
+
|
|
43
|
+
::: fuzzytool.fuzzynum
|
|
44
|
+
|
|
45
|
+
## Fuzzy MCDM
|
|
46
|
+
|
|
47
|
+
::: fuzzytool.mcdm
|
|
48
|
+
|
|
49
|
+
## Serialization
|
|
50
|
+
|
|
51
|
+
::: fuzzytool.serialize
|
|
52
|
+
|
|
33
53
|
## Interval type-2 — sets
|
|
34
54
|
|
|
35
55
|
::: fuzzytool.type2.sets
|
|
@@ -58,6 +78,30 @@ Generated from docstrings with `mkdocstrings`.
|
|
|
58
78
|
|
|
59
79
|
::: fuzzytool.viz
|
|
60
80
|
|
|
81
|
+
## Integrations — pandas
|
|
82
|
+
|
|
83
|
+
::: fuzzytool.integrations.pandas
|
|
84
|
+
|
|
85
|
+
## Integrations — scikit-learn
|
|
86
|
+
|
|
87
|
+
::: fuzzytool.integrations.sklearn
|
|
88
|
+
|
|
89
|
+
## Integrations — SciPy
|
|
90
|
+
|
|
91
|
+
::: fuzzytool.integrations.scipy
|
|
92
|
+
|
|
93
|
+
## Integrations — Optuna
|
|
94
|
+
|
|
95
|
+
::: fuzzytool.integrations.optuna
|
|
96
|
+
|
|
97
|
+
## Integrations — Joblib / Dask
|
|
98
|
+
|
|
99
|
+
::: fuzzytool.integrations.parallel
|
|
100
|
+
|
|
101
|
+
## Integrations — LLM agents
|
|
102
|
+
|
|
103
|
+
::: fuzzytool.integrations.agents
|
|
104
|
+
|
|
61
105
|
## Datasets
|
|
62
106
|
|
|
63
107
|
::: fuzzytool.datasets
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Citing
|
|
4
4
|
|
|
5
|
-
If you use fuzzytool in academic work, please cite it.
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
If you use fuzzytool in academic work, please cite it. The archival DOI (all
|
|
6
|
+
versions) is [10.5281/zenodo.20836712](https://doi.org/10.5281/zenodo.20836712);
|
|
7
|
+
each release also mints its own versioned DOI. Repository citation metadata lives
|
|
8
|
+
in [`CITATION.cff`](https://github.com/fuzzytool/fuzzytool.github.io/blob/main/CITATION.cff).
|
|
8
9
|
|
|
9
10
|
## Releasing (maintainers)
|
|
10
11
|
|
|
@@ -41,8 +41,8 @@ sys.rule(score["good"] | score["excellent"], premium["low"])
|
|
|
41
41
|
The system is **callable**. Pass crisp inputs by variable name:
|
|
42
42
|
|
|
43
43
|
```python
|
|
44
|
-
sys(score=800, dti=10) # strong borrower -> low premium
|
|
45
|
-
sys(score=520, dti=42) # weak borrower
|
|
44
|
+
sys(score=800, dti=10) # strong borrower -> 2.45 pts (low premium)
|
|
45
|
+
sys(score=520, dti=42) # weak borrower -> 9.93 pts (high premium)
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
## 4. Visualize (optional)
|
|
@@ -55,3 +55,7 @@ viz.plot_variable(score)
|
|
|
55
55
|
viz.control_surface(sys, score, dti)
|
|
56
56
|
plt.show()
|
|
57
57
|
```
|
|
58
|
+
|
|
59
|
+

|
|
60
|
+
|
|
61
|
+

|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Batch inference, serialization & scikit-learn
|
|
2
|
+
|
|
3
|
+
## Batch (vectorized) inference
|
|
4
|
+
|
|
5
|
+
Calling a system evaluates one sample. `predict(**arrays)` evaluates many at once
|
|
6
|
+
— pass an array per variable and get an array back. Available on `Mamdani` and
|
|
7
|
+
`TSK`.
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import numpy as np
|
|
11
|
+
from fuzzytool import datasets
|
|
12
|
+
|
|
13
|
+
sys, *_ = datasets.credit_risk()
|
|
14
|
+
scores = np.array([520.0, 660.0, 800.0])
|
|
15
|
+
dtis = np.array([42.0, 30.0, 10.0])
|
|
16
|
+
|
|
17
|
+
sys.predict(score=scores, dti=dtis) # -> array([10.16, 6. , 1.91]), one premium per sample
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The result matches calling the system once per sample, but the firing, implication
|
|
21
|
+
and aggregation steps run vectorized.
|
|
22
|
+
|
|
23
|
+
## Saving and loading systems
|
|
24
|
+
|
|
25
|
+
Serialize a Mamdani or TSK system to JSON and restore it later. Connectives and
|
|
26
|
+
the defuzzifier must be given **by name**, variables must use **built-in**
|
|
27
|
+
membership functions, and TSK consequents must be numbers or coefficient mappings.
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import fuzzytool as fz
|
|
31
|
+
|
|
32
|
+
fz.save(sys, "credit_risk.json")
|
|
33
|
+
restored = fz.load("credit_risk.json")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`fuzzytool.membership.to_dict`/`from_dict` and `Variable.to_dict`/`from_dict`
|
|
37
|
+
expose the building blocks if you need finer control.
|
|
38
|
+
|
|
39
|
+
## scikit-learn compatibility
|
|
40
|
+
|
|
41
|
+
`ANFIS` follows the estimator protocol (`fit` returns `self`, plus `predict`,
|
|
42
|
+
`get_params`, `set_params`), so it drops into a `Pipeline` or `GridSearchCV`
|
|
43
|
+
without importing scikit-learn at all:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import fuzzytool as fz
|
|
47
|
+
|
|
48
|
+
model = fz.ANFIS(n_inputs=2, n_mf=3)
|
|
49
|
+
model.get_params() # {'n_inputs': 2, 'n_mf': 3, 'learning_rate': 0.05}
|
|
50
|
+
clone = fz.ANFIS(**model.get_params())
|
|
51
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Worked example: fraud-alert score
|
|
2
|
+
|
|
3
|
+
A complete, runnable Mamdani system that scores card transactions for fraud. A
|
|
4
|
+
payment monitor turns how far a charge deviates from the customer's usual spend
|
|
5
|
+
(**amount anomaly**, in standard deviations, 0–8) and how many card swipes
|
|
6
|
+
happened in the last hour (**velocity**, 0–30) into a **fraud-risk** score
|
|
7
|
+
(0–100).
|
|
8
|
+
|
|
9
|
+
The full script lives in
|
|
10
|
+
[`examples/fraud_alert.py`](https://github.com/fuzzytool/fuzzytool/blob/main/examples/fraud_alert.py).
|
|
11
|
+
|
|
12
|
+
## 1. Define the linguistic variables
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
import fuzzytool as fz
|
|
16
|
+
|
|
17
|
+
amount_anomaly = fz.Variable("amount_anomaly", (0, 8))
|
|
18
|
+
amount_anomaly["normal"] = fz.trap(0, 0, 1, 2.5)
|
|
19
|
+
amount_anomaly["elevated"] = fz.tri(2, 3.5, 5)
|
|
20
|
+
amount_anomaly["extreme"] = fz.trap(4.5, 6, 8, 8)
|
|
21
|
+
|
|
22
|
+
velocity = fz.Variable("velocity", (0, 30))
|
|
23
|
+
velocity["low"] = fz.trap(0, 0, 3, 6)
|
|
24
|
+
velocity["moderate"] = fz.tri(4, 9, 14)
|
|
25
|
+
velocity["burst"] = fz.trap(12, 20, 30, 30)
|
|
26
|
+
|
|
27
|
+
fraud_risk = fz.Variable("fraud_risk", (0, 100))
|
|
28
|
+
fraud_risk["low"] = fz.tri(0, 12, 35)
|
|
29
|
+
fraud_risk["medium"] = fz.tri(30, 50, 70)
|
|
30
|
+
fraud_risk["high"] = fz.tri(65, 85, 100)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 2. Write the rule base
|
|
34
|
+
|
|
35
|
+
`&` is AND (t-norm), `|` is OR (s-norm), `~` is NOT (complement):
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
sys = fz.Mamdani(defuzz="centroid")
|
|
39
|
+
sys.rule(amount_anomaly["extreme"] | velocity["burst"], fraud_risk["high"])
|
|
40
|
+
sys.rule(amount_anomaly["elevated"] & velocity["moderate"], fraud_risk["medium"])
|
|
41
|
+
sys.rule(amount_anomaly["normal"] & velocity["low"], fraud_risk["low"])
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 3. Score transactions
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
sys(amount_anomaly=0.5, velocity=2) # routine charge -> ~16/100
|
|
48
|
+
sys(amount_anomaly=3.5, velocity=9) # borderline -> 50/100
|
|
49
|
+
sys(amount_anomaly=6.5, velocity=22) # likely fraud -> ~83/100
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 4. Visualize (optional)
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
import matplotlib.pyplot as plt
|
|
56
|
+
from fuzzytool import viz
|
|
57
|
+
|
|
58
|
+
viz.plot_variable(amount_anomaly)
|
|
59
|
+
viz.control_surface(sys, amount_anomaly, velocity)
|
|
60
|
+
plt.show()
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+

|
|
@@ -7,7 +7,7 @@ uses a uniform triangular partition whose basis functions sum to 1 everywhere
|
|
|
7
7
|
|
|
8
8
|
- the **direct** transform reduces the data to `n_basis` components, each a
|
|
9
9
|
membership-weighted average of the samples under one basis function;
|
|
10
|
-
- the **inverse** transform reconstructs
|
|
10
|
+
- the **inverse** transform reconstructs $\hat{f}(x) = \sum_k F_k \, A_k(x)$.
|
|
11
11
|
|
|
12
12
|
Few components → a smoothing/denoising round trip; many components → a close
|
|
13
13
|
approximation.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Fuzzy numbers & MCDM
|
|
2
|
+
|
|
3
|
+
## Fuzzy numbers
|
|
4
|
+
|
|
5
|
+
[`fuzzytool.fuzzynum`][fuzzytool.fuzzynum] provides triangular (TFN) and
|
|
6
|
+
trapezoidal (TrFN) fuzzy numbers with arithmetic, alpha-cuts, a crisp centroid,
|
|
7
|
+
and a vertex distance.
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from fuzzytool.fuzzynum import tfn, trfn, rank
|
|
11
|
+
|
|
12
|
+
a, b = tfn(1, 2, 3), tfn(2, 3, 4)
|
|
13
|
+
a + b # TFN(3, 5, 7)
|
|
14
|
+
a * 2 # TFN(2, 4, 6)
|
|
15
|
+
a.centroid() # 2.0
|
|
16
|
+
a.alpha_cut(0.5) # (1.5, 2.5)
|
|
17
|
+
rank([tfn(0,1,2), tfn(5,6,7)]) # [1, 0] (largest first)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`+`/`-` are exact; `*`/`/` use the standard positive-support approximation.
|
|
21
|
+
|
|
22
|
+
## Fuzzy multi-criteria decision making
|
|
23
|
+
|
|
24
|
+
[`fuzzytool.mcdm`][fuzzytool.mcdm] offers two classic methods.
|
|
25
|
+
|
|
26
|
+
### Fuzzy TOPSIS (Chen)
|
|
27
|
+
|
|
28
|
+
Rank alternatives by closeness to the fuzzy positive-ideal solution. The decision
|
|
29
|
+
matrix and weights are triangular fuzzy numbers; `benefit[j]` says whether
|
|
30
|
+
criterion `j` is maximized.
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from fuzzytool.fuzzynum import tfn
|
|
34
|
+
from fuzzytool.mcdm import fuzzy_topsis
|
|
35
|
+
|
|
36
|
+
matrix = [
|
|
37
|
+
[tfn(7, 8, 9), tfn(5, 6, 7)], # alternative A: ratings per criterion
|
|
38
|
+
[tfn(3, 4, 5), tfn(8, 9, 9)], # alternative B
|
|
39
|
+
]
|
|
40
|
+
weights = [tfn(0.4, 0.5, 0.6), tfn(0.3, 0.4, 0.5)]
|
|
41
|
+
res = fuzzy_topsis(matrix, weights, benefit=[True, True])
|
|
42
|
+
res.closeness # -> array([0.369, 0.316]), closeness coefficient per alternative
|
|
43
|
+
res.ranking # -> [0, 1], alternative indices, best first
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Fuzzy AHP (Chang's extent analysis)
|
|
47
|
+
|
|
48
|
+
Derive crisp criterion weights from a fuzzy pairwise-comparison matrix.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from fuzzytool.fuzzynum import tfn
|
|
52
|
+
from fuzzytool.mcdm import fuzzy_ahp
|
|
53
|
+
|
|
54
|
+
one = tfn(1, 1, 1)
|
|
55
|
+
matrix = [
|
|
56
|
+
[one, tfn(1, 2, 3)],
|
|
57
|
+
[tfn(1/3, 1/2, 1), one],
|
|
58
|
+
]
|
|
59
|
+
fuzzy_ahp(matrix) # -> array([0.69, 0.31]), normalized crisp weights
|
|
60
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Rule learning
|
|
2
|
+
|
|
3
|
+
## Learning a rule base from data (Wang-Mendel)
|
|
4
|
+
|
|
5
|
+
[`wang_mendel`][fuzzytool.learn.wang_mendel] generates a Mamdani rule base from
|
|
6
|
+
data: each sample becomes one rule (picking the highest-membership term per
|
|
7
|
+
variable), and antecedent conflicts are resolved by rule degree.
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import numpy as np
|
|
11
|
+
import fuzzytool as fz
|
|
12
|
+
|
|
13
|
+
X = np.random.default_rng(0).uniform(0, 10, size=(300, 2))
|
|
14
|
+
y = (X[:, 0] + X[:, 1]) / 2
|
|
15
|
+
|
|
16
|
+
a = fz.Variable("a", (0, 10), terms=["lo", "mid", "hi"])
|
|
17
|
+
b = fz.Variable("b", (0, 10), terms=["lo", "mid", "hi"])
|
|
18
|
+
out = fz.Variable("out", (0, 10), terms=["lo", "mid", "hi"])
|
|
19
|
+
|
|
20
|
+
sys = fz.wang_mendel(X, y, [a, b], out) # a ready-to-use Mamdani system
|
|
21
|
+
sys(a=8, b=7) # -> 5.88 (learned system approximates the mean (a + b) / 2)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The input variables supply the partition; the learned system is a plain
|
|
25
|
+
`Mamdani`, so it also supports batch [`predict`](batch-and-io.md) and
|
|
26
|
+
serialization.
|
|
27
|
+
|
|
28
|
+
## Tsukamoto inference
|
|
29
|
+
|
|
30
|
+
[`Tsukamoto`][fuzzytool.inference.tsukamoto.Tsukamoto] consequents are
|
|
31
|
+
**monotonic** membership functions; a rule firing with strength `w` outputs the
|
|
32
|
+
value where its consequent reaches `w` (its inverse), and the system returns the
|
|
33
|
+
firing-weighted average — no defuzzification.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import fuzzytool as fz
|
|
37
|
+
|
|
38
|
+
x = fz.Variable("x", (0, 10), terms=["lo", "hi"])
|
|
39
|
+
sys = fz.Tsukamoto()
|
|
40
|
+
sys.rule(x["lo"], fz.ramp_down(0, 30)) # monotonic consequents only
|
|
41
|
+
sys.rule(x["hi"], fz.ramp_up(0, 30))
|
|
42
|
+
sys(x=7) # -> 21.0
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Use [`ramp_up`][fuzzytool.membership.ramp_up],
|
|
46
|
+
[`ramp_down`][fuzzytool.membership.ramp_down], or
|
|
47
|
+
[`sigmoid`][fuzzytool.membership.sigmoid] — each exposes the `inverse` Tsukamoto
|
|
48
|
+
needs.
|
|
@@ -20,7 +20,7 @@ sys.rule(x["small"], 0.0) # zero-order
|
|
|
20
20
|
sys.rule(x["large"], {"const": 1.0, "x": 1.0}) # first-order: 1 + x
|
|
21
21
|
sys.rule(x["small"], lambda x: x**2) # arbitrary callable
|
|
22
22
|
|
|
23
|
-
sys(x=10.0)
|
|
23
|
+
sys(x=10.0) # -> 11.0
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
TSK systems are typically faster and differentiable, which makes them the basis
|