# initialization
import numpy as np

# importing Qiskit
from qiskit import *

# import basic plot tools
from qiskit.visualization import plot_histogram

from qiskit_textbook.tools import simon_oracle

from qiskit.providers.fake_provider import FakeJakarta

from qiskit.providers.fake_provider import FakeNairobi

#defining  a function to create the Simon's Algorithm circuit. Function takes in the oracle and number of qubits 
# and ouputs the quantum circuit 

def Simons_algo(oracle,n):
    
    # n input qubits and n helper qubit
    qc = QuantumCircuit(2*n,n)
    
    
    # creating superposition of all the inputs
    for i in range(n):
        qc.h(i)
    qc.barrier()
    
    # applying the oracle that has the funciton and the secret string encoded in it to the circuit 
    qc.append(oracle, range(2*n))
    qc.barrier()
    
    #applying the hadamard gates again to collapse the superposition to one state that has the final result 
    #encoded in it. 
    for i in range(n):
        qc.h(i)
    
    # measuring the input qubits to find the final result. 
    qc.measure(range(n),range(n))
    
    return (qc)
    
    

a = '10'
n = len(a)
ora = simon_oracle(a)

ora.draw('mpl')

q1 = Simons_algo(ora, n)
q1.draw('mpl')

# Running on non-noisy simulator

backend = Aer.get_backend('aer_simulator')
job = execute(q1,backend, shots=1024)
results = job.result()
counts = results.get_counts()
plot_histogram(counts)

# Running on noisy simulator

backend = FakeJakarta()
job = execute(q1,backend)
results = job.result()
counts = results.get_counts()
plot_histogram(counts)

# Running on noisy simulator

backend = FakeNairobi()
job = execute(q1,backend)
results = job.result()
counts = results.get_counts()
plot_histogram(counts)

a = '101'
n = len(a)
ora = simon_oracle(a)

ora.draw('mpl')

q1 = Simons_algo(ora, n)
q1.draw('mpl')


# Running on non-noisy simulator

backend = Aer.get_backend('aer_simulator')
job = execute(q1,backend, shots=1024)
results = job.result()
counts = results.get_counts()
plot_histogram(counts)

# Running on noisy simulator

backend = FakeJakarta()
job = execute(q1,backend)
results = job.result()
counts = results.get_counts()
plot_histogram(counts)

# Running on noisy simulator

backend = FakeNairobi()
job = execute(q1,backend)
results = job.result()
counts = results.get_counts()
plot_histogram(counts)

