Qiskit Services through REST APIs under `docs/run` section (#1492)

Added a new menu `Qiskit Runtime through REST APIs` under the `docs/run`
section to cater to the API-only IBM Quantum partners.

**Menu structure (all using REST APIs only):**
- Initialize account and setup tokens
- Qiskit Transpiler Service
- Working with Sampler Primitive
- Working with Estimator Primitive
- Run jobs in different Execution modes

@pacomf @johannesgreiner @Bagherpoor

---------

Co-authored-by: ABBY CROSS <across@us.ibm.com>
This commit is contained in:
Syed Farhan Ahmad 2024-07-10 13:09:17 -04:00 committed by GitHub
parent e86afc7db6
commit f340811de1
8 changed files with 983 additions and 1 deletions

View File

@ -236,6 +236,10 @@
{
"title": "AI transpiler passes",
"url": "/guides/ai-transpiler-passes"
},
{
"title": "Transpile using REST API",
"url": "/guides/transpile-rest-api"
}
]
}
@ -287,6 +291,10 @@
{
"title": "Primitives examples",
"url": "/guides/primitives-examples"
},
{
"title": "Primitives with REST API",
"url": "/guides/primitives-rest-api"
}
]
},
@ -336,6 +344,10 @@
"title": "Fixed and dynamic repetition rate execution",
"url": "/guides/repetition-rate-execution"
},
{
"title": "Execution modes using REST API",
"url": "/guides/execution-modes-rest-api"
},
{
"title": "Manage jobs",
"children": [

View File

@ -29,6 +29,7 @@ expectation values of observables corresponding to physical quantities or cost f
* [Introduction to primitives](./primitives)
* [Get started with primitives](./get-started-with-primitives)
* [Primitives examples](./primitives-examples)
* [Primitives with REST API](./primitives-rest-api)
### Configure runtime options
* [Configure runtime compilation](./configure-error-suppression)
@ -42,6 +43,7 @@ expectation values of observables corresponding to physical quantities or cost f
* [Run jobs in a session](./run-jobs-session)
* [Run jobs in a batch](./run-jobs-batch)
* [Fixed and dynamic repetition rate execution](./repetition-rate-execution)
* [Execution modes using REST API](./execution-modes-rest-api)
* [Execution modes FAQs](./execution-modes-faq)
### Manage jobs

View File

@ -0,0 +1,268 @@
---
title: Execution modes using REST API
description: How to run a quantum computing job in a Qiskit Runtime session.
---
# Execution modes using REST API
You can run your Qiskit primitive workloads using REST APIs in one of three execution modes, depending on your needs: job, session, and batch. This topic explains these modes.
<Admonition type="note">
This documentation utilizes the Python `requests` module to demonstrate the Qiskit Runtime REST API. However, this workflow can be executed using any language or framework that supports working with REST APIs. Refer to the [API reference documentation](/api/runtime/tags/jobs) for details.
</Admonition>
## Job mode with REST API
In job mode, a single primitive request of the Estimator or the Sampler is made without a context manager. See how to run a quantum circuit using [Estimator](primitives-rest-api#estimator-primitive-with-rest-api) and [Sampler](primitives-rest-api#sampler-primitive-with-rest-api) for some examples.
## Session mode with REST API
A session is a Qiskit Runtime feature that lets you efficiently run multi-job iterative workloads on quantum computers. Using sessions helps avoid delays caused by queuing each job separately, which can be particularly useful for iterative tasks that require frequent communication between classical and quantum resources. More details about Sessions can be found in the [documentation](./sessions).
### Start a session
Begin with creating a session and obtaining a session ID.
```python
import json
sessionsUrl = "https://api.quantum-computing.ibm.com/runtime/sessions"
headersList = {
"Accept": "application/json",
'x-access-token':auth_id,
"Content-Type": "application/json"
}
payload = json.dumps({
"backend": backend,
"instance": "hub1/group1/project1",
})
response = requests.request("POST", sessionsUrl, data=payload, headers=headersList)
sessionId = response.json()['id']
print(response.json())
```
Output
```text
{'id': 'crw9s7cdbt40008jxesg'}
```
### Close a session
It is good practice to close a `Session` when all jobs are done. This will reduce wait time for subsequent users.
```python
closureURL="https://api.quantum-computing.ibm.com/runtime/sessions/"+sessionId+"/close"
headersList = {
"Accept": "application/json",
'x-access-token':auth_id,
}
closure_response = requests.request(
"DELETE",
closureURL,
headers=headersList)
print("Session closure response ok?:",closure_response.ok,closure_response.text)
```
Output
```text
Session closure response ok?: True
```
## Batch mode with REST API
Alternatively, you can submit a batch job by specifying the `mode` in the request payload. Batch mode can help shorten processing time if all jobs can be provided at the outset. More details about batch mode can be found in the [documentation](./run-jobs-batch).
```python
import json
sessionsUrl = "https://api.quantum-computing.ibm.com/runtime/sessions"
headersList = {
"Accept": "application/json",
'x-access-token':auth_id,
"Content-Type": "application/json"
}
payload = json.dumps({
"backend": backend,
"instance": "hub1/group1/project1",
"mode": "batch"
})
response = requests.request("POST", sessionsUrl, data=payload, headers=headersList)
sessionId = response.json()['id']
```
## Examples of jobs submitted in a session
Once a session is set up, one or more `Sampler`or `Estimator` jobs can be submitted to the same session by specifying the session ID.
<Admonition type="note">
The `<parameter values>` in a `PUB` can either be a single parameter or a list of parameters. It also supports `numpy` broadcasting.
</Admonition>
### Estimator jobs in session mode
<Tabs>
<TabItem value="1 circuit, 4 observables" label="1 circuit, 4 observables">
```python
job_input = {
'program_id': 'estimator',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"session_id": sessionId, # This specifies the previously created Session
"params": {
"pubs": [[resulting_qasm, [obs1, obs2, obs3, obs4]]], #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2, #this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options":{
"transpilation":{"optimization_level": 1},
"twirling": {"enable_gates": True,"enable_measure": True}, #c.f. documentation at https://docs.quantum.ibm.com/run/configure-error-mitigation#custom-error-settings-v2-primitives
# "dynamical_decoupling": {"enable": True, "sequence_type": "XpXm"}, #(optional)
},
}
}
```
</TabItem>
<TabItem value="1 circuit, 4 observables, 2 parameter sets" label="1 circuit, 4 observables, 2 parameter sets">
```python
job_input = {
'program_id': 'estimator',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"session_id": sessionId, # This specifies the previously created Session
"params": {
"pubs": [[resulting_qasm, [[obs1], [obs2], [obs3], [obs4]], [[vals1], [vals2]]]], #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2, #this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options":{
"transpilation":{"optimization_level": 1},
"twirling": {"enable_gates": True,"enable_measure": True}, #c.f. documentation at https://docs.quantum.ibm.com/run/configure-error-mitigation#custom-error-settings-v2-primitives
# "dynamical_decoupling": {"enable": True, "sequence_type": "XpXm"}, #(optional)
},
}
}
```
</TabItem>
<TabItem value="2 circuits, 2 observables" label="2 circuits, 2 observables">
```python
job_input = {
'program_id': 'estimator',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"session_id": sessionId, # This specifies the previously created Session
"params": {
"pubs": [[resulting_qasm, obs1],[resulting_qasm, obs2]], #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2, #this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options":{
"transpilation":{"optimization_level": 1},
"twirling": {"enable_gates": True,"enable_measure": True}, #c.f. documentation at https://docs.quantum.ibm.com/run/configure-error-mitigation#custom-error-settings-v2-primitives
# "dynamical_decoupling": {"enable": True, "sequence_type": "XpXm"}, #(optional)
},
}
}
```
</TabItem>
</Tabs>
### Sampler jobs in session mode
<Tabs>
<TabItem value="1 circuit, no parameters" label="1 circuit, no parameters">
```python
job_input = {
'program_id': 'sampler',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"session_id": sessionId, # This specifies the previously created Session
"params": {
"pubs": [[resulting_qasm]], #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2, #this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options":{
"transpilation":{"optimization_level": 1},
"twirling": {"enable_gates": True,"enable_measure": True}, #c.f. documentation at https://docs.quantum.ibm.com/run/configure-error-mitigation#custom-error-settings-v2-primitives
# "dynamical_decoupling": {"enable": True, "sequence_type": "XpXm"}, #(optional)
},
}
}
```
</TabItem>
<TabItem value="1 circuit, 3 parameter sets" label="1 circuit, 3 parameter sets">
```python
job_input = {
'program_id': 'sampler',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"session_id": sessionId, # This specifies the previously created Session
"params": {
"pubs": [[resulting_qasm, [vals1, vals2, vals3]]], #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2, #this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options":{
"transpilation":{"optimization_level": 1},
"twirling": {"enable_gates": True,"enable_measure": True}, #c.f. documentation at https://docs.quantum.ibm.com/run/configure-error-mitigation#custom-error-settings-v2-primitives
# "dynamical_decoupling": {"enable": True, "sequence_type": "XpXm"}, #(optional)
},
}
}
```
</TabItem>
<TabItem value="2 circuits, 1 parameter set" label="2 circuits, 1 parameter set">
```python
job_input = {
'program_id': 'sampler',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"session_id": sessionId, # This specifies the previously created Session
"params": {
"pubs": [[resulting_qasm, [val1]],[resulting_qasm,None,100]], #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2, #this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options":{
"transpilation":{"optimization_level": 1},
"twirling": {"enable_gates": True,"enable_measure": True}, #c.f. documentation at https://docs.quantum.ibm.com/run/configure-error-mitigation#custom-error-settings-v2-primitives
# "dynamical_decoupling": {"enable": True, "sequence_type": "XpXm"}, #(optional)
},
}
}
```
</TabItem>
</Tabs>
## Next steps
<Admonition type="tip" title="Recommendations">
- Review detailed [Sampler and Estimator](primitives-rest-api) primitives examples using REST API.
- Learn how to [transpile circuits using REST API](./transpile-rest-api).
- Read [Migrate to V2 primitives](/api/migration-guides/v2-primitives).
- Practice with primitives by working through the [Cost function lesson](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions#primitives) in IBM Quantum&trade; Learning.
- Learn how to transpile locally in the [Transpile](./transpile) section.
</Admonition>

View File

@ -38,6 +38,7 @@ can be run on IBM&reg; hardware using IBM Qiskit Runtime.
* [Transpile against custom backends](./custom-backend)
* [Install and use transpiler plugins](./transpiler-plugins)
* [Create a transpiler plugin](./create-transpiler-plugin)
* [Transpile using REST API](./transpile-rest-api)
### Qiskit transpiler service
* [Transpile circuits remotely with the Qiskit transpiler service](./qiskit-transpiler-service)

View File

@ -0,0 +1,489 @@
---
title: Primitives with REST API
description: How to use the Sampler and Estimator primitives with Qiskit Runtime REST API.
---
# Primitives with REST API
The steps in this topic describe how to run and configure primitive workloads with REST API, and demonstrate how to invoke them in any program of your choice.
<Admonition type="note">
This documentation utilizes the Python `requests` module to demonstrate the Qiskit Runtime REST API. However, this workflow can be executed using any language or framework that supports working with REST APIs. Refer to the [API reference documentation](/api/runtime/tags/jobs) for details.
</Admonition>
<span id="start-estimator"></span>
## Estimator primitive with REST API
### 1. Initialize the account
Because Qiskit Runtime `Estimator` is a managed service, you first need to initialize your account. You can then select the device you want to use to calculate the expectation value.
Find details on how to initialize your account, view available backends, and invalidate tokens in this [topic](./setup-channel#set-up-to-use-ibm-quantum-platform-with-rest-api).
### 2. Create a QASM circuit
You need at least one circuit as the input to the `Estimator` primitive.
Define a QASM quantum circuit. For example:
```python
qasm_string='''
OPENQASM 3;
include "stdgates.inc";
qreg q[2];
creg c[2];
x q[0];
cx q[0], q[1];
c[0] = measure q[0];
c[1] = measure q[1];
'''
```
The following code snippets assume that the `qasm_string` has been transpiled to a new string `resulting_qasm`. Find detailed instructions on how to use the Cloud Transpiler API in this [topic](./transpile-rest-api).
### 3. Run the quantum circuit using the Estimator V2 API
<Admonition type="note">
The following jobs use [Qiskit Runtime V2 primitives](/api/migration-guides/v2-primitives). Both `SamplerV2` and `EstimatorV2` take one or more primitive unified blocs (PUBs) as the input. Each PUB is a tuple that contains one circuit and the data broadcasted to that circuit, which can be multiple observables and parameters. Each PUB returns a result.
</Admonition>
```python
import requests
url = 'https://api.quantum-computing.ibm.com/runtime/jobs'
headers = {
'Content-Type': 'application/json',
'x-access-token':auth_id,
'x-qx-client-application': 'qiskit-version-2/0.39.2/'+'your_application' # specifying the application you might be running from. For an actual Integration project, this option is invaluable to know where jobs are coming from. At this time the "qiskit-version-2/0.39.2/" string is a necessary prefix.
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"start_session": "False", # set to False if you just need to run a single job.
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]],
"version": 2 # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
}}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")
```
### 4. Check job status and get results
Next, pass the `job_id` to the API:
```python
response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')
```
Output
```text
>>> Job ID: 58223448-5100-4dec-a47a-942fb30edcad
>>> Job Status: JobStatus.RUNNING
```
Get job results:
```python
response_result= requests.get(url+'/'+job_id+'/results', headers=headers)
res_dict=response_result.json()
estimator_result=res_dict['results']
print(estimator_result)
```
Output
```text
[{'data': {'evs': 0.7428980350102542, 'stds': 0.029884014518789213, 'ensemble_standard_error': 0.03261147170624149}, 'metadata': {'shots': 10016, 'target_precision': 0.01, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}}]
```
### 5. Work with Runtime options
Error mitigation techniques allow users to mitigate circuit errors by modeling the device noise at the time of execution. This typically results in quantum pre-processing overhead related to model training, and classical post-processing overhead to mitigate errors in the raw results by using the generated model.
The error mitigation techniques built in to primitives are advanced resilience options. To specify these options, use the `resilience_level` option when submitting your job.
The following examples demonstrate the default options for dynamical decoupling, twirling, and TREX + ZNE. Find more options and further details in the [Error mitigation and suppression techniques](./error-mitigation-and-suppression-techniques) topic.
<Tabs>
<TabItem value="TREX + ZNE" label="TREX + ZNE">
```python
import requests
url = 'https://api.quantum-computing.ibm.com/runtime/jobs'
headers = {
'Content-Type': 'application/json',
'x-access-token':auth_id,
'x-qx-client-application': 'qiskit-version-2/0.39.2/'+'your_application' # specifying the application you might be running from. For an actual Integration project, this option is invaluable to know where jobs are coming from. At this time the "qiskit-version-2/0.39.2/" string is a necessary prefix.
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"start_session": "False", # set to False if you just need to run a single job.
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]],
"version": 2, # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options": {
"resilience": {
"measure_mitigation": True,
"zne_mitigation": True,
"zne": {
"extrapolator":["exponential", "linear"],
"noise_factors":[1, 3, 5],
},
#"pec_mitigation": False,
#"pec": None,
#"layer_noise_learning":None,
},
},
}
}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")
```
</TabItem>
<TabItem value="Dynamical Decoupling" label="Dynamical Decoupling">
```python
import requests
url = 'https://api.quantum-computing.ibm.com/runtime/jobs'
headers = {
'Content-Type': 'application/json',
'x-access-token':auth_id,
'x-qx-client-application': 'qiskit-version-2/0.39.2/'+'your_application' # specifying the application you might be running from. For an actual Integration project, this option is invaluable to know where jobs are coming from. At this time the "qiskit-version-2/0.39.2/" string is a necessary prefix.
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"start_session": "False", # set to False if you just need to run a single job.
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]],
"version": 2, # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options": {
"dynamical_decoupling": {
"enable": True,
"sequence_type": 'XpXm',
"extra_slack_distribution": 'middle',
"scheduling_method": 'alap',
},
},
}
}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")
```
</TabItem>
<TabItem value="Twirling" label="Twirling">
```python
import requests
url = 'https://api.quantum-computing.ibm.com/runtime/jobs'
headers = {
'Content-Type': 'application/json',
'x-access-token':auth_id,
'x-qx-client-application': 'qiskit-version-2/0.39.2/'+'your_application' # specifying the application you might be running from. For an actual Integration project, this option is invaluable to know where jobs are coming from. At this time the "qiskit-version-2/0.39.2/" string is a necessary prefix.
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"start_session": "False", # set to False if you just need to run a single job.
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]],
"version": 2, # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options": {
"twirling": {
"enable_gates": True,
"enable_measure": True,
"num_randomizations": "auto",
"shots_per_randomization": "auto",
"strategy": "active-accum",
},
},
}
}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")
```
</TabItem>
</Tabs>
<span id="start-sampler"></span>
## Sampler primitive with REST API
### 1. Initialize the account
Because Qiskit Runtime `Sampler` is a managed service, you first need to initialize your account. You can then select the device you want to use to run your calculations on.
Find details on how to initialize your account, view available backends, and invalidate tokens in this [topic](./setup-channel#set-up-to-use-ibm-quantum-platform-with-rest-api).
### 2. Create a QASM circuit
You need at least one circuit as the input to the `Sampler` primitive.
Define a QASM quantum circuit:
```python
qasm_string='''
OPENQASM 3;
include "stdgates.inc";
qreg q[2];
creg c[2];
x q[0];
cx q[0], q[1];
c[0] = measure q[0];
c[1] = measure q[1];
'''
```
The code snippets given below assume that the `qasm_string` has been transpiled to a new string `resulting_qasm`. Find detailed instructions on how to use the Cloud Transpiler API in this [topic](./transpile-rest-api).
### 3. Run the quantum circuit using Sampler V2 API
<Admonition type="note">
The jobs below use [Qiskit Runtime V2 primitives](/api/migration-guides/v2-primitives). Both `SamplerV2` and `EstimatorV2` take one or more primitive unified blocs (PUBs) as the input. Each PUB is a tuple that contains one circuit and the data broadcasted to that circuit, which can be multiple observables and parameters. Each PUB returns a result.
</Admonition>
```python
import requests
url = 'https://api.quantum-computing.ibm.com/runtime/jobs'
headers = {
'Content-Type': 'application/json',
'x-access-token':auth_id,
'x-qx-client-application': 'qiskit-version-2/0.39.2/'+'your_application' # specifying the application you might be running from. For an actual Integration project, this option is invaluable to know where jobs are coming from. At this time the "qiskit-version-2/0.39.2/" string is a necessary prefix.
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"start_session": "False", # set to False if you just need to run a single job.
"params": {
"pubs": [[resulting_qasm],[resulting_qasm,None,500]], # primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2 # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
}}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")
```
### 4. Check job status and get results
Next, pass the `job_id` to the API:
```python
response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')
```
Output
```text
>>> Job ID: 58223448-5100-4dec-a47a-942fb30edced
>>> Job Status: JobStatus.RUNNING
```
Get job results:
```python
response_result= requests.get(url+'/'+job_id+'/results', headers=headers)
res_dict=response_result.json()
# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']
print(counts[:20])
```
Output
```text
['0x3', '0x0', '0x2', '0x1', '0x0', '0x3', '0x0', '0x3', '0x1', '0x2', '0x2', '0x0', '0x2', '0x0', '0x3', '0x3', '0x2', '0x0', '0x1', '0x0']
```
### 5. Work with Runtime options
Error mitigation techniques allow users to mitigate circuit errors by modeling the device noise at the time of execution. This typically results in quantum pre-processing overhead related to model training, and classical post-processing overhead to mitigate errors in the raw results by using the generated model.
The error mitigation techniques built in to primitives are advanced resilience options. To specify these options, use the `resilience_level` option when submitting your job.
Sampler V2 does not support specifying resilience levels. However, you can turn on or off individual error mitigation / suppression methods.
The following examples demonstrate the default options for dynamical decoupling and twirling. Find more options and further details in the [Error mitigation and suppression techniques](./error-mitigation-and-suppression-techniques) topic.
<Tabs>
<TabItem value="Dynamical Decoupling" label="Dynamical Decoupling">
```python
import requests
url = 'https://api.quantum-computing.ibm.com/runtime/jobs'
headers = {
'Content-Type': 'application/json',
'x-access-token':auth_id,
'x-qx-client-application': 'qiskit-version-2/0.39.2/'+'your_application' # specifying the application you might be running from. For an actual Integration project, this option is invaluable to know where jobs are coming from. At this time the "qiskit-version-2/0.39.2/" string is a necessary prefix.
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"start_session": "False", # set to False if you just need to run a single job.
"params": {
"pubs": [[resulting_qasm]], # primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2, # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options": {
"dynamical_decoupling": {
"enable": True,
"sequence_type": 'XpXm',
"extra_slack_distribution": 'middle',
"scheduling_method": 'alap',
},
},
}
}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")
```
</TabItem>
<TabItem value="Twirling" label="Twirling">
```python
import requests
url = 'https://api.quantum-computing.ibm.com/runtime/jobs'
headers = {
'Content-Type': 'application/json',
'x-access-token':auth_id,
'x-qx-client-application': 'qiskit-version-2/0.39.2/'+'your_application' # specifying the application you might be running from. For an actual Integration project, this option is invaluable to know where jobs are coming from. At this time the "qiskit-version-2/0.39.2/" string is a necessary prefix.
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"hub": "hub1",
"group": "group1",
"project": "project1",
"start_session": "False", # set to False if you just need to run a single job.
"params": {
"pubs": [[resulting_qasm]], # primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"version": 2, # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/api/migration-guides/v2-primitives
"options": {
"twirling": {
"enable_gates": True,
"enable_measure": True,
"num_randomizations": "auto",
"shots_per_randomization": "auto",
"strategy": "active-accum",
},
},
}
}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")
```
</TabItem>
</Tabs>
## Next steps
<Admonition type="tip" title="Recommendations">
- There are several ways to run workloads, depending on your needs: job mode, session mode and batch mode. Learn how to work with session mode and batch mode in the [execution modes topic](./execution-modes-rest-api).
- Learn how to [initialize your account](./setup-channel#set-up-to-use-ibm-quantum-platform-with-rest-api) with REST API.
- Learn how to [transpile circuits using REST API](./transpile-rest-api).
- Read [Migrate to V2 primitives](/api/migration-guides/v2-primitives).
- Practice with primitives by working through the [Cost function lesson](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions#primitives) in IBM Quantum Learning.
- Learn how to transpile locally in the [Transpile](./transpile) section.
</Admonition>

View File

@ -113,6 +113,76 @@ result = job.result()
print(result)
```
<span id="iqp-rest-api"></span>
## Set up to use IBM Quantum Platform with REST API
Alternatively, you can also access quantum processors with REST APIs, enabling you to work with QPUs using any programming language or framework.
1. Retrieve your IBM Quantum token from the [IBM Quantum account page](https://quantum.ibm.com/account).
2. If you do not already have a user account, get one at the [IBM Quantum login page.](https://quantum.ibm.com/login) Your user account is associated with one or more [instances](./instances) (in the form hub / group / project) that give access to IBM Quantum services. Additionally, a unique token is assigned to each account, allowing for IBM Quantum access from Qiskit. The instructions in this section use our default instance. For instructions to choose a specific instance, see [Connect to an instance](./instances#connect-instance).
<Admonition type="note">
The Instances section in your [IBM Quantum account page](https://quantum.ibm.com/account) lists the instances that you can access.
</Admonition>
3. Optionally obtain a temporary access token by supplying the API token obtained above. This is especially useful if you would like control over tokens, such as token invalidation. Alternatively, you can work directly with your IBM Quantum Platform API token.
```python
import requests
url = 'https://auth.quantum-computing.ibm.com/api/users/loginWithToken'
input={'apiToken': "<MY_IBM_QUANTUM_TOKEN>"}
auth_response = requests.post(url, json=input)
auth_id=auth_response.json()['id']
```
4. View your available backends:
```python
url_backends = 'https://api.quantum-computing.ibm.com/runtime/backends'
headers = {'Content-Type': 'application/json',
'x-access-token':auth_id}
backends_response = requests.get(url_backends, headers=headers)
print(backends_response.json()['devices'][:5],"...")
```
You can then [transpile circuits using REST API](./transpile-rest-api) and run them using either the [Sampler or the Estimator primitives](./primitives-rest-api).
5. After your experiments are complete, you can proceed to invalidate your token and then test its invalidation.
```python
logout_url = 'https://auth.quantum-computing.ibm.com/api/users/logout'
headers = {'x-access-token':auth_id}
logout_response = requests.post(logout_url, headers=headers)
print("response ok?:",logout_response.ok,logout_response.text)
```
This should yield an error (Error 401) once the access token is invalidated.
```python
logout_url = 'https://auth.quantum-computing.ibm.com/api/users/logout'
headers = {'x-access-token':auth_id}
logout_response = requests.post(logout_url, headers=headers)
if logout_response.status_code == 200:
job_id = logout_response.json().get('id')
print("Job created:",logout_response.text)
elif logout_response.status_code == 401:
print("invalid credentials. Access token should be successfully invalidated.")
else:
print(logout_response.text,"\n")
print(f"Error: {logout_response.status_code}")
```
Output
```text
invalid credentials. Access token should be successfully invalidated.
```
<span id="cloud"></span>
## Set up to use IBM Cloud
@ -179,7 +249,7 @@ print(result)
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
```
```
## Next steps

View File

@ -0,0 +1,125 @@
---
title: Transpile using REST API
description: How to transpile quantum circuits using REST APIs.
---
# Transpile using REST API
<Admonition type="note">
This documentation utilizes the Python `requests` module to demonstrate the Cloud Transpiler API. However, this workflow can be executed using any language or framework that supports working with REST APIs. Refer to the [API reference documentation](/api/runtime/tags/jobs) for details.
</Admonition>
The process of rewriting a given input circuit to match the topology of a specific quantum device, and optimizing the circuit instructions for execution on noisy quantum systems, is known as [transpilation](./transpile).
You have two transpilation options:
* Transpile [locally via Qiskit](./defaults-and-configuration-options) before generating the QASM string.
* Use the [Cloud Transpiler API](https://cloud-transpiler.quantum.ibm.com/docs).
<Admonition type="note">
[Transpilation is necessary](https://docs.quantum.ibm.com/announcements/product-updates/2024-02-14-qiskit-runtime-primitives-update) prior to submitting a circuit to IBM&reg; QPUs.
</Admonition>
The steps in this topic describe how to transpile a given QASM circuit and obtain results using the Cloud Transpiler REST API, and include suggestions on how to submit the transpiled quantum circuit to IBM compute resources.
## Query the Qiskit transpiler service
Query the [Cloud Transpiler API](https://cloud-transpiler.quantum-computing.ibm.com/docs) and provide your QASM string as input. See more details in the [API reference documentation](/api/qiskit-transpiler-service-rest).
There are two ways to invoke the Qiskit transpiler service using REST API: with regular transpilation, and with AI-enhanced transpilation. The following demonstrates both ways to invoke the Cloud Transpiler API.
<Admonition type="note">
This experimental service is only available to IBM Quantum&trade; Premium Plan users.
</Admonition>
<Tabs>
<TabItem value="Qiskit Transpiler Service" label="Qiskit Transpiler Service">
```python
backend='ibm_brisbane' #choose your IBM Backend
headers = {
"accept": "application/json",
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
body= {
"qasm_circuits": qasm_string,
}
params = {
"backend": backend,
"optimization_level": 1,
"ai": "false", # "true", "false" and "auto"
}
resp = requests.post(
"https://cloud-transpiler.quantum.ibm.com/transpile",
headers=headers,
json=body,
params=params,
)
```
</TabItem>
<TabItem value="Qiskit Transpiler Service with AI" label="Qiskit Transpiler Service with AI-enhanced passes">
```python
backend='ibm_brisbane' #choose your IBM Backend
headers = {
"accept": "application/json",
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
body= {
"qasm_circuits": qasm_string,
}
params = {
"backend": backend,
"optimization_level": 1,
"ai": "true", # "true", "false" and "auto"
"coupling_map": [],
"qiskit_transpile_options": [],
"ai_layout_mode": 'OPTIMIZE', # 'KEEP', 'OPTIMIZE', 'IMPROVE'
}
resp = requests.post(
"https://cloud-transpiler.quantum.ibm.com/transpile",
headers=headers,
json=body,
params=params,
)
```
</TabItem>
</Tabs>
<Admonition type="note">
Since there might be cases where its more effective not to use AI-enhanced passes, you can set the `ai` parameter to `ai="auto"` to enable the system to decide automatically whether to apply the standard Qiskit heuristic passes or the new AI-powered passes, based on the particulars of your circuit.
</Admonition>
## Request results based on the `task_id`
Request the transpilation service results using the `task_id`.
```python
task_id=resp.json()['task_id']
res = requests.get(url=f"https://cloud-transpiler.quantum.ibm.com/transpile/{task_id}", headers=headers)
if res.json().get("state") == "SUCCESS":
resulting_qasm=res.json().get("result")[0].get("qasm")
print(resulting_qasm)
```
Output
```text
OPENQASM 3.0; include "stdgates.inc"; gate rzx_140040114706704(_gate_p_0) _gate_q_0, _gate_q_1 { h _gate_q_1; cx _gate_q_0, _gate_q_1; rz(pi/4) _gate_q_1; cx _gate_q_0, _gate_q_1; h _gate_q_1; } gate rzx_140040024191376(_gate_p_0) _gate_q_0, _gate_q_1 { h _gate_q_1; cx _gate_q_0, _gate_q_1; rz(-pi/4) _gate_q_1; cx _gate_q_0, _gate_q_1; h _gate_q_1; } gate ecr _gate_q_0, _gate_q_1 { rzx_140040114706704(pi/4) _gate_q_0, _gate_q_1; x _gate_q_0; rzx_140040024191376(-pi/4) _gate_q_0, _gate_q_1; } bit[2] c; rz(-pi) $0; sx $0; rz(pi/2) $0; rz(-pi/2) $1; sx $1; rz(-pi) $1; ecr $1, $0; rz(-pi/2) $0; sx $0; rz(pi/2) $0; rz(pi/2) $1; sx $1; rz(pi/2) $1; barrier $0, $1; c[0] = measure $0; c[1] = measure $1;
```
## Next steps
<Admonition type="tip" title="Recommendations">
- Review detailed [Sampler and Estimator](./primitives-rest-api) primitives examples using REST API.
- Read [Migrate to V2 primitives](/api/migration-guides/v2-primitives).
- Practice with primitives by working through the [Cost function lesson](https://learning.quantum.ibm.com/course/variational-algorithm-design/cost-functions#primitives) in IBM Quantum Learning.
- Learn how to transpile locally in the [Transpile](./transpile) section.
</Admonition>

View File

@ -255,3 +255,18 @@ notifications:
- "@jyu00"
- "@ElePT"
- "@beckykd"
"docs/guides/primitives-rest-api":
- "@born-2learn"
- "@johannesgreiner"
- "@pacomf"
- "@Bagherpoor"
"docs/guides/execution-modes-rest-api":
- "@born-2learn"
- "@johannesgreiner"
- "@pacomf"
- "@Bagherpoor"
"docs/guides/transpile-rest-api":
- "@born-2learn"
- "@johannesgreiner"
- "@pacomf"
- "@Bagherpoor"