Source code for mercurial.core.entropy

"""Generalized entropy calculations for patterns (MERCURIAL A.8)."""

import numpy as np

from mercurial.core.patterns import Pattern


[docs] def shannon_entropy(probabilities: np.ndarray, base: float = 2.0) -> float: """ Shannon entropy H = -Σ p_i log(p_i). Parameters ---------- probabilities : array Probability distribution (must sum to 1). base : float Logarithm base (2 for bits, e for nats). Returns ------- float Entropy in chosen units. """ probs = probabilities[probabilities > 0] if base == 2: return -np.sum(probs * np.log2(probs)) elif base == np.e: return -np.sum(probs * np.log(probs)) else: return -np.sum(probs * np.log(probs) / np.log(base))
[docs] def thermodynamic_entropy(energy_distribution: np.ndarray, temperature: float) -> float: """ Thermodynamic entropy S_therm = (U - F)/T. Here we approximate from energy distribution variance. """ np.mean(energy_distribution) variance = np.var(energy_distribution) # Simple approximation: S ~ k_B * log(σ²) for a Gaussian distribution return 1.380649e-23 * 0.5 * np.log(max(variance, 1e-30))
[docs] def phenomenological_disorder(pattern_coherence: float) -> float: """ Phenomenological disorder measure (0 = fully ordered, 1 = fully disordered). pattern_coherence ∈ [0,1] (1 = maximal coherence). """ return 1.0 - pattern_coherence
[docs] class GeneralizedEntropy: """Implements S_gen from Definition 1.6.""" def __init__(self, beta_info: float = 1.0, beta_therm: float = 1.0, beta_ph: float = 1.0): self.beta_info = beta_info self.beta_therm = beta_therm self.beta_ph = beta_ph
[docs] def compute(self, info_entropy: float, therm_entropy: float, ph_disorder: float) -> float: """S_gen = β_info * I + β_therm * S_therm + β_ph * S_ph.""" return ( self.beta_info * info_entropy + self.beta_therm * therm_entropy + self.beta_ph * ph_disorder )
[docs] def from_pattern(self, pattern: "Pattern") -> float: """Compute S_gen directly from a Pattern object.""" info = pattern.information_content() # Simplified: use pattern's free energy as proxy for therm entropy therm = pattern.free_energy() / 1e-20 # scaling ph = phenomenological_disorder(pattern.coherence()) return self.compute(info, therm, ph)