#initialization
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import math

# importing Qiskit
from qiskit import IBMQ, BasicAer
from qiskit.providers.ibmq import least_busy
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, execute

# import basic plot tools
from qiskit.tools.visualization import plot_histogram

q = QuantumRegister(3, 'q')
c = ClassicalRegister(2, 'c')

qpe = QuantumCircuit(q, c)
qpe.x(q[2])

qpe.h(q[0])
qpe.h(q[1])

# controlled unitary from q[0] is the identity matrix

# controlled unitary from q[1] is a controlled-Z gate
qpe.cz(q[1], q[2]);

def qft(circ, q, n):
    """n-qubit QFT on q in circ."""
    for j in range(n):
        circ.h(q[j])
        for k in range(j+1,n):
            circ.cu1(math.pi/float(2**(k-j)), q[k], q[j])
            
def qft_dagger(circ, q, n):
    """n-qubit QFTdagger on q in circ."""
    for j in range(n):
        k = (n-1) - j
        for m in range(k):
            circ.cu1(-math.pi/float(2**(k-m)), q[k], q[m])
        circ.h(q[k])

qft_dagger(qpe, q, 2)

qpe.measure(q[0],c[0])
qpe.measure(q[1],c[1])

qpe.draw(output="mpl")

nancilla = 4
q2 = QuantumRegister(nancilla+2, 'q')
c2 = ClassicalRegister(nancilla, 'c')

qpe2 = QuantumCircuit(q2, c2)
qpe2.x(q2[nancilla])
qpe2.x(q2[nancilla+1])

for i in range(nancilla):
    qpe2.h(q2[i])

# controlled unitary from q[0] is the identity matrix
# controlled unitary from q[1] is the identity matrix
# controlled unitary from q[2] is a controlled-Z gate
qpe2.h(q2[nancilla+1])
qpe2.ccx(q2[nancilla-1], q2[nancilla], q2[nancilla+1])
qpe2.h(q2[nancilla+1])


qft_dagger(qpe2, q2, nancilla)

for i in range(nancilla):
    qpe2.measure(q2[i],c2[i])

qpe2.draw(output="mpl")

backend = BasicAer.get_backend('qasm_simulator')
shots = 2048
results = execute(qpe, backend=backend, shots=shots).result()
answer = results.get_counts()
plot_histogram(answer)

results2 = execute(qpe2, backend=backend, shots=shots).result()
answer2 = results2.get_counts()
plot_histogram(answer2)

# Load our saved IBMQ accounts and get the least busy backend device
IBMQ.load_account()
IBMQ.get_provider(hub='ibm-q')
provider.backends()

backend = provider.get_backend('ibmq_vigo')
from qiskit.tools.monitor import job_monitor
shots = 2048
job_exp = execute(qpe, backend=backend, shots=shots)

job_monitor(job_exp, interval = 2)

# get the results from the computation
results = job_exp.result()
answer = results.get_counts(qpe)
plot_histogram(answer)