!pip install tabulate
%matplotlib inline
# Importing standard Qiskit libraries and configuring account
from qiskit import QuantumCircuit, execute, Aer, IBMQ
from qiskit.compiler import transpile, assemble
from qiskit.tools.jupyter import *
from qiskit.visualization import *
from tabulate import tabulate
# Loading your IBM Q account(s)
provider = IBMQ.load_account()
#Get the library to check the answers
%pip install -I git+https://github.com/mnp-club/MnP_QC_Workshop.git
from mnp_qc_workshop_2020.discrete_logarithm import qft_dagger, oracle, check_answer

n_qubits = 3 #Number of qubits for the registers of |x1> and |x2>
#For figuring out you would just need 2*n_qubits classical bits
qc_disc_log = QuantumCircuit(4+n_qubits+n_qubits, n_qubits+n_qubits)

for i in range(6):
    qc_disc_log.h(i)

qc_disc_log.x(9)#Flip the first bit in third register to bring in state |1> taking q6 as LSB

qc_disc_log.append(oracle(),range(10))#Applying oracle

qc_disc_log.append(qft_dagger(n_qubits), range(n_qubits))#Inverse QFT on register 1
qc_disc_log.append(qft_dagger(n_qubits), range(n_qubits,2*n_qubits))#Inverse QFT on register 2

qc_disc_log.measure(range(6),range(6))

qc_disc_log.draw('text')

backend = Aer.get_backend('qasm_simulator')
results = execute(qc_disc_log, backend, shots=8192).result()
counts = results.get_counts()
plot_histogram(counts)

rows_x_1, eigenvalues_x_1 = [], []
for output in counts:
    decimal = int(output, 2)//8
    eigenvalue = decimal/(2**3)
    eigenvalues_x_1.append(eigenvalue)
    rows_x_1.append(["%s(bin) = %i(dec)" % (output[0:3], decimal), "%i/%i = %.2f" % (decimal, 2**3, eigenvalue)])
print(tabulate(rows_x_1, headers=["Register Output", "Phase"]))

rows_x_2, eigenvalues_x_2 = [], []
for output in counts:
    decimal = int(output, 2) - ((int(output, 2)//8)*8)
    eigenvalue = decimal/(2**3)
    eigenvalues_x_2.append(eigenvalue)
    rows_x_2.append(["%s(bin) = %i(dec)" % (output[3:6], decimal), "%i/%i = %.2f" % (decimal, 2**3, eigenvalue)])
print(tabulate(rows_x_2, headers=["Register Output", "Phase"]))

def make_guess_for_s(e1,e2):
    if e1==0 or e2==0:
        return "NaN"
    for a in range(2,4):
        if ((e1*a) - int(e1*a)) == e2: #This is because there will be roll over of the values in the register
            return a
    return "Nan"




rows = []
for i in range(len(eigenvalues_x_1)):
    eigenvalue_x_1 = eigenvalues_x_1[i]
    numerator1, denominator1 = eigenvalue_x_1.as_integer_ratio()
    eigenvalue_x_2 = eigenvalues_x_2[i]
    numerator2, denominator2 = eigenvalue_x_2.as_integer_ratio()
    s_val = make_guess_for_s(eigenvalue_x_1,eigenvalue_x_2)
    rows.append([eigenvalue_x_1, "%i/%i" % (numerator1, denominator1), eigenvalue_x_2, "%i/%i" % (numerator2, denominator2), s_val])
print(tabulate(rows, headers=["Phase in 1st register","Fraction", "Phase in 2nd register", "Fraction", "Guess for s"], colalign=('right','right','right','right','right')))

#Store your value for s here
s = 3

from math import gcd
for i in range(2,15):
    j = 1
    if(gcd(i,15)!=1):
        continue
    while(True):
        if (i**j)%15 == 1:
            break
        j = j+1
    if(j == 4):
        print(i)

qc_an = QuantumCircuit(10,4)

qc_an.x(0)#This way the oracle multiplies by a mod 15
qc_an.x(9)#Flip the first bit in third register to bring in state |1>

qc_an.append(oracle(),range(10))#Applying oracle

qc_an.measure(range(6,10),range(4))

qc_an.draw('text')


backend = Aer.get_backend('qasm_simulator')
results = execute(qc_an, backend, shots=1024).result()
counts = results.get_counts()
plot_histogram(counts)

qc_bn = QuantumCircuit(10,4)

qc_bn.x(3)#This way the oracle multiplies by b mod 15
qc_bn.x(9)#Flip the first bit in third register to bring in state |1>

qc_bn.append(oracle(),range(10))#Applying oracle

qc_bn.measure(range(6,10),range(4))

qc_bn.draw('text')


backend = Aer.get_backend('qasm_simulator')
results = execute(qc_bn, backend, shots=1024).result()
counts = results.get_counts()
plot_histogram(counts)

#Store values of a and b here
a, b = 2,8

check_answer(s,a,b)