import numpy as np
from scipy.optimize import minimize_scalar
import matplotlib.pyplot as plt
from numpy import genfromtxt

def binary_entropy(p):
    return -p * np.log2(p) - (1 - p) * np.log2(1 - p)

def inverse_H(arr):
    vals = []
    for val in arr:
        # Define a function that returns the absolute difference between H(p) and the desired value
        func = lambda p: abs(binary_entropy(p) - val)
        # Use minimize_scalar to find the value of p that minimizes the absolute difference
        result = minimize_scalar(func, bounds=(1e-15, 1-1e-15), method='bounded')
        vals.append(result.x)
    vals = np.array(vals)
    vals[vals > 0.5] = 1 - vals[vals > 0.5]
    return vals
import matplotlib
matplotlib.rcParams['mathtext.fontset'] = 'stix'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
def sim_histogram(trials, N):
    num_incorrect = np.zeros(trials)
    k = 0.2
    epsilon = inverse_H([1-k])

    num_incorrect = genfromtxt('simulator_histogram.csv', delimiter=',')

    num_incorrect = np.array(num_incorrect)

    binomialRV = np.random.binomial(N, epsilon, trials).astype(int)

    ax1 = plt.subplot(211)
    plt.hist(num_incorrect, bins=30)
    plt.title("Histogram of Simulation Number of Bits incorrect from Y to X")
    plt.xlabel("Number of bits incorrect from Y to X")
    plt.ylabel("Number of trials")

    plt.subplot(212, sharex = ax1)
    plt.hist(binomialRV, bins=30, color='orange')
    plt.title("Histogram of Binomial Random Variable with Parameters" + str((N,np.round(epsilon[0],2))))
    plt.xlabel("Binomial RV Values")
    plt.ylabel("Number of trials")

    plt.tight_layout()
    plt.show()

# sim_histogram(800, 8192)