Compiling and Submitting Circuits onto Sqale via Cirq

Open in Colab Launch Binder

Import Requirements

This tutorial will showcase how to compile and submit a circuit onto Infleqtion’s hardware, Sqale, using the cirq-superstaq client.

[1]:
# Required imports
try:
    import cirq
    import cirq_superstaq as css
except ImportError:
    print("Installing cirq-superstaq...")
    %pip install --quiet 'cirq-superstaq[examples]'
    print("Installed cirq-superstaq.")
    print("You may need to restart the kernel to import newly installed packages.")
    import cirq
    import cirq_superstaq as css

# Optional imports
import os  # Used if setting a token as an environment variable

To interface Superstaq via Cirq, we must first instantiate a service provider in cirq-superstaq with Service(). We then supply a Superstaq API key (which you can get from https://superstaq.infleqtion.com) by either providing the API key as an argument of Service, i.e., css.Service(api_key="token"), or by setting it as an environment variable. (see more details here).

[2]:
service = css.Service()

Create a Circuit

First, we will create an example Cirq circuit that we can then compile and submit to the Sqale QPU

[3]:
qubits = cirq.LineQubit.range(2)
circuit1 = cirq.Circuit(cirq.H(qubits[0]), cirq.CNOT(qubits[0], qubits[1]), cirq.measure(*qubits))
circuit1
[3]:
0: ───H───@───M───
          │   │
1: ───────X───M───

Single Circuit Compilation

We will now compile the above circuit onto Sqale’s native gateset and visualize the differences by drawing the compiled circuit

[4]:
compiler_output = service.cq_compile(circuit1)
[5]:
compiler_output.circuit
[5]:
0: ───RGate(0.5π, -0.5π)───@───RGate(-0.25π, -0.5π)───────RGate(0.25π, -0.5π)───M───
      │                    │   │                          │                     │
1: ───#2───────────────────@───#2─────────────────────Z───#2────────────────────M───
      │                        │                          │
2: ───#3───────────────────────#3─────────────────────────#3────────────────────────
      │                        │                          │
3: ───#4───────────────────────#4─────────────────────────#4────────────────────────
      │                        │                          │
4: ───#5───────────────────────#5─────────────────────────#5────────────────────────
      │                        │                          │
5: ───#6───────────────────────#6─────────────────────────#6────────────────────────

If you would like to compile (or submit) on a different number of qubits, this can be done via the grid_shape option. This simply sets the shape of the rectangular qubit grid. However, specifying a grid that is incompatible with Sqale’s current capabilities will result in an error when submitting. Anything equal to or smaller than than (6,4) is compatible with Sqale’s current capabilities.

[6]:
example_circuit = cirq.Circuit(cirq.H.on_each(*qubits))
new_compiler_output = service.cq_compile(example_circuit, grid_shape=(4, 1))
new_compiler_output.circuit
[6]:
(0, 0): ───RGate(0.5π, -0.5π)───Z───
           │
(1, 0): ───#2───────────────────Z───
           │
(2, 0): ───#3───────────────────────
           │
(3, 0): ───#4───────────────────────

Multiple circuit compilation

If you would like to compile a batch of circuits in one-go, cirq-superstaq accepts a list of circuits as well. To illustrate this, let us first create a different example circuit, and compile both circuits we have created so far at the same time.

[7]:
circuit2 = cirq.Circuit(cirq.H(qubits[0]), cirq.measure(qubits[0]))
circuit2
[7]:
0: ───H───M───
[8]:
compiler_output = service.cq_compile([circuit1, circuit2])
[9]:
compiler_output.circuits[0]
[9]:
0: ───RGate(0.5π, -0.5π)───@───RGate(-0.25π, -0.5π)───────RGate(0.25π, -0.5π)───M───
      │                    │   │                          │                     │
1: ───#2───────────────────@───#2─────────────────────Z───#2────────────────────M───
      │                        │                          │
2: ───#3───────────────────────#3─────────────────────────#3────────────────────────
      │                        │                          │
3: ───#4───────────────────────#4─────────────────────────#4────────────────────────
      │                        │                          │
4: ───#5───────────────────────#5─────────────────────────#5────────────────────────
      │                        │                          │
5: ───#6───────────────────────#6─────────────────────────#6────────────────────────
[10]:
compiler_output.circuits[1]
[10]:
0: ───RGate(0.5π, -0.5π)───M───
      │
1: ───#2───────────────────────
      │
2: ───#3───────────────────────
      │
3: ───#4───────────────────────
      │
4: ───#5───────────────────────
      │
5: ───#6───────────────────────

Circuit Submission

All the functionalities we have seen so far can be applied to submit single- or multi-circuit jobs. For example, the code below will submit both the circuits from earlier to the noiseless Sqale simulator. If you would like to run on the Sqale QPU, change the target argument in create_job() from cq_sqale_simulator to cq_sqale_qpu. It is recommended to first submit to the simulator for testing to ensure your code runs before submitting to the Sqale QPU.

[11]:
job_css = service.create_job([circuit1, circuit2], repetitions=100, target="cq_sqale_simulator")
result_job_1 = job_css.counts(index=0)
result_job_2 = job_css.counts(index=1)

print(f"Counts from cirq-superstaq submission for 1st circuit: {result_job_1}")
print(f"Counts from cirq-superstaq submission for 2nd circuit: {result_job_2}")
Counts from cirq-superstaq submission for 1st circuit: {'00': 50, '11': 50}
Counts from cirq-superstaq submission for 2nd circuit: {'0': 44, '1': 56}

If you would like to submit circuits to a noisy simulator, to see the effects of noise on your simulated measurements without submitting to an actual device, you can additionally pass the argument method=noise-sim in create_job(). Here’s an example code snippet for a single-circuit simulation:

[12]:
job_css = service.create_job(
    circuit1, repetitions=100, target="cq_sqale_simulator", method="noise-sim"
)
result_css = job_css.counts(0)
print(f"Counts from noisy cirq-superstaq submission: {result_css}")
Counts from noisy cirq-superstaq submission: {'00': 47, '11': 46, '10': 6, '01': 1}