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)
#print(p_0)
p_1 = 1-p_0
#print(p_1)
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.7], [0.3]])
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='--')

from qiskit import QuantumCircuit, execute,QuantumCircuit, ClassicalRegister, QuantumRegister, Aer
from qiskit.visualization import plot_histogram, plot_bloch_vector,plot_bloch_multivector,plot_state_qsphere
from math import sqrt, pi
import numpy as np
%matplotlib inline

qc = QuantumCircuit(1) # Create a quantum circuit with one qubit

backend = Aer.get_backend('statevector_simulator') # Tell Qiskit how to simulate our circuit
job = execute(qc,backend).result() # Do the simulation, returning the state vector
plot_bloch_multivector(job.get_statevector()) # Display the output state vector

initial_state = [0,1]   # Define initial_state as |1>
qc.initialize(initial_state, 0) # Apply initialisation operation to the 0th qubit
qc.draw()# Let's view our circuit

result = execute(qc,backend).result() # Do the simulation, returning the state vector
plot_bloch_multivector(result.get_statevector()) # Display the output state vector

out_state = result.get_statevector()
print(out_state) # Display the output state vector

qc.measure_all()
qc.draw()

result = execute(qc,backend).result()
counts = result.get_counts()
plot_histogram(counts)

initial_state = [1/sqrt(2), 1j/sqrt(2)]  # Define state |q>

qc = QuantumCircuit(1) # Must redefine qc
qc.initialize(initial_state, 0)# Initialise the 0th qubit in the state `initial_state`
qc.h(0)
qc.draw()

state = execute(qc,backend).result().get_statevector() # Execute the circuit
print(state) # Print the result

results = execute(qc,backend).result().get_counts()
plot_histogram(results)

vector = [0,1]
qc.initialize(vector, 0)

qc = QuantumCircuit(1) # Redefine qc
initial_state = [0.+1.j/sqrt(2),1/sqrt(2)+0.j]
qc.initialize(initial_state, 0)
print(initial_state)
qc.draw()

state = execute(qc, backend).result().get_statevector()
print("Qubit State = " + str(state))

qc.measure_all()
qc.draw()

state = execute(qc, backend).result().get_statevector()
print("State of Measured Qubit = " + str(state))


π = np.pi

backend = BasicAer.get_backend('qasm_simulator')

q = QuantumRegister(1)
c = ClassicalRegister(1)
circuit = QuantumCircuit(q, c)

circuit.measure(q, c)

job = execute(circuit, backend, shots=100)

result = job.result()
result.get_counts(circuit)

backend_statevector = BasicAer.get_backend('statevector_simulator')
circuit = QuantumCircuit(q, c)
circuit.iden(q[0])
job = execute(circuit, backend_statevector)
plot_bloch_multivector(job.result().get_statevector(circuit))

circuit = QuantumCircuit(q, c)
circuit.ry(π/2, q[0])
circuit.measure(q, c)
job = execute(circuit, backend, shots=100)
plot_histogram(job.result().get_counts(circuit))

circuit = QuantumCircuit(q, c)
circuit.ry(π/2, q[0])
job = execute(circuit, backend_statevector)
plot_bloch_multivector(job.result().get_statevector(circuit))

circuit = QuantumCircuit(q, c)
circuit.x(q[0])
circuit.ry(π/2, q[0])
job = execute(circuit, backend_statevector)
plot_bloch_multivector(job.result().get_statevector(circuit))

circuit.measure(q, c)
job = execute(circuit, backend, shots=100)
plot_histogram(job.result().get_counts(circuit))

circuit = QuantumCircuit(q, c)
circuit.ry(π/2, q[0])
circuit.ry(π/2, q[0])
circuit.measure(q, c)
job = execute(circuit, backend, shots=100)
plot_histogram(job.result().get_counts(circuit))

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 = execute(circuit, backend, shots=100)
plot_histogram(job.result().get_counts(circuit))