from qiskit import *
from qiskit.visualization import plot_histogram

def simon_oracle(b):
    n = len(b)
    circ = QuantumCircuit(2*n, n)

    for i in range(n):
        circ.cx(i, i+n)

    # for i in range(n):
    #     if b[n-1-i] == '1':
    #         for j in range(n):
    #             if b[j] == '1':
    #                 circ.cx(i, j + n)
    #         break
    for i in range(n):
        if b[n-1-i] == '1':
            circ.cx(i, i+n)

    return circ

b = '1001'
n = len(b)

circ = QuantumCircuit(2*n, n)
circ.h(range(n))
circ.barrier()

circ = circ.compose(simon_oracle(b))

circ.barrier()

circ.h(range(n))

circ.measure(range(n), range(n))

print("the coresponding function should saticfy")
b_dex = int(b, base=2)
for num in range(2**(n-1)):
    print(f"f({num}) = f({num ^ b_dex})")

circ.draw('mpl')

sim = Aer.get_backend("qasm_simulator")
result = execute(circ, backend=sim).result()

plot_histogram(result.get_counts())

#find b

def bdotz(b, z):
    accum = 0
    for i in range(len(b)):
        accum += int(b[i]) * int(z[i])
    return (accum % 2)

shots = 1024
for z in result.get_counts().keys():
    print( '{} . {} = {} (mod 2) ({:.1f}%)'.format(b, z, bdotz(b,z), result.get_counts()[z]*100/shots))

import random
import timeit
import matplotlib.colors as mcolors
from backend_operation import run_simulator, get_transpiled_circuits_of_circuit, get_fake_backend_list,get_unitary, get_fake_backend, get_fake_backend_list
from itertools import combinations, permutations

fake_backed_name = 'FakeAuckland'

transpiled_circuit = get_transpiled_circuits_of_circuit(circ, ['Aer', fake_backed_name], 
                                                    [None, "Full_Range"],
                                                    optimization_level_list=[0,3])

result_for_circuiut =  [
        run_simulator(qc,shots = 1024 * 4)
        for qc in transpiled_circuit   
]


output = []
for index, run_circuit in enumerate(result_for_circuiut): 
    result_dict= run_circuit.to_dict()
    cirq_result = result_dict['results'][0]
    cirq_counts = cirq_result['data']['counts']
    cirq_time = cirq_result['time_taken']
    cirq_name = cirq_result['header']['name']
    cirq_depth = transpiled_circuit[index].depth()
    output.append({'name' : cirq_name, 'time_taken' :cirq_time, 'depth':cirq_depth, 'count':cirq_counts})

print(output)

import pandas as pd

df = pd.DataFrame(output)
df

plot_histogram([run_simulator(qc,shots = 1024).get_counts() for qc in transpiled_circuit], 
               legend=[qc.name for qc in transpiled_circuit], color=list(random.choices(list(mcolors.get_named_colors_mapping().values()), k = len(transpiled_circuit))),
               title="Result transpilers")

plot_histogram({
    qc.name : qc.depth()
    for qc in transpiled_circuit
})