# ============================================================
# Law of Large Numbers on ENTROPY (not raw values)
# ============================================================

def demonstrate_entropy_lln():
    """
    Show that entropy values generalize across seeds.
    Raw values don't converge. Entropy values do.
    """
    
    sim = EntropyCollapseSimulator(N=100)
    
    # Track convergence as we add more seeds
    seed_counts = [10, 50, 100, 200, 500, 1000, 2000, 5000]
    
    means_shannon = []
    stds_shannon = []
    means_spectral = []
    means_conditional = []
    
    all_H_shannon = []
    
    for n in seed_counts:
        result = sim.aggregate_entropy_field(n, distribution='normal')
        all_H_shannon = result['H_shannon_field']
        
        means_shannon.append(np.mean(all_H_shannon))
        stds_shannon.append(np.std(all_H_shannon) / np.sqrt(n))  # Standard error
        means_spectral.append(result['mean_spectral'])
        means_conditional.append(result['mean_conditional'])
    
    # Plot
    fig, axes = plt.subplots(2, 2, figsize=(14, 10))
    
    # Plot 1: Shannon Entropy Convergence
    ax1 = axes[0, 0]
    ax1.errorbar(seed_counts, means_shannon, yerr=stds_shannon, 
                 fmt='bo-', capsize=5, lw=2, markersize=8)
    ax1.set_xscale('log')
    ax1.set_xlabel('Number of Seeds (Collapse Events)')
    ax1.set_ylabel('Mean Shannon Entropy')
    ax1.set_title('Law of Large Numbers on ENTROPY: Converges!')
    
    # Horizontal line at theoretical max entropy for this bin count
    theoretical_max = np.log(sim.num_bins)
    ax1.axhline(y=theoretical_max, color='red', linestyle='--', 
                label=f'Theoretical Max (ln({sim.num_bins})={theoretical_max:.2f})')
    ax1.legend()
    ax1.grid(True, alpha=0.3)
    
    # Plot 2: Raw Values Don't Converge (control experiment)
    ax2 = axes[0, 1]
    raw_means = []
    raw_stds = []
    
    for n in seed_counts:
        all_raw = []
        for seed in range(n):
            np.random.seed(seed)
            raw = np.random.normal(0, 1, 100)
            all_raw.append(np.mean(raw))
        raw_means.append(np.mean(all_raw))
        raw_stds.append(np.std(all_raw) / np.sqrt(n))
    
    ax2.errorbar(seed_counts, raw_means, yerr=raw_stds, 
                 fmt='go-', capsize=5, lw=2, markersize=8)
    ax2.set_xscale('log')
    ax2.set_xlabel('Number of Seeds')
    ax2.set_ylabel('Mean of Raw Values')
    ax2.set_title('Raw Values: Converge to 0 (as expected, but fragile)')
    ax2.axhline(y=0, color='red', linestyle='--', label='True Mean = 0')
    ax2.legend()
    ax2.grid(True, alpha=0.3)
    
    # Plot 3: Distribution of Entropy Values (does it stabilize?)
    ax3 = axes[1, 0]
    for idx, n in enumerate([50, 500, 5000]):
        result = sim.aggregate_entropy_field(n, distribution='normal')
        ax3.hist(result['H_shannon_field'], bins=30, alpha=0.5, 
                 density=True, label=f'{n} seeds')
    
    ax3.set_xlabel('Shannon Entropy Value')
    ax3.set_ylabel('Probability Density')
    ax3.set_title('Entropy Field Stabilizes: Different Seeds → Same Entropy')
    ax3.legend()
    
    # Plot 4: Spectral Entropy (captures periodicity)
    ax4 = axes[1, 1]
    ax4.plot(seed_counts, means_spectral, 'ro-', lw=2, markersize=8)
    ax4.set_xscale('log')
    ax4.set_xlabel('Number of Seeds')
    ax4.set_ylabel('Mean Spectral Entropy')
    ax4.set_title('Spectral Entropy: Captures Internal Structure')
    ax4.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('entropy_lln_convergence.png', dpi=150)
    plt.show()
    
    return {
        'seed_counts': seed_counts,
        'means_shannon': means_shannon,
        'stds_shannon': stds_shannon,
        'theoretical_max': theoretical_max
    }

result_lln = demonstrate_entropy_lln()

print("\n" + "="*60)
print("KEY FINDING: Entropy converges via Law of Large Numbers")
print("="*60)
print(f"Final mean entropy: {result_lln['means_shannon'][-1]:.4f}")
print(f"Theoretical max: {result_lln['theoretical_max']:.4f}")
print(f"Convergence ratio: {result_lln['means_shannon'][-1] / result_lln['theoretical_max']:.2%}")
