Executing QIR programs

Contents

Executing QIR programs#

If you have a QIR string or bitcode, you can start by creating Pulla-compatible circuits representation. You can also generate a QIR string or bitcode from a qiskit circuit using IQM’s fork of qiskit_qir, available as the package iqm-qiskit-qir.

import os

from qiskit import QuantumCircuit, visualization
from qiskit.compiler import transpile
from qiskit_qir import to_qir_module

from iqm.pulla.pulla import Pulla
from iqm.pulla.utils_qiskit import sweep_job_to_qiskit
from iqm.pulla.utils_qir import qir_to_pulla, generate_qiskit_qir_qubit_mapping
from iqm.qiskit_iqm import IQMProvider
from iqm.station_control.interface.models import MoveGateFrameTrackingMode
# Create a Pulla object and a qiskit-iqm backend for accessing the quantum computer.
iqm_server_url = os.environ['PULLA_IQM_SERVER_URL']  # or set the URL directly here
os.environ["IQM_TOKEN"] = os.environ.get("IQM_TOKEN")  # or set the token directly here

p = Pulla(iqm_server_url)
provider = IQMProvider(iqm_server_url)
backend = provider.get_backend()
compiler = p.get_standard_compiler()
# Define a quantum circuit (for visualization).
qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0, 1)
qc.cx(0, 2)
qc.measure_all()
qc.draw(output='mpl')
_images/e610f434a3c8bbe9ab19c09262bd84f466437f79a042080cee16bd8d6d1930f0.png
# Transpile the circuit using Qiskit
qc_transpiled = transpile(qc, backend=backend, layout_method='sabre', optimization_level=3)

print(qc_transpiled.draw(output='text'))

#Generate the QIR
module, _ = to_qir_module(qc_transpiled, "BasicExecution")

qir = str(module)
               ┌─────────────┐                  ┌─────────────┐ ░       ┌─┐
ancilla_2 -> 2 ┤ R(π/2,3π/2) ├──────────■───────┤ R(π/2,5π/2) ├─░───────┤M├
               ├─────────────┤          │       └─────────────┘ ░ ┌─┐   └╥┘
ancilla_0 -> 0 ┤ R(π/2,3π/2) ├─■────────■───────────────────────░─┤M├────╫─
               ├─────────────┤ │ ┌─────────────┐                ░ └╥┘┌─┐ ║ 
ancilla_1 -> 1 ┤ R(π/2,3π/2) ├─■─┤ R(π/2,5π/2) ├────────────────░──╫─┤M├─╫─
               └─────────────┘   └─────────────┘                ░  ║ └╥┘ ║ 
       meas: 3/════════════════════════════════════════════════════╩══╩══╩═
                                                                   0  1  2 
# qiskit-qir has a bug, which causes qubit pointers to not be generated correctly
qubits_mapping = generate_qiskit_qir_qubit_mapping(qc_transpiled, backend)

Executing QIR#

# Pass qubit mapping to qir_to_pulla converter to correctly interpret opaque qubit pointer indices in QIR
# and convert them to physical IQM qubit names.
circuits, _ = qir_to_pulla(compiler, qir, qubits_mapping)

# Get settings from the compiler
settings = compiler.get_settings(circuits=circuits)

# Configure settings as in other notebooks
settings.stages.timebox_stage.prepend_heralding.add_heralding = False
settings.stages.circuit_resolution.resolve_circuits.scheduling_strategy = "ASAP"
settings.stages.circuit_stage.subscribe_and_probe.convert_terminal_measurements = True
settings.stages.schedule_stage.apply_move_gate_phase_corrections.move_gate_frame_tracking_mode = MoveGateFrameTrackingMode.FULL
settings.stages.circuit_stage.subscribe_and_probe.probe_all = False

shots = 5000
settings.controllers.options.playlist_repeats = shots

# Compile and submit
job_definition, context = compiler.compile(circuits=circuits, settings=settings)
job = p.submit_playlist(job_definition, context=context)
job.wait_for_completion()

# Retrieve results using qiskit-iqm integration
qiskit_result = sweep_job_to_qiskit(job, shots=shots)
print(f"Qiskit result counts: {qiskit_result.get_counts()}")
visualization.plot_histogram(qiskit_result.get_counts())
[03-03 15:20:20;I] Required number of qubits: 20
[03-03 15:20:20;I] Required number of results: 3
[03-03 15:20:20;I] QIR version: 1.0
/home/zeus/code/continuous-delivery/iqm-qccsw/pulla/src/iqm/pulla/utils_qir.py:193: UserWarning: custom may not be a supported QIR profile
  warnings.warn(f"{_qir_profiles} may not be a supported QIR profile")
[03-03 15:20:22;I] Waiting for job 019cb412-4526-7e13-8bab-458fddf2b8fa to finish...
Qiskit result counts: {'0 0 0': 973, '1 1 1': 27}
_images/5aad26b28f77799aaec151e36241a79ac333ea5c77caf99a2acda665a929d32f.png