Learning Home Catalog Composer
Learning
Home Catalog Composer Return to tutorial
Learning
Submit transpiled circuits
BackgroundRequirementsSetupStep 1: Map classical inputs to a quantum problemStep 2: Optimize problem for quantum execution.Step 3: Execute using Qiskit Primitives.Step 4: Post-process, return result in classical format.

Submit transpiled circuits

Category

How-to

Topics

Transpilation
Download notebook Download notebook

Background

To get the best performance from your circuits, the Qiskit Runtime service will pass all circuits through Qiskit's transpiler before running them. While this is usually a good thing, we might sometimes want to disable this by passing the argument skip_transpilation=True to the primitive we're using.

For example, we may know better than the transpiler in some cases, or want to target a specific subset of qubits on a specific device. In this tutorial, we'll disable automatic transpilation to test the performance of different transpiler settings. This example will take you through the full process of creating, transpiling, and submitting circuits.

Requirements

Before starting this tutorial, ensure that you have the following installed:

  • Qiskit SDK 1.0 or later, with visualization support (pip install 'qiskit[visualization]')
  • Qiskit Runtime (pip install qiskit-ibm-runtime) 0.22 or later

Setup

Authenticate to run code cells
Reset Copy to clipboard

No output produced

Authenticate to run code cells
Reset Copy to clipboard

Output:

'ibmq_mumbai'

Step 1: Map classical inputs to a quantum problem

In the following code cell, we create a small circuit that our transpiler will try to optimize. In this example, we create a circuit that carries out Grover's algorithm, with an oracle that marks the state 111. We then simulate the ideal distribution (what we'd expect to measure if we ran this on a perfect quantum computer, an infinite number of times) for comparison later.

Authenticate to run code cells
Reset Copy to clipboard

Output:

Authenticate to run code cells
Reset Copy to clipboard

Output:

Step 2: Optimize problem for quantum execution.

Next, we transpile the circuits for our backend. We're going to compare the performance of the transpiler with optimization_level set to 0 (lowest) against 3 (highest). The lowest optimization level just does the bare minimum needed to get the circuit running on the device; it maps the circuit qubits to the device qubits, and adds swaps gates to allow all 2-qubit operations. The highest optimization level is much smarter and uses lots of tricks to reduce the overall gate count. Since multi-qubit gates have high error rates, and qubits decohere over time, the shorter circuits should give better results.

In the following cell, we transpile qc for both values of optimization_level, print the number of CNOT gates, and add the transpiled circuits to a list. Some of the transpiler's algorithms are randomized, so we set a seed for reproducibility.

Authenticate to run code cells
Reset Copy to clipboard

Output:

CNOTs (optimization_level=0):  27
CNOTs (optimization_level=3):  14

Since CNOTs usually have a high error rate, the circuit transpiled with optimization_level=3 should perform much better.

Another way we can improve performance is through dynamic decoupling, where we apply a sequence of gates to idling qubits. This cancels out some unwanted interactions with the environment. In the following cell, we add dynamic decoupling to the circuit transpiled with optimization_level=3, and add it to our list.

Authenticate to run code cells
Reset Copy to clipboard

No output produced

Authenticate to run code cells
Reset Copy to clipboard

Output:

Step 3: Execute using Qiskit Primitives.

At this point, we have a list of circuits transpiled for our system. In the following cell, we create an instance of the sampler primitive, and start a batched job using the context manager (with ...:), which automatically opens and closes the Batch for us. This is where we pass the skip_transpilation=True argument.

Within the context manager, we sample the circuits and store the results to result.

Authenticate to run code cells
Reset Copy to clipboard

No output produced

Step 4: Post-process, return result in classical format.

Finally, we can plot the results from the device runs against the ideal distribution. You can see the results with optimization_level=3 are closer to the ideal distribution due to the lower gate count, and optimization_level=3 + dd is even closer due to the dynamic decoupling we applied.

Authenticate to run code cells
Reset Copy to clipboard

Output:

We can confirm this by computing the Hellinger fidelity between each set of results and the ideal distribution (higher is better, and 1 is perfect fidelity).

Authenticate to run code cells
Reset Copy to clipboard

Output:

0.873
0.983
0.981

Authenticate to run code cells
Reset Copy to clipboard

Output:

'0.19.1'
Authenticate to run code cells
Reset Copy to clipboard

Output:

'1.0.0rc1'