QIR Submission¶

Quantinuum Nexus devices support the submission of Quantum Intermediate Representation (QIR).

import qnexus as qnx

qnx.login()

Get/create a project and set it as the active project.

import datetime

project = qnx.projects.get_or_create(name="QIR-Demonstration")
qnx.context.set_active_project(project)

qir_name = "QIR Bell circuit"
jobname_suffix = datetime.datetime.now().strftime("%Y_%m_%d-%H-%M-%S")

In this example, we have some LLVM QIR for a Bell circuit.

bell_circuit_qir = """
; ModuleID = 'QIR Bell circuit'
source_filename = "QIR Bell circuit"

%Qubit = type opaque
%Result = type opaque

; Note the double slash here due to the enclosing triple quote
@0 = internal constant [2 x i8] c"c\\00"

define void @main() #0 {
entry:
  %0 = call i1* @create_creg(i64 2)
  call void @__quantum__qis__h__body(%Qubit* null)
  call void @__quantum__qis__cnot__body(%Qubit* null, %Qubit* inttoptr (i64 1 to %Qubit*))
  call void @mz_to_creg_bit(%Qubit* null, i1* %0, i64 0)
  call void @mz_to_creg_bit(%Qubit* inttoptr (i64 1 to %Qubit*), i1* %0, i64 1)
  %1 = call i64 @get_int_from_creg(i1* %0)
  call void @__quantum__rt__int_record_output(i64 %1, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @0, i32 0, i32 0))
  ret void
}

declare i1 @__quantum__qis__read_result__body(%Result*)

declare void @__quantum__rt__int_record_output(i64, i8*)

declare i1 @get_creg_bit(i1*, i64)

declare void @set_creg_bit(i1*, i64, i1)

declare void @set_creg_to_int(i1*, i64)

declare i1* @create_creg(i64)

declare i64 @get_int_from_creg(i1*)

declare void @mz_to_creg_bit(%Qubit*, i1*, i64)

declare void @__quantum__qis__h__body(%Qubit*)

declare void @__quantum__qis__cnot__body(%Qubit*, %Qubit*)

attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="custom" "required_num_qubits"="2" "required_num_results"="2" }

!llvm.module.flags = !{!0, !1, !2, !3}

!0 = !{i32 1, !"qir_major_version", i32 1}
!1 = !{i32 7, !"qir_minor_version", i32 0}
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
!3 = !{i32 1, !"dynamic_result_management", i1 false}
"""

Compile the QIR to bitcode.

import pyqir

qir = pyqir.Module.from_ir(pyqir.Context(), bell_circuit_qir).bitcode

Upload the bitcode to Nexus.

qir_program_ref = qnx.qir.upload(qir=qir, name=qir_name, project=project)

Run the bitcode on the syntax checker.

# Run on the H1-1 Syntax checker
device_name = "H1-1SC"

qnx.context.set_active_project(project)
config = qnx.QuantinuumConfig(device_name=device_name)

job_name = f"execution-job-qir-{qir_name}-{device_name}-{jobname_suffix}"
ref_execute_job = qnx.start_execute_job(
    programs=[qir_program_ref],
    n_shots=[10],
    backend_config=config,
    name=job_name,
)

qnx.jobs.wait_for(ref_execute_job)

Run the bitcode on the H1-1E emulator.

# Run on H1-1E
device_name = "H1-1E"

qnx.context.set_active_project(project)
config = qnx.QuantinuumConfig(device_name=device_name)

job_name = f"execution-job-qir-{qir_name}-{device_name}-{jobname_suffix}"
ref_execute_job = qnx.start_execute_job(
    programs=[qir_program_ref],
    n_shots=[10],
    backend_config=config,
    name=job_name,
)

qnx.jobs.wait_for(ref_execute_job)
qir_result = qnx.jobs.results(ref_execute_job)[0].download_result()
qir_result.get_counts()