Source code for uniqc.transpiler.timeline
"""Compiled circuit timeline analysis and visualization.
This module provides tools for analyzing and visualizing the temporal
execution schedule of compiled quantum programs.
"""
__all__ = ["format_result", "create_time_line_table", "plot_time_line"]
import pandas as pd
import matplotlib.pyplot as plt
import json
import os
from pathlib import Path
[docs]
def format_result(compiled_prog):
"""Format compiled program JSON into gate layers and qubit/time lists.
Args:
compiled_prog: JSON string of compiled program.
Returns:
tuple: (gate_layers, qubit_list, time_line)
"""
prog = json.loads(compiled_prog)
layer_time = {}
gate_layers = {}
layer_count = 0
qubit_list = []
time_line = []
for gate in prog:
gate_name = list(gate.keys())[0]
gate_parameter = gate[gate_name]
if gate_name == 'RPhi' and gate_parameter[2] == 90.0:
gate_name = 'RPhi90'
qubit = gate_parameter[0]
angle = gate_parameter[1]
use_time = gate_parameter[3]
qubit_list.append(qubit)
elif gate_name == 'RPhi' and gate_parameter[2] == 180.0:
gate_name = 'RPhi180'
qubit = gate_parameter[0]
angle = gate_parameter[1]
use_time = gate_parameter[3]
qubit_list.append(qubit)
elif gate_name == 'CZ':
qubit = [gate_parameter[0], gate_parameter[1]]
angle = 0
use_time = gate_parameter[2]
qubit_list.extend(qubit)
elif gate_name == 'Measure':
qubit = gate_parameter[0]
angle = 0
use_time = gate_parameter[1]
qubit_list.extend(qubit)
else:
qubit = gate_parameter[0]
angle = 0
use_time = gate_parameter[-1]
print('something wrong', gate, qubit)
qubit_list.append(qubit)
if use_time not in layer_time:
layer_time[use_time] = layer_count
layer_count += 1
layer_of_gate = layer_time[use_time]
if layer_of_gate not in gate_layers:
gate_layers[layer_of_gate] = []
gate_layers[layer_of_gate].append((gate_name, qubit, angle, use_time))
time_line.append(use_time)
return gate_layers, sorted(list(set(qubit_list))), sorted(list(set(time_line)))
[docs]
def create_time_line_table(layer_dict, qubit_list, time_line):
"""Create a pandas DataFrame timeline table.
Args:
layer_dict: Dict mapping layer index to gate info.
qubit_list: List of qubit indices.
time_line: List of time steps.
Returns:
pd.DataFrame: Timeline table with qubits as rows and time steps as columns.
"""
time_line_table = pd.DataFrame(columns=time_line, index=['qubit ' + str(i) for i in qubit_list])
for layer, gates in layer_dict.items():
for gate_name, qubit, angle, time in gates:
angle = round(angle, 3)
if isinstance(qubit, int):
qubit_name = 'qubit '+str(qubit)
time_line_table.loc[qubit_name][time] = gate_name + ' ' + str(angle)
else:
for q in qubit:
qubit_name = 'qubit '+str(q)
time_line_table.loc[qubit_name][time] = gate_name + ' ' + str(angle)
time_line_table = time_line_table.fillna('idle')
return time_line_table
[docs]
def plot_time_line(compiled_prog, figure_save_path = Path.cwd() / 'timeline_plot'):
"""Plot the quantum circuit timeline and save as PDF.
Args:
compiled_prog: JSON string of compiled program.
figure_save_path: Directory to save timeline PDF files.
"""
format_prog, qubit_list, time_line = format_result(compiled_prog)
time_line_table = create_time_line_table(format_prog, qubit_list, time_line)
depth = len(time_line)
split_table = depth // 20 + 1
width = min(20, depth)
for i in range(1, split_table + 1):
plt.figure(figsize=(width, len(qubit_list)/2))
plt.axis('off')
cmap = {'RPhi90': 'lightblue', 'RPhi180': 'orange', 'CZ': 'mistyrose', 'idle': 'white', 'Measure': 'gray'}
if i*20 < depth:
values = time_line_table.values[:, (i-1)*20:i*20]
columns = time_line_table.columns[(i-1)*20:i*20]
else:
values = time_line_table.values[:, (i-1)*20:]
columns = time_line_table.columns[(i-1)*20:]
cellColours = [[cmap[x.split(' ')[0]] for x in row] for row in values]
table = plt.table(cellText=values, colLabels=columns,
colWidths=[0.05]*len(columns),
rowLabels=time_line_table.index,
loc='center',
cellColours=cellColours)
if not os.path.exists(figure_save_path):
os.mkdir(figure_save_path)
plt.savefig(figure_save_path / f'timeline {i}.pdf')