Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds edesign padding and tests. #290

Merged
merged 2 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion pygsti/tools/edesigntools.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

import numpy as _np


def calculate_edesign_estimated_runtime(edesign, gate_time_dict=None, gate_time_1Q=None,
gate_time_2Q=None, measure_reset_time=0.0,
interbatch_latency=0.0, total_shots_per_circuit=1000,
Expand Down Expand Up @@ -331,3 +330,35 @@ def calculate_fisher_information_matrices_by_L(model, circuits, num_shots=1, ter
prev_L = L

return fisher_information_by_L

def pad_edesign_with_idle_lines(edesign, line_labels):
"""Utility to explicitly pad out ExperimentDesigns with idle lines.

Parameters
----------
edesign: ExperimentDesign
The edesign to be padded.

line_labels: tuple of int or str
Full line labels for the padded edesign.

Returns
-------
ExperimentDesign
An edesign where all circuits have been padded out with missing idle lines
"""
from pygsti.protocols import CombinedExperimentDesign as _CombinedDesign
from pygsti.protocols import SimultaneousExperimentDesign as _SimulDesign

if set(edesign.qubit_labels) == set(line_labels):
return edesign

if isinstance(edesign, _CombinedDesign):
new_designs = {}
for subkey, subdesign in edesign.items():
new_designs[subkey] = pad_edesign_with_idle_lines(subdesign, line_labels)

return _CombinedDesign(new_designs, qubit_labels=line_labels)

# SimultaneousDesign with single design + full qubit labels tensors out the circuits with idle lines
return _SimulDesign([edesign], qubit_labels=line_labels)
98 changes: 97 additions & 1 deletion test/unit/tools/test_edesigntools.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from pygsti.baseobjs import Label
from pygsti.modelpacks import smq2Q_XYICNOT, smq1Q_XYI
from pygsti.tools import edesigntools as et
from pygsti.protocols import CircuitListsDesign, SimultaneousExperimentDesign, CombinedExperimentDesign
from pygsti.circuits import Circuit as C

from ..util import BaseCase

Expand Down Expand Up @@ -144,4 +146,98 @@ def test_fisher_information(self):
self.assertArraysAlmostEqual(v, fim_by_L[k])
self.assertLess(10*fim_by_L2_time, fim1_time) # Cached version should be very fast compared to uncached



def test_generic_design_padding(self):
# Create a series of designs with some overlap when they will be padded out
design_124 = CircuitListsDesign([[
C.cast('Gx:Q1Gy:Q1@(Q1,Q2,Q4)'),
C.cast('Gx:Q2Gy:Q2@(Q1,Q2,Q4)'), # Will be repeat with design_2
C.cast('Gx:Q4Gy:Q4@(Q1,Q2,Q4)'), # Will be repeat with design_14 (but only on Q4)
C.cast('Gx:Q1Gy:Q4@(Q1,Q2,Q4)'), # Will be repeat with design_14 (on both Q1 and Q4)
C.cast('[Gx:Q1Gy:Q2][Gy:Q1Gx:Q2]@(Q1,Q2,Q4)') # Will be repeat with sim_design_12
]], qubit_labels=('Q1', 'Q2', 'Q4'))

design_2 = CircuitListsDesign([[
C.cast('Gx:Q2Gy:Q2@(Q2)'), # Repeat from design_124 after padding
C.cast('Gy:Q2@(Q2)')
]], qubit_labels=('Q2',))

design_14 = CircuitListsDesign([[
C.cast('Gx:Q4Gy:Q4@(Q1,Q4)'), # Repeat from design_124 after padding
C.cast('Gx:Q1Gy:Q4@(Q1,Q4)'), # Repeat from design_124 after padding
C.cast('Gx:Q1@(Q1,Q4)')
]], qubit_labels=('Q1', 'Q4'))

sim_design_1 = CircuitListsDesign([[
C.cast('Gx:Q1Gy:Q1@(Q1)'), # Q1 part of repeat from design_124 after padding
C.cast('Gx:Q1Gx:Q1')
]], qubit_labels=('Q1',))

sim_design_2 = CircuitListsDesign([[
C.cast('Gy:Q2Gx:Q2@(Q2)'), # Q2 part of repeat from design_124 after padding
C.cast('Gx:Q2Gx:Q2')
]], qubit_labels=('Q2',))

sim_design_12 = SimultaneousExperimentDesign([sim_design_1, sim_design_2], qubit_labels=('Q1', 'Q2'))

# The expected deduplicated experiment
expected_design_012345 = CircuitListsDesign([[
C.cast('Gx:Q1Gy:Q1@(Q0,Q1,Q2,Q3,Q4,Q5)'), # design_124
C.cast('Gx:Q2Gy:Q2@(Q0,Q1,Q2,Q3,Q4,Q5)'), # design_124 and design_2
C.cast('Gx:Q4Gy:Q4@(Q0,Q1,Q2,Q3,Q4,Q5)'), # design_124 and design_14
C.cast('Gx:Q1Gy:Q4@(Q0,Q1,Q2,Q3,Q4,Q5)'), # design_124 and design_14
C.cast('Gy:Q2@(Q0,Q1,Q2,Q3,Q4,Q5)'), # design_2
C.cast('Gx:Q1@(Q0,Q1,Q2,Q3,Q4,Q5)'), # design_14
C.cast('[Gx:Q1Gy:Q2][Gy:Q1Gx:Q2]@(Q0,Q1,Q2,Q3,Q4,Q5)'), # design_124 and sim_design_12
C.cast('[Gx:Q1Gx:Q2][Gx:Q1Gx:Q2]@(Q0,Q1,Q2,Q3,Q4,Q5)') # sim_design_12
]], qubit_labels=('Q0', 'Q1', 'Q2', 'Q3', 'Q4', 'Q5'))


# Create nested combined designs and test padding
nested_design = CombinedExperimentDesign({
'2': design_2,
'14': design_14
})

full_design = CombinedExperimentDesign({
'124': design_124,
'2+14': nested_design,
'sim_12': sim_design_12
})

# Padding should dedup "repeats" and add qubits before/during/after the current lines
padded_design = et.pad_edesign_with_idle_lines(full_design, ('Q0', 'Q1', 'Q2', 'Q3', 'Q4', 'Q5'))

self.assertTrue(set(padded_design.all_circuits_needing_data) == set(expected_design_012345.all_circuits_needing_data),
"Padded experiment circuits did not match expected experiment circuits")

def test_gst_design_padding(self):
# Get GST designs
gst_1 = smq1Q_XYI.create_gst_experiment_design(8, ('Q1',))
gst_2 = smq1Q_XYI.create_gst_experiment_design(8, ('Q2',))
gst_12 = smq2Q_XYICNOT.create_gst_experiment_design(8, ('Q1', 'Q2'))

# Get nested combined design
nested_12 = CombinedExperimentDesign({
'1': gst_1,
'2': gst_2,
})

full_gst = CombinedExperimentDesign({
'1+2': nested_12,
'12': gst_12
})

# Pad and test
padded_gst_design = et.pad_edesign_with_idle_lines(full_gst, ('Q1', 'Q2'))

padded_circs_1 = [circ.insert_idling_lines(None, ('Q2',)) for circ in gst_1.all_circuits_needing_data]
self.assertTrue(set(padded_gst_design.all_circuits_needing_data).issuperset(set(padded_circs_1)),
"GST on qubit 1 was not a subset of padded experiment design")

padded_circs_2 = [circ.insert_idling_lines('Q2', ('Q1',)) for circ in gst_2.all_circuits_needing_data]
self.assertTrue(set(padded_gst_design.all_circuits_needing_data).issuperset(set(padded_circs_2)),
"GST on qubit 2 was not a subset of the padded experiment design")

self.assertTrue(set(padded_gst_design.all_circuits_needing_data).issuperset(set(gst_12.all_circuits_needing_data)),
"2Q GST was not a subset of the padded experiment design")