pyrauli 0.3.1__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyrauli-0.3.1 → pyrauli-0.3.2}/PKG-INFO +3 -2
- {pyrauli-0.3.1 → pyrauli-0.3.2}/README.md +1 -1
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/guides/how_to_qiskit.rst +14 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/pyproject.toml +3 -2
- {pyrauli-0.3.1 → pyrauli-0.3.2}/src/pyrauli/backend.py +2 -2
- {pyrauli-0.3.1 → pyrauli-0.3.2}/src/pyrauli/estimator.py +96 -32
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_backend.py +48 -2
- {pyrauli-0.3.1 → pyrauli-0.3.2}/.clang-format +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/.github/workflows/benchmark.yml +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/.github/workflows/ci.yml +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/.github/workflows/doc.yml +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/.github/workflows/pypi.yml +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/.gitignore +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/CMakeLists.txt +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/LICENSE +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/benchmarks/test_benchmark_circuit.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/benchmarks/test_benchmark_observable.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/benchmarks/test_benchmark_qiskit.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/.gitignore +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/Makefile +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/_static/.gitkeep +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/_templates/.gitkeep +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/conf.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/explanation/theory.rst +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/guides/how_to_circuit.rst +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/guides/how_to_complexity.rst +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/guides/how_to_noise.rst +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/guides/how_to_observables.rst +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/index.rst +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/make.bat +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/reference/api.rst +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/requirements.txt +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/docs/tutorials/getting_started.rst +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/examples/qiskit_backend.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/src/pyrauli/__init__.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/src/pyrauli/_core/bindings.cpp +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/src/pyrauli/converters.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/snippets/test_basic_circuit.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/snippets/test_observable_evolution.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/snippets/test_qiskit_backend_usage.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/snippets/test_readme.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_circuit.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_circuit_qiskit.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_noise_model.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_observable.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_observable_qiskit.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_pauli.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_policies.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_pyrauli.py +0 -0
- {pyrauli-0.3.1 → pyrauli-0.3.2}/tests/test_truncator.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: pyrauli
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.2
|
4
4
|
Summary: A very fast and easy to use Quantum circuit simulator relying on Pauli propagation. Compatible with qiskit.
|
5
5
|
License: GNU GENERAL PUBLIC LICENSE
|
6
6
|
Version 3, 29 June 2007
|
@@ -686,6 +686,7 @@ Project-URL: Homepage, https://github.com/zefresk/pyrauli
|
|
686
686
|
Requires-Python: >=3.9
|
687
687
|
Provides-Extra: qiskit
|
688
688
|
Requires-Dist: qiskit>=2.0.0; extra == "qiskit"
|
689
|
+
Requires-Dist: numpy; extra == "qiskit"
|
689
690
|
Provides-Extra: test
|
690
691
|
Requires-Dist: pytest>=8.0.0; extra == "test"
|
691
692
|
Requires-Dist: pytest-cov>=5.0.0; extra == "test"
|
@@ -753,7 +754,7 @@ final_observable = circuit.run(observable)
|
|
753
754
|
|
754
755
|
# 5. Retrieve the final expectation value
|
755
756
|
# The expectation value is calculated with respect to the initial |00...0> state
|
756
|
-
expectation_value = final_observable.
|
757
|
+
expectation_value = final_observable.expectation_value()
|
757
758
|
|
758
759
|
print(f"Final observable: {final_observable}")
|
759
760
|
print(f"Expectation value: {expectation_value}")
|
@@ -58,7 +58,7 @@ final_observable = circuit.run(observable)
|
|
58
58
|
|
59
59
|
# 5. Retrieve the final expectation value
|
60
60
|
# The expectation value is calculated with respect to the initial |00...0> state
|
61
|
-
expectation_value = final_observable.
|
61
|
+
expectation_value = final_observable.expectation_value()
|
62
62
|
|
63
63
|
print(f"Final observable: {final_observable}")
|
64
64
|
print(f"Expectation value: {expectation_value}")
|
@@ -60,6 +60,20 @@ the hood.
|
|
60
60
|
:end-before: # [estimator_complex]
|
61
61
|
:dedent: 4
|
62
62
|
|
63
|
+
Full PUBs support
|
64
|
+
-----------------
|
65
|
+
|
66
|
+
``pyrauli`` intends to be fully compatible with Qiskit and the provided backends and estimators should be able to be swapped with any other qiskit backend. Therefore, :py:class:`~pyrauli.PyrauliEstimator` and :py:class:`~pyrauli.PBackend` `.run` methods allows for any PUB (see `Qiskit documentation on PUBs https://qiskit.qotlabs.org/docs/guides/primitive-input-output`).
|
67
|
+
|
68
|
+
Below is an example of what is possible:
|
69
|
+
|
70
|
+
.. literalinclude:: /../tests/test_backend.py
|
71
|
+
:language: python
|
72
|
+
:start-after: # [qiskit_multiparameters]
|
73
|
+
:end-before: # [qiskit_multiparameters]
|
74
|
+
:dedent: 4
|
75
|
+
|
76
|
+
|
63
77
|
Qiskit and reverse qubit ordering
|
64
78
|
---------------------------------
|
65
79
|
|
@@ -5,7 +5,7 @@ build-backend = "scikit_build_core.build"
|
|
5
5
|
|
6
6
|
[project]
|
7
7
|
name = "pyrauli"
|
8
|
-
version = "0.3.
|
8
|
+
version = "0.3.2"
|
9
9
|
description = "A very fast and easy to use Quantum circuit simulator relying on Pauli propagation. Compatible with qiskit."
|
10
10
|
readme = "README.md"
|
11
11
|
requires-python = ">=3.9"
|
@@ -25,7 +25,8 @@ Homepage = "https://github.com/zefresk/pyrauli"
|
|
25
25
|
|
26
26
|
[project.optional-dependencies]
|
27
27
|
qiskit = [
|
28
|
-
"qiskit>=2.0.0"
|
28
|
+
"qiskit>=2.0.0",
|
29
|
+
"numpy"
|
29
30
|
]
|
30
31
|
test = [
|
31
32
|
"pytest>=8.0.0",
|
@@ -93,14 +93,14 @@ class PBackend(BackendV2):
|
|
93
93
|
"""Default options for the backend."""
|
94
94
|
return Options()
|
95
95
|
|
96
|
-
def run(self, run_input: Union[
|
96
|
+
def run(self, run_input: Union[List[Tuple], Tuple], **options) -> JobV1:
|
97
97
|
"""
|
98
98
|
Run a circuit or a list of circuits on the backend.
|
99
99
|
|
100
100
|
This backend uses a PyrauliEstimator to execute the circuits.
|
101
101
|
|
102
102
|
Args:
|
103
|
-
run_input: A
|
103
|
+
run_input: A list of pubs, where each pub is a tuple of (circuit, observables, parameter_values) or any other PUBs structure.
|
104
104
|
**options: Runtime options for the execution. may include: "noise_model", "truncator", "merge_policy", "truncate_policy"
|
105
105
|
|
106
106
|
Returns:
|
@@ -7,15 +7,17 @@ managing simulation jobs.
|
|
7
7
|
"""
|
8
8
|
import uuid
|
9
9
|
import numpy as np
|
10
|
-
from typing import List, Tuple, Union
|
10
|
+
from typing import List, Tuple, Union, Optional, Any, Callable, Dict
|
11
11
|
from concurrent.futures import ThreadPoolExecutor
|
12
12
|
|
13
|
+
from qiskit import QuantumCircuit
|
13
14
|
from qiskit.primitives import BaseEstimatorV2
|
14
15
|
from qiskit.providers import BackendV2, JobV1, Options, JobStatus
|
15
16
|
from qiskit.result import Result
|
16
17
|
from qiskit.primitives.primitive_job import PrimitiveJob
|
17
18
|
from qiskit.primitives.containers import PubResult, PrimitiveResult, DataBin
|
18
19
|
from qiskit.quantum_info import SparsePauliOp
|
20
|
+
from qiskit.circuit import ParameterVector
|
19
21
|
|
20
22
|
from . import Circuit, Observable, NoiseModel, Truncator, NeverTruncator, SchedulingPolicy, AlwaysAfterSplittingPolicy
|
21
23
|
from .converters import from_qiskit
|
@@ -43,7 +45,11 @@ class PyrauliEstimator(BaseEstimatorV2):
|
|
43
45
|
result = job.result()
|
44
46
|
print(result[0].data.evs[0])
|
45
47
|
"""
|
46
|
-
def __init__(self,
|
48
|
+
def __init__(self,
|
49
|
+
noise_model: Optional[NoiseModel] = None,
|
50
|
+
truncator: Truncator = NeverTruncator(),
|
51
|
+
merge_policy: SchedulingPolicy = AlwaysAfterSplittingPolicy(),
|
52
|
+
truncate_policy: SchedulingPolicy = AlwaysAfterSplittingPolicy()) -> None:
|
47
53
|
"""
|
48
54
|
Initializes the PyrauliEstimator.
|
49
55
|
|
@@ -59,18 +65,16 @@ class PyrauliEstimator(BaseEstimatorV2):
|
|
59
65
|
self._truncator = truncator or NeverTruncator()
|
60
66
|
self._merge_policy = merge_policy or AlwaysAfterSplittingPolicy()
|
61
67
|
self._truncate_policy = truncate_policy or AlwaysAfterSplittingPolicy()
|
62
|
-
|
63
68
|
self._executor = ThreadPoolExecutor(max_workers=1)
|
64
69
|
|
65
|
-
|
66
|
-
def run(self, run_input: List[Tuple], **options) -> 'PJob':
|
70
|
+
def run(self, run_input: Union[List[Tuple], Tuple], **options: Any) -> 'PJob':
|
67
71
|
"""
|
68
72
|
Run a list of pubs (Primitive Unified Blocs) on the estimator.
|
69
73
|
|
70
74
|
Args:
|
71
|
-
run_input: A list of pubs, where each pub is a tuple of
|
72
|
-
|
73
|
-
|
75
|
+
run_input: A list of pubs, where each pub is a tuple of (circuit, observables, parameter_values). See qiskit documentation on PUBs
|
76
|
+
**options: Additional circuit options: "noise_model", "truncator",
|
77
|
+
"truncate_policy", "merge_policy".
|
74
78
|
|
75
79
|
Returns:
|
76
80
|
A PJob object that represents the asynchronous execution.
|
@@ -80,13 +84,14 @@ class PyrauliEstimator(BaseEstimatorV2):
|
|
80
84
|
job.submit()
|
81
85
|
return job
|
82
86
|
|
83
|
-
def _run_job(self, job_id: str, pubs: List[Tuple], **options) -> Result:
|
87
|
+
def _run_job(self, job_id: str, pubs: List[Tuple], **options: Any) -> Result:
|
84
88
|
"""
|
85
89
|
The core simulation logic that is executed by the PJob.
|
86
90
|
|
87
91
|
Args:
|
88
92
|
job_id: The ID for the job.
|
89
93
|
pubs: The list of pubs to execute.
|
94
|
+
**options: Runtime options passed to the run method.
|
90
95
|
|
91
96
|
Returns:
|
92
97
|
A Qiskit Result object containing the simulation results.
|
@@ -95,45 +100,78 @@ class PyrauliEstimator(BaseEstimatorV2):
|
|
95
100
|
trunc = self._truncator if "truncator" not in options else options.get("truncator")
|
96
101
|
trunc_pol = self._truncate_policy if "truncate_policy" not in options else options.get("truncate_policy")
|
97
102
|
merge_pol = self._merge_policy if "merge_policy" not in options else options.get("merge_policy")
|
98
|
-
print(nm, self._noise_model)
|
99
103
|
|
100
104
|
results = []
|
101
105
|
for pub in pubs:
|
102
106
|
circuit, observables, parameter_values = self._unpack_pub(pub)
|
103
107
|
|
104
108
|
# Bind parameters if they exist
|
105
|
-
|
109
|
+
bound_circuits = self._assign_parameters(circuit, parameter_values)
|
106
110
|
|
107
111
|
# Convert to pyrauli objects and simulate
|
108
|
-
|
109
|
-
pyrauli_circuit
|
110
|
-
|
111
|
-
|
112
|
-
|
112
|
+
pyrauli_circuits = [from_qiskit(bqc, noise_model=nm) for bqc in bound_circuits]
|
113
|
+
for pyrauli_circuit in pyrauli_circuits:
|
114
|
+
pyrauli_circuit.set_truncator(trunc)
|
115
|
+
pyrauli_circuit.set_merge_policy(merge_pol)
|
116
|
+
pyrauli_circuit.set_truncate_policy(trunc_pol)
|
117
|
+
|
118
|
+
exp_values = self._simulate_observables(pyrauli_circuits, observables, trunc, merge_pol, trunc_pol)
|
113
119
|
|
114
120
|
# Format the result for this pub
|
115
|
-
results.append({"success": True, "data": {"evs": exp_values}, "metadata": {}, 'shots': 1})
|
121
|
+
results.append({"success": True, "data": {"evs": np.atleast_1d(np.squeeze(np.array(exp_values)))}, "metadata": {}, 'shots': 1})
|
116
122
|
|
117
123
|
return Result.from_dict({"job_id": job_id, "results": results, "success": True, "backend_name": self.name})
|
118
124
|
|
119
|
-
def _simulate_observables(self,
|
125
|
+
def _simulate_observables(self,
|
126
|
+
pyrauli_circuits: List[Circuit],
|
127
|
+
observables: List[SparsePauliOp],
|
128
|
+
trunc: Optional[Truncator] = None,
|
129
|
+
merge_pol: Optional[SchedulingPolicy] = None,
|
130
|
+
trunc_pol: Optional[SchedulingPolicy] = None) -> List[List[float]]:
|
120
131
|
"""
|
121
132
|
Simulates a list of observables for a given pyrauli circuit.
|
122
133
|
"""
|
123
|
-
|
124
|
-
for
|
134
|
+
ret = []
|
135
|
+
for olist in observables:
|
136
|
+
exp_values = []
|
137
|
+
for obs in olist:
|
125
138
|
pyrauli_obs = from_qiskit(obs, reverse=True)
|
126
|
-
|
127
|
-
|
128
|
-
|
139
|
+
for pqc in pyrauli_circuits:
|
140
|
+
final_observable = pqc.run(pyrauli_obs)
|
141
|
+
exp_values.append(final_observable.expectation_value())
|
142
|
+
ret += [exp_values]
|
143
|
+
return ret
|
129
144
|
|
130
|
-
def _unpack_pub(self, pub: Tuple) -> Tuple:
|
145
|
+
def _unpack_pub(self, pub: Tuple) -> Tuple[QuantumCircuit, List[SparsePauliOp], Optional[Any]]:
|
131
146
|
"""
|
132
147
|
Unpacks a pub into its components, ensuring observables are always a list.
|
133
148
|
"""
|
134
149
|
circuit, observables, params = (pub[0], pub[1], pub[2] if len(pub) > 2 else None)
|
135
150
|
return circuit, observables if isinstance(observables, list) else [observables], params
|
136
151
|
|
152
|
+
def _assign_parameters(self, circuit: QuantumCircuit, params: Optional[Any]) -> List[QuantumCircuit]:
|
153
|
+
"""
|
154
|
+
Assigns parameter values to a circuit.
|
155
|
+
|
156
|
+
This method handles different shapes for the parameter values, including
|
157
|
+
no parameters, a single set of parameters, or multiple sets for
|
158
|
+
parameter sweeping.
|
159
|
+
|
160
|
+
Args:
|
161
|
+
circuit: The circuit with unbound parameters.
|
162
|
+
params: The parameter values to bind. Can be a 1D array for a single
|
163
|
+
binding or a 2D array for multiple bindings.
|
164
|
+
|
165
|
+
Returns:
|
166
|
+
A list of circuits with bound parameters.
|
167
|
+
"""
|
168
|
+
if params is None:
|
169
|
+
return [circuit]
|
170
|
+
elif (hasattr(params, 'ndim') and params.ndim == 2) or ((isinstance(params, list) or hasattr(params, 'ndim')) and len(params) > 0 and isinstance(params[0], (list, tuple, dict, ParameterVector))):
|
171
|
+
return [circuit.assign_parameters(e) for e in params]
|
172
|
+
else:
|
173
|
+
return [circuit.assign_parameters(params)]
|
174
|
+
|
137
175
|
class PJob(JobV1):
|
138
176
|
"""
|
139
177
|
A JobV1-compliant class for handling jobs from PBackend and PyrauliEstimator.
|
@@ -141,7 +179,12 @@ class PJob(JobV1):
|
|
141
179
|
This class wraps the execution of the simulation in a manner consistent
|
142
180
|
with Qiskit's job management system.
|
143
181
|
"""
|
144
|
-
def __init__(self,
|
182
|
+
def __init__(self,
|
183
|
+
backend: BackendV2,
|
184
|
+
job_id: str,
|
185
|
+
fn: Callable[..., Result],
|
186
|
+
pubs: List[Tuple],
|
187
|
+
**options: Any) -> None:
|
145
188
|
"""
|
146
189
|
Initializes the PJob.
|
147
190
|
|
@@ -155,11 +198,11 @@ class PJob(JobV1):
|
|
155
198
|
super().__init__(backend, job_id)
|
156
199
|
self._fn = fn
|
157
200
|
self._pubs = pubs
|
158
|
-
self._result = None
|
201
|
+
self._result: Optional[Result] = None
|
159
202
|
self._status = JobStatus.INITIALIZING
|
160
203
|
self._options = options
|
161
204
|
|
162
|
-
def submit(self):
|
205
|
+
def submit(self) -> None:
|
163
206
|
"""
|
164
207
|
Submit the job for execution.
|
165
208
|
|
@@ -173,7 +216,7 @@ class PJob(JobV1):
|
|
173
216
|
self._status = JobStatus.ERROR
|
174
217
|
raise e
|
175
218
|
|
176
|
-
def result(self) -> Result:
|
219
|
+
def result(self) -> Optional[List[Result]]:
|
177
220
|
"""Return the result of the job."""
|
178
221
|
return self._result.results if self._result is not None else None
|
179
222
|
|
@@ -182,17 +225,38 @@ class PJob(JobV1):
|
|
182
225
|
return self._status
|
183
226
|
|
184
227
|
def running(self) -> bool:
|
185
|
-
"""
|
228
|
+
"""
|
229
|
+
Return whether the job is actively running.
|
230
|
+
|
231
|
+
Returns:
|
232
|
+
True if the job's status is 'RUNNING', False otherwise.
|
233
|
+
"""
|
186
234
|
return self._status == JobStatus.RUNNING
|
187
235
|
|
188
236
|
def cancelled(self) -> bool:
|
189
|
-
"""
|
237
|
+
"""
|
238
|
+
Return whether the job has been cancelled.
|
239
|
+
|
240
|
+
Returns:
|
241
|
+
True if the job's status is 'CANCELLED', False otherwise.
|
242
|
+
"""
|
190
243
|
return self._status == JobStatus.CANCELLED
|
191
244
|
|
192
245
|
def done(self) -> bool:
|
193
|
-
"""
|
246
|
+
"""
|
247
|
+
Return whether the job has successfully run.
|
248
|
+
|
249
|
+
Returns:
|
250
|
+
True if the job's status is 'DONE', False otherwise.
|
251
|
+
"""
|
194
252
|
return self._status == JobStatus.DONE
|
195
253
|
|
196
254
|
def in_final_state(self) -> bool:
|
197
|
-
"""
|
255
|
+
"""
|
256
|
+
Return whether the job is in a final job state.
|
257
|
+
|
258
|
+
Returns:
|
259
|
+
True if the job is in a final state (DONE, ERROR, or
|
260
|
+
CANCELLED), False otherwise.
|
261
|
+
"""
|
198
262
|
return self._status in {JobStatus.DONE, JobStatus.ERROR, JobStatus.CANCELLED}
|
@@ -3,7 +3,7 @@ import pytest
|
|
3
3
|
import numpy as np
|
4
4
|
|
5
5
|
# Conditional imports for Qiskit and Aer
|
6
|
-
qiskit = pytest.importorskip("qiskit", minversion="
|
6
|
+
qiskit = pytest.importorskip("qiskit", minversion="2.0", reason="Qiskit >= 2.0 is required")
|
7
7
|
|
8
8
|
from qiskit.circuit import QuantumCircuit, Parameter, ParameterVector
|
9
9
|
from qiskit.circuit.random import random_circuit
|
@@ -68,7 +68,11 @@ def test_estimator_multiple_observables_per_pub():
|
|
68
68
|
|
69
69
|
job = estimator.run([(qc, observables)])
|
70
70
|
result = job.result()
|
71
|
-
|
71
|
+
|
72
|
+
jobq = StatevectorEstimator().run([(qc, observables)])
|
73
|
+
resultq = jobq.result()[0]
|
74
|
+
assert resultq.data.evs.shape == result[0].data.evs.shape
|
75
|
+
|
72
76
|
expected_evs = [p1_to_ev(0.5), p1_to_ev(0.25)]
|
73
77
|
assert result[0].data.evs == pytest.approx(expected_evs, abs=1e-6)
|
74
78
|
|
@@ -92,6 +96,48 @@ def test_estimator_multiobs_multiparams():
|
|
92
96
|
assert result[0].data.evs == pytest.approx([p1_to_ev(0.5), p1_to_ev(0.25)], abs=1e-6)
|
93
97
|
assert result[1].data.evs == pytest.approx([p1_to_ev(0.25), p1_to_ev(0.5)], abs=1e-6)
|
94
98
|
|
99
|
+
def test_backend_transpile_batch_params_from_doc():
|
100
|
+
"""Tests a single circuit against a list of observables in one PUB."""
|
101
|
+
# [qiskit_multiparameters]
|
102
|
+
backend = PBackend(num_qubits=2)
|
103
|
+
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
|
104
|
+
|
105
|
+
circuit = QuantumCircuit(2)
|
106
|
+
circuit.h(0)
|
107
|
+
circuit.cx(0, 1)
|
108
|
+
circuit.ry(Parameter("a"), 0)
|
109
|
+
circuit.rz(Parameter("b"), 0)
|
110
|
+
circuit.cx(0, 1)
|
111
|
+
circuit.h(0)
|
112
|
+
|
113
|
+
transpiled_circuit = pm.run(circuit)
|
114
|
+
|
115
|
+
params = np.vstack(
|
116
|
+
[
|
117
|
+
np.linspace(-np.pi, np.pi, 100),
|
118
|
+
np.linspace(-4 * np.pi, 4 * np.pi, 100),
|
119
|
+
]
|
120
|
+
).T
|
121
|
+
|
122
|
+
observables = [
|
123
|
+
[SparsePauliOp(["XX", "IY"], [0.5, 0.5])],
|
124
|
+
[SparsePauliOp("XX")],
|
125
|
+
[SparsePauliOp("IY")],
|
126
|
+
]
|
127
|
+
|
128
|
+
estimator_pub = (transpiled_circuit, observables, params)
|
129
|
+
|
130
|
+
job = backend.run([estimator_pub])
|
131
|
+
result = job.result()
|
132
|
+
# [qiskit_multiparameters]
|
133
|
+
|
134
|
+
jobq = StatevectorEstimator().run([estimator_pub])
|
135
|
+
resultq = jobq.result()[0]
|
136
|
+
assert resultq.data.evs.shape == result[0].data.evs.shape
|
137
|
+
|
138
|
+
|
139
|
+
assert result[0].data.evs == pytest.approx(resultq.data.evs, abs=1e-4)
|
140
|
+
|
95
141
|
def test_noise_model_is_correctly_applied():
|
96
142
|
"""Confirms the noise model passed to the estimator alters the result."""
|
97
143
|
p = 0.1
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|