from qiskit import QuantumCircuit; qc = QuantumCircuit(2,2)
qc.barrier()
qc.cx(0,1); qc.h(0)
qc.barrier()
qc.measure([0,1],[0,1])
qc.draw('mpl')

from qiskit import QuantumCircuit, execute, Aer; from qiskit.tools.visualization import plot_histogram
simulator = Aer.get_backend('qasm_simulator'); nshots = 2**13
qc = QuantumCircuit(2,2)
qc.h(0); qc.cx(0,1) # prepara |Phi+>
qc.barrier()
qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]) # mede na BB
qc.draw('mpl')

job = execute(qc, backend=simulator, shots=nshots)
plot_histogram(job.result().get_counts())

qc = QuantumCircuit(2,2)
qc.x(1); qc.h(0); qc.cx(0,1) # prepara |Psi+>
qc.barrier()
qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]) # mede na BB
qc.draw('mpl')

job = execute(qc, backend=simulator, shots=nshots)
plot_histogram(job.result().get_counts())

qc = QuantumCircuit(2,2)
qc.x(0); qc.h(0); qc.cx(0,1) # prepara |Phi->
qc.barrier()
qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]) # mede na BB
qc.draw('mpl')

job = execute(qc, backend=simulator, shots=nshots)
plot_histogram(job.result().get_counts())

qc = QuantumCircuit(2,2)
qc.x([0,1]); qc.h(0); qc.cx(0,1) # prepara |Psi->
qc.barrier()
qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]) # mede na BB
qc.draw('mpl')

job = execute(qc, backend=simulator, shots=nshots)
plot_histogram(job.result().get_counts())

import qiskit
qiskit.IBMQ.save_account('72f5d1e3769658b4908c384492eb3a9bd6d6ac4ab1fdf613d7fbe72884114d62728d6fd60a8bf8d0b6698f2f5463a605742658fee1ce3318181105c6acb8120e', 
                  overwrite = True)
qiskit.IBMQ.load_account()
provider = qiskit.IBMQ.get_provider(hub='ibm-q', group='open', project='main')
device = provider.get_backend('ibm_nairobi')
nshots = 2**13

qc = QuantumCircuit(2,2)
qc.h(0); qc.cx(0,1) # prepara |Phi+>
qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]) # mede na BB
job = execute(qc, backend=device, shots=nshots)
print(job.job_id())

job = device.retrieve_job('cmjn5w752bbg00825esg')
from qiskit.tools.visualization import plot_histogram; plot_histogram(job.result().get_counts())

qc = QuantumCircuit(2,2)
qc.x(1); qc.h(0); qc.cx(0,1) # prepara |Psi+>
qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]) # mede na BB
job = execute(qc, backend=device, shots=nshots); print(job.job_id())

job = device.retrieve_job('cmjn66rffjhg0084we5g')
plot_histogram(job.result().get_counts())

qc = QuantumCircuit(2,2)
qc.x(0); qc.h(0); qc.cx(0,1) # prepara |Phi->
qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]) # mede na BB
job = execute(qc, backend=device, shots=nshots); print(job.job_id())

job = device.retrieve_job('cmjn6wk6n5g0008xpgg0')
plot_histogram(job.result().get_counts())

provider = qiskit.IBMQ.get_provider(hub='ibm-q-research-2', group='federal-uni-sant-1', project='main')
device = provider.get_backend('ibm_nairobi')
qc = QuantumCircuit(2,2)
qc.x([0,1]); qc.h(0); qc.cx(0,1) # prepara |Psi->
qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]) # mede na BB
job = execute(qc, backend=device, shots=nshots); print(job.job_id())

job = device.retrieve_job('cmjnb9nz44x0008bwa3g'); plot_histogram(job.result().get_counts())

def qc_psi(th,ph,lb): # prepara o estado a ser teletransportado
    from qiskit import QuantumCircuit
    qc = QuantumCircuit(1, name=r'$|\psi\rangle$'); qc.x(0); qc.u(th,ph,lb, 0)
    return qc
qc_psi_ = qc_psi(0.1,0.2,0.3); qc_psi_.draw('mpl')

from qiskit.quantum_info import random_statevector
for j in range(0,6):
    psi = random_statevector(2)
    print(psi)

def angulos(psi): # psi = [c0,c1]
    c0_abs = math.sqrt(psi[0].real**2 + psi[0].imag**2); c1_abs = math.sqrt(psi[1].real**2 + psi[1].imag**2)
    ph0 = math.acos(psi[0].real/c0_abs); ph1 = math.acos(psi[1].real/c1_abs)
    th = 2*math.acos(c1_abs)
    lb = ph0 - math.pi; ph = ph1 - lb    
    return th, ph, lb # existem erros de sinal!

