diff --git a/docs/guides/primitive-input-output.ipynb b/docs/guides/primitive-input-output.ipynb index c5432fd2c8..ae0f52e3af 100644 --- a/docs/guides/primitive-input-output.ipynb +++ b/docs/guides/primitive-input-output.ipynb @@ -15,6 +15,7 @@ "id": "04b9204f-f058-433b-89f9-05df14645e27", "metadata": {}, "source": [ + "\n", "## Overview of PUBs\n", "\n", "When invoking a primitive's [`run()`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.EstimatorV2#run) method, the main argument that is required is a `list` of one or more tuples -- one for each circuit being executed by the primitive. Each of these tuples is considered a PUB, and the required elements of each tuple in the list depends on the the primitive used. The data provided to these tuples can also be arranged in a variety of shapes to provide flexibility in a workload through broadcasting -- the rules of which are described in a [following section](#broadcasting-rules).\n", diff --git a/docs/guides/primitives-rest-api.mdx b/docs/guides/primitives-rest-api.mdx index e2c9cbfe00..06cccbb33f 100644 --- a/docs/guides/primitives-rest-api.mdx +++ b/docs/guides/primitives-rest-api.mdx @@ -58,7 +58,8 @@ 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. + # The following is useful to help you understand where jobs are coming from. + 'x-qx-client-application': f'//', } job_input = { 'program_id': 'estimator', @@ -290,7 +291,7 @@ Find details on how to initialize your account, view available backends, and inv You need at least one circuit as the input to the Sampler primitive. -Define a QASM quantum circuit: +Define a QASM quantum circuit: ```python qasm_string=''' @@ -302,7 +303,7 @@ x q[0]; cx q[0], q[1]; c[0] = measure q[0]; c[1] = measure q[1]; -''' +''' ``` @@ -328,11 +329,11 @@ headers = { } job_input = { 'program_id': 'sampler', - "backend": backend, + "backend": backend, "hub": "hub1", "group": "group1", "project": "project1", - "start_session": "False", # set to False if you just need to run a single job. + "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/migration-guides/v2-primitives "version": 2 # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/migration-guides/v2-primitives @@ -384,9 +385,9 @@ Output 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. +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. +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. @@ -403,16 +404,16 @@ headers = { } job_input = { 'program_id': 'sampler', - "backend": backend, + "backend": backend, "hub": "hub1", "group": "group1", "project": "project1", - "start_session": "False", # set to False if you just need to run a single job. + "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/migration-guides/v2-primitives "version": 2, # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/migration-guides/v2-primitives "options": { - "dynamical_decoupling": { + "dynamical_decoupling": { "enable": True, "sequence_type": 'XpXm', "extra_slack_distribution": 'middle', @@ -446,17 +447,17 @@ headers = { } job_input = { 'program_id': 'sampler', - "backend": backend, + "backend": backend, "hub": "hub1", "group": "group1", "project": "project1", - "start_session": "False", # set to False if you just need to run a single job. + "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/migration-guides/v2-primitives "version": 2, # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/migration-guides/v2-primitives "options": { - "twirling": { - "enable_gates": True, + "twirling": { + "enable_gates": True, "enable_measure": True, "num_randomizations": "auto", "shots_per_randomization": "auto", @@ -479,6 +480,144 @@ else: + +## Sampler primitive with REST API and parameterized circuits + +### 1. Initialize the account + +Because Qiskit Runtime 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. Define parameters + +```python +import requests +import qiskit_ibm_runtime +from qiskit_ibm_runtime import QiskitRuntimeService +from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager +from qiskit.qasm3 import dumps +from qiskit import QuantumCircuit +from qiskit.circuit import Parameter +from qiskit import transpile + +service = QiskitRuntimeService(channel='ibm_quantum') +backend = service.backend("") + +pm = generate_preset_pass_manager(backend=backend, optimization_level=1) + +theta = Parameter('theta') +phi = Parameter('phi') +parameter_values = {'theta': 1.57, 'phi': 3.14} # In case we want to pass a dictionary +``` + + +### 3. Create a quantum circuit and add parameterized gates + +```python +qc = QuantumCircuit(2) + +# Add parameterized gates +qc.rx(theta, 0) +qc.ry(phi, 1) +qc.cx(0, 1) +qc.measure_all() + +# Draw the original circuit +qc.draw('mpl') + +# Get an ISA circuit +isa_circuit = pm.run(qc) +``` + +### 4. Generate QASM 3 code + +```python +qasm_str = dumps(isa_circuit) +print("Generated QASM 3 code:") +print(qasm_str) +``` + +### 5. Run the quantum circuit using Sampler V2 API + + + + The following jobs use Qiskit Runtime V2 [primitives](/guides/primitives). Both [`SamplerV2`](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.SamplerV2) and [`EstimatorV2`](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.EstimatorV2) take one or more [primitive unified blocs (PUBs)](/guides/primitive-input-output#pub-overview) 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. + + + +```python +import requests + +url = 'https://api.quantum-computing.ibm.com/runtime/jobs' +headers = { + 'Content-Type': 'application/json', + '"Authorization": f"Bearer xxxxxxx", + 'x-qx-client-application': 'qiskit-version-2//'+'' # This is set by the client making the request. You can use it to include information such as the package version used. For an integration project, this option is helpful in understanding where jobs are coming from. The prefix 'qiskit-version-2//' is required. +} + +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": { + # Choose one option: direct parameter transfer or through a dictionary + #"pubs": [[qasm_str,[1,2],500]], # primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/migration-guides/v2-primitives + "pubs": [[qasm_str,parameter_values,500]], # primitive unified blocs (PUBs) containing one circuit each. c.f. https://docs.quantum.ibm.com/migration-guides/v2-primitives + "version": 2 # this defines the version of the Qiskit Runtime Primitive to use, c.f. https://docs.quantum.ibm.com/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(f"Job created: {response.text}") +else: + print(f"Error: {response.status_code}") +``` + +```python +print(response.text) +``` + + +### 6. Check job status and get results + +Next, pass the `job_id` to the API: + +```python +response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers) +response_status_singlejob.json().get('state') +``` + +Output + +```text +{'status': 'Completed'} +``` + +Get job results: + +```python +response_result = requests.get(f"{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 +['0x1', '0x2', '0x1', '0x2', '0x1', '0x2', '0x0', '0x2', '0x1', '0x1', '0x2', '0x2', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1'] +``` + ## Next steps @@ -488,4 +627,5 @@ else: - Read [Migrate to V2 primitives](/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. + - [Migrate to the Qiskit Runtime V2 primitives.](/migration-guides/v2-primitives) \ No newline at end of file diff --git a/docs/guides/transpile-rest-api.mdx b/docs/guides/transpile-rest-api.mdx index ef29dde222..e98835dc4f 100644 --- a/docs/guides/transpile-rest-api.mdx +++ b/docs/guides/transpile-rest-api.mdx @@ -11,7 +11,7 @@ description: How to transpile quantum circuits using REST APIs. 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 QPUs, is known as [transpilation](./transpile). -You have two transpilation options: +You have two transpilation options: * Transpile [locally via Qiskit](./defaults-and-configuration-options) before generating the QASM string. @@ -21,7 +21,7 @@ You have two transpilation options: [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® QPUs. -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. +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. For an example that uses parameterized input, see [Sampler primitive with REST API and parameterized circuits.](/guides/primitives-rest-api#start-sampler-parms) ## Query the Qiskit Transpiler Service @@ -94,7 +94,7 @@ resp = requests.post( - Since there might be cases where it’s more effective not to use AI-enhanced passes, you can set the `ai` parameter to `ai="auto"` to enable the QPU to decide automatically whether to apply the standard Qiskit heuristic passes or the new AI-powered passes, based on the particulars of your circuit. + Since there might be cases where it’s more effective not to use AI-enhanced passes, you can set the `ai` parameter to `ai="auto"` to enable the QPU to decide automatically whether to apply the standard Qiskit heuristic passes or the new AI-powered passes, based on the particulars of your circuit. ## Request results based on the `task_id`