# !pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org Ipython

# pip install -U notebook-as-pdf

from IPython.display import display, Latex
from IPython.display import Image
from qiskit import *
from qiskit.visualization import *
from qiskit.quantum_info import Statevector


import numpy as np
import warnings

# warnings.filterwarnings("ignore", category=DepriciationWarning)
warnings.filterwarnings("ignore", category=UserWarning)


qc = QuantumCircuit(3)
qc.ry (np.pi/4, 0) # optional, we want to transfer state 1 in this example
save = Statevector.from_instruction(qc)
qc.draw('mpl')


simulator = Aer.get_backend('statevector_simulator')
result = execute(qc, backend= simulator, shots = 100000).result().get_statevector()

print(f'Amplitudes alpha e beta são: [{np.round(np.cos(np.pi/8)**2,5)} {np.round(np.sin(np.pi/8)**2,5)}]')


plot_bloch_multivector(result)


alice = QuantumRegister(2, 'a')
bob = QuantumRegister(1,'b')
cr_alice = ClassicalRegister(2, 'ca')
cr_bob = ClassicalRegister(1,'cb')

qc = QuantumCircuit(alice,bob,cr_alice, cr_bob)

qc.ry(np.pi/4, alice[0]) # optional, we want to transfer state 1 in this example
qc.barrier()
qc.draw('mpl')

qc.h(alice[1])
qc.cx(alice[1],bob[0])
qc.barrier()
qc.draw('mpl')

qc.cx(alice[0],alice[1])
qc.h(alice[0])

qc.barrier()

qc.draw('mpl')

qc.measure(alice, cr_alice)
qc.barrier()
qc.draw('mpl')

qc.cx(alice[1], bob[0])
qc.cz(alice[0], bob[0])
# qc.measure(bob, cr_bob)


qc.draw('mpl')

simulator = Aer.get_backend('statevector_simulator')
result = execute(qc, backend= simulator, shots = 10000).result().get_statevector()
# plot_histogram(result)
states = [format(i,'0'+str(n)+'b')[::-1] for i in range(2**n)]

print(states)
res = [round(i.real, 5) for i in result]
array_to_latex(result)

n = 3
states = [format(i,'0'+str(n)+'b')[::-1] for i in range(2**n)]

medida = [(j,i) for i,j in zip(res,states) if i >  0]

print(f'\n\nAlice mediu {medida[0][0][:2]} o estado que está com Bob é [{medida[0][1]} {medida[1][1]}]\n\n')

alice = QuantumRegister(2, 'a')
bob = QuantumRegister(1,'b')
cr_alice = ClassicalRegister(2, 'ca')
cr_bob = ClassicalRegister(1,'cb')

qc = QuantumCircuit(alice,bob,cr_alice, cr_bob)

qc.ry(np.pi/4, alice[0]) # optional, we want to transfer state 1 in this example
qc.barrier()
save1 = Statevector.from_instruction(qc)


qc.h(alice[1])
qc.cx(alice[1],bob[0])
qc.barrier()


qc.cx(alice[0],alice[1])
qc.h(alice[0])

qc.barrier()


# qc.measure(alice, cr_alice)
qc.barrier()

qc.cx(alice[1], bob[0])
qc.cz(alice[0], bob[0])
save2 = Statevector.from_instruction(qc)


qc.measure(bob, cr_bob)


qc.draw('mpl')

plot_bloch_multivector(save1)

plot_bloch_multivector(save2)

alice = QuantumRegister(2, 'a')
bob = QuantumRegister(1,'b')
cr_alice = ClassicalRegister(2, 'ca')
cr_bob = ClassicalRegister(1,'cb')

qc = QuantumCircuit(alice,bob,cr_alice, cr_bob)

qc.ry(np.pi/4, alice[0]) # optional, we want to transfer state 1 in this example
qc.barrier()


qc.h(alice[1])
qc.cx(alice[1],bob[0])
qc.barrier()


qc.cx(alice[0],alice[1])
qc.h(alice[0])

qc.barrier()


qc.measure(alice, cr_alice)
qc.barrier()

qc.cx(alice[1], bob[0])
qc.cz(alice[0], bob[0])


qc.measure(bob, cr_bob)


qc.draw('mpl')

simulator = Aer.get_backend('qasm_simulator')
shots = 100000
result = execute(qc, backend=simulator, shots=shots).result().get_counts()

from qiskit.visualization import plot_histogram
plot_histogram(result)

prob0 = 0
prob1 = 0



for i in result.keys():
    if i[0] == '0':
        prob0+= result[i]
    if i[0] == '1':
        prob1+= result[i]

        

print(prob0/shots,prob1/shots)

print(np.round(np.cos(np.pi/8)**2,5), np.round(np.sin(np.pi/8)**2,5))

np.cos(np.pi/8)**2

simulator = Aer.get_backend('statevector_simulator')
result = execute(qc, backend= simulator, shots = 10000).result().get_statevector()
# plot_histogram(result)

array_to_latex(result, prefix= '\\vert \psi \\rangle = ')



