Cirq Integration

This notebook shows a simple example of how to use pyGSTi with Cirq. It has three sections:

  1. Sets up pyGSTi.
  2. Shows how pyGSTi circuits can be converted to Cirq circuits.
  3. Shows how the Cirq circuits can be run and the results loaded back into pyGSTi for analysis.
In [1]:
import cirq
import pygsti
from pygsti.modelpacks import smq1Q_XYI
import numpy as np
import tqdm

1. Generate the GST circuits

Make target gate set $\{\sqrt{X},\sqrt{Y},I\}$

In [2]:
target_model = smq1Q_XYI.target_model()

Preparation and measurement fiducials, germs

In [3]:
preps = smq1Q_XYI.prep_fiducials()
effects = smq1Q_XYI.meas_fiducials()
germs = smq1Q_XYI.germs()

Construct pyGSTi circuits

In [4]:
max_lengths = list(np.logspace(0, 10, 11, base=2, dtype=int))
In [5]:
print(max_lengths)
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
In [6]:
pygsti_circuits = pygsti.construction.create_lsgst_circuits(target_model, preps, effects, germs, max_lengths)
In [7]:
len(pygsti_circuits)
Out[7]:
1624

2. Convert to runable cirq.Circuit's

Setup

Now, we need to map the qubit names from pyGSTi (0, 1, etc.) into cirq qubits. There's nothing special about cirq.GridQubit(8, 3); it's just an example.

In [8]:
q0 = cirq.GridQubit(8, 3)
qubit_label_dict = {0: q0}

Testing examples

Do an example conversion.

In [9]:
pygsti_circuit = pygsti_circuits[111]
print('pyGSTi:')
print(pygsti_circuit)
print('Cirq:')
print(pygsti_circuit.convert_to_cirq(qubit_label_dict))
pyGSTi:
Qubit 0 ---|Gxpi2|-|Gxpi2|-| |-| |-|Gxpi2|---

Cirq:
(8, 3): ───X^0.5───X^0.5───────────X^0.5───

Do another example conversion.

In [10]:
pygsti_circuit = pygsti_circuits[90]
print('pyGSTi:')
print(pygsti_circuit)
print('Cirq:')
print(pygsti_circuit.convert_to_cirq(qubit_label_dict))
pyGSTi:
Qubit 0 ---|Gypi2|-|Gypi2|-|Gypi2|-|Gypi2|-|Gxpi2|-|Gxpi2|-|Gxpi2|---

Cirq:
(8, 3): ───Y^0.5───Y^0.5───Y^0.5───Y^0.5───X^0.5───X^0.5───X^0.5───

Now, lets try the same thing but specifing a wait duration for the idle operation.

In [11]:
wait_duration = cirq.Duration(nanos=100)
In [12]:
pygsti_circuit = pygsti_circuits[111]
print('pyGSTi:')
print(pygsti_circuit)
print('Cirq:')
print(pygsti_circuit.convert_to_cirq(qubit_label_dict, wait_duration))
pyGSTi:
Qubit 0 ---|Gxpi2|-|Gxpi2|-| |-| |-|Gxpi2|---

Cirq:
(8, 3): ───X^0.5───X^0.5───WaitGate(100 ns)───WaitGate(100 ns)───X^0.5───
In [13]:
pygsti_circuit = pygsti_circuits[90]
print('pyGSTi:')
print(pygsti_circuit)
print('Cirq:')
print(pygsti_circuit.convert_to_cirq(qubit_label_dict, wait_duration))
pyGSTi:
Qubit 0 ---|Gypi2|-|Gypi2|-|Gypi2|-|Gypi2|-|Gxpi2|-|Gxpi2|-|Gxpi2|---

Cirq:
(8, 3): ───Y^0.5───Y^0.5───Y^0.5───Y^0.5───X^0.5───X^0.5───X^0.5───

The real thing

Now, convert all the circuits.

In [14]:
cirq_circuits = [c.convert_to_cirq(qubit_label_dict, wait_duration) for c in tqdm.tqdm(pygsti_circuits)]
100%|██████████| 1624/1624 [00:08<00:00, 189.73it/s]

Note that we're missing the measurments, the idle operations don't have a time associated with them, and the first circuit is empty (it's should just be an idle). Otherwise, the results look good, and those things should be easy to fix.

3. Run the circuits

Add measurements to the circuits.

In [15]:
for circuit in cirq_circuits:
    circuit.append(cirq.measure(q0, key='result'))

Simulate the circuits (or run them on a real quantum computer!)

In [16]:
simulator = cirq.Simulator()
results = [simulator.run(circuit, repetitions=1000) for circuit in tqdm.tqdm(cirq_circuits)]
100%|██████████| 1624/1624 [00:39<00:00, 41.60it/s]

Load everything the results into a pyGSTi dataset.

In [17]:
dataset = pygsti.objects.dataset.DataSet()
for pygsti_circuit, trial_result in zip(pygsti_circuits, results):
    dataset.add_cirq_trial_result(pygsti_circuit, trial_result, key='result')

Perform GST.

In [18]:
gst_results = pygsti.run_stdpractice_gst(dataset, target_model, preps, effects, germs, max_lengths, modes="TP,Target", verbosity=1)
--- Circuit Creation ---
-- Std Practice:  [##################################################] 100.0%  (Target) --

See what if finds.

In [19]:
mdl_estimate = gst_results.estimates['TP'].models['stdgaugeopt']
print("2DeltaLogL(estimate, data): ", pygsti.tools.two_delta_logl(mdl_estimate, dataset))
print("2DeltaLogL(ideal, data): ", pygsti.tools.two_delta_logl(target_model, dataset))
2DeltaLogL(estimate, data):  1102.0101377779301
2DeltaLogL(ideal, data):  1118.865389448009
In [ ]: