from qiskit import QuantumCircuit

qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0,0)
qc.x(0).c_if(0, 0)
qc.draw(output='mpl')

from qiskit import QuantumRegister, ClassicalRegister

q = QuantumRegister(3, 'q')
c = ClassicalRegister(3, 'c')
qc = QuantumCircuit(q, c)

qc.h([0, 1, 2])
qc.barrier()
qc.measure(q, c)

qc.draw('mpl')

print(bin(3))
print(bin(7))

qc.x(2).c_if(c, 3) # for the 011 case
qc.x(2).c_if(c, 7) # for the 111 case

qc.draw(output='mpl')

nq = 2
m = 2
q = QuantumRegister(nq, 'q')
c = ClassicalRegister(m, 'c')

qc_S = QuantumCircuit(q,c)

qc_S.h(0)
qc_S.x(1)
qc_S.draw('mpl')

from math import pi

cu_circ = QuantumCircuit(2)
cu_circ.cp(pi/2, 0, 1)
cu_circ.draw('mpl')

for _ in range(2 ** (m - 1)):
    qc_S.cp(pi/2, 0, 1)
qc_S.draw('mpl')

def x_measurement(qc, qubit, cbit):
    """Measure 'qubit' in the X-basis, and store the result in 'cbit'"""
    qc.h(qubit)
    qc.measure(qubit, cbit)

x_measurement(qc_S, q[0], c[0])
qc_S.draw('mpl')

qc_S.reset(0)
qc_S.h(0)
qc_S.draw('mpl')

qc_S.p(-pi/2, 0).c_if(c, 1)
qc_S.draw('mpl')

## 2^t c-U operations (with t=m-2)
for _ in range(2 ** (m - 2)):
    qc_S.cp(pi/2, 0, 1)

x_measurement(qc_S, q[0], c[1]) 

qc_S.draw('mpl')

import matplotlib.pyplot as plt

from qiskit.tools.visualization import plot_histogram
from qiskit_aer.primitives import Sampler

sampler = Sampler()

job = sampler.run(qc_S)
result = job.result()

dist0 = result.quasi_dists[0]

key_new = [str(key/2**m) for key in list(dist0.keys())]
dist1 = dict(zip(key_new, dist0.values()))

fig, ax = plt.subplots(1,2)
plot_histogram(dist0, ax=ax[0])
plot_histogram(dist1, ax=ax[1])
plt.tight_layout()

nq = 3    # number of qubits
m = 3    # number of classical bits
q = QuantumRegister(nq,'q')
c = ClassicalRegister(m,'c')

qc = QuantumCircuit(q,c)

qc.h(0)
qc.x([1, 2])
qc.draw('mpl')

cu_circ = QuantumCircuit(nq)
cu_circ.mcp(pi/4, [0, 1], 2)
cu_circ.draw('mpl')

for _ in range(2 ** (m - 1)):
    qc.mcp(pi/4, [0, 1], 2)
qc.draw('mpl')

x_measurement(qc, q[0], c[0])
qc.draw('mpl')

qc.reset(0)
qc.h(0)
qc.draw('mpl')

qc.p(-pi/2, 0).c_if(c, 1)
qc.draw('mpl')

for _ in range(2 ** (m - 2)):
    qc.mcp(pi/4, [0, 1], 2)
x_measurement(qc, q[0], c[1])
qc.draw('mpl')

# initialization of qubit q0
qc.reset(0)
qc.h(0)

# phase correction
qc.p(-pi/4, 0).c_if(c, 1)

qc.p(-pi/2, 0).c_if(c, 2)
qc.p(-3*pi/2, 0).c_if(c, 3)

# c-U operations
for _ in range(2 ** (m - 3)):
    qc.mcp(pi/4, [0, 1], 2)

# X measurement  
qc.h(0)
qc.measure(0, 2)

qc.draw('mpl')

result = sampler.run(qc).result()
dist0 = result.quasi_dists[0]

key_new = [str(key/2**m) for key in list(dist0.keys())]
dist1 = dict(zip(key_new, dist0.values()))

fig, ax = plt.subplots(1,2)
plot_histogram(dist0, ax=ax[0])
plot_histogram(dist1, ax=ax[1])
plt.tight_layout()

import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright