pyaif-toolkit 0.1.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 (42) hide show
  1. pyaif_toolkit-0.1.0/CHANGELOG.md +32 -0
  2. pyaif_toolkit-0.1.0/CONTRIBUTING.md +45 -0
  3. pyaif_toolkit-0.1.0/LICENSE +30 -0
  4. pyaif_toolkit-0.1.0/MANIFEST.in +15 -0
  5. pyaif_toolkit-0.1.0/PKG-INFO +218 -0
  6. pyaif_toolkit-0.1.0/PyAIF/__init__.py +51 -0
  7. pyaif_toolkit-0.1.0/PyAIF/aif_agent.py +3101 -0
  8. pyaif_toolkit-0.1.0/PyAIF/generative_model.py +55 -0
  9. pyaif_toolkit-0.1.0/PyAIF/inference/__init__.py +35 -0
  10. pyaif_toolkit-0.1.0/PyAIF/inference/base.py +8 -0
  11. pyaif_toolkit-0.1.0/PyAIF/inference/deep_temporal.py +396 -0
  12. pyaif_toolkit-0.1.0/PyAIF/inference/shallow.py +256 -0
  13. pyaif_toolkit-0.1.0/PyAIF/learning/__init__.py +19 -0
  14. pyaif_toolkit-0.1.0/PyAIF/learning/categorical.py +256 -0
  15. pyaif_toolkit-0.1.0/PyAIF/likelihoods/__init__.py +5 -0
  16. pyaif_toolkit-0.1.0/PyAIF/likelihoods/base.py +18 -0
  17. pyaif_toolkit-0.1.0/PyAIF/likelihoods/categorical.py +70 -0
  18. pyaif_toolkit-0.1.0/PyAIF/numerics.py +143 -0
  19. pyaif_toolkit-0.1.0/PyAIF/utils.py +213 -0
  20. pyaif_toolkit-0.1.0/README.md +185 -0
  21. pyaif_toolkit-0.1.0/docs/model-shapes.md +58 -0
  22. pyaif_toolkit-0.1.0/docs/public-api.md +81 -0
  23. pyaif_toolkit-0.1.0/examples/learning_under_uncertainty/Figure_1.png +0 -0
  24. pyaif_toolkit-0.1.0/examples/learning_under_uncertainty/README.md +93 -0
  25. pyaif_toolkit-0.1.0/examples/learning_under_uncertainty/aleatoric_uncertainty.py +392 -0
  26. pyaif_toolkit-0.1.0/examples/learning_under_uncertainty/epistemic_uncertainty.py +420 -0
  27. pyaif_toolkit-0.1.0/examples/learning_under_uncertainty/main.py +65 -0
  28. pyaif_toolkit-0.1.0/examples/learning_under_uncertainty/make_vfe_animation.py +232 -0
  29. pyaif_toolkit-0.1.0/examples/learning_under_uncertainty/vfe_transition.gif +0 -0
  30. pyaif_toolkit-0.1.0/examples/quickstart_discrete.py +67 -0
  31. pyaif_toolkit-0.1.0/pyaif_toolkit.egg-info/PKG-INFO +218 -0
  32. pyaif_toolkit-0.1.0/pyaif_toolkit.egg-info/SOURCES.txt +40 -0
  33. pyaif_toolkit-0.1.0/pyaif_toolkit.egg-info/dependency_links.txt +1 -0
  34. pyaif_toolkit-0.1.0/pyaif_toolkit.egg-info/requires.txt +10 -0
  35. pyaif_toolkit-0.1.0/pyaif_toolkit.egg-info/top_level.txt +1 -0
  36. pyaif_toolkit-0.1.0/pyproject.toml +74 -0
  37. pyaif_toolkit-0.1.0/setup.cfg +4 -0
  38. pyaif_toolkit-0.1.0/tests/test_component_api.py +264 -0
  39. pyaif_toolkit-0.1.0/tests/test_learning.py +201 -0
  40. pyaif_toolkit-0.1.0/tests/test_learning_example.py +51 -0
  41. pyaif_toolkit-0.1.0/tests/test_numerics.py +61 -0
  42. pyaif_toolkit-0.1.0/tests/test_public_api.py +17 -0
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - 2026-07-24
4
+
5
+ ### Added
6
+
7
+ - Component-based `GenerativeModel`, `CategoricalLikelihood`,
8
+ `ShallowInference`, and `DeepTemporalInference` APIs.
9
+ - Reusable shallow and deep categorical inference strategies.
10
+ - Reusable categorical parameter learning for `A`, `B`, `C`, `D`, and `E`.
11
+ - Numerical and end-to-end learning-example regression tests.
12
+ - Reproducible VFE-surprise animation for the uncertainty-learning example.
13
+ - Wheel validation, continuous integration, and guarded release automation.
14
+ - BSD-3-Clause licensing for the packaged software.
15
+
16
+ ### Changed
17
+
18
+ - PyPI distribution name set to `pyaif-toolkit`; the import package remains
19
+ `PyAIF`.
20
+ - Domain-specific likelihood construction moved out of the package.
21
+ - `ActiveInfAgent` now delegates reusable inference and learning behavior to
22
+ focused modules.
23
+ - The retained learning-under-uncertainty example now uses the public component
24
+ API and supports configurable trials, output directories, and random seeds.
25
+ - Deep expected-free-energy signs and cumulative initial-state learning retain
26
+ the behavior of the validated research simulation.
27
+ - The obsolete handover and autonomous pick-and-place examples were removed.
28
+
29
+ ### Compatibility
30
+
31
+ - The legacy agent constructor remains available while examples migrate.
32
+ - Continuous-observation support is planned for the `0.2.x` release line.
@@ -0,0 +1,45 @@
1
+ # Contributing
2
+
3
+ ## Development setup
4
+
5
+ ```bash
6
+ python -m venv .venv
7
+ python -m pip install -e ".[dev]"
8
+ ```
9
+
10
+ Run the local checks before opening a pull request:
11
+
12
+ ```bash
13
+ ruff check PyAIF tests
14
+ ruff format --check PyAIF tests
15
+ pytest
16
+ python -m build
17
+ python -m twine check dist/*
18
+ ```
19
+
20
+ ## Change policy
21
+
22
+ - Keep reusable inference and learning code under `PyAIF/`.
23
+ - Keep domain-specific generative models and likelihood construction under
24
+ `examples/` or in an application repository.
25
+ - Add numerical regression tests for changes to inference, expected free
26
+ energy, learning, or policy construction.
27
+ - Preserve structural zeros in categorical `A` and `B` updates.
28
+ - Do not add continuous-observation behavior to the `0.1.x` release line.
29
+
30
+ ## Pull requests
31
+
32
+ Pull requests should describe the behavioral change, identify affected
33
+ examples, and include test evidence. CI tests Python 3.9 through 3.13 and builds
34
+ the wheel and source distribution.
35
+
36
+ ## Releases
37
+
38
+ 1. Update the version in `pyproject.toml`.
39
+ 2. Update `CHANGELOG.md`.
40
+ 3. Merge a pull request with all CI checks passing.
41
+ 4. Create and publish a GitHub release for the matching version tag.
42
+ 5. The protected `pypi` environment publishes with PyPI Trusted Publishing.
43
+
44
+ The repository owner must configure the PyPI trusted publisher and GitHub
45
+ `pypi` environment before the first release.
@@ -0,0 +1,30 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Diluna A. Warnakulasuriya
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,15 @@
1
+ include CHANGELOG.md
2
+ include CONTRIBUTING.md
3
+ include LICENSE
4
+ recursive-include docs *.md
5
+ recursive-include examples *.py *.md *.png *.gif
6
+
7
+ prune profiling_results
8
+ prune PyAIF/likelihood_models
9
+
10
+ global-exclude *.csv
11
+ global-exclude *.jsonl
12
+ global-exclude *.log
13
+ global-exclude *.npy
14
+ global-exclude *.npz
15
+ global-exclude *.zip
@@ -0,0 +1,218 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyaif-toolkit
3
+ Version: 0.1.0
4
+ Summary: A Python package for Active Inference agents and simulations
5
+ Author: Diluna A. Warnakulasuriya
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/Diluna98/python_active_inference
8
+ Project-URL: Issues, https://github.com/Diluna98/python_active_inference/issues
9
+ Project-URL: Repository, https://github.com/Diluna98/python_active_inference.git
10
+ Keywords: active-inference,bayesian-inference,generative-models
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: numpy
24
+ Requires-Dist: scipy
25
+ Requires-Dist: matplotlib
26
+ Requires-Dist: joblib
27
+ Provides-Extra: dev
28
+ Requires-Dist: build>=1.2; extra == "dev"
29
+ Requires-Dist: pytest>=8; extra == "dev"
30
+ Requires-Dist: ruff>=0.12; extra == "dev"
31
+ Requires-Dist: twine>=6; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ # PyAIF
35
+
36
+ PyAIF is a Python package for constructing discrete active-inference agents
37
+ with factorised hidden states. Version 0.1 provides categorical observations,
38
+ single-step inference, deep temporal inference, policy evaluation, action
39
+ selection, and categorical parameter learning.
40
+
41
+ Continuous-observation likelihoods are intentionally reserved for version 0.2.
42
+ Research applications and domain-specific likelihood construction belong in
43
+ the `examples/` directory or in separate repositories.
44
+
45
+ ## Installation
46
+
47
+ PyAIF requires Python 3.9 or newer.
48
+
49
+ Install the published distribution:
50
+
51
+ ```bash
52
+ python -m pip install pyaif-toolkit
53
+ ```
54
+
55
+ The distribution is named `pyaif-toolkit` on PyPI, while the Python import
56
+ package remains `PyAIF`.
57
+
58
+ To install from a source checkout:
59
+
60
+ ```bash
61
+ python -m pip install .
62
+ ```
63
+
64
+ For development:
65
+
66
+ ```bash
67
+ python -m pip install -e ".[dev]"
68
+ pytest
69
+ ```
70
+
71
+ ## Quick start
72
+
73
+ The public API separates the state-transition model, observation model, and
74
+ inference algorithm.
75
+
76
+ ```python
77
+ import numpy as np
78
+
79
+ from PyAIF import (
80
+ ActiveInfAgent,
81
+ CategoricalLikelihood,
82
+ GenerativeModel,
83
+ ShallowInference,
84
+ )
85
+
86
+
87
+ def object_array(*values):
88
+ result = np.empty(len(values), dtype=object)
89
+ for index, value in enumerate(values):
90
+ result[index] = np.asarray(value, dtype=float)
91
+ return result
92
+
93
+
94
+ # A[o, s]: categorical observation likelihood.
95
+ A = object_array(
96
+ np.array([
97
+ [0.95, 0.05],
98
+ [0.05, 0.95],
99
+ ])
100
+ )
101
+
102
+ # B[s_next, s_previous, action]: controlled transitions.
103
+ B_factor = np.zeros((2, 2, 2))
104
+ B_factor[:, :, 0] = np.eye(2)
105
+ B_factor[:, :, 1] = np.fliplr(np.eye(2))
106
+ B = object_array(B_factor)
107
+
108
+ # D[s]: initial-state prior. C[o]: outcome preferences.
109
+ D = object_array(np.array([0.5, 0.5]))
110
+ C = object_array(np.zeros(2))
111
+
112
+ model = GenerativeModel(
113
+ B=B,
114
+ D=D,
115
+ controls_dim=[2],
116
+ controllable_factors=[0],
117
+ )
118
+ likelihood = CategoricalLikelihood(
119
+ A=A,
120
+ preferences=C,
121
+ modality_dependencies=[[0]],
122
+ )
123
+ agent = ActiveInfAgent(
124
+ model=model,
125
+ likelihood=likelihood,
126
+ inference=ShallowInference(),
127
+ action_selection="deterministic",
128
+ )
129
+
130
+ agent.reset()
131
+ agent.observe([0])
132
+ agent.infer_states()
133
+ expected_free_energy, _ = agent.infer_policies()
134
+ action = agent.select_action()
135
+ ```
136
+
137
+ Use `DeepTemporalInference(horizon=...)` for policy-dependent beliefs over
138
+ multiple time steps. Deep preferences have shape
139
+ `(number_of_outcomes, horizon)`.
140
+
141
+ ## Agent lifecycle
142
+
143
+ The supported component-based lifecycle is:
144
+
145
+ ```python
146
+ agent.reset(trial=trial)
147
+ agent.observe(observation, time_step=t)
148
+ agent.infer_states()
149
+ agent.infer_policies()
150
+ action = agent.select_action()
151
+ agent.learn() # only when parameter learning is enabled
152
+ ```
153
+
154
+ The older matrix-heavy constructor and methods such as `choose_action()` and
155
+ `perform_learning()` remain available while examples migrate, but new projects
156
+ should use the component constructor and lifecycle above.
157
+
158
+ ## Model structure
159
+
160
+ - `GenerativeModel` owns state transitions (`B`), initial-state priors (`D`),
161
+ control dimensions, controllable factors, and optional policies.
162
+ - `CategoricalLikelihood` owns observation likelihoods (`A`), preferences
163
+ (`C`), and modality-to-factor dependencies.
164
+ - `ShallowInference` performs single-step factorised inference.
165
+ - `DeepTemporalInference` performs marginal message passing over a horizon.
166
+ - `PyAIF.learning` contains reusable categorical updates for `A`, `B`, `C`,
167
+ `D`, and `E`.
168
+
169
+ See [Model shapes](docs/model-shapes.md) and
170
+ [Public API](docs/public-api.md) for details.
171
+
172
+ ## Examples
173
+
174
+ - `examples/quickstart_discrete.py`: minimal categorical agent.
175
+ - `examples/learning_under_uncertainty/`: deep temporal parameter-learning
176
+ experiments under epistemic and aleatoric uncertainty.
177
+
178
+ Model-selection and bounded-rationality experiments are maintained separately
179
+ from the reusable PyAIF package.
180
+
181
+ The automated regression suite covers the reusable component API and executes
182
+ one trial of each parameter-learning experiment.
183
+
184
+ Run the minimal component example with:
185
+
186
+ ```bash
187
+ python examples/quickstart_discrete.py
188
+ ```
189
+
190
+ ## Version policy
191
+
192
+ - `0.1.x`: categorical observations and discrete parameter learning.
193
+ - `0.2.x`: planned continuous-observation likelihood components.
194
+
195
+ Behavioral changes are protected with numerical regression tests. Research
196
+ experiments may evolve independently from the packaged API.
197
+
198
+ ## License
199
+
200
+ PyAIF is distributed under the
201
+ [BSD 3-Clause License](LICENSE). Copyright © 2026
202
+ Diluna A. Warnakulasuriya.
203
+
204
+ This software license does not automatically apply to papers, datasets,
205
+ figures, trained models, or other research artifacts.
206
+
207
+ ## Development
208
+
209
+ ```bash
210
+ ruff check PyAIF tests
211
+ ruff format --check PyAIF tests
212
+ pytest
213
+ python -m build
214
+ python -m twine check dist/*
215
+ ```
216
+
217
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the pull-request and release
218
+ process.
@@ -0,0 +1,51 @@
1
+ """Public API for PyAIF's discrete active-inference package."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ from . import utils
6
+ from .aif_agent import ActiveInfAgent
7
+ from .generative_model import GenerativeModel
8
+ from .inference import (
9
+ DeepPolicyInferenceResult,
10
+ DeepStateInferenceResult,
11
+ DeepTemporalInference,
12
+ ShallowInference,
13
+ ShallowPolicyInferenceResult,
14
+ ShallowStateInferenceResult,
15
+ deep_categorical_policy_ambiguity,
16
+ deep_categorical_policy_risk,
17
+ deep_expected_free_energy,
18
+ )
19
+ from .likelihoods import CategoricalLikelihood
20
+ from .learning import (
21
+ CategoricalLearningResult,
22
+ categorical_observation_evidence,
23
+ categorical_transition_evidence,
24
+ update_dirichlet_parameters,
25
+ )
26
+
27
+ try:
28
+ __version__ = version("pyaif-toolkit")
29
+ except PackageNotFoundError:
30
+ __version__ = "0.1.0"
31
+
32
+ __all__ = [
33
+ "__version__",
34
+ "ActiveInfAgent",
35
+ "CategoricalLikelihood",
36
+ "CategoricalLearningResult",
37
+ "DeepPolicyInferenceResult",
38
+ "DeepStateInferenceResult",
39
+ "DeepTemporalInference",
40
+ "deep_categorical_policy_ambiguity",
41
+ "deep_categorical_policy_risk",
42
+ "deep_expected_free_energy",
43
+ "GenerativeModel",
44
+ "ShallowInference",
45
+ "ShallowPolicyInferenceResult",
46
+ "ShallowStateInferenceResult",
47
+ "categorical_observation_evidence",
48
+ "categorical_transition_evidence",
49
+ "update_dirichlet_parameters",
50
+ "utils",
51
+ ]