-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5765597
commit b46a78a
Showing
17 changed files
with
12,488 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
names,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,c20,c21,c22,c23,c24,c25,c26,c27,c28,c29,c30,c31 | ||
Falcon,0.7071067811865476,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.7071067811865476 | ||
Hummingbird,0.0,0.7071067811865476,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.7071067811865476,0.0 | ||
Eagle,0.0,0.0,0.7071067811865476,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.7071067811865476,0.0,0.0 | ||
Osprey,0.0,0.0,0.0,0.7071067811865476,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.7071067811865476,0.0,0.0,0.0 | ||
Heron,0.0,0.0,0.0,0.0,0.7071067811865476,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.7071067811865476,0.0,0.0,0.0,0.0 | ||
Peacock,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 | ||
Parrot,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 | ||
Swan,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 | ||
Toucan,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 | ||
Cardinal,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
528 changes: 528 additions & 0 deletions
528
IBM Quantum Challenge 2024/lab-3-ai-transpiler-solution.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
1,511 changes: 1,511 additions & 0 deletions
1,511
IBM Quantum Challenge 2024/lab-3-circuit-knitting(1).ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
1,234 changes: 1,234 additions & 0 deletions
1,234
IBM Quantum Challenge 2024/lab-3-serverless-solution.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# transpile_parallel.py | ||
|
||
from qiskit import QuantumCircuit | ||
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager | ||
from qiskit_transpiler_service.transpiler_service import TranspilerService | ||
from qiskit_serverless import get_arguments, save_result, distribute_task, get | ||
from qiskit_ibm_runtime import QiskitRuntimeService | ||
from timeit import default_timer as timer | ||
|
||
@distribute_task(target={"cpu": 2}) | ||
def transpile_parallel(circuit: QuantumCircuit, config): | ||
"""Distributed transpilation for an abstract circuit into an ISA circuit for a given backend.""" | ||
transpiled_circuit = config.run(circuit) | ||
return transpiled_circuit | ||
|
||
|
||
# Get program arguments | ||
arguments = get_arguments() | ||
circuits = arguments.get("circuits") | ||
backend_name = arguments.get("backend_name") | ||
|
||
# Get backend | ||
service = QiskitRuntimeService(channel="ibm_quantum") | ||
backend = service.get_backend(backend_name) | ||
|
||
# Define Configs | ||
optimization_levels = [1, 2, 3] | ||
pass_managers = [{'pass_manager': generate_preset_pass_manager(optimization_level=level, backend=backend), 'optimization_level': level} for level in optimization_levels] | ||
|
||
transpiler_services = [ | ||
{'service': TranspilerService( | ||
backend_name="ibm_sherbrooke", | ||
ai=False, | ||
optimization_level=3, | ||
)}, | ||
{'service': TranspilerService( | ||
backend_name="ibm_sherbrooke", | ||
ai=True, | ||
optimization_level=3, | ||
) } | ||
] | ||
configs = pass_managers + transpiler_services | ||
|
||
# Start process | ||
print("Starting timer") | ||
start = timer() | ||
|
||
# run distributed tasks as async function | ||
# we get task references as a return type | ||
sample_task_references = [] | ||
for circuit in circuits: | ||
sample_task_references.append([transpile_parallel(circuit, config) for config in configs]) | ||
|
||
|
||
# now we need to collect results from task references | ||
results = get([task for subtasks in sample_task_references for task in subtasks]) | ||
|
||
end = timer() | ||
|
||
# Record execution time | ||
execution_time_serverless = end-start | ||
print("Execution time: ", execution_time_serverless) | ||
|
||
save_result({ | ||
"transpiled_circuits": results, | ||
"execution_time" : execution_time_serverless | ||
|
||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import numpy as np | ||
from qiskit import transpile, QuantumCircuit | ||
|
||
def version_check(): | ||
import qiskit | ||
if qiskit.version.VERSION == '1.0.2': | ||
return print("You have the right version! Enjoy the challenge!") | ||
else: | ||
return print("please install right version by copy/paste and execute - !pip install 'qiskit[visualization]' == 1.0.2'") | ||
|
||
def transpile_scoring(circ, layout, backend): | ||
|
||
""" | ||
A custom cost function that includes T1 and T2 computed during idle periods | ||
Parameters: | ||
circ (QuantumCircuit): circuit of interest | ||
layouts (list of lists): List of specified layouts | ||
backend (IBMQBackend): An IBM Quantum backend instance | ||
Returns: | ||
float: Fidelity of circ | ||
""" | ||
|
||
fid = 1 | ||
|
||
touched = set() | ||
dt = backend.dt | ||
num_qubits = backend.num_qubits | ||
|
||
error=0 | ||
|
||
t1s = [backend.qubit_properties(qq).t1 for qq in range(num_qubits)] | ||
t2s = [backend.qubit_properties(qq).t2 for qq in range(num_qubits)] | ||
|
||
|
||
for item in circ._data: | ||
for gate in backend.operation_names: | ||
if item[0].name == gate: | ||
if (item[0].name == 'cz') or (item[0].name == 'ecr'): | ||
q0 = circ.find_bit(item[1][0]).index | ||
q1 = circ.find_bit(item[1][1]).index | ||
fid *= 1 - backend.target[item[0].name][(q0, q1)].error | ||
touched.add(q0) | ||
touched.add(q1) | ||
elif item[0].name == 'measure': | ||
q0 = circ.find_bit(item[1][0]).index | ||
fid *= 1 - backend.target[item[0].name][(q0, )].error | ||
touched.add(q0) | ||
|
||
elif item[0].name == 'delay': | ||
q0 = circ.find_bit(item[1][0]).index | ||
# Ignore delays that occur before gates | ||
# This assumes you are in ground state and errors | ||
# do not occur. | ||
if q0 in touched: | ||
time = item[0].duration * dt | ||
fid *= 1-qubit_error(time, t1s[q0], t2s[q0]) | ||
else: | ||
q0 = circ.find_bit(item[1][0]).index | ||
fid *= 1 - backend.target[item[0].name][(q0, )].error | ||
touched.add(q0) | ||
|
||
return fid | ||
|
||
|
||
def qubit_error(time, t1, t2): | ||
"""Compute the approx. idle error from T1 and T2 | ||
Parameters: | ||
time (float): Delay time in sec | ||
t1 (float): T1 time in sec | ||
t2 (float): T2 time in sec | ||
Returns: | ||
float: Idle error | ||
""" | ||
t2 = min(t1, t2) | ||
rate1 = 1/t1 | ||
rate2 = 1/t2 | ||
p_reset = 1-np.exp(-time*rate1) | ||
p_z = (1-p_reset)*(1-np.exp(-time*(rate2-rate1)))/2 | ||
return p_z + p_reset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
|
||
def plot_execution_times(execution_time_serverless, execution_time_local): | ||
""" | ||
Plots a comparison of execution times between serverless and local executions. | ||
Parameters: | ||
execution_time_serverless (int): Execution time for serverless execution. | ||
execution_time_local (int): Execution time for local execution. | ||
""" | ||
# Create labels for the x-axis | ||
labels = ['Serverless', 'Local'] | ||
|
||
# Execution times | ||
execution_times = [execution_time_serverless, execution_time_local] | ||
|
||
# Plotting | ||
plt.figure(figsize=(8, 6)) | ||
bars = plt.bar(labels, execution_times, color=['skyblue', 'orange']) | ||
|
||
# Add annotations to display the execution times on the bars | ||
for bar in bars: | ||
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() - 1, f'{bar.get_height()}', | ||
ha='center', va='bottom', color='black') | ||
|
||
# Adding labels and title | ||
plt.xlabel('Execution Type') | ||
plt.ylabel('Execution Time (seconds)') | ||
plt.title('Comparison of Execution Times: Serverless vs Local') | ||
plt.tight_layout() | ||
plt.grid(axis='y', linestyle='--', alpha=0.7) | ||
plt.show() | ||
|
||
import matplotlib.pyplot as plt | ||
|
||
def process_transpiled_circuits(configs, result): | ||
""" | ||
Processes transpiled circuits, plots the depths for each configuration chunk, and stores the best circuits. | ||
Parameters: | ||
configs (list): List of configuration dictionaries. | ||
result (dict): Dictionary containing transpiled circuits. | ||
Returns: | ||
best_circuits (list): List of best transpiled circuits. | ||
best_depths (list): List of depths of the best transpiled circuits. | ||
best_methods (list): List of methods used to obtain the best depths. | ||
""" | ||
# Helper function to create configuration names | ||
def get_config_name(config): | ||
if 'service' in config: | ||
return f"TranspilerService(ai={config['ai']}, optimization_level={config['optimization_level']})" | ||
else: | ||
return f"PassManager(optimization_level={config['optimization_level']})" | ||
|
||
# Generate the full list of configurations to match the number of transpiled circuits | ||
full_configs = configs * (len(result) // len(configs)) | ||
|
||
# Number of results to process in each chunk | ||
chunk_size = 5 | ||
|
||
# Lists to store the best circuits, depths, and methods | ||
best_circuits = [] | ||
best_depths = [] | ||
best_methods = [] | ||
|
||
# Process each chunk of results | ||
for chunk_start in range(0, len(result), chunk_size): | ||
chunk_end = chunk_start + chunk_size | ||
current_chunk = result[chunk_start:chunk_end] | ||
current_configs = full_configs[chunk_start:chunk_end] | ||
|
||
depths = [transpiled_circuit.depth() for transpiled_circuit in current_chunk] | ||
config_names = [get_config_name(config) for config in current_configs] | ||
|
||
# Find the index of the minimum depth | ||
min_depth_index = depths.index(min(depths)) | ||
|
||
# Store the best circuit, depth, and method | ||
best_circuit = current_chunk[min_depth_index] | ||
best_depth = depths[min_depth_index] | ||
best_method = config_names[min_depth_index] | ||
best_circuits.append(best_circuit) | ||
best_depths.append(best_depth) | ||
best_methods.append(best_method) | ||
|
||
# Plotting | ||
plt.figure(figsize=(12, 8)) | ||
bars = plt.bar(range(len(depths)), depths, tick_label=config_names, color='skyblue') | ||
|
||
# Highlight the bar with the minimum depth | ||
bars[min_depth_index].set_color('green') | ||
|
||
# Add annotations to highlight the minimum depth | ||
for i, bar in enumerate(bars): | ||
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() - 1, f'{bar.get_height()}', | ||
ha='center', va='bottom', color='black') | ||
|
||
plt.xlabel('Configuration') | ||
plt.ylabel('Transpiled Circuit Depth') | ||
plt.title(f'Transpiled result for circuit {chunk_start // chunk_size}') | ||
plt.xticks(rotation=45, ha='right') | ||
plt.grid(axis='y', linestyle='--', alpha=0.7) | ||
plt.tight_layout() | ||
plt.show() | ||
|
||
return best_circuits, best_depths, best_methods |
Oops, something went wrong.