import math; import numpy as np
for j in range(0,3):
    psi = random_statevector(2); print('rand = ',psi); th, ph, lb = angulos(psi)
    psin = np.array([(math.cos(math.pi+lb)+1j*math.sin(math.pi+lb))*math.sin(th/2), 
                     (math.cos(ph+lb)+1j*math.sin(ph+lb))*math.cos(th/2)])
    print('new = ',psin) # existem erros de sinal!

def acosm(x): # solução do chagpt não funciona
    angle = math.acos(x)
    if x >= 0:
        return angle
    else:
        return 2*math.pi - angle

import math; import numpy as np
thmax = 2*math.pi; npt = 10; dth = thmax/npt; th = np.arange(0,thmax+dth,dth)
for j in range(0,len(th)):
    cs = math.cos(th[j]); acs = math.acos(cs); nacs = acosm(cs)
    print('th=',th[j],', acs=',acs,', nacs=',nacs) # não funcionam

for j in range(0,len(th)):
    tg = math.tan(th[j]); atg = math.atan(tg); sn = math.sin(th[j]); asn = math.asin(sn)
    print('th=', th[j], ', atg=', atg,', asn=', asn) # também não funcionam

# As funções anteriores não funcionam pois o mapa é 2 pra 1
# Essa função retorna o ângulo cert0, fornecidos os valores (seno,cosseno)
def arc_fun(cs, sn):
    if sn >= 0:
        return math.acos(cs)
    if sn < 0:
        return 2*math.pi - math.acos(cs)

for j in range(0,len(th)):
    cs = math.cos(th[j]); sn = math.sin(th[j])
    print('th=', th[j], ', nth=', arc_fun(cs, sn))

def angulosn(psi): # psi = [c0,c1]
    c0_abs = math.sqrt(psi[0].real**2 + psi[0].imag**2); c1_abs = math.sqrt(psi[1].real**2 + psi[1].imag**2)
    ph0 = arc_fun(psi[0].real/c0_abs, psi[0].imag/c0_abs); ph1 = arc_fun(psi[1].real/c1_abs, psi[1].imag/c1_abs)
    th = 2*arc_fun(c1_abs,c0_abs)
    lb = ph0 - math.pi; ph = ph1 - lb    
    return th, ph, lb

import math; import numpy as np
for j in range(0,5):
    psi = random_statevector(2); print('rand = ',psi); th, ph, lb = angulosn(psi)
    psin = np.array([(math.cos(math.pi+lb)+1j*math.sin(math.pi+lb))*math.sin(th/2), 
                     (math.cos(ph+lb)+1j*math.sin(ph+lb))*math.cos(th/2)])
    print('new = ',psin) # Agora está certo ...

from qiskit import *
def qc_teleport(th,ph,lb):
    qc = QuantumCircuit(3,2, name='tel')
    qc_psi_ = qc_psi(th,ph,lb); qc.append(qc_psi_, [0]); qc.barrier()
    qc.h(2); qc.cx(2,1); qc.barrier()
    qc.cx(0,1); qc.h(0); qc.measure([0,1],[0,1]); qc.barrier()
    qc.x(2).c_if(1, 1); qc.z(2).c_if(0, 1) # oprações condicionadas em info clássica
    return qc
qc_teleport_ = qc_teleport(0.1,0.2,0.3); qc_teleport_.draw('mpl')

import qiskit; import math; import numpy as np; from qiskit import Aer, QuantumCircuit, execute
from qiskit.quantum_info import state_fidelity
from qiskit.ignis.verification.tomography import state_tomography_circuits, StateTomographyFitter
simulator = Aer.get_backend('qasm_simulator')
nshots = 2**13; qc = QuantumCircuit(3)
psi = np.array([1/math.sqrt(2),1/math.sqrt(2)]); th,ph,lb=angulosn(psi) # estado a ser teletransportado
qc_teleport_ = qc_teleport(th,ph,lb); qc.append(qc_teleport_, [0,1,2])
qstc = state_tomography_circuits(qc_teleport_, [2])
job = execute(qstc, backend = simulator, shots = nshots)
qstf = StateTomographyFitter(job.result(), qstc)
rho_sim = qstf.fit(method='lstsq')
F = state_fidelity(rho_sim, psi); from sympy import Matrix
rho_teo = Matrix([[1/2,1/2],[1/2,1/2]]); print('rho_teo = ',rho_teo); print('rho_sim =',rho_sim); print('F = ', F)

import qiskit
qiskit.IBMQ.save_account('7ec48a29167ab443c525564bd84b033895cf87b6c6da8d263be59ad00a2d9e70718cf1398362403ace62320d0044793f08dbaa2629bfde7f6ec339f90fe74e7b', 
                  overwrite = True)
