import numpy as np
from qiskit import QuantumCircuit, execute, Aer, IBMQ, QuantumRegister, ClassicalRegister
from qiskit import IBMQ, BasicAer
from qiskit.circuit.library import QFT
from IPython.core.display import Image, display

#INITIALISE THE QUANTUM AND CLASSICAL REGISTERS
q = QuantumRegister(4,'q')
c = ClassicalRegister(3,'c')
circuit1 = QuantumCircuit(q,c)

#PUT THE COUNTING QUBITS IN TO SUPERPOSITION
circuit1.h(q[0])
circuit1.h(q[1])
circuit1.h(q[2])
circuit1.x(q[3]) # Flips Q[3] to 1
circuit1.draw('mpl')


pi= np.pi
angle = 2*pi/3 #The phase angle we wish to encode

actual_phase = angle/(2*pi) # This is the actual phase rotation ie 0.5 would be half a rotation. 
                            #Our expected rotation will be 0.33.  

circuit1.cu1(angle, q[0], q[3]);#where angle is the rotation amount, q[0] is the control qubit and q[3] is the target qubit

circuit1.cu1(angle, q[1], q[3]); 
circuit1.cu1(angle, q[1], q[3]);

circuit1.cu1(angle, q[2], q[3]);
circuit1.cu1(angle, q[2], q[3]);
circuit1.cu1(angle, q[2], q[3]);
circuit1.cu1(angle, q[2], q[3]);

circuit1.barrier()
circuit1.draw('mpl')

circuit1.swap(q[0],q[2])
circuit1.h(q[0])
circuit1.cu1(-pi/2, q[0], q[1]);
circuit1.h(q[1])
circuit1.cu1(-pi/4, q[0], q[2]);
circuit1.cu1(-pi/2, q[1], q[2]);
circuit1.h(q[2])

circuit1.barrier()
circuit1.draw('mpl')

#### Measuring counting qubits ####
circuit1.measure(q[0],0)
circuit1.measure(q[1],1)
circuit1.measure(q[2],2)

from qiskit.visualization import plot_histogram
simulator = Aer.get_backend('qasm_simulator')
counts = execute(circuit1, backend=simulator, shots=1000).result().get_counts(circuit1)
plot_histogram(counts)

maxcounts = max(counts, key=counts.get) # take the most often obtaned result
print(maxcounts)
a=int(maxcounts, 2)#convert to decimal
print(a)

print('Most frequent measurement: ',a,'\n')
n=3
phase = a/(2**n)# The calculation used to estimate the phase


print('Actual phase is: ',actual_phase)
print('Estimated phase is: ',phase)

