fuzzytool 0.3.0__tar.gz → 0.5.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.3.0 → fuzzytool-0.5.0}/CHANGELOG.md +30 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/CITATION.cff +2 -2
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/PKG-INFO +17 -2
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/README.md +14 -1
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/ROADMAP.md +16 -5
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/api/python.md +8 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/type2.md +46 -0
- fuzzytool-0.5.0/docs/images/gt2_zslices.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/integrations.md +33 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/__init__.py +9 -1
- fuzzytool-0.5.0/fuzzytool/integrations/_util.py +96 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/integrations/scipy.py +9 -50
- fuzzytool-0.5.0/fuzzytool/integrations/turboswarm.py +120 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/type2/__init__.py +10 -0
- fuzzytool-0.5.0/fuzzytool/type2/general.py +211 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/pyproject.toml +2 -1
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_integrations.py +20 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_type2.py +56 -0
- fuzzytool-0.3.0/fuzzytool/integrations/_util.py +0 -39
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/.github/workflows/ci.yml +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/.github/workflows/docs.yml +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/.github/workflows/release-pypi.yml +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/.gitignore +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/.zenodo.json +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/CLAUDE.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/CONTRIBUTING.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/LICENSE +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/citing.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/extending.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/getting-started.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/anfis.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/batch-and-io.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/clustering.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/defuzzification.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/fraud-alert.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/ftransform.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/mamdani.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/mcdm.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/membership.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/rule-learning.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/rules.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/tsk.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/guide/visualization.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/clusters.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/credit_control_surface.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/fraud_anomaly_terms.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/fraud_control_surface.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/gs_score_terms.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/it2_score.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/premium_terms.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/tut_advisor_surface.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/tut_advisor_volatility.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/tut_anfis.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/images/tut_clusters.png +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/index.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/installation.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/javascripts/mathjax.js +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/tutorials/anfis-learning.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/tutorials/clustering-segmentation.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/tutorials/risk-advisor.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/docs/tutorials/topsis-decision.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/examples/anfis.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/examples/clustering.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/examples/credit_risk.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/examples/credit_risk_it2.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/examples/fraud_alert.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/examples/ftransform.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/examples/mcdm.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/anfis.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/cluster.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/datasets.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/defuzz.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/ftransform.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/fuzzynum.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/inference/__init__.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/inference/mamdani.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/inference/tsk.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/inference/tsukamoto.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/integrations/__init__.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/integrations/agents.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/integrations/optuna.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/integrations/pandas.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/integrations/parallel.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/integrations/sklearn.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/integrations/torch.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/learn.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/mcdm.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/membership.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/norms.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/rules.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/serialize.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/sets.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/type2/inference.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/type2/reduction.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/type2/sets.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/fuzzytool/viz.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/mkdocs.yml +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/notebooks/01_quickstart.ipynb +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/notebooks/02_type2.ipynb +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/notebooks/03_clustering.ipynb +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/notebooks/04_learning.ipynb +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/notebooks/README.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/paper.bib +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/paper.md +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_cluster.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_engineering.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_inference.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_learn.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_learning.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_mcdm.py +0 -0
- {fuzzytool-0.3.0 → fuzzytool-0.5.0}/tests/test_membership.py +0 -0
|
@@ -6,6 +6,36 @@ All notable changes to this project are documented here. The format is based on
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.5.0] - 2026-06-28
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **General type-2 (GT2) fuzzy sets** via the zSlices / alpha-plane
|
|
14
|
+
representation (`fuzzytool.type2.general`):
|
|
15
|
+
- `GeneralType2MF` — a GT2 set as a stack of IT2 z-slices; also exposes the
|
|
16
|
+
overall FOU (`lower`/`upper`), so it can stand in for its IT2 footprint.
|
|
17
|
+
- Constructors `gt2_from_it2`, `gt2_gauss_uncertain_mean`, `gt2_scale`
|
|
18
|
+
(triangular secondary membership peaking at the principal MF).
|
|
19
|
+
- `GeneralType2Mamdani` — inference as a z-weighted stack of IT2 Mamdani
|
|
20
|
+
runs, reusing the Karnik-Mendel machinery.
|
|
21
|
+
- `centroid_gt2` — zSlices type reduction of a single GT2 set.
|
|
22
|
+
|
|
23
|
+
## [0.4.0] - 2026-06-28
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- **turboswarm integration** (`fuzzytool.integrations.turboswarm`, extra
|
|
28
|
+
`[turboswarm]`): `tune` fits a system's built-in membership-function
|
|
29
|
+
parameters to data with the sibling library's gradient-free, global Particle
|
|
30
|
+
Swarm Optimization — the metaheuristic counterpart of the SciPy least-squares
|
|
31
|
+
tuner. Returns turboswarm's `PsoResult`.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- Shared membership-function tuning helpers (`sanitize_mf_params`,
|
|
36
|
+
`tunable_terms`, `MF_PENALTY`) moved to `fuzzytool.integrations._util` and
|
|
37
|
+
reused by both the SciPy and turboswarm tuners.
|
|
38
|
+
|
|
9
39
|
## [0.3.0] - 2026-06-27
|
|
10
40
|
|
|
11
41
|
### Added
|
|
@@ -5,8 +5,8 @@ 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.5.0
|
|
9
|
+
date-released: 2026-06-28
|
|
10
10
|
doi: 10.5281/zenodo.20836712
|
|
11
11
|
license: MIT
|
|
12
12
|
repository-code: "https://github.com/fuzzytool/fuzzytool.github.io"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fuzzytool
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.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
|
|
@@ -53,6 +53,8 @@ Provides-Extra: sklearn
|
|
|
53
53
|
Requires-Dist: scikit-learn>=1.0; extra == 'sklearn'
|
|
54
54
|
Provides-Extra: torch
|
|
55
55
|
Requires-Dist: torch>=1.12; extra == 'torch'
|
|
56
|
+
Provides-Extra: turboswarm
|
|
57
|
+
Requires-Dist: turboswarm>=0.7; extra == 'turboswarm'
|
|
56
58
|
Provides-Extra: viz
|
|
57
59
|
Requires-Dist: matplotlib>=3.4; extra == 'viz'
|
|
58
60
|
Description-Content-Type: text/markdown
|
|
@@ -114,7 +116,20 @@ s-norm, `~` the complement.
|
|
|
114
116
|
| 4 | **Fuzzy clustering**: fuzzy c-means, Gustafson-Kessel, possibilistic | ✅ |
|
|
115
117
|
| 5 | **ANFIS** (trainable TSK) + **F-transform** (direct/inverse) | ✅ |
|
|
116
118
|
| 6 | Notebooks, JOSS `paper.md`, Zenodo DOI, PyPI release | ✅ |
|
|
117
|
-
| 7 | **Ecosystem integrations**: pandas, scikit-learn, PyTorch, SciPy, Optuna, Joblib/Dask, LLM agents | ✅ |
|
|
119
|
+
| 7 | **Ecosystem integrations**: pandas, scikit-learn, PyTorch, SciPy, turboswarm, Optuna, Joblib/Dask, LLM agents | ✅ |
|
|
120
|
+
|
|
121
|
+
### v0.5.0
|
|
122
|
+
|
|
123
|
+
- **General type-2 (GT2) fuzzy sets** via the zSlices / alpha-plane
|
|
124
|
+
representation: `GeneralType2MF`, the `gt2_*` constructors,
|
|
125
|
+
`GeneralType2Mamdani` inference and `centroid_gt2` type reduction — reusing
|
|
126
|
+
the existing interval type-2 / Karnik-Mendel machinery.
|
|
127
|
+
|
|
128
|
+
### v0.4.0
|
|
129
|
+
|
|
130
|
+
- **turboswarm integration:** gradient-free, global tuning of a fuzzy system's
|
|
131
|
+
membership functions with Particle Swarm Optimization
|
|
132
|
+
(`integrations.turboswarm.tune`) — the metaheuristic sibling of the SciPy tuner.
|
|
118
133
|
|
|
119
134
|
### v0.3.0
|
|
120
135
|
|
|
@@ -55,7 +55,20 @@ s-norm, `~` the complement.
|
|
|
55
55
|
| 4 | **Fuzzy clustering**: fuzzy c-means, Gustafson-Kessel, possibilistic | ✅ |
|
|
56
56
|
| 5 | **ANFIS** (trainable TSK) + **F-transform** (direct/inverse) | ✅ |
|
|
57
57
|
| 6 | Notebooks, JOSS `paper.md`, Zenodo DOI, PyPI release | ✅ |
|
|
58
|
-
| 7 | **Ecosystem integrations**: pandas, scikit-learn, PyTorch, SciPy, Optuna, Joblib/Dask, LLM agents | ✅ |
|
|
58
|
+
| 7 | **Ecosystem integrations**: pandas, scikit-learn, PyTorch, SciPy, turboswarm, Optuna, Joblib/Dask, LLM agents | ✅ |
|
|
59
|
+
|
|
60
|
+
### v0.5.0
|
|
61
|
+
|
|
62
|
+
- **General type-2 (GT2) fuzzy sets** via the zSlices / alpha-plane
|
|
63
|
+
representation: `GeneralType2MF`, the `gt2_*` constructors,
|
|
64
|
+
`GeneralType2Mamdani` inference and `centroid_gt2` type reduction — reusing
|
|
65
|
+
the existing interval type-2 / Karnik-Mendel machinery.
|
|
66
|
+
|
|
67
|
+
### v0.4.0
|
|
68
|
+
|
|
69
|
+
- **turboswarm integration:** gradient-free, global tuning of a fuzzy system's
|
|
70
|
+
membership functions with Particle Swarm Optimization
|
|
71
|
+
(`integrations.turboswarm.tune`) — the metaheuristic sibling of the SciPy tuner.
|
|
59
72
|
|
|
60
73
|
### v0.3.0
|
|
61
74
|
|
|
@@ -63,6 +63,8 @@ Each pulls its dependency in only on import, behind its own extra.
|
|
|
63
63
|
`nn.Module` trainable by autograd and composable into a network.
|
|
64
64
|
- [x] **SciPy** (`[scipy]`): `tune` MF parameters to data via
|
|
65
65
|
`scipy.optimize.least_squares` (returns the `OptimizeResult`).
|
|
66
|
+
- [x] **turboswarm** (`[turboswarm]`): `tune` MF parameters with gradient-free
|
|
67
|
+
Particle Swarm Optimization (the sibling PSO library; returns `PsoResult`).
|
|
66
68
|
- [x] **Optuna** (`[optuna]`): `suggest_inference_spec`, `suggest_anfis` and a
|
|
67
69
|
ready-made `tune_anfis` study.
|
|
68
70
|
- [x] **Joblib / Dask** (`[parallel]`, `[dask]`): `parallel_predict`,
|
|
@@ -70,17 +72,26 @@ Each pulls its dependency in only on import, behind its own extra.
|
|
|
70
72
|
- [x] **Agents (LangChain/LangGraph)** (`[agents]`): `explain` plus an
|
|
71
73
|
`inference_tool` LangChain tool that reports which rules fired.
|
|
72
74
|
|
|
75
|
+
## ✅ General type-2 (zSlices)
|
|
76
|
+
|
|
77
|
+
- [x] `GeneralType2MF` via the zSlices / alpha-plane representation (a stack of
|
|
78
|
+
IT2 slices; also exposes the overall FOU, so it degrades to IT2).
|
|
79
|
+
- [x] Constructors `gt2_from_it2`, `gt2_gauss_uncertain_mean`, `gt2_scale`
|
|
80
|
+
(triangular secondary MF).
|
|
81
|
+
- [x] `GeneralType2Mamdani` (z-weighted stack of IT2 Mamdani inferences) and
|
|
82
|
+
`centroid_gt2` zSlices type reduction.
|
|
83
|
+
|
|
73
84
|
## Ideas for later
|
|
74
85
|
|
|
75
86
|
- Fuzzy cognitive maps (+ grey FCM).
|
|
76
|
-
-
|
|
77
|
-
- FIS tuning via metaheuristics (e.g. PSO).
|
|
87
|
+
- More defuzzifiers; non-triangular GT2 secondary MFs.
|
|
78
88
|
|
|
79
89
|
## ⏳ Phase 6 — Release (v0.1.0)
|
|
80
90
|
|
|
81
91
|
- [x] Example notebooks (`notebooks/`) and a comparison page vs scikit-fuzzy.
|
|
82
92
|
- [x] JOSS `paper.md`; Zenodo metadata (`.zenodo.json`) and a citing/releasing page.
|
|
83
93
|
- [x] GitHub Pages live (`https://fuzzytool.github.io`).
|
|
84
|
-
- [
|
|
85
|
-
|
|
86
|
-
- [
|
|
94
|
+
- [x] PyPI trusted publisher registered; tagging a version runs `release-pypi.yml`
|
|
95
|
+
(published 0.1.0 → 0.4.0 via OIDC, no stored token).
|
|
96
|
+
- [x] Zenodo GitHub integration; each GitHub release is archived with a DOI
|
|
97
|
+
(`10.5281/zenodo.20836712`).
|
|
@@ -62,6 +62,10 @@ Generated from docstrings with `mkdocstrings`.
|
|
|
62
62
|
|
|
63
63
|
::: fuzzytool.type2.reduction
|
|
64
64
|
|
|
65
|
+
## General type-2 (zSlices)
|
|
66
|
+
|
|
67
|
+
::: fuzzytool.type2.general
|
|
68
|
+
|
|
65
69
|
## Fuzzy clustering
|
|
66
70
|
|
|
67
71
|
::: fuzzytool.cluster
|
|
@@ -90,6 +94,10 @@ Generated from docstrings with `mkdocstrings`.
|
|
|
90
94
|
|
|
91
95
|
::: fuzzytool.integrations.scipy
|
|
92
96
|
|
|
97
|
+
## Integrations — turboswarm (PSO)
|
|
98
|
+
|
|
99
|
+
::: fuzzytool.integrations.turboswarm
|
|
100
|
+
|
|
93
101
|
## Integrations — Optuna
|
|
94
102
|
|
|
95
103
|
::: fuzzytool.integrations.optuna
|
|
@@ -82,3 +82,49 @@ plt.show()
|
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|

|
|
85
|
+
|
|
86
|
+
## General type-2 (zSlices)
|
|
87
|
+
|
|
88
|
+
An IT2 set treats every point inside its FOU as equally possible. A **general
|
|
89
|
+
type-2** set adds a *secondary* membership that weights those possibilities —
|
|
90
|
+
the third dimension IT2 discards. fuzzytool represents a GT2 set with the
|
|
91
|
+
**zSlices / alpha-plane** decomposition: slicing the secondary domain at levels
|
|
92
|
+
`z` turns the GT2 set into a stack of ordinary IT2 sets, so inference and type
|
|
93
|
+
reduction reuse the IT2 machinery and combine the slices weighted by `z`.
|
|
94
|
+
|
|
95
|
+
Each constructor builds a GT2 set from an IT2 footprint plus a **triangular
|
|
96
|
+
secondary** peaking at the principal (mid) MF — narrow at `z = 1`, the full FOU
|
|
97
|
+
at `z → 0`:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import fuzzytool as fz
|
|
101
|
+
|
|
102
|
+
score = fz.Variable("score", (300, 850))
|
|
103
|
+
score["good"] = fz.gt2_gauss_uncertain_mean(740, 780, 50, n_slices=5)
|
|
104
|
+
score["poor"] = fz.gt2_gauss_uncertain_mean(420, 480, 70, n_slices=5)
|
|
105
|
+
premium = fz.Variable("premium", (0, 12))
|
|
106
|
+
premium["low"] = fz.gt2_gauss_uncertain_mean(1.5, 2.5, 1.5)
|
|
107
|
+
premium["high"] = fz.gt2_gauss_uncertain_mean(9.5, 10.5, 1.5)
|
|
108
|
+
|
|
109
|
+
sys = fz.GeneralType2Mamdani()
|
|
110
|
+
sys.rule(score["good"], premium["low"])
|
|
111
|
+
sys.rule(score["poor"], premium["high"])
|
|
112
|
+
sys(score=780) # -> 2.31 (z-weighted average of per-slice IT2 results)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+

|
|
116
|
+
|
|
117
|
+
A GT2 term also exposes `lower`/`upper` (its overall FOU), so it can stand in for
|
|
118
|
+
its IT2 footprint inside an `IT2Mamdani` if you want the cheaper approximation.
|
|
119
|
+
Build a GT2 set from *any* IT2 footprint with
|
|
120
|
+
[`gt2_from_it2`][fuzzytool.type2.general.gt2_from_it2], and type-reduce a single
|
|
121
|
+
GT2 set with `centroid_gt2`:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import numpy as np
|
|
125
|
+
from fuzzytool.type2 import centroid_gt2
|
|
126
|
+
|
|
127
|
+
good = fz.gt2_gauss_uncertain_mean(740, 780, 50, n_slices=6)
|
|
128
|
+
universe = np.linspace(300, 850, 400)
|
|
129
|
+
centroid_gt2(good, universe) # -> ~754.7 (z-weighted centroid)
|
|
130
|
+
```
|
|
Binary file
|
|
@@ -10,6 +10,7 @@ third-party dependency **only when imported**, so the base install stays light.
|
|
|
10
10
|
| scikit-learn | `fuzzytool.integrations.sklearn` | `pip install fuzzytool[sklearn]` |
|
|
11
11
|
| PyTorch | `fuzzytool.integrations.torch` | `pip install fuzzytool[torch]` |
|
|
12
12
|
| SciPy | `fuzzytool.integrations.scipy` | `pip install fuzzytool[scipy]` |
|
|
13
|
+
| turboswarm | `fuzzytool.integrations.turboswarm` | `pip install fuzzytool[turboswarm]` |
|
|
13
14
|
| Optuna | `fuzzytool.integrations.optuna` | `pip install fuzzytool[optuna]` |
|
|
14
15
|
| Joblib / Dask | `fuzzytool.integrations.parallel` | `pip install fuzzytool[parallel]` / `[dask]` |
|
|
15
16
|
| LLM agents | `fuzzytool.integrations.agents` | `pip install fuzzytool[agents]` |
|
|
@@ -199,6 +200,38 @@ Only built-in shapes (`tri`, `trap`, `gauss`, `gbell`, `sigmoid`, `ramp_up`,
|
|
|
199
200
|
`tune_outputs=False` to keep a Mamdani's output sets fixed, and forward any
|
|
200
201
|
`least_squares` keyword (e.g. `max_nfev=200`).
|
|
201
202
|
|
|
203
|
+
## turboswarm
|
|
204
|
+
|
|
205
|
+
[turboswarm](https://pypi.org/project/turboswarm/) is fuzzytool's sibling
|
|
206
|
+
Particle Swarm Optimization library. Its `tune` is the **gradient-free, global**
|
|
207
|
+
counterpart of the SciPy one: slower, but it escapes poor local optima and needs
|
|
208
|
+
no derivatives — a good fit for the rugged error surfaces fuzzy rule bases
|
|
209
|
+
produce. Same call shape, returns turboswarm's `PsoResult`:
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
import numpy as np
|
|
213
|
+
import fuzzytool as fz
|
|
214
|
+
from fuzzytool.integrations.turboswarm import tune
|
|
215
|
+
|
|
216
|
+
rng = np.random.default_rng(0)
|
|
217
|
+
X = rng.uniform(0, 10, size=(150, 1))
|
|
218
|
+
y = np.sin(X[:, 0]) + 0.1 * X[:, 0]
|
|
219
|
+
|
|
220
|
+
x = fz.Variable("x", (0, 10), terms=["lo", "mid", "hi"])
|
|
221
|
+
sys = fz.TSK()
|
|
222
|
+
sys.rule(x["lo"], 0.0)
|
|
223
|
+
sys.rule(x["mid"], 0.5)
|
|
224
|
+
sys.rule(x["hi"], 1.0)
|
|
225
|
+
|
|
226
|
+
result = tune(sys, X, y, columns=["x"], n_particles=20, max_iter=40, seed=0)
|
|
227
|
+
result.best_value # PsoResult; the system now fits the data better
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Each parameter is searched within `±margin × universe` around its current value
|
|
231
|
+
(`margin=0.5` by default); shape validity is enforced every evaluation. Any
|
|
232
|
+
`turboswarm.minimize` keyword (`topology`, `patience`, `max_time`, …) is
|
|
233
|
+
forwarded.
|
|
234
|
+
|
|
202
235
|
## Optuna
|
|
203
236
|
|
|
204
237
|
Fuzzy systems have many discrete/continuous knobs. These helpers turn an Optuna
|
|
@@ -29,14 +29,19 @@ from .serialize import load, save
|
|
|
29
29
|
from .sets import Variable
|
|
30
30
|
from .type2 import (
|
|
31
31
|
IT2TSK,
|
|
32
|
+
GeneralType2Mamdani,
|
|
33
|
+
GeneralType2MF,
|
|
32
34
|
IT2Mamdani,
|
|
35
|
+
gt2_from_it2,
|
|
36
|
+
gt2_gauss_uncertain_mean,
|
|
37
|
+
gt2_scale,
|
|
33
38
|
it2,
|
|
34
39
|
it2_gauss_uncertain_mean,
|
|
35
40
|
it2_gauss_uncertain_std,
|
|
36
41
|
it2_scale,
|
|
37
42
|
)
|
|
38
43
|
|
|
39
|
-
__version__ = "0.
|
|
44
|
+
__version__ = "0.5.0"
|
|
40
45
|
|
|
41
46
|
__all__ = [
|
|
42
47
|
"__version__",
|
|
@@ -51,6 +56,9 @@ __all__ = [
|
|
|
51
56
|
# interval type-2
|
|
52
57
|
"IT2Mamdani", "IT2TSK",
|
|
53
58
|
"it2", "it2_scale", "it2_gauss_uncertain_mean", "it2_gauss_uncertain_std",
|
|
59
|
+
# general type-2
|
|
60
|
+
"GeneralType2Mamdani", "GeneralType2MF",
|
|
61
|
+
"gt2_from_it2", "gt2_gauss_uncertain_mean", "gt2_scale",
|
|
54
62
|
# fuzzy clustering
|
|
55
63
|
"fuzzy_cmeans", "gustafson_kessel", "possibilistic_cmeans",
|
|
56
64
|
# learning & approximation
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Shared helpers for the integration submodules."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .. import membership as mf
|
|
6
|
+
|
|
7
|
+
# Returned in place of a non-finite residual so tuners avoid degenerate regions.
|
|
8
|
+
MF_PENALTY = 1e6
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def input_variable_names(system) -> list[str]:
|
|
12
|
+
"""Ordered, de-duplicated names of the input variables a system reads.
|
|
13
|
+
|
|
14
|
+
Walks every rule's antecedent tree of a :class:`~fuzzytool.inference.Mamdani`
|
|
15
|
+
or :class:`~fuzzytool.inference.TSK` system and collects the variables its
|
|
16
|
+
propositions reference, in first-seen order. This is the natural column
|
|
17
|
+
order for feeding a 2-D array or a DataFrame to the system.
|
|
18
|
+
"""
|
|
19
|
+
names: list[str] = []
|
|
20
|
+
seen: set[str] = set()
|
|
21
|
+
|
|
22
|
+
def walk(node) -> None:
|
|
23
|
+
if hasattr(node, "variable"): # Proposition (atom)
|
|
24
|
+
name = node.variable.name
|
|
25
|
+
if name not in seen:
|
|
26
|
+
seen.add(name)
|
|
27
|
+
names.append(name)
|
|
28
|
+
if hasattr(node, "left"): # And / Or
|
|
29
|
+
walk(node.left)
|
|
30
|
+
walk(node.right)
|
|
31
|
+
if hasattr(node, "operand"): # Not
|
|
32
|
+
walk(node.operand)
|
|
33
|
+
|
|
34
|
+
for rule in getattr(system, "rules", []):
|
|
35
|
+
walk(rule.antecedent)
|
|
36
|
+
return names
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def output_name(system, default: str = "output") -> str:
|
|
40
|
+
"""Best-effort name for a single-output system (Mamdani tracks it; TSK does not)."""
|
|
41
|
+
outputs = getattr(system, "_outputs", None)
|
|
42
|
+
if outputs:
|
|
43
|
+
return next(iter(outputs))
|
|
44
|
+
return default
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def sanitize_mf_params(kind: str, params) -> list[float]:
|
|
48
|
+
"""Repair a membership-function parameter slice so it is always a valid shape.
|
|
49
|
+
|
|
50
|
+
Keeps breakpoints ordered and widths positive, so a tuner (SciPy least-squares
|
|
51
|
+
or turboswarm PSO) can explore freely without producing degenerate sets.
|
|
52
|
+
"""
|
|
53
|
+
p = [float(v) for v in params]
|
|
54
|
+
if kind in ("tri", "trap", "ramp_up", "ramp_down"):
|
|
55
|
+
return sorted(p) # keep breakpoints ordered
|
|
56
|
+
if kind == "gauss":
|
|
57
|
+
return [p[0], abs(p[1]) or 1e-6] # sigma > 0
|
|
58
|
+
if kind == "gbell":
|
|
59
|
+
return [abs(p[0]) or 1e-6, abs(p[1]) or 1e-6, p[2]] # width, slope > 0
|
|
60
|
+
return p
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def tunable_terms(system, tune_outputs: bool = True):
|
|
64
|
+
"""Collect ``(variable, term_name, kind, params)`` for every tunable MF.
|
|
65
|
+
|
|
66
|
+
Walks the rules' propositions (and, if ``tune_outputs``, the Mamdani output
|
|
67
|
+
variables), keeping only terms backed by a built-in membership shape; custom
|
|
68
|
+
callables are skipped.
|
|
69
|
+
"""
|
|
70
|
+
seen: dict[int, object] = {}
|
|
71
|
+
|
|
72
|
+
def walk(node):
|
|
73
|
+
if hasattr(node, "variable"):
|
|
74
|
+
seen.setdefault(id(node.variable), node.variable)
|
|
75
|
+
if hasattr(node, "left"):
|
|
76
|
+
walk(node.left)
|
|
77
|
+
walk(node.right)
|
|
78
|
+
if hasattr(node, "operand"):
|
|
79
|
+
walk(node.operand)
|
|
80
|
+
|
|
81
|
+
for rule in getattr(system, "rules", []):
|
|
82
|
+
walk(rule.antecedent)
|
|
83
|
+
variables = dict(seen)
|
|
84
|
+
if tune_outputs:
|
|
85
|
+
for out in getattr(system, "_outputs", {}).values():
|
|
86
|
+
variables.setdefault(id(out), out)
|
|
87
|
+
|
|
88
|
+
terms = []
|
|
89
|
+
for var in variables.values():
|
|
90
|
+
for term_name, membership in var.terms.items():
|
|
91
|
+
try:
|
|
92
|
+
spec = mf.to_dict(membership)
|
|
93
|
+
except TypeError:
|
|
94
|
+
continue # custom callable: skip
|
|
95
|
+
terms.append((var, term_name, spec["type"], list(spec["params"])))
|
|
96
|
+
return terms
|
|
@@ -20,27 +20,18 @@ from typing import TYPE_CHECKING
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
|
|
22
22
|
from .. import membership as mf
|
|
23
|
-
from ._util import
|
|
23
|
+
from ._util import (
|
|
24
|
+
MF_PENALTY,
|
|
25
|
+
input_variable_names,
|
|
26
|
+
sanitize_mf_params,
|
|
27
|
+
tunable_terms,
|
|
28
|
+
)
|
|
24
29
|
|
|
25
30
|
if TYPE_CHECKING:
|
|
26
31
|
from scipy.optimize import OptimizeResult
|
|
27
32
|
|
|
28
33
|
from ..inference import TSK, Mamdani
|
|
29
34
|
|
|
30
|
-
# Per-shape repair applied before rebuilding, so every candidate is a valid MF.
|
|
31
|
-
_PENALTY = 1e6
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def _sanitize(kind: str, params: list[float]) -> list[float]:
|
|
35
|
-
p = [float(v) for v in params]
|
|
36
|
-
if kind in ("tri", "trap", "ramp_up", "ramp_down"):
|
|
37
|
-
return sorted(p) # keep breakpoints ordered
|
|
38
|
-
if kind == "gauss":
|
|
39
|
-
return [p[0], abs(p[1]) or 1e-6] # sigma > 0
|
|
40
|
-
if kind == "gbell":
|
|
41
|
-
return [abs(p[0]) or 1e-6, abs(p[1]) or 1e-6, p[2]] # width, slope > 0
|
|
42
|
-
return p
|
|
43
|
-
|
|
44
35
|
|
|
45
36
|
def _require_scipy():
|
|
46
37
|
try:
|
|
@@ -53,38 +44,6 @@ def _require_scipy():
|
|
|
53
44
|
return least_squares
|
|
54
45
|
|
|
55
46
|
|
|
56
|
-
def _tunable_terms(system, tune_outputs: bool):
|
|
57
|
-
"""Variables and term names whose membership functions can be tuned."""
|
|
58
|
-
# Collect the Variable instances behind the rules' propositions.
|
|
59
|
-
seen: dict[int, object] = {}
|
|
60
|
-
|
|
61
|
-
def walk(node):
|
|
62
|
-
if hasattr(node, "variable"):
|
|
63
|
-
seen.setdefault(id(node.variable), node.variable)
|
|
64
|
-
if hasattr(node, "left"):
|
|
65
|
-
walk(node.left)
|
|
66
|
-
walk(node.right)
|
|
67
|
-
if hasattr(node, "operand"):
|
|
68
|
-
walk(node.operand)
|
|
69
|
-
|
|
70
|
-
for rule in system.rules:
|
|
71
|
-
walk(rule.antecedent)
|
|
72
|
-
variables = dict(seen)
|
|
73
|
-
if tune_outputs:
|
|
74
|
-
for out in getattr(system, "_outputs", {}).values():
|
|
75
|
-
variables.setdefault(id(out), out)
|
|
76
|
-
|
|
77
|
-
terms = []
|
|
78
|
-
for var in variables.values():
|
|
79
|
-
for term_name, membership in var.terms.items():
|
|
80
|
-
try:
|
|
81
|
-
spec = mf.to_dict(membership)
|
|
82
|
-
except TypeError:
|
|
83
|
-
continue # custom callable: skip
|
|
84
|
-
terms.append((var, term_name, spec["type"], list(spec["params"])))
|
|
85
|
-
return terms
|
|
86
|
-
|
|
87
|
-
|
|
88
47
|
def tune(
|
|
89
48
|
system: Mamdani | TSK,
|
|
90
49
|
X: np.ndarray,
|
|
@@ -115,7 +74,7 @@ def tune(
|
|
|
115
74
|
names = list(columns) if columns is not None else input_variable_names(system)
|
|
116
75
|
inputs = {name: X[:, j] for j, name in enumerate(names)}
|
|
117
76
|
|
|
118
|
-
terms =
|
|
77
|
+
terms = tunable_terms(system, tune_outputs)
|
|
119
78
|
if not terms:
|
|
120
79
|
raise ValueError("the system has no tunable built-in membership functions")
|
|
121
80
|
|
|
@@ -130,13 +89,13 @@ def tune(
|
|
|
130
89
|
def apply(p):
|
|
131
90
|
for (var, term_name, kind, _params), (start, size) in zip(terms, slices):
|
|
132
91
|
var[term_name] = mf.from_dict(
|
|
133
|
-
{"type": kind, "params":
|
|
92
|
+
{"type": kind, "params": sanitize_mf_params(kind, p[start:start + size])})
|
|
134
93
|
|
|
135
94
|
def residual(p):
|
|
136
95
|
apply(p)
|
|
137
96
|
pred = np.asarray(system.predict(**inputs), dtype=float)
|
|
138
97
|
r = pred - y
|
|
139
|
-
return np.where(np.isfinite(r), r,
|
|
98
|
+
return np.where(np.isfinite(r), r, MF_PENALTY)
|
|
140
99
|
|
|
141
100
|
result = least_squares(residual, p0, **least_squares_kwargs)
|
|
142
101
|
apply(result.x) # leave the system at the best fit
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""turboswarm integration: tune a fuzzy system with Particle Swarm Optimization.
|
|
2
|
+
|
|
3
|
+
Install with ``pip install fuzzytool[turboswarm]``. :func:`tune` fits the
|
|
4
|
+
parameters of a system's built-in membership functions to data with
|
|
5
|
+
`turboswarm <https://pypi.org/project/turboswarm/>`_'s PSO — a **gradient-free,
|
|
6
|
+
global** optimizer. It is the metaheuristic sibling of
|
|
7
|
+
:func:`fuzzytool.integrations.scipy.tune` (local least-squares): slower, but it
|
|
8
|
+
escapes poor local optima and needs no derivatives, which suits the rugged,
|
|
9
|
+
non-smooth error surfaces fuzzy rule bases often produce.
|
|
10
|
+
|
|
11
|
+
Each parameter is searched within a box of ``±margin × universe`` around its
|
|
12
|
+
current value; shape validity (ordered breakpoints, positive widths) is enforced
|
|
13
|
+
every evaluation, so the swarm explores freely. The system is mutated in place
|
|
14
|
+
with the best parameters found and the turboswarm ``PsoResult`` is returned.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import TYPE_CHECKING
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
from .. import membership as mf
|
|
24
|
+
from ._util import (
|
|
25
|
+
MF_PENALTY,
|
|
26
|
+
input_variable_names,
|
|
27
|
+
sanitize_mf_params,
|
|
28
|
+
tunable_terms,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from turboswarm import PsoResult
|
|
33
|
+
|
|
34
|
+
from ..inference import TSK, Mamdani
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _require_turboswarm():
|
|
38
|
+
try:
|
|
39
|
+
from turboswarm import minimize
|
|
40
|
+
except ImportError as exc: # pragma: no cover
|
|
41
|
+
raise ImportError(
|
|
42
|
+
"the turboswarm integration needs turboswarm; install with "
|
|
43
|
+
"`pip install fuzzytool[turboswarm]`"
|
|
44
|
+
) from exc
|
|
45
|
+
return minimize
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def tune(
|
|
49
|
+
system: Mamdani | TSK,
|
|
50
|
+
X: np.ndarray,
|
|
51
|
+
y: np.ndarray,
|
|
52
|
+
columns: list[str] | None = None,
|
|
53
|
+
tune_outputs: bool = True,
|
|
54
|
+
margin: float = 0.5,
|
|
55
|
+
n_particles: int = 30,
|
|
56
|
+
max_iter: int = 100,
|
|
57
|
+
seed: int | None = None,
|
|
58
|
+
**minimize_kwargs,
|
|
59
|
+
) -> PsoResult:
|
|
60
|
+
"""Fit a system's membership-function parameters to data with PSO.
|
|
61
|
+
|
|
62
|
+
Extra keyword arguments are forwarded to :func:`turboswarm.minimize`
|
|
63
|
+
(e.g. ``topology``, ``patience``, ``max_time``).
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
system: a Mamdani or TSK system (mutated in place with the best params).
|
|
67
|
+
X: inputs, shape ``(n_samples, n_inputs)``.
|
|
68
|
+
y: targets, shape ``(n_samples,)``.
|
|
69
|
+
columns: input variable names matching ``X``'s columns, in order.
|
|
70
|
+
Defaults to the variables the rules reference.
|
|
71
|
+
tune_outputs: also tune the output variables' MFs (Mamdani only).
|
|
72
|
+
margin: search half-width per parameter as a fraction of its variable's
|
|
73
|
+
universe span (``0.5`` searches ±50% of the span around each value).
|
|
74
|
+
n_particles: swarm size.
|
|
75
|
+
max_iter: PSO iterations.
|
|
76
|
+
seed: PSO seed for reproducibility.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The turboswarm ``PsoResult`` (``.best_position``, ``.best_value``, …).
|
|
80
|
+
"""
|
|
81
|
+
minimize = _require_turboswarm()
|
|
82
|
+
X = np.asarray(X, dtype=float)
|
|
83
|
+
y = np.asarray(y, dtype=float)
|
|
84
|
+
names = list(columns) if columns is not None else input_variable_names(system)
|
|
85
|
+
inputs = {name: X[:, j] for j, name in enumerate(names)}
|
|
86
|
+
|
|
87
|
+
terms = tunable_terms(system, tune_outputs)
|
|
88
|
+
if not terms:
|
|
89
|
+
raise ValueError("the system has no tunable built-in membership functions")
|
|
90
|
+
|
|
91
|
+
# Flatten parameters; each gets a search box of ±(margin * span) around p0.
|
|
92
|
+
slices, p0, bounds = [], [], []
|
|
93
|
+
for var, _term, _kind, params in terms:
|
|
94
|
+
delta = margin * (var.high - var.low)
|
|
95
|
+
start = len(p0)
|
|
96
|
+
for value in params:
|
|
97
|
+
p0.append(value)
|
|
98
|
+
bounds.append((value - delta, value + delta))
|
|
99
|
+
slices.append((start, len(params)))
|
|
100
|
+
|
|
101
|
+
def apply(position):
|
|
102
|
+
for (var, term_name, kind, _params), (start, size) in zip(terms, slices):
|
|
103
|
+
var[term_name] = mf.from_dict(
|
|
104
|
+
{"type": kind,
|
|
105
|
+
"params": sanitize_mf_params(kind, position[start:start + size])})
|
|
106
|
+
|
|
107
|
+
def objective(position):
|
|
108
|
+
apply(position)
|
|
109
|
+
pred = np.asarray(system.predict(**inputs), dtype=float)
|
|
110
|
+
r = pred - y
|
|
111
|
+
r = np.where(np.isfinite(r), r, MF_PENALTY)
|
|
112
|
+
return float(np.mean(r * r)) # mean squared error
|
|
113
|
+
|
|
114
|
+
result = minimize(objective, bounds=bounds, n_particles=n_particles,
|
|
115
|
+
max_iter=max_iter, seed=seed, **minimize_kwargs)
|
|
116
|
+
apply(result.best_position) # leave the system at the best fit
|
|
117
|
+
return result
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
__all__ = ["tune"]
|
|
@@ -9,6 +9,14 @@ IT2 rules reuse the very same operator syntax as type-1 rules (``|``, ``&``,
|
|
|
9
9
|
tree and collapse the result with Karnik-Mendel type reduction.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
+
from .general import (
|
|
13
|
+
GeneralType2Mamdani,
|
|
14
|
+
GeneralType2MF,
|
|
15
|
+
centroid_gt2,
|
|
16
|
+
gt2_from_it2,
|
|
17
|
+
gt2_gauss_uncertain_mean,
|
|
18
|
+
gt2_scale,
|
|
19
|
+
)
|
|
12
20
|
from .inference import IT2TSK, IT2Mamdani
|
|
13
21
|
from .reduction import centroid_it2, karnik_mendel, km_endpoint
|
|
14
22
|
from .sets import (
|
|
@@ -24,4 +32,6 @@ __all__ = [
|
|
|
24
32
|
"it2", "it2_scale", "it2_gauss_uncertain_mean", "it2_gauss_uncertain_std",
|
|
25
33
|
"IT2Mamdani", "IT2TSK",
|
|
26
34
|
"karnik_mendel", "km_endpoint", "centroid_it2",
|
|
35
|
+
"GeneralType2MF", "GeneralType2Mamdani", "centroid_gt2",
|
|
36
|
+
"gt2_from_it2", "gt2_gauss_uncertain_mean", "gt2_scale",
|
|
27
37
|
]
|