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

Support for Quantinuum within QED-C benchmarking suite #282

Open
vprusso opened this issue Jun 7, 2023 · 7 comments
Open

Support for Quantinuum within QED-C benchmarking suite #282

vprusso opened this issue Jun 7, 2023 · 7 comments

Comments

@vprusso
Copy link
Contributor

vprusso commented Jun 7, 2023

As of a recent fix based on this issue on the qiskit-quantinuum-provider project, one can now invoke a backend instance of a Quantinuum device via the Qiskit provider interface (as is done for the other supported backends within QED-C).

As a proof of concept (assuming one has access to a Quantinuum device), doing this following:

    import os
    from qiskit_quantinuum import Quantinuum
    from qiskit import execute
    Quantinuum.save_account(os.environ.get("QUANTINUUM_USERNAME"))

    backends = Quantinuum.backends()
    backend = Quantinuum.get_backend("H1-2E")

    qc = QuantumCircuit(2, 2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure([0,1], [0,1])
    result = execute(qc, backend).result()
    print(result.get_counts())

yields the following output:

Your id token is expired. Refreshing...
{'11': 502, '0': 512, '1': 4, '10': 6}

indicating a successful run on the device.

Now, presumably, one can run one of the QED-C benchmarking algorithms via the newly obtained provider functionality. Taking the quantum-fourier-transform Qiskit benchmark as an example, adding the following snippet to the bottom of this file:

if __name__ == "__main__":
    import os
    from qiskit_quantinuum import Quantinuum
    Quantinuum.save_account(os.environ.get("QUANTINUUM_USERNAME"))

    backends = Quantinuum.backends()
    backend = Quantinuum.get_backend("H1-2E")
    run(provider_backend=backend)

supplies the QFT benchmark with the custom Quantinuum Qiskit provider. However, running:

python qft_benchmark.py

with this addition appears to fail:

Quantum Fourier Transform Benchmark Program - Qiskit
... using circuit method 1
... execution starting at Jun 07, 2023 17:22:56 UTC
************
Executing [3] circuits with num_qubits = 2
... number of gates, depth = 11, 8
Traceback (most recent call last):
  File "/Users/vincent.russo/Projects/research/unitary_fund/metriq-api/benchmark/benchmark/QC-App-Oriented-Benchmarks/quantum-fourier-transform/qiskit/qft_benchmark.py", line 410, in <module>
    print(run(provider_backend=backend, min_qubits=min_qubits, max_qubits=max_qubits, num_shots=num_shots))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/vincent.russo/Projects/research/unitary_fund/metriq-api/benchmark/benchmark/QC-App-Oriented-Benchmarks/quantum-fourier-transform/qiskit/qft_benchmark.py", line 330, in run
    ex.throttle_execution(metrics.finalize_group)
  File "/Users/vincent.russo/Projects/research/unitary_fund/metriq-api/benchmark/benchmark/QC-App-Oriented-Benchmarks/quantum-fourier-transform/qiskit/../../_common/qiskit/execute.py", line 922, in throttle_execution
    check_jobs(completion_handler)
  File "/Users/vincent.russo/Projects/research/unitary_fund/metriq-api/benchmark/benchmark/QC-App-Oriented-Benchmarks/quantum-fourier-transform/qiskit/../../_common/qiskit/execute.py", line 1039, in check_jobs
    job_complete(job)
  File "/Users/vincent.russo/Projects/research/unitary_fund/metriq-api/benchmark/benchmark/QC-App-Oriented-Benchmarks/quantum-fourier-transform/qiskit/../../_common/qiskit/execute.py", line 741, in job_complete
    if job.status() == JobStatus.DONE:
       ^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/qiskit_quantinuum/quantinuumjob.py", line 313, in status
    self._result = self._process_results()
                   ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/qiskit_quantinuum/quantinuumjob.py", line 337, in _process_results
    status = res_resp.get('status', 'failed')
             ^^^^^^^^^^^^
AttributeError: 'JobStatus' object has no attribute 'get'

Am I making use of the provider_backend argument correctly? Based on the initial code example we know that we can successfully connect to and run a simple circuit on the Quantinuum device, so presumably this is failing because either I am using this incorrectly or because the QFT circuit is more involved and requires some type of transpilation for the Quantinuum device, or something else.

Any obvious reason as to why this is presently failing?

@rtvuser1 @WrathfulSpatula @nathanshammah @ninjab3381

@WrathfulSpatula
Copy link

WrathfulSpatula commented Jun 7, 2023

@vprusso Remember that we've seen already that the Quantinuum provider in its current form might not fully adhere to the ProviderV1 API defined in Qiskit. (I'm referencing the earlier the issue you ran into trying to pull results out by the job ID, which isn't supported.)

Actually, looking at the stack trace, this might be exactly the issue, as Quantinuum currently only supports 1 job at a time, and the provider developers opted to deviate from the usual API by cutting certain metadata and metadata query capabilities designed to support multiple jobs.

WrathfulSpatula added a commit to WrathfulSpatula/qiskit-quantinuum-provider that referenced this issue Jun 7, 2023
@WrathfulSpatula
Copy link

WrathfulSpatula commented Jun 7, 2023

@vprusso Please do me a huge favor, since you have Quantinuum API access: please check what happens if you (locally) install the branch that commit 346469e is in (from above) and run this again.

WrathfulSpatula added a commit to WrathfulSpatula/qiskit-quantinuum-provider that referenced this issue Jun 7, 2023
@rtvuser1
Copy link
Collaborator

rtvuser1 commented Jun 7, 2023

Note: You can also set the global variable

 # maximum number of active jobs
 _common.execute.max_jobs_active = 5;

to just 1 and it will only launch one job at a time.

Or, even better, you can set the following variable to True

# job mode: False = wait, True = submit multiple jobs
job_mode = False

Either way will execute only one job at a time, but the job_mode will process the result directly returned from backend.execute() instead of from querying for the job_id

@rtvuser1
Copy link
Collaborator

rtvuser1 commented Jun 7, 2023

Note: you should also pass the backend_id to the run method, as we do in the benchmark notebooks. In this case it seem like it should be "H1-2E". This is only used for identifying the run in the charts that get created and is not likely the source of your status issue

@WrathfulSpatula
Copy link

Thank you, @rtvuser1! That's excellent to know, and we likely need to do that, too.

All the same, now that I've perused the Quantinuum provider code and compared to the stack trace from @vprusso, I think we (also) nonetheless need to open a PR on the upstream provider repo for my branch, above. That variable isn't anticipated to be a JobStatus at all, but it looks like that's what they're getting back from Quantinuum, here, hence the case needs handling in general.

@vprusso
Copy link
Contributor Author

vprusso commented Jun 10, 2023

I flipped both of these global variables such that

max_jobs_active = 1
...
job_mode = True

within execute.py. Indeed, the job still fails, but now it fails serially:

Quantum Fourier Transform Benchmark Program - Qiskit
... using circuit method 1
... execution starting at Jun 10, 2023 13:34:54 UTC
************
Executing [3] circuits with num_qubits = 2
... number of gates, depth = 11, 8
... error occurred during job.status() for circuit 2 2 -- retry 1
....

I also attempted to pull down the patch from @WrathfulSpatula:

pip install https://github.com/WrathfulSpatula/qiskit-quantinuum-provider/archive/282_qed-c.zip

And ran again, but this still appears to fail with the same output as stated above. The code I'm running has been updated to reflect the "*Provider" pattern that is used in the benchmarks-qiskit.ipynb file as well, specifically:

    import os
    from qiskit_quantinuum import QuantinuumProvider
    provider = QuantinuumProvider()

    provider.save_account(os.environ.get("QUANTINUUM_USERNAME"))
    backends = provider.backends()
    backend = provider.get_backend("H1-2E")
    run(provider_backend=backend)

@WrathfulSpatula
Copy link

@vprusso I can take another look at this if I have the stack trace from the error in jobs.status().

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

3 participants