Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate QIR compatible with azure-quantum #152

Open
cqc-alec opened this issue Jul 8, 2024 · 8 comments
Open

Generate QIR compatible with azure-quantum #152

cqc-alec opened this issue Jul 8, 2024 · 8 comments
Assignees

Comments

@cqc-alec
Copy link
Collaborator

cqc-alec commented Jul 8, 2024

Attempts to submit QIR generated by pytket_to_qir() via azure-quantum currently fail with

RuntimeError: Cannot retrieve results as job execution failed(status: Failed.error: {'additional_properties': {}, 'code': 'QIRPreProcessingFailed', 'message': 'No match found for output recording set'})

The same error occurs when submitting to ionq.simulator or quantinuum.sim.h1-1sc.

from azure.quantum import Workspace
workspace = Workspace(
    resource_id="...",
    location="...",
)
target = workspace.get_targets(name="ionq.simulator")
job = target.submit(
    input_data=open("test-qir.ll").read(),
    input_data_format="qir.v1",
    output_data_format="microsoft.quantum-results.v1",
    name="test-submission",
    input_params={"entryPoint": "main", "arguments": [], "count": 100},
)
job.wait_until_completed()
result = job.get_results()

test-qir.ll:

; ModuleID = 'Generated from input pytket circuit'
source_filename = "Generated from input pytket circuit"

%Qubit = type opaque
%Result = type opaque

@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)
  call void @__quantum__rt__tuple_start_record_output()
  %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))
  call void @__quantum__rt__tuple_end_record_output()
  ret void
}

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 @__quantum__qis__read_result__body(%Result*)
declare i1* @create_creg(i64)
declare i64 @get_int_from_creg(i1*)
declare void @mz_to_creg_bit(%Qubit*, i1*, i64)
declare void @__quantum__rt__int_record_output(i64, i8*)
declare void @__quantum__rt__tuple_start_record_output()
declare void @__quantum__rt__tuple_end_record_output()
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}
@cqc-melf
Copy link
Collaborator

cqc-melf commented Jul 8, 2024

I think this is expected, because of the use of create_creg and friends, and the use of __quantum__rt__tuple_start_record_output .

Should we split this up into several subtasks?

@cqc-alec
Copy link
Collaborator Author

cqc-alec commented Jul 8, 2024

I think this is expected, because of the use of create_creg and friends, and the use of __quantum__rt__tuple_start_record_output .

That was my guess too.

But I note that submitting the following QIR to quantinuum.sim.h1-1e via azure-quantum does work:

; ModuleID = 'qiskit-qir.bc'
source_filename = "circuit-171"

%Qubit = type opaque
%Result = type opaque

define void @circuit-171() #0 {
entry:
  call void @__quantum__rt__initialize(i8* null)
  call void @__quantum__qis__h__body(%Qubit* null)
  call void @__quantum__qis__cnot__body(%Qubit* null, %Qubit* inttoptr (i64 1 to %Qubit*))
  call void @__quantum__qis__mz__body(%Qubit* null, %Result* null)
  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
  call void @__quantum__rt__array_record_output(i64 2, i8* null)
  call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
  call void @__quantum__rt__result_record_output(%Result* null, i8* null)
  ret void
}

declare void @__quantum__rt__initialize(i8*)
declare void @__quantum__qis__h__body(%Qubit*)
declare void @__quantum__qis__cnot__body(%Qubit*, %Qubit*)
declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
declare void @__quantum__rt__array_record_output(i64, i8*)
declare void @__quantum__rt__result_record_output(%Result*, i8*)

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

!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}

So I wonder if those functions are actually necessary, at least for this simple case...

@cqc-alec
Copy link
Collaborator Author

cqc-alec commented Jul 8, 2024

Apparently there is some magic QIR conversion going on behind the scenes.

@cqc-melf
Copy link
Collaborator

cqc-melf commented Jul 8, 2024

Not sure what you wanted to show with the example? Yes it is not using the functions that are problematic?

I think we should generally try to upgrade everything to not use them? Or what do you mean?

@cqc-melf
Copy link
Collaborator

cqc-melf commented Jul 8, 2024

Apparently there is some magic QIR conversion going on behind the scenes.

I think the magic is that it updates the results handling which is required in a non profile way by the device, but sending that off to azure will be rejected for now? At least it sounded like that?

@cqc-alec
Copy link
Collaborator Author

cqc-alec commented Jul 8, 2024

Not sure what you wanted to show with the example? Yes it is not using the functions that are problematic?

I was surprised that it worked, because I thought quantinuum needed to use those other (non-standard) methods.

I think we should generally try to upgrade everything to not use them? Or what do you mean?

Yes agreed that should be the goal.

@cqc-melf
Copy link
Collaborator

I think it would be helpful to add more subtasks for this. One for adding the phi node generation and one for updating the result recording. Should I do that @cqc-alec ?

@cqc-alec
Copy link
Collaborator Author

I think it would be helpful to add more subtasks for this. One for adding the phi node generation and one for updating the result recording. Should I do that @cqc-alec ?

It's not currently clear to me exactly what the subtasks are, but yes if you can break it down that would be great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants