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.
Files changed (108) hide show
  1. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/CHANGELOG.md +59 -20
  2. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/CITATION.cff +3 -2
  3. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/PKG-INFO +47 -4
  4. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/README.md +24 -3
  5. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/ROADMAP.md +37 -3
  6. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/api/python.md +44 -0
  7. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/citing.md +4 -3
  8. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/getting-started.md +6 -2
  9. fuzzytool-0.3.0/docs/guide/batch-and-io.md +51 -0
  10. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/clustering.md +2 -0
  11. fuzzytool-0.3.0/docs/guide/fraud-alert.md +65 -0
  12. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/ftransform.md +1 -1
  13. fuzzytool-0.3.0/docs/guide/mcdm.md +60 -0
  14. fuzzytool-0.3.0/docs/guide/rule-learning.md +48 -0
  15. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/tsk.md +1 -1
  16. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/type2.md +12 -1
  17. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/visualization.md +4 -0
  18. fuzzytool-0.3.0/docs/images/clusters.png +0 -0
  19. fuzzytool-0.3.0/docs/images/credit_control_surface.png +0 -0
  20. fuzzytool-0.3.0/docs/images/fraud_anomaly_terms.png +0 -0
  21. fuzzytool-0.3.0/docs/images/fraud_control_surface.png +0 -0
  22. fuzzytool-0.3.0/docs/images/gs_score_terms.png +0 -0
  23. fuzzytool-0.3.0/docs/images/it2_score.png +0 -0
  24. fuzzytool-0.3.0/docs/images/premium_terms.png +0 -0
  25. fuzzytool-0.3.0/docs/images/tut_advisor_surface.png +0 -0
  26. fuzzytool-0.3.0/docs/images/tut_advisor_volatility.png +0 -0
  27. fuzzytool-0.3.0/docs/images/tut_anfis.png +0 -0
  28. fuzzytool-0.3.0/docs/images/tut_clusters.png +0 -0
  29. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/index.md +6 -0
  30. fuzzytool-0.3.0/docs/integrations.md +293 -0
  31. fuzzytool-0.3.0/docs/javascripts/mathjax.js +12 -0
  32. fuzzytool-0.3.0/docs/tutorials/anfis-learning.md +69 -0
  33. fuzzytool-0.3.0/docs/tutorials/clustering-segmentation.md +76 -0
  34. fuzzytool-0.3.0/docs/tutorials/risk-advisor.md +97 -0
  35. fuzzytool-0.3.0/docs/tutorials/topsis-decision.md +66 -0
  36. fuzzytool-0.3.0/examples/fraud_alert.py +39 -0
  37. fuzzytool-0.3.0/examples/mcdm.py +39 -0
  38. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/__init__.py +13 -5
  39. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/anfis.py +13 -0
  40. fuzzytool-0.3.0/fuzzytool/fuzzynum.py +161 -0
  41. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/inference/__init__.py +2 -1
  42. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/inference/mamdani.py +32 -0
  43. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/inference/tsk.py +21 -0
  44. fuzzytool-0.3.0/fuzzytool/inference/tsukamoto.py +65 -0
  45. fuzzytool-0.3.0/fuzzytool/integrations/__init__.py +14 -0
  46. fuzzytool-0.3.0/fuzzytool/integrations/_util.py +39 -0
  47. fuzzytool-0.3.0/fuzzytool/integrations/agents.py +96 -0
  48. fuzzytool-0.3.0/fuzzytool/integrations/optuna.py +107 -0
  49. fuzzytool-0.3.0/fuzzytool/integrations/pandas.py +116 -0
  50. fuzzytool-0.3.0/fuzzytool/integrations/parallel.py +156 -0
  51. fuzzytool-0.3.0/fuzzytool/integrations/scipy.py +146 -0
  52. fuzzytool-0.3.0/fuzzytool/integrations/sklearn.py +178 -0
  53. fuzzytool-0.3.0/fuzzytool/integrations/torch.py +116 -0
  54. fuzzytool-0.3.0/fuzzytool/learn.py +73 -0
  55. fuzzytool-0.3.0/fuzzytool/mcdm.py +124 -0
  56. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/membership.py +92 -2
  57. fuzzytool-0.3.0/fuzzytool/serialize.py +97 -0
  58. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/sets.py +59 -1
  59. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/mkdocs.yml +26 -1
  60. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/pyproject.toml +11 -2
  61. fuzzytool-0.3.0/tests/test_engineering.py +78 -0
  62. fuzzytool-0.3.0/tests/test_integrations.py +281 -0
  63. fuzzytool-0.3.0/tests/test_learn.py +62 -0
  64. fuzzytool-0.3.0/tests/test_mcdm.py +77 -0
  65. fuzzytool-0.1.0/docs/comparison.md +0 -72
  66. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.github/workflows/ci.yml +0 -0
  67. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.github/workflows/docs.yml +0 -0
  68. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.github/workflows/release-pypi.yml +0 -0
  69. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.gitignore +0 -0
  70. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/.zenodo.json +0 -0
  71. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/CLAUDE.md +0 -0
  72. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/CONTRIBUTING.md +0 -0
  73. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/LICENSE +0 -0
  74. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/extending.md +0 -0
  75. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/anfis.md +0 -0
  76. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/defuzzification.md +0 -0
  77. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/mamdani.md +0 -0
  78. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/membership.md +0 -0
  79. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/guide/rules.md +0 -0
  80. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/docs/installation.md +0 -0
  81. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/anfis.py +0 -0
  82. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/clustering.py +0 -0
  83. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/credit_risk.py +0 -0
  84. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/credit_risk_it2.py +0 -0
  85. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/examples/ftransform.py +0 -0
  86. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/cluster.py +0 -0
  87. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/datasets.py +0 -0
  88. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/defuzz.py +0 -0
  89. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/ftransform.py +0 -0
  90. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/norms.py +0 -0
  91. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/rules.py +0 -0
  92. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/type2/__init__.py +0 -0
  93. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/type2/inference.py +0 -0
  94. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/type2/reduction.py +0 -0
  95. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/type2/sets.py +0 -0
  96. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/fuzzytool/viz.py +0 -0
  97. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/01_quickstart.ipynb +0 -0
  98. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/02_type2.ipynb +0 -0
  99. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/03_clustering.ipynb +0 -0
  100. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/04_learning.ipynb +0 -0
  101. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/notebooks/README.md +0 -0
  102. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/paper.bib +0 -0
  103. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/paper.md +0 -0
  104. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_cluster.py +0 -0
  105. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_inference.py +0 -0
  106. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_learning.py +0 -0
  107. {fuzzytool-0.1.0 → fuzzytool-0.3.0}/tests/test_membership.py +0 -0
  108. {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: a comparison page vs scikit-fuzzy and a citing/releasing page;
14
- `.zenodo.json` for DOI archival; `notebooks` optional dependency group.
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.1.0
9
- date-released: 2026-06-24
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.1.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, tipper example, tests | ✅ |
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/tipper.py
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, tipper example, tests | ✅ |
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/tipper.py
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] Tipper example, test suite, packaging, docs, CI.
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 (tipper, TSK, comparison).
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
- ## Phase 6 Release
45
+ ## v0.2.0Decision-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. Repository metadata lives
6
- in [`CITATION.cff`](https://github.com/fuzzytool/fuzzytool.github.io/blob/main/CITATION.cff);
7
- once a release is archived on Zenodo, cite the versioned DOI it mints.
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 -> high premium
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
+ ![Membership functions of the score variable: poor, fair, good and excellent terms](images/gs_score_terms.png)
60
+
61
+ ![Control surface: risk premium as a function of score and dti](images/credit_control_surface.png)
@@ -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
+ ```
@@ -48,3 +48,5 @@ from fuzzytool import viz
48
48
  viz.plot_clusters(X, res) # 2-D scatter; opacity encodes top membership
49
49
  plt.show()
50
50
  ```
51
+
52
+ ![Fuzzy c-means on three blobs: points colored by cluster, centers marked, opacity encoding top membership](../images/clusters.png)
@@ -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
+ ![Membership functions of amount_anomaly: normal, elevated and extreme terms](../images/fraud_anomaly_terms.png)
64
+
65
+ ![Control surface: fraud risk as a function of amount anomaly and transaction velocity](../images/fraud_control_surface.png)
@@ -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 `f̂(x) = Σ_k F_k · A_k(x)`.
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