Source code for mercurial.spectral.perception

"""Bayesian perception as pattern completion (MERCURIAL D)."""

from typing import Optional

import numpy as np

from mercurial.spectral.modalities import ModalityEnergyHierarchy


[docs] class BayesianPerception: """ Implements perceptual inference via variational free energy minimization. """
[docs] def __init__( self, hierarchy: ModalityEnergyHierarchy, prior_strength: float = 1.0, learning_rate: float = 0.1, ): """ Parameters ---------- hierarchy : ModalityEnergyHierarchy Energy hierarchy for modality thresholds. prior_strength : float β_prior for prior influence. learning_rate : float Step size for gradient descent. """ self.hierarchy = hierarchy self.prior_strength = prior_strength self.lr = learning_rate # Import DPR pathway optimizer here to avoid circular import from mercurial.spectral.dpr_pathways import DPRPathwayOptimizer self.dpr_optimizer = DPRPathwayOptimizer()
[docs] def free_energy( self, sensory_input: np.ndarray, predicted_pattern: np.ndarray, prior_pattern: Optional[np.ndarray] = None, ) -> float: """ F_perc = ||sensory - predicted||^2 + β_prior ||predicted - prior||^2 """ likelihood_term = np.linalg.norm(sensory_input - predicted_pattern) ** 2 if prior_pattern is not None: prior_term = ( self.prior_strength * np.linalg.norm(predicted_pattern - prior_pattern) ** 2 ) else: prior_term = 0.0 return likelihood_term + prior_term
[docs] def infer_hidden_state( self, sensory_input: np.ndarray, prior: Optional[np.ndarray] = None, max_iter: int = 20 ) -> np.ndarray: """ Find pattern that minimizes free energy (gradient descent). """ if prior is not None: hidden = prior.copy() else: hidden = sensory_input.copy() for _ in range(max_iter): grad = 2 * (hidden - sensory_input) if prior is not None: grad += 2 * self.prior_strength * (hidden - prior) hidden -= self.lr * grad return hidden
[docs] def detection_threshold( self, pattern_intensity: float, observer_coherence: float, environmental_noise: float ) -> float: """ Θ_perc = Θ_0 * (1 + β_state ψ_obs) / (1 + γ_noise N_env) * (1 - S/S_crit) """ Theta0 = 0.1 # base threshold beta_state = 0.5 gamma_noise = 0.1 S = 1.0 - observer_coherence # entropy proxy S_crit = 10.0 numerator = 1.0 + beta_state * observer_coherence denominator = 1.0 + gamma_noise * environmental_noise entropy_factor = 1.0 - S / S_crit return Theta0 * (numerator / denominator) * max(0.0, entropy_factor)
[docs] def detect( self, pattern_intensity: float, observer_coherence: float, environmental_noise: float ) -> bool: """Return True if pattern is consciously perceived.""" threshold = self.detection_threshold( pattern_intensity, observer_coherence, environmental_noise ) return pattern_intensity > threshold
[docs] def dpr_perception( self, sensory_input: np.ndarray, pattern_energy: float, pattern_coherence: float, environmental_noise: float, branch_similarity: float = 1.0, ) -> np.ndarray: """ Use optimal DPR pathway for perception. """ pathway, eff = self.dpr_optimizer.select_optimal_pathway( pattern_energy, pattern_coherence, environmental_noise, branch_similarity ) if eff > 0.5: # DPR is viable; use direct transfer return self.dpr_optimizer.simulate_dpr_transfer(sensory_input, pathway, eff) else: # Fallback to variational inference return self.infer_hidden_state(sensory_input)