import numpy as np
n_samples = 100
p_1 = 0.2
x_data = np.random.binomial(1, p_1, (n_samples,))
print(x_data)

frequency_of_zeros, frequency_of_ones = 0, 0
for x in x_data:
    if x:
        frequency_of_ones += 1/n_samples
    else:
        frequency_of_zeros += 1/n_samples
print(frequency_of_ones+frequency_of_zeros)

import matplotlib.pyplot as plt
%matplotlib inline
p_0 = np.linspace(0, 1, 100)
p_1 = 1-p_0
fig, ax = plt.subplots()
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2, 1.2)
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlabel("$p_0$")
ax.xaxis.set_label_coords(1.0, 0.5)
ax.set_ylabel("$p_1$")
ax.yaxis.set_label_coords(0.5, 1.0)
plt.plot(p_0, p_1)

p = np.array([[0.8], [0.2]])
np.linalg.norm(p, ord=1)

Π_0 = np.array([[1, 0], [0, 0]])
np.linalg.norm(Π_0 @ p, ord=1)

Π_1 = np.array([[0, 0], [0, 1]])
np.linalg.norm(Π_1 @ p, ord=1)

p = np.array([[.5], [.5]])
M = np.array([[0.7, 0.6], [0.3, 0.4]])
np.linalg.norm(M @ p, ord=1)

ϵ = 10e-10
p_0 = np.linspace(ϵ, 1-ϵ, 100)
p_1 = 1-p_0
H = -(p_0*np.log2(p_0) + p_1*np.log2(p_1))
fig, ax = plt.subplots()
ax.set_xlim(0, 1)
ax.set_ylim(0, -np.log2(0.5))
ax.set_xlabel("$p_0$")
ax.set_ylabel("$H$")
plt.plot(p_0, H)
plt.axvline(x=0.5, color='k', linestyle='--')

# %pip install qiskit

from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram, plot_bloch_multivector
from qiskit.primitives import BackendEstimator, BackendSampler

import numpy as np
π = np.pi

backend = AerSimulator(method='statevector')

q = QuantumRegister(1)
c = ClassicalRegister(1)
circuit = QuantumCircuit(q, c)
circuit.measure(q, c)
circuit.draw(output='mpl')


sampler = BackendSampler(backend=backend)
result = sampler.run(circuit).result()
print(result.quasi_dists[0])


# get the statevcector
from qiskit.quantum_info import Statevector
q = QuantumRegister(1)
c = ClassicalRegister(1)
circuit = QuantumCircuit(q, c)
state = Statevector.from_instruction(circuit)
print(state)
plot_bloch_multivector(state)

circuit = QuantumCircuit(q, c)
circuit.ry(π/2, q[0])
circuit.measure(q, c)
circuit.draw(output='mpl')


job = sampler.run(circuit)
result = job.result()
print(result.quasi_dists[0])
plot_histogram(result.quasi_dists[0])

circuit = QuantumCircuit(q, c)
circuit.ry(π/2, q[0])
# get statevector
state = Statevector.from_instruction(circuit)
print(state)
plot_bloch_multivector(state)


circuit = QuantumCircuit(q, c)
circuit.x(q[0])
circuit.ry(π/2, q[0])

# get statevector
state = Statevector.from_instruction(circuit)
print(state)

plot_bloch_multivector(state)

circuit.measure(q, c)

job = sampler.run(circuit)
result = job.result()
print(result.quasi_dists[0])
plot_histogram(result.quasi_dists[0])



circuit = QuantumCircuit(q, c)
circuit.ry(π/2, q[0])
circuit.ry(π/2, q[0])
circuit.measure(q, c)

job = sampler.run(circuit)
result = job.result()
print(result.quasi_dists[0])
plot_histogram(result.quasi_dists[0])



q0 = np.array([[1], [0]])
q1 = np.array([[1], [0]])
np.kron(q0, q1)

q = QuantumRegister(2)
c = ClassicalRegister(2)
circuit = QuantumCircuit(q, c)
circuit.h(q[0])
circuit.cx(q[0], q[1])
circuit.measure(q, c)

job = sampler.run(circuit)
result = job.result()
print(result.quasi_dists[0])
plot_histogram(result.quasi_dists[0])


