diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 6680993..94331f8 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -163,26 +163,29 @@ }, "active": "0ba8a1b9b9dd949a", "lastOpenFiles": [ + "Things/Simple_POMDP/Output/efe_components_detailed.png", + "Things/Simple_POMDP/Output/policy_evolution.png", + "Things/Simple_POMDP/Output/free_energies.png", + "Things/Simple_POMDP/Output/belief_history.png", + "Things/Simple_POMDP/Output/action_history.png", + "Things/Simple_POMDP/Output/observation_likelihood.png", + "Things/Simple_POMDP/Output/state_transitions.png", + "Things/Simple_POMDP/Output/belief_evolution.png", + "Things/Simple_POMDP/Output/simulation_log.txt", + "Things/Simple_POMDP/Output/all_matrices.png", + "Things/Simple_POMDP/Output/C_preferences.png", + "Things/Simple_POMDP/Output/B_matrices.png", + "Things/Simple_POMDP/Output/matrix_validation.txt", + "Things/Simple_POMDP/Output", + "src/models/active_inference/docs/dispatcher.md", + "src/models/active_inference/docs/active_inference_dispatcher.md", + "src/models/active_inference/docs/active_inference.md", + "src/models/active_inference/docs", + "src/models/active_inference/config_examples/continuous_sampling.yaml", + "src/models/active_inference/config_examples/discrete_variational.yaml", + "src/models/active_inference/config_examples", "src/models/active_inference/dispatcher.py", "Things/Continuous_Generic/__pycache__/test_continuous_generic.cpython-310-pytest-8.3.2.pyc", - "Things/Continuous_Generic/__pycache__/conftest.cpython-310-pytest-8.3.2.pyc", - "Things/Continuous_Generic/Output/tests/single_step", - "Things/Continuous_Generic/Output/tests/multi_step", - "Things/Continuous_Generic/Output/tests/complex", - "Things/Continuous_Generic/Output/tests/basic", - "Things/Continuous_Generic/Output/tests", - "Things/Continuous_Generic/Output", - "Things/Continuous_Generic/__pycache__/visualization.cpython-310.pyc", - "Things/Continuous_Generic/__pycache__/continuous_generic.cpython-310.pyc", - "Things/Continuous_Generic/Output/tests/complex/energy_conservation/energy_evolution.gif", - "Things/Continuous_Generic/Output/tests/complex/energy_conservation/energy_analysis.png", - "Things/Continuous_Generic/Output/tests/complex/taylor_prediction/prediction_analysis.png", - "Things/Continuous_Generic/Output/tests/complex/generalized_coordinates/error_analysis.png", - "Things/Continuous_Generic/Output/tests/complex/generalized_coordinates/derivative_analysis.png", - "Things/Continuous_Generic/Output/tests/complex/generalized_coordinates/generalized_coordinates.gif", - "Things/Continuous_Generic/Output/tests/complex/driven_oscillator/prediction_analysis.png", - "Things/Continuous_Generic/Output/tests/complex/driven_oscillator/state_correlations.png", - "Things/Continuous_Generic/Output/tests/complex/driven_oscillator/time_evolution.png", - "Things/Continuous_Generic/Output/tests/complex/driven_oscillator/phase_space.png" + "Things/Continuous_Generic/__pycache__/conftest.cpython-310-pytest-8.3.2.pyc" ] } \ No newline at end of file diff --git a/Things/Simple_POMDP/Output/A_matrix.png b/Things/Simple_POMDP/Output/A_matrix.png index 9010667..add1958 100644 Binary files a/Things/Simple_POMDP/Output/A_matrix.png and b/Things/Simple_POMDP/Output/A_matrix.png differ diff --git a/Things/Simple_POMDP/Output/B_matrices.png b/Things/Simple_POMDP/Output/B_matrices.png index fef1379..b923526 100644 Binary files a/Things/Simple_POMDP/Output/B_matrices.png and b/Things/Simple_POMDP/Output/B_matrices.png differ diff --git a/Things/Simple_POMDP/Output/C_matrix.png b/Things/Simple_POMDP/Output/C_matrix.png deleted file mode 100644 index 49c7f4d..0000000 Binary files a/Things/Simple_POMDP/Output/C_matrix.png and /dev/null differ diff --git a/Things/Simple_POMDP/Output/action_history.png b/Things/Simple_POMDP/Output/action_history.png index 4e8bf78..3e3ad75 100644 Binary files a/Things/Simple_POMDP/Output/action_history.png and b/Things/Simple_POMDP/Output/action_history.png differ diff --git a/Things/Simple_POMDP/Output/all_matrices.png b/Things/Simple_POMDP/Output/all_matrices.png index 68489ee..611c297 100644 Binary files a/Things/Simple_POMDP/Output/all_matrices.png and b/Things/Simple_POMDP/Output/all_matrices.png differ diff --git a/Things/Simple_POMDP/Output/belief_evolution.png b/Things/Simple_POMDP/Output/belief_evolution.png index 9fb2e3b..11e8a16 100644 Binary files a/Things/Simple_POMDP/Output/belief_evolution.png and b/Things/Simple_POMDP/Output/belief_evolution.png differ diff --git a/Things/Simple_POMDP/Output/belief_history.png b/Things/Simple_POMDP/Output/belief_history.png index d9aca0f..0002729 100644 Binary files a/Things/Simple_POMDP/Output/belief_history.png and b/Things/Simple_POMDP/Output/belief_history.png differ diff --git a/Things/Simple_POMDP/Output/efe_components_detailed.png b/Things/Simple_POMDP/Output/efe_components_detailed.png index 21a6cb4..ca2eed9 100644 Binary files a/Things/Simple_POMDP/Output/efe_components_detailed.png and b/Things/Simple_POMDP/Output/efe_components_detailed.png differ diff --git a/Things/Simple_POMDP/Output/free_energies.png b/Things/Simple_POMDP/Output/free_energies.png index 269604e..dac7372 100644 Binary files a/Things/Simple_POMDP/Output/free_energies.png and b/Things/Simple_POMDP/Output/free_energies.png differ diff --git a/Things/Simple_POMDP/Output/matrix_validation.txt b/Things/Simple_POMDP/Output/matrix_validation.txt index c49fcb4..e283d55 100644 --- a/Things/Simple_POMDP/Output/matrix_validation.txt +++ b/Things/Simple_POMDP/Output/matrix_validation.txt @@ -7,15 +7,15 @@ A Matrix (Observation Model): - Non-negative: True Observation probabilities: - P(Low|Low) = 0.092 - P(Low|Medium) = 0.219 - P(Low|High) = 0.423 - P(Medium|Low) = 0.270 - P(Medium|Medium) = 0.375 - P(Medium|High) = 0.405 - P(High|Low) = 0.638 - P(High|Medium) = 0.406 - P(High|High) = 0.173 + P(Low|Low) = 0.202 + P(Low|Medium) = 0.003 + P(Low|High) = 0.411 + P(Medium|Low) = 0.582 + P(Medium|Medium) = 0.714 + P(Medium|High) = 0.186 + P(High|Low) = 0.216 + P(High|Medium) = 0.283 + P(High|High) = 0.403 B Matrix (Transition Model): - Shape: (3, 3, 3) @@ -25,45 +25,45 @@ Action: Decrease - Non-negative: True Transition probabilities: - P(Low|Low,Decrease) = 0.172 - P(Low|Medium,Decrease) = 0.278 - P(Low|High,Decrease) = 0.042 - P(Medium|Low,Decrease) = 0.158 - P(Medium|Medium,Decrease) = 0.296 - P(Medium|High,Decrease) = 0.157 - P(High|Low,Decrease) = 0.670 - P(High|Medium,Decrease) = 0.426 - P(High|High,Decrease) = 0.801 + P(Low|Low,Decrease) = 0.324 + P(Low|Medium,Decrease) = 0.186 + P(Low|High,Decrease) = 0.012 + P(Medium|Low,Decrease) = 0.320 + P(Medium|Medium,Decrease) = 0.162 + P(Medium|High,Decrease) = 0.722 + P(High|Low,Decrease) = 0.356 + P(High|Medium,Decrease) = 0.651 + P(High|High,Decrease) = 0.266 Action: Stay - Column stochastic: True - Non-negative: True Transition probabilities: - P(Low|Low,Stay) = 0.413 - P(Low|Medium,Stay) = 0.319 - P(Low|High,Stay) = 0.453 - P(Medium|Low,Stay) = 0.048 - P(Medium|Medium,Stay) = 0.660 - P(Medium|High,Stay) = 0.462 - P(High|Low,Stay) = 0.539 - P(High|Medium,Stay) = 0.021 - P(High|High,Stay) = 0.085 + P(Low|Low,Stay) = 0.423 + P(Low|Medium,Stay) = 0.005 + P(Low|High,Stay) = 0.182 + P(Medium|Low,Stay) = 0.257 + P(Medium|Medium,Stay) = 0.738 + P(Medium|High,Stay) = 0.719 + P(High|Low,Stay) = 0.320 + P(High|Medium,Stay) = 0.257 + P(High|High,Stay) = 0.099 Action: Increase - Column stochastic: True - Non-negative: True Transition probabilities: - P(Low|Low,Increase) = 0.272 - P(Low|Medium,Increase) = 0.423 - P(Low|High,Increase) = 0.258 - P(Medium|Low,Increase) = 0.264 - P(Medium|Medium,Increase) = 0.401 - P(Medium|High,Increase) = 0.364 - P(High|Low,Increase) = 0.464 - P(High|Medium,Increase) = 0.176 - P(High|High,Increase) = 0.377 + P(Low|Low,Increase) = 0.320 + P(Low|Medium,Increase) = 0.367 + P(Low|High,Increase) = 0.486 + P(Medium|Low,Increase) = 0.241 + P(Medium|Medium,Increase) = 0.364 + P(Medium|High,Increase) = 0.264 + P(High|Low,Increase) = 0.438 + P(High|Medium,Increase) = 0.269 + P(High|High,Increase) = 0.250 C Matrix (Log Preferences over Observations): - Shape: (3,) diff --git a/Things/Simple_POMDP/Output/observation_likelihood.png b/Things/Simple_POMDP/Output/observation_likelihood.png index 2f91128..23d16c1 100644 Binary files a/Things/Simple_POMDP/Output/observation_likelihood.png and b/Things/Simple_POMDP/Output/observation_likelihood.png differ diff --git a/Things/Simple_POMDP/Output/policy_distribution.png b/Things/Simple_POMDP/Output/policy_distribution.png deleted file mode 100644 index c7304ac..0000000 Binary files a/Things/Simple_POMDP/Output/policy_distribution.png and /dev/null differ diff --git a/Things/Simple_POMDP/Output/policy_evolution.png b/Things/Simple_POMDP/Output/policy_evolution.png index a625c80..8561e09 100644 Binary files a/Things/Simple_POMDP/Output/policy_evolution.png and b/Things/Simple_POMDP/Output/policy_evolution.png differ diff --git a/Things/Simple_POMDP/Output/simulation_log.txt b/Things/Simple_POMDP/Output/simulation_log.txt index d807acc..f1a97f9 100644 --- a/Things/Simple_POMDP/Output/simulation_log.txt +++ b/Things/Simple_POMDP/Output/simulation_log.txt @@ -3,321 +3,321 @@ Simulation Log Step 1: -State: Low -Observation: High -Action: Increase -Variational FE: 0.914 +State: High +Observation: Low +Action: Decrease +Variational FE: 1.557 Expected Free Energies: -Decrease: 0.095 -Stay: 0.319 -Increase: 0.330 +Decrease: 0.047 +Stay: -0.200 +Increase: 0.052 Beliefs: -Low: 0.420 -Medium: 0.340 -High: 0.240 +Low: 0.250 +Medium: 0.170 +High: 0.580 Step 2: -State: Low -Observation: High -Action: Decrease -Variational FE: 1.194 +State: High +Observation: Low +Action: Increase +Variational FE: 1.561 Expected Free Energies: -Decrease: 0.116 -Stay: 0.334 -Increase: 0.330 +Decrease: -0.112 +Stay: -0.280 +Increase: 0.031 Beliefs: -Low: 0.396 -Medium: 0.307 -High: 0.296 +Low: 0.329 +Medium: 0.087 +High: 0.584 Step 3: -State: Low +State: Medium Observation: Medium -Action: Stay -Variational FE: 1.077 +Action: Increase +Variational FE: 0.708 Expected Free Energies: -Decrease: 0.094 -Stay: 0.332 -Increase: 0.328 +Decrease: -0.131 +Stay: -0.230 +Increase: 0.043 Beliefs: -Low: 0.355 -Medium: 0.351 -High: 0.294 +Low: 0.413 +Medium: 0.235 +High: 0.351 Step 4: State: High Observation: Medium -Action: Stay -Variational FE: 1.078 +Action: Decrease +Variational FE: 0.729 Expected Free Energies: -Decrease: 0.109 -Stay: 0.323 -Increase: 0.331 +Decrease: 0.025 +Stay: -0.153 +Increase: 0.064 Beliefs: -Low: 0.333 -Medium: 0.388 -High: 0.280 +Low: 0.317 +Medium: 0.432 +High: 0.252 Step 5: State: Medium Observation: Medium Action: Increase -Variational FE: 1.049 +Variational FE: 0.702 Expected Free Energies: -Decrease: 0.123 -Stay: 0.315 -Increase: 0.333 +Decrease: 0.090 +Stay: -0.206 +Increase: 0.051 Beliefs: -Low: 0.292 -Medium: 0.379 -High: 0.329 +Low: 0.383 +Medium: 0.432 +High: 0.186 Step 6: State: Medium -Observation: Medium -Action: Increase -Variational FE: 1.048 - -Expected Free Energies: -Decrease: 0.111 -Stay: 0.304 -Increase: 0.332 - -Beliefs: -Low: 0.271 -Medium: 0.376 -High: 0.353 - -Step 7: -State: Medium -Observation: Low -Action: Stay -Variational FE: 1.577 - -Expected Free Energies: -Decrease: 0.105 -Stay: 0.298 -Increase: 0.332 - -Beliefs: -Low: 0.223 -Medium: 0.412 -High: 0.365 - -Step 8: -State: Medium Observation: High Action: Stay -Variational FE: 0.778 +Variational FE: 1.204 Expected Free Energies: -Decrease: 0.114 -Stay: 0.276 -Increase: 0.333 +Decrease: 0.110 +Stay: -0.158 +Increase: 0.062 Beliefs: -Low: 0.382 -Medium: 0.406 -High: 0.212 +Low: 0.263 +Medium: 0.475 +High: 0.262 + +Step 7: +State: High +Observation: Low +Action: Decrease +Variational FE: 1.465 + +Expected Free Energies: +Decrease: 0.090 +Stay: -0.247 +Increase: 0.042 + +Beliefs: +Low: 0.209 +Medium: 0.240 +High: 0.551 + +Step 8: +State: Low +Observation: Low +Action: Stay +Variational FE: 2.159 + +Expected Free Energies: +Decrease: -0.082 +Stay: -0.306 +Increase: 0.025 + +Beliefs: +Low: 0.270 +Medium: 0.128 +High: 0.601 Step 9: State: High Observation: Low -Action: Decrease -Variational FE: 1.149 +Action: Increase +Variational FE: 1.554 Expected Free Energies: -Decrease: 0.142 -Stay: 0.325 -Increase: 0.334 +Decrease: -0.134 +Stay: -0.269 +Increase: 0.034 Beliefs: -Low: 0.218 -Medium: 0.277 -High: 0.505 +Low: 0.338 +Medium: 0.066 +High: 0.595 Step 10: State: Medium Observation: High Action: Stay -Variational FE: 0.772 +Variational FE: 1.244 Expected Free Energies: -Decrease: 0.036 -Stay: 0.287 -Increase: 0.327 +Decrease: -0.143 +Stay: -0.226 +Increase: 0.044 Beliefs: -Low: 0.390 -Medium: 0.326 -High: 0.284 +Low: 0.264 +Medium: 0.310 +High: 0.426 Step 11: -State: Medium +State: High Observation: High -Action: Stay -Variational FE: 0.818 +Action: Increase +Variational FE: 1.229 Expected Free Energies: -Decrease: 0.103 -Stay: 0.331 -Increase: 0.330 +Decrease: 0.000 +Stay: -0.255 +Increase: 0.039 Beliefs: -Low: 0.480 -Medium: 0.331 -High: 0.189 +Low: 0.282 +Medium: 0.295 +High: 0.424 Step 12: -State: Low -Observation: Medium -Action: Increase -Variational FE: 1.045 - -Expected Free Energies: -Decrease: 0.123 -Stay: 0.339 -Increase: 0.329 - -Beliefs: -Low: 0.362 -Medium: 0.340 -High: 0.297 - -Step 13: -State: High -Observation: Medium -Action: Increase -Variational FE: 1.046 - -Expected Free Energies: -Decrease: 0.105 -Stay: 0.325 -Increase: 0.330 - -Beliefs: -Low: 0.304 -Medium: 0.352 -High: 0.345 - -Step 14: State: High Observation: Low Action: Increase -Variational FE: 1.403 +Variational FE: 1.564 Expected Free Energies: -Decrease: 0.099 -Stay: 0.310 -Increase: 0.331 +Decrease: -0.000 +Stay: -0.242 +Increase: 0.042 Beliefs: -Low: 0.212 -Medium: 0.330 -High: 0.458 +Low: 0.336 +Medium: 0.149 +High: 0.515 + +Step 13: +State: Medium +Observation: Medium +Action: Stay +Variational FE: 0.547 + +Expected Free Energies: +Decrease: -0.075 +Stay: -0.217 +Increase: 0.047 + +Beliefs: +Low: 0.287 +Medium: 0.424 +High: 0.289 + +Step 14: +State: High +Observation: Medium +Action: Increase +Variational FE: 0.697 + +Expected Free Energies: +Decrease: 0.075 +Stay: -0.229 +Increase: 0.046 + +Beliefs: +Low: 0.370 +Medium: 0.427 +High: 0.203 Step 15: State: Medium Observation: High -Action: Increase -Variational FE: 0.910 - -Expected Free Energies: -Decrease: 0.066 -Stay: 0.280 -Increase: 0.330 - -Beliefs: -Low: 0.356 -Medium: 0.344 -High: 0.300 - -Step 16: -State: Low -Observation: High -Action: Increase -Variational FE: 0.913 +Action: Stay +Variational FE: 1.205 Expected Free Energies: Decrease: 0.105 -Stay: 0.324 -Increase: 0.331 +Stay: -0.167 +Increase: 0.060 Beliefs: -Low: 0.433 -Medium: 0.345 -High: 0.223 +Low: 0.256 +Medium: 0.476 +High: 0.268 + +Step 16: +State: Low +Observation: Medium +Action: Increase +Variational FE: 0.692 + +Expected Free Energies: +Decrease: 0.088 +Stay: -0.252 +Increase: 0.041 + +Beliefs: +Low: 0.353 +Medium: 0.456 +High: 0.191 Step 17: State: High -Observation: Medium -Action: Stay -Variational FE: 1.074 +Observation: High +Action: Increase +Variational FE: 1.214 Expected Free Energies: -Decrease: 0.121 -Stay: 0.336 -Increase: 0.330 +Decrease: 0.111 +Stay: -0.178 +Increase: 0.058 Beliefs: -Low: 0.370 -Medium: 0.365 -High: 0.265 +Low: 0.312 +Medium: 0.371 +High: 0.316 Step 18: State: High Observation: Low -Action: Decrease -Variational FE: 1.134 +Action: Increase +Variational FE: 1.563 Expected Free Energies: -Decrease: 0.119 -Stay: 0.325 -Increase: 0.332 +Decrease: 0.059 +Stay: -0.213 +Increase: 0.049 Beliefs: -Low: 0.210 -Medium: 0.253 -High: 0.537 +Low: 0.344 +Medium: 0.188 +High: 0.468 Step 19: -State: Medium +State: Low Observation: Medium Action: Stay -Variational FE: 1.089 +Variational FE: 0.553 Expected Free Energies: -Decrease: 0.019 -Stay: 0.286 -Increase: 0.325 +Decrease: -0.041 +Stay: -0.206 +Increase: 0.050 Beliefs: -Low: 0.270 -Medium: 0.363 -High: 0.367 +Low: 0.289 +Medium: 0.443 +High: 0.267 Step 20: -State: High -Observation: High -Action: Decrease -Variational FE: 1.214 +State: Low +Observation: Medium +Action: Stay +Variational FE: 0.565 Expected Free Energies: -Decrease: 0.098 -Stay: 0.298 -Increase: 0.331 +Decrease: 0.085 +Stay: -0.227 +Increase: 0.047 Beliefs: -Low: 0.310 -Medium: 0.324 -High: 0.367 +Low: 0.233 +Medium: 0.595 +High: 0.172 diff --git a/Things/Simple_POMDP/Output/state_transitions.png b/Things/Simple_POMDP/Output/state_transitions.png index 19557b1..8f99f6a 100644 Binary files a/Things/Simple_POMDP/Output/state_transitions.png and b/Things/Simple_POMDP/Output/state_transitions.png differ diff --git a/src/models/active_inference/__init__.py b/src/models/active_inference/__init__.py index f097dc6..830caf2 100644 --- a/src/models/active_inference/__init__.py +++ b/src/models/active_inference/__init__.py @@ -2,4 +2,21 @@ Active Inference model implementations. """ -from .base import ActiveInferenceModel \ No newline at end of file +from .base import ActiveInferenceModel, ModelState +from .dispatcher import ( + ActiveInferenceDispatcher, + ActiveInferenceFactory, + InferenceConfig, + InferenceMethod, + PolicyType +) + +__all__ = [ + 'ActiveInferenceModel', + 'ModelState', + 'ActiveInferenceDispatcher', + 'ActiveInferenceFactory', + 'InferenceConfig', + 'InferenceMethod', + 'PolicyType' +] \ No newline at end of file diff --git a/src/models/active_inference/config_examples/continuous_sampling.yaml b/src/models/active_inference/config_examples/continuous_sampling.yaml new file mode 100644 index 0000000..e063ad4 --- /dev/null +++ b/src/models/active_inference/config_examples/continuous_sampling.yaml @@ -0,0 +1,30 @@ +# Example configuration for continuous sampling-based active inference + +method: sampling +policy_type: continuous +temporal_horizon: 10 +learning_rate: 0.005 +precision_init: 1.0 +use_gpu: false +num_samples: 2000 +temperature: 0.8 + +# Model-specific parameters +custom_params: + exploration_weight: 0.4 + state_dimensions: [6] # Continuous state space dimension + action_dimensions: [2] # Continuous action space dimension + + # Sampling parameters + proposal_std: 0.1 + min_acceptance_rate: 0.2 + adaptation_rate: 0.01 + + # Prior parameters + state_prior_mean: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + state_prior_std: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + + # MCMC parameters + burn_in: 500 + thinning: 2 + num_chains: 4 \ No newline at end of file diff --git a/src/models/active_inference/config_examples/discrete_variational.yaml b/src/models/active_inference/config_examples/discrete_variational.yaml new file mode 100644 index 0000000..1f9809a --- /dev/null +++ b/src/models/active_inference/config_examples/discrete_variational.yaml @@ -0,0 +1,23 @@ +# Example configuration for discrete variational active inference + +method: variational +policy_type: discrete +temporal_horizon: 5 +learning_rate: 0.01 +precision_init: 1.0 +use_gpu: false + +# Model-specific parameters +custom_params: + exploration_weight: 0.3 # Balance between exploration and exploitation + state_dimensions: [10, 10] # Example state space dimensions + action_dimensions: [4] # Example action space dimensions + + # Prior preferences + goal_prior_weight: 2.0 + entropy_weight: 0.5 + + # Learning parameters + belief_momentum: 0.9 + policy_temperature: 0.5 + max_iterations: 100 \ No newline at end of file diff --git a/src/models/active_inference/dispatcher.py b/src/models/active_inference/dispatcher.py index 101beb8..27ef917 100644 --- a/src/models/active_inference/dispatcher.py +++ b/src/models/active_inference/dispatcher.py @@ -34,6 +34,8 @@ class InferenceConfig: learning_rate: float precision_init: float use_gpu: bool = False + num_samples: int = 1000 # For sampling-based methods + temperature: float = 1.0 # For policy selection custom_params: Optional[Dict[str, Any]] = None class ActiveInferenceDispatcher: @@ -47,6 +49,7 @@ class ActiveInferenceDispatcher: self.config = config self._setup_implementations() self._initialize_matrices() + self._rng = np.random.default_rng() # For sampling methods def _setup_implementations(self): """Set up mapping of operations to implementations.""" @@ -121,9 +124,41 @@ class ActiveInferenceDispatcher: observation: np.ndarray, state: ModelState, **kwargs) -> np.ndarray: - """Sampling-based implementation of belief updates.""" - # Implementation for sampling-based updates - raise NotImplementedError("Sampling-based belief updates not yet implemented") + """Sampling-based implementation of belief updates using particle filtering.""" + num_samples = self.config.num_samples + generative_matrix = kwargs.get('generative_matrix', np.eye(len(state.beliefs))) + + # Initialize particles + particles = self._rng.dirichlet( + state.beliefs * num_samples, + size=num_samples + ) + + # Compute weights based on likelihood + likelihoods = np.array([ + self._compute_likelihood(observation, p, generative_matrix) + for p in particles + ]) + weights = likelihoods / np.sum(likelihoods) + + # Resample particles + resampled_indices = self._rng.choice( + num_samples, + size=num_samples, + p=weights + ) + particles = particles[resampled_indices] + + # Return mean belief state + return np.mean(particles, axis=0) + + def _compute_likelihood(self, + observation: np.ndarray, + particle: np.ndarray, + generative_matrix: np.ndarray) -> float: + """Compute likelihood of observation given particle state.""" + prediction = np.dot(particle, generative_matrix) + return np.exp(-0.5 * np.sum(np.square(observation - prediction))) def _mean_field_belief_update(self, observation: np.ndarray, @@ -150,8 +185,45 @@ class ActiveInferenceDispatcher: state: ModelState, goal_prior: Optional[np.ndarray] = None, **kwargs) -> np.ndarray: - """Sampling-based implementation of policy inference.""" - raise NotImplementedError("Sampling-based policy inference not yet implemented") + """Sampling-based implementation of policy inference using MCMC.""" + if goal_prior is None: + goal_prior = np.ones(len(state.policies)) / len(state.policies) + + num_samples = self.config.num_samples + current_policies = state.policies.copy() + accepted_policies = [] + + # MCMC sampling + for _ in range(num_samples): + # Propose new policy distribution + proposal = self._propose_policy(current_policies) + + # Compute acceptance ratio + current_energy = self._policy_energy(current_policies, state, goal_prior) + proposal_energy = self._policy_energy(proposal, state, goal_prior) + + # Accept/reject + if np.log(self._rng.random()) < proposal_energy - current_energy: + current_policies = proposal + + accepted_policies.append(current_policies.copy()) + + # Return mean policy distribution + return np.mean(accepted_policies, axis=0) + + def _propose_policy(self, current: np.ndarray) -> np.ndarray: + """Generate policy proposal for MCMC.""" + proposal = current + self._rng.normal(0, 0.1, size=current.shape) + return self.matrix_ops.normalize_rows(np.maximum(proposal, 0)) + + def _policy_energy(self, + policies: np.ndarray, + state: ModelState, + goal_prior: np.ndarray) -> float: + """Compute energy (negative log probability) for policy distribution.""" + expected_free_energy = self._calculate_expected_free_energy( + state, goal_prior) + return np.sum(policies * expected_free_energy) def _mean_field_policy_inference(self, state: ModelState, @@ -165,15 +237,43 @@ class ActiveInferenceDispatcher: goal_prior: np.ndarray, **kwargs) -> np.ndarray: """Calculate expected free energy for policy evaluation.""" - # Basic implementation - can be extended based on specific needs - pragmatic_value = -np.log(goal_prior + 1e-8) # Avoid log(0) + # Enhanced implementation with both pragmatic and epistemic value + pragmatic_value = self._calculate_pragmatic_value(state, goal_prior) epistemic_value = self._calculate_epistemic_value(state) - return pragmatic_value + epistemic_value + + # Weight between exploration and exploitation + exploration_weight = kwargs.get('exploration_weight', 0.5) + return (1 - exploration_weight) * pragmatic_value + exploration_weight * epistemic_value + + def _calculate_pragmatic_value(self, + state: ModelState, + goal_prior: np.ndarray) -> np.ndarray: + """Calculate pragmatic value component of expected free energy.""" + # KL divergence from current state to goal state + return -np.log(goal_prior + 1e-8) def _calculate_epistemic_value(self, state: ModelState) -> np.ndarray: """Calculate epistemic value component of expected free energy.""" - # Simple implementation - can be extended - return -state.prediction_error * np.ones(len(state.policies)) + # Information gain approximation + uncertainty = -np.sum(state.beliefs * np.log(state.beliefs + 1e-8)) + return -uncertainty * np.ones(len(state.policies)) + + def update_precision(self, prediction_error: float) -> float: + """Update precision parameter based on prediction errors.""" + if self.config.method == InferenceMethod.VARIATIONAL: + # Precision updates for variational method + self.config.precision_init = ( + 0.9 * self.config.precision_init + + 0.1 / (prediction_error + 1e-8) + ) + elif self.config.method == InferenceMethod.SAMPLING: + # Adaptive step size for sampling method + self.config.precision_init = np.clip( + 1.0 / (prediction_error + 1e-8), + 0.1, + 10.0 + ) + return self.config.precision_init class ActiveInferenceFactory: """Factory for creating Active Inference instances with specific configurations.""" @@ -197,6 +297,8 @@ class ActiveInferenceFactory: learning_rate=config_dict['learning_rate'], precision_init=config_dict['precision_init'], use_gpu=config_dict.get('use_gpu', False), + num_samples=config_dict.get('num_samples', 1000), + temperature=config_dict.get('temperature', 1.0), custom_params=config_dict.get('custom_params', None) ) return ActiveInferenceFactory.create(config) \ No newline at end of file diff --git a/src/models/active_inference/docs/active_inference_dispatcher.md b/src/models/active_inference/docs/active_inference_dispatcher.md new file mode 100644 index 0000000..f0848d7 --- /dev/null +++ b/src/models/active_inference/docs/active_inference_dispatcher.md @@ -0,0 +1,212 @@ +# Active Inference Implementation Documentation + +## Overview + +This document describes the implementation of [[Active Inference]] methods in the cognitive modeling framework. The implementation provides a flexible and extensible architecture for different inference approaches and policy types. + +## Core Components + +### Dispatcher Pattern +The [[ActiveInferenceDispatcher]] serves as the main interface for routing operations to specific implementations. It handles: +- Belief updates +- Policy inference +- Free energy calculations +- Precision updates + +### Configuration +[[InferenceConfig]] provides a structured way to configure the active inference process: +- Inference method selection +- Policy type specification +- Temporal horizon +- Learning parameters +- GPU acceleration options + +### Inference Methods +Three main inference methods are supported: + +1. [[Variational Inference]] + - Gradient-based belief updates + - Deterministic policy optimization + - Precision-weighted prediction errors + +2. [[Sampling Based Inference]] + - Particle filtering for belief updates + - MCMC for policy inference + - Adaptive precision updates + +3. [[Mean Field Inference]] + - Factorized approximations + - Independent treatment of variables + - (Implementation pending) + +### Policy Types + +The framework supports multiple [[Policy Types]]: +- `DISCRETE`: Finite action spaces +- `CONTINUOUS`: Continuous action spaces +- `HIERARCHICAL`: Nested policy structures + +## Usage Examples + +### Basic Configuration +```yaml +method: variational +policy_type: discrete +temporal_horizon: 5 +learning_rate: 0.01 +precision_init: 1.0 +``` + +See [[Configuration Examples]] for more detailed examples. + +### Code Usage +```python +from models.active_inference import ( + ActiveInferenceFactory, + InferenceConfig, + InferenceMethod, + PolicyType +) + +# Create configuration +config = InferenceConfig(...) +dispatcher = ActiveInferenceFactory.create(config) + +# Update beliefs +updated_beliefs = dispatcher.dispatch_belief_update( + observation=current_observation, + current_state=model_state +) +``` + +## Implementation Details + +### Free Energy Calculation +The [[Expected Free Energy]] calculation combines: +1. Pragmatic value (goal-directed behavior) +2. Epistemic value (information seeking) + +```python +def _calculate_expected_free_energy(self, state, goal_prior, **kwargs): + pragmatic_value = self._calculate_pragmatic_value(state, goal_prior) + epistemic_value = self._calculate_epistemic_value(state) + exploration_weight = kwargs.get('exploration_weight', 0.5) + return (1 - exploration_weight) * pragmatic_value + exploration_weight * epistemic_value +``` + +### Belief Updates +Different methods for [[Belief Updates]]: + +1. Variational: + - Gradient-based updates + - Precision-weighted errors + +2. Sampling: + - Particle filtering + - Importance resampling + +3. Mean Field: + - Factorized updates + - Independent parameter optimization + +### Policy Inference +[[Policy Inference]] implementations: + +1. Variational: + ```python + expected_free_energy = self._calculate_expected_free_energy(...) + return self.matrix_ops.softmax(-expected_free_energy) + ``` + +2. MCMC: + - Metropolis-Hastings sampling + - Proposal distribution + - Energy-based acceptance + +## Advanced Features + +### Precision Updates +[[Precision Updates]] adapt based on prediction errors: +- Variational: Running average updates +- Sampling: Adaptive step sizes +- Bounded optimization + +### Matrix Operations +Utility functions in [[Matrix Operations]]: +- Normalization +- Softmax +- Information metrics + +### GPU Acceleration +[[GPU Support]] preparation: +- Flag in configuration +- Matrix operation optimization +- Batch processing support + +## Configuration Examples + +### [[Discrete Variational Config]] +```yaml +method: variational +policy_type: discrete +temporal_horizon: 5 +custom_params: + exploration_weight: 0.3 + state_dimensions: [10, 10] +``` + +### [[Continuous Sampling Config]] +```yaml +method: sampling +policy_type: continuous +num_samples: 2000 +custom_params: + proposal_std: 0.1 + burn_in: 500 +``` + +## Best Practices + +### [[Performance Optimization]] +1. Use appropriate number of samples +2. Enable GPU for large state spaces +3. Tune precision updates + +### [[Numerical Stability]] +1. Add small constants to denominators +2. Use log probabilities where appropriate +3. Implement bounds checking + +### [[Debugging Tips]] +1. Monitor acceptance rates in MCMC +2. Track prediction errors +3. Validate belief normalization + +## Related Topics + +- [[Free Energy Principle]] +- [[Active Inference Theory]] +- [[Variational Bayes]] +- [[MCMC Methods]] +- [[Particle Filtering]] + +## Future Extensions + +### Planned Features +1. [[Hierarchical Policies]] + - Nested action spaces + - Multi-scale temporal horizons + +2. [[Advanced Sampling]] + - Hamiltonian Monte Carlo + - Sequential Monte Carlo + +3. [[Neural Implementation]] + - Deep active inference + - Learned generative models + +## References + +1. Friston, K. (2010). [[The Free-Energy Principle]] +2. Da Costa, L., et al. (2020). [[Active Inference Algorithms]] +3. Parr, T., & Friston, K. (2019). [[Discrete Active Inference]] \ No newline at end of file diff --git a/src/models/active_inference/docs/dispatcher.md b/src/models/active_inference/docs/dispatcher.md new file mode 100644 index 0000000..6854d41 --- /dev/null +++ b/src/models/active_inference/docs/dispatcher.md @@ -0,0 +1,214 @@ +# Active Inference Dispatcher + +## Overview + +The [[ActiveInferenceDispatcher]] is the core component that manages different implementations of active inference methods. It provides a clean interface for routing operations while handling the complexity of different inference approaches. + +## Class Structure + +```python +class ActiveInferenceDispatcher: + def __init__(self, config: InferenceConfig): + self.config = config + self._setup_implementations() + self._initialize_matrices() +``` + +## Key Components + +### 1. Method Dispatch +The dispatcher uses a dictionary-based routing system to map methods to their implementations: + +```python +self._implementations = { + InferenceMethod.VARIATIONAL: { + 'belief_update': self._variational_belief_update, + 'policy_inference': self._variational_policy_inference + }, + # ... other methods +} +``` + +See [[Implementation Mapping]] for details. + +### 2. Configuration +Uses [[InferenceConfig]] for structured configuration: +- Method selection +- Policy type +- Learning parameters +- Custom parameters + +### 3. Matrix Operations +Integrates with [[Matrix Operations]] for efficient computations: +- Normalization +- Softmax +- Information metrics + +## Core Operations + +### Belief Updates + +The [[Belief Update Methods]] include: + +1. **Variational** + ```python + def _variational_belief_update(self, observation, state, **kwargs): + prediction = np.dot(state.beliefs, generative_matrix) + prediction_error = observation - prediction + return state.beliefs + state.precision * prediction_error + ``` + +2. **Sampling** + ```python + def _sampling_belief_update(self, observation, state, **kwargs): + particles = self._initialize_particles(state) + weights = self._compute_weights(particles, observation) + return self._resample_particles(particles, weights) + ``` + +See [[Belief Update Implementation]] for more details. + +### Policy Inference + +[[Policy Inference Methods]]: + +1. **Variational** + - Expected free energy minimization + - Softmax policy selection + +2. **MCMC** + - Metropolis-Hastings algorithm + - Proposal distribution + - Energy-based acceptance + +## Advanced Features + +### 1. Precision Updates +[[Precision Adaptation]] mechanisms: +```python +def update_precision(self, prediction_error: float) -> float: + if self.config.method == InferenceMethod.VARIATIONAL: + return self._update_variational_precision(prediction_error) + elif self.config.method == InferenceMethod.SAMPLING: + return self._update_sampling_precision(prediction_error) +``` + +### 2. Free Energy Calculation +[[Free Energy Components]]: +1. Pragmatic value +2. Epistemic value +3. Exploration-exploitation balance + +### 3. GPU Support +[[GPU Acceleration]] features: +- Configuration flag +- Matrix operation optimization +- Batch processing + +## Usage Examples + +### Basic Usage +```python +# Create dispatcher +config = InferenceConfig(method=InferenceMethod.VARIATIONAL, ...) +dispatcher = ActiveInferenceFactory.create(config) + +# Update beliefs +new_beliefs = dispatcher.dispatch_belief_update( + observation=current_observation, + current_state=model_state +) + +# Infer policies +policies = dispatcher.dispatch_policy_inference( + state=model_state, + goal_prior=goal_distribution +) +``` + +See [[Usage Examples]] for more scenarios. + +## Configuration + +### Variational Configuration +```yaml +method: variational +policy_type: discrete +temporal_horizon: 5 +learning_rate: 0.01 +precision_init: 1.0 +``` + +### Sampling Configuration +```yaml +method: sampling +policy_type: continuous +num_samples: 2000 +custom_params: + proposal_std: 0.1 +``` + +See [[Configuration Guide]] for details. + +## Best Practices + +### Performance +[[Performance Guidelines]]: +1. Use appropriate batch sizes +2. Enable GPU for large models +3. Optimize matrix operations + +### Numerical Stability +[[Stability Guidelines]]: +1. Use log probabilities +2. Add small constants +3. Check bounds + +### Debugging +[[Debugging Strategies]]: +1. Monitor convergence +2. Track prediction errors +3. Validate distributions + +## Extension Points + +### Adding New Methods +To add a new inference method: +1. Add to [[InferenceMethod]] enum +2. Implement belief update method +3. Implement policy inference method +4. Add to implementation mapping + +### Custom Policies +[[Custom Policy Implementation]]: +1. Extend PolicyType enum +2. Implement policy-specific methods +3. Add configuration support + +## Related Components + +- [[Active Inference Model]] +- [[Matrix Operations]] +- [[Configuration System]] +- [[Visualization Tools]] + +## Future Development + +### Planned Features +1. [[Hierarchical Implementation]] + - Nested policies + - Multi-scale inference + +2. [[Advanced Methods]] + - Hamiltonian Monte Carlo + - Variational message passing + +3. [[Optimization]] + - Parallel processing + - Memory efficiency + +## References + +1. [[Implementation Architecture]] +2. [[Method Specifications]] +3. [[API Documentation]] \ No newline at end of file