qiskit.IBMQ.load_account()
provider = qiskit.IBMQ.get_provider(hub='ibm-q', group='open', project='main')
device = provider.get_backend('ibm_nairobi')
qc = QuantumCircuit(3)
psi = np.array([1/math.sqrt(2),1/math.sqrt(2)])
th,ph,lb=angulosn(psi)
qc_teleport_ = qc_teleport(th,ph,lb)
qc.append(qc_teleport_, [0,1,2])
qstc = state_tomography_circuits(qc_teleport_, [2])
job = execute(qstc, backend = device, shots = nshots)
jobid = job.job_id()
print(jobid)

def qc_teleport_coe(th,ph,lb):
    from qiskit import QuantumCircuit
    qc = QuantumCircuit(3, name='tel')
    qc_psi_ = qc_psi(th,ph,lb); qc.append(qc_psi_, [0]); qc.barrier()
    qc.h(2); qc.cx(2,1); qc.barrier(); qc.cx(0,1); qc.h(0); qc.barrier()
    qc.cx(1,2); qc.cz(0,2) # oprações quânticas controladas
    return qc
qc_teleport_coe_ = qc_teleport_coe(0.1,0.2,0.3); qc_teleport_coe_.draw('mpl')

import qiskit; import math; import numpy as np
from qiskit import Aer, QuantumCircuit, execute
from qiskit.quantum_info import state_fidelity
from qiskit.ignis.verification.tomography import state_tomography_circuits, StateTomographyFitter
simulator = Aer.get_backend('qasm_simulator'); nshots = 2**13; qc = QuantumCircuit(3)
psi = np.array([1/math.sqrt(2),(1/math.sqrt(2))*1j]); th,ph,lb=angulosn(psi)
qc_teleport_coe_ = qc_teleport_coe(th,ph,lb); qc.append(qc_teleport_coe_, [0,1,2])
qstc = state_tomography_circuits(qc_teleport_coe_, [2])
job = qiskit.execute(qstc, backend = simulator, shots = nshots)
qstf = StateTomographyFitter(job.result(), qstc)
rho_sim = qstf.fit(method='lstsq')
F = state_fidelity(rho_sim, psi)
from sympy import Matrix,sqrt; rho = Matrix([[1/2,-1j/2],[1j/2,1/2]]); print('rho_teo =',rho)
print('rho_sim =',rho_sim); print('F = ', F)

import qiskit
qiskit.IBMQ.save_account('585d2242bad08223e0d894363adf8e4f76b1d426a84e85b2fbd51678adcb8e54e39cf0f33ff6c84c41e60a534a61ad4775091a01e338f0f9eff2265aa59a6a19', 
                  overwrite = True); qiskit.IBMQ.load_account()
#provider = qiskit.IBMQ.get_provider(hub='ibm-q', group='open', project='main')
provider = qiskit.IBMQ.get_provider(hub='ibm-q-research-2', group='federal-uni-sant-1', project='main')
device = provider.get_backend('ibm_nairobi')

qc = QuantumCircuit(3)
psi = np.array([1/math.sqrt(2),(1/math.sqrt(2))*1j])
th,ph,lb=angulosn(psi)
qc_teleport_coe_ = qc_teleport_coe(th,ph,lb)
qc.append(qc_teleport_coe_, [0,1,2])
qstc = state_tomography_circuits(qc_teleport_coe_, [2])
job = execute(qstc, backend = device, shots = nshots)
jobid = job.job_id()
print(jobid)

provider = qiskit.IBMQ.get_provider(hub='ibm-q', group='open', project='main')
device = provider.get_backend('ibm_nairobi')
job = device.retrieve_job('cmke9bn8tsq00080987g')
qstf = StateTomographyFitter(job.result(), qstc)
rho_exp = qstf.fit(method='lstsq')
psi = np.array([1/math.sqrt(2),(1/math.sqrt(2))*1j])
from sympy import Matrix, sqrt
rho = Matrix([[0.5,-0.5*1j],[0.5*1j,0.5]])
print('rho_teo =',rho)
F = state_fidelity(psi, rho_exp)
print('rho_exp = ',rho_exp,', F = ', F)

import qiskit; import math; import numpy as np
from qiskit import Aer, QuantumCircuit, execute
from qiskit.quantum_info import state_fidelity
from qiskit.ignis.verification.tomography import state_tomography_circuits, StateTomographyFitter
simulator = Aer.get_backend('qasm_simulator'); nshots = 2**13

for j in range(0,13):
    qc = QuantumCircuit(3)
    psi = random_statevector(2); th,ph,lb = angulosn(psi)#; print('psi=',psi)
    qc_teleport_coe_ = qc_teleport_coe(th,ph,lb); qc.append(qc_teleport_coe_, [0,1,2])
    qstc = state_tomography_circuits(qc_teleport_coe_, [2])
    job = qiskit.execute(qstc, backend=simulator, shots=nshots)
    qstf = StateTomographyFitter(job.result(), qstc); rho_sim = qstf.fit(method='lstsq')
    F = state_fidelity(rho_sim, psi); print('F=', F)

