import warnings
from qiskit import QuantumRegister, ClassicalRegister
from qiskit import QuantumCircuit, execute, Aer, transpile
from qiskit.tools.monitor import job_monitor
from qiskit.circuit.library import QFT
from qiskit.visualization import plot_histogram, plot_bloch_multivector
warnings.filterwarnings("ignore", category=DeprecationWarning)
import numpy as np

pi = np.pi

def flip_endian(dict):
    newdict = {}
    for key in list(dict):
        newdict[key[::-1]] = dict.pop(key)
    return newdict

def set_measure_x(circuit, n):
    for num in range(n):
        circuit.h(num)

def set_measure_y(circuit, n):
    for num in range(n):
        circuit.sdg(num)
        circuit.h(num)

def qft_rotations(circuit, n):
    #if qubit amount is 0, then do nothing and return
    if n == 0:
        #set it to measure the x axis
        set_measure_x(qc, 4)
        qc.measure_all()
        return circuit
    n -= 1
    circuit.h(n)
    for qubit in range(n):
        circuit.cp(pi/2**(n-qubit), qubit, n)
    return qft_rotations(circuit, n)

backend = Aer.get_backend('aer_simulator') 
qc = QuantumCircuit(4)

qc.x(0)

qft_rotations(qc,4)#call the recursive qft method
#set it to measure the x axis
set_measure_x(qc, 4)

job = execute(qc, backend, shots=100000)#run the circuit 1000000 times
print(flip_endian(job.result().get_counts()))#return the result counts

def qft_rotations(circuit, n):
    #if qubit amount is 0, then do nothing and return
    if n == 0:
        return circuit
    n -= 1
    circuit.h(n)
    for qubit in range(n):
        circuit.cp(pi/2**(n-qubit), qubit, n)
        #print(n)
        #print(qubit)
    return qft_rotations(circuit, n)

sim = Aer.get_backend('aer_simulator') 
q = QuantumRegister(4,'q')
c = ClassicalRegister(4,'c')
qc = QuantumCircuit(q,c)

qc.x(0)
qc.x(1)
qc.x(2)
#qc.x(3)

#qc.h(0)
#qc.p( 20 * pi / 180, 0)

qft_rotations(qc,4)#call the recursive qft method

qc.save_statevector()
statevector = sim.run(qc).result().get_statevector()
print(statevector)
plot_bloch_multivector(statevector)

backend = Aer.get_backend('aer_simulator') 
q = QuantumRegister(4,'q')
c = ClassicalRegister(1,'c')
qc = QuantumCircuit(q,c)

qc.x(0)

qft_rotations(qc,4)#call the recursive qft method
set_measure_x(qc, 4)
print(qc)

qc.measure(q[3],c)#select qubits registers to measure
job = execute(qc, backend, shots=1000000)#run the circuit 1000 times
dictRes = job.result().get_counts()#return the result counts
print(dictRes)

