from Grover.grover_num_list_cirq import find_num, find_num_list
from qiskit.visualization import plot_histogram, plot_coupling_map
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 qiskit import transpile
import qiskit.providers.fake_provider
from qiskit_ibm_provider import IBMProvider
from qiskit.transpiler.passes import RemoveBarriers
from qiskit_aer import AerSimulator, Aer

Aer.get_backend('aer_simulator')

x=AerSimulator()


AerSimulator.available_methods(x)

5

import qiskit_ibm_runtime.fake_provider
from qiskit import QuantumCircuit, QuantumRegister, AncillaRegister
from bit_functions import full_bitfield, get_qubit_list

dir(qiskit_ibm_runtime.fake_provider)

backend = qiskit_ibm_runtime.fake_provider.FakeAuckland()

# GenericBackendV2 = Aer ()

backend = qiskit.providers.fake_provider.GenericBackendV2(num_qubits=5)
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0,1)
circuit.cx(0,2)
circuit.measure_all()
circuit.draw('mpl')


backend.coupling_map.draw()

circuit.data

# Transpile the ideal circuit to a circuit that can be directly executed by the backend
transpiled_circuit = transpile(circuit, backend, optimization_level=0)
transpiled_circuit.draw('mpl')

transpiled_circuit.data

# Run the transpiled circuit using the simulated backend
job = backend.run(transpiled_circuit)
counts = job.result().get_counts()
plot_histogram(counts)

dir(qiskit.providers.fake_provider)

import random
import timeit
import matplotlib.colors as mcolors

from itertools import combinations, permutations

block_diagram = False
qc_size = 4

fake_backed_name = 'FakeAuckland' #random.sample(get_fake_backend_list(min_qubit=len(experiments[0].qubits), max_qubit=len(experiments[0].qubits) + 10),1)[0][0]

num_qubits = 3
num_list = list(range(2**num_qubits))
final_expermient = []
for winner in num_list:
    grover_num = find_num()
    grover_num.build_iteration([winner],circuit_nqubits=num_qubits, block_diagram=block_diagram)
    grover_num.create_grover(solutions = 1, block_diagram=block_diagram)
    final_expermient.append(grover_num.measure_qc[0])

transpiled_circuit = [
    get_transpiled_circuits_of_circuit(qc, ['Aer', fake_backed_name], 
                                                    [None] + list(permutations(range(num_qubits))),
                                                    optimization_level_list=[0,3])
    for qc in final_expermient
]


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

output = []
for value, circuits in enumerate(result_for_circuiut):
    for index, run_circuit in enumerate(circuits): 
        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[value][index].depth()
        output.append({'value' : value, 'name' : cirq_name, 'time_taken' :cirq_time, 'depth':cirq_depth, 'count':cirq_counts})

data = {
    'Value' : [],
    'Backend' : [],
    'Qubit_Position' : [],
    'Optimization_level' : [],
    'Depth' : [],
    'Time_Taken' : [],
    'Counts' : []
}

for cur_data in output:
    data['Value'].append(cur_data['value'])
    data['Backend'].append(cur_data['name'].split('|')[0].replace(" ",""))
    data['Qubit_Position'].append(cur_data['name'].split('|')[1].replace(" ",""))
    data['Optimization_level'].append(cur_data['name'].split('|')[2].replace(" ",""))
    data['Depth'].append(cur_data['depth'])
    data['Time_Taken'].append(cur_data['time_taken'])
    data['Counts'].append([cur_data['count'][f'0x{index}'] for index in range(len(cur_data['count']))])

for cur_data in output:
    data['Value'].append(cur_data['value'])  # Assuming value is stored at index 0 in each sublist
    backend, qubit_position, optimization_level = cur_data['name'].split('|')
    data['Backend'].append(backend.strip())
    data['Qubit_Position'].append(qubit_position.strip())
    data['Optimization_level'].append(optimization_level.strip())
    data['Depth'].append(cur_data['depth'])  # Assuming depth is stored at index 2 in each sublist
    data['Time_Taken'].append(cur_data['time_taken'])  # Assuming time_taken is stored at index 3 in each sublist
    counts = [cur_data['count'][f'0x{index}'] for index in range(len(cur_data['count']))]  # Assuming counts is stored at index 4 in each sublist
    data['Counts'].append(counts)


import pandas as pd
data = pd.DataFrame(data) 

data

output



min_value = 5
max_value = 15
win = random.sample(range(min_value, max_value),1)
print(win)

grover_find_value_win_size = find_num()
grover_find_value_win_size.build_iteration(win, block_diagram=block_diagram)
grover_find_value_win_size.create_grover(block_diagram=block_diagram, solutions=len(list(win)))
experiments = grover_find_value_win_size.measure_qc

experiments[0].draw('mpl')

fake_backed_name = 'FakeAuckland' #random.sample(get_fake_backend_list(min_qubit=len(experiments[0].qubits), max_qubit=len(experiments[0].qubits) + 10),1)[0][0]

get_fake_backend_list()

backend = get_fake_backend('FakeGuadalupeV2')
print(backend.coupling_map)
backend.coupling_map.draw()

transpiled_qc_list = get_transpiled_circuits_of_circuit(experiments[0], ['Aer', fake_backed_name], 
                                                   [None, 'Full_Range'],
                                                   optimization_level_list=[0,3])

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

transpiled_qc_list[0].draw('mpl')

transpiled_qc_list[1].draw('mpl')

transpiled_qc_list[4].draw('mpl')

transpiled_qc_list[5].draw('mpl')

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

num_list_num = 4
data_arr = list(range(num_list_num))
random.shuffle(data_arr)
win = random.sample(data_arr, 1)

print(f"Data array: {data_arr} , the winner: {win}")

st = timeit.default_timer()
sol = []
for i, val in enumerate(data_arr):
    if val in win:
        sol.append(i)
        
end = timeit.default_timer()
print(f"Time: {end - st} , solution : {sol}")

grover_find_value_list = find_num_list()
grover_find_value_list.build_iteration(win, block_diagram=block_diagram, num_array = data_arr)
grover_find_value_list.create_grover(block_diagram=block_diagram, num_solutions=len(list(win)))
experiments = grover_find_value_list.measure_qc
print(experiments)
experiments[0].draw('mpl')

x =  find_num_list()
x.build_iteration(winner_list=[5],num_array = [0,5,3], block_diagram=False)
x.create_grover(num_solutions=1,block_diagram=False)
x.measure_qc[0].draw('mpl')


from Grover.transpiler import *

qc = remove_barriar_gate(x.measure_qc[0])
qc.draw('mpl')

qc, did_remove = remove_similiar_adjacent(qc)


qc.draw('mpl')

transpiled_qc_list = get_transpiled_circuits_of_circuit(experiments[0], ['Aer', fake_backed_name], 
                                                   [None, 'Full_Range'],
                                                   optimization_level_list=[0,3])
plot_histogram({
    qc.name : qc.depth()
    for qc in transpiled_qc_list
})

qc_result = [run_simulator(qc, shots = 1024 * 4) for qc in transpiled_qc_list]

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

[{qc.name : result.time_taken} for result, qc in zip(qc_result, transpiled_qc_list)]

for qc in transpiled_qc_list:
    print(qc.qubits)

transpiled_qc_list[1].draw('mpl')

transpiled_qc_list[6].draw('mpl')

transpiled_qc_list[1].draw('mpl')

for gate in transpiled_qc_list[1].data:
    print(gate)

transpiled_qc_list[5].draw('mpl')