Skip to content

Commit 7fa2366

Browse files
committed
update EstimatorV2 and tests
1 parent aab5345 commit 7fa2366

File tree

4 files changed

+59
-19
lines changed

4 files changed

+59
-19
lines changed

qiskit_aer/primitives/estimator_v2.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import numpy as np
2121
from qiskit.primitives.base import BaseEstimatorV2
22-
from qiskit.primitives.containers import EstimatorPubLike, PrimitiveResult, PubResult
22+
from qiskit.primitives.containers import DataBin, EstimatorPubLike, PrimitiveResult, PubResult
2323
from qiskit.primitives.containers.estimator_pub import EstimatorPub
2424
from qiskit.primitives.primitive_job import PrimitiveJob
2525
from qiskit.quantum_info import Pauli
@@ -132,7 +132,6 @@ def _run_pub(self, pub: EstimatorPub) -> PubResult:
132132
).result()
133133

134134
# calculate expectation values (evs) and standard errors (stds)
135-
rng = np.random.default_rng(self.options.run_options.get("seed_simulator"))
136135
flat_indices = list(param_indices.ravel())
137136
evs = np.zeros_like(bc_param_ind, dtype=float)
138137
stds = np.full(bc_param_ind.shape, precision)
@@ -143,10 +142,11 @@ def _run_pub(self, pub: EstimatorPub) -> PubResult:
143142
expval = result.data(flat_index)[pauli]
144143
evs[index] += expval * coeff
145144
if precision > 0:
146-
evs = rng.normal(evs, precision)
147-
data_bin_cls = self._make_data_bin(pub)
148-
data_bin = data_bin_cls(evs=evs, stds=stds)
145+
rng = np.random.default_rng(self.options.run_options.get("seed_simulator"))
146+
if not np.all(np.isreal(evs)):
147+
raise ValueError("Given operator is not Hermitian and noise cannot be added.")
148+
evs = rng.normal(evs, precision, evs.shape)
149149
return PubResult(
150-
data_bin,
150+
DataBin(evs=evs, stds=stds, shape=evs.shape),
151151
metadata={"target_precision": precision, "simulator_metadata": result.metadata},
152152
)

qiskit_aer/primitives/sampler_v2.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,12 @@ def _run_pubs(self, pubs: list[SamplerPub], shots: int) -> list[SamplerPubResult
184184
end = start + p_v.size
185185
results.append(
186186
self._postprocess_pub(
187-
result_memory[start:end], shots, p_v.shape, meas_info, max_num_bytes
187+
result_memory[start:end],
188+
shots,
189+
p_v.shape,
190+
meas_info,
191+
max_num_bytes,
192+
result.metadata,
188193
)
189194
)
190195
start = end
@@ -198,6 +203,7 @@ def _postprocess_pub(
198203
shape: tuple[int, ...],
199204
meas_info: list[_MeasureInfo],
200205
max_num_bytes: int,
206+
metadata: dict,
201207
) -> SamplerPubResult:
202208
"""Converts the memory data into an array of bit arrays with the shape of the pub."""
203209
arrays = {
@@ -214,7 +220,9 @@ def _postprocess_pub(
214220
meas = {
215221
item.creg_name: BitArray(arrays[item.creg_name], item.num_bits) for item in meas_info
216222
}
217-
return SamplerPubResult(DataBin(**meas, shape=shape), metadata={})
223+
return SamplerPubResult(
224+
DataBin(**meas, shape=shape), metadata={"simulator_metadata": metadata}
225+
)
218226

219227

220228
def _convert_parameter_bindings(pub: SamplerPub) -> dict:

test/terra/primitives/test_estimator_v2.py

+34-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333

3434
class TestEstimatorV2(QiskitAerTestCase):
35-
"""Test Estimator"""
35+
"""Test Estimator V2"""
3636

3737
def setUp(self):
3838
super().setUp()
@@ -84,6 +84,7 @@ def test_estimator_run(self):
8484
job = estimator.run([(psi1, ham1, [theta1])])
8585
result = job.result()
8686
np.testing.assert_allclose(result[0].data.evs, [1.5555572817900956], rtol=self._rtol)
87+
self.assertIn("simulator_metadata", result[0].metadata)
8788

8889
# Objects can be passed instead of indices.
8990
# Note that passing objects has an overhead
@@ -93,12 +94,14 @@ def test_estimator_run(self):
9394
ham1 = hamiltonian1.apply_layout(psi2.layout)
9495
result2 = estimator.run([(psi2, ham1, theta2)]).result()
9596
np.testing.assert_allclose(result2[0].data.evs, [2.97797666], rtol=self._rtol)
97+
self.assertIn("simulator_metadata", result2[0].metadata)
9698

9799
# calculate [ <psi1(theta1)|H2|psi1(theta1)>, <psi1(theta1)|H3|psi1(theta1)> ]
98100
ham2 = hamiltonian2.apply_layout(psi1.layout)
99101
ham3 = hamiltonian3.apply_layout(psi1.layout)
100102
result3 = estimator.run([(psi1, [ham2, ham3], theta1)]).result()
101103
np.testing.assert_allclose(result3[0].data.evs, [-0.551653, 0.07535239], rtol=self._rtol)
104+
self.assertIn("simulator_metadata", result3[0].metadata)
102105

103106
# calculate [ [<psi1(theta1)|H1|psi1(theta1)>,
104107
# <psi1(theta3)|H3|psi1(theta3)>],
@@ -114,6 +117,8 @@ def test_estimator_run(self):
114117
).result()
115118
np.testing.assert_allclose(result4[0].data.evs, [1.55555728, -1.08766318], rtol=self._rtol)
116119
np.testing.assert_allclose(result4[1].data.evs, [0.17849238], rtol=self._rtol)
120+
self.assertIn("simulator_metadata", result4[0].metadata)
121+
self.assertIn("simulator_metadata", result4[1].metadata)
117122

118123
def test_estimator_with_pub(self):
119124
"""Test estimator with explicit EstimatorPubs."""
@@ -296,10 +301,9 @@ def test_run_errors(self):
296301
est.run([(qc, op, None, -1)]).result()
297302
with self.assertRaises(ValueError):
298303
est.run([(qc, op)], precision=-1).result()
299-
# Comment out after Qiskit 1.0.3
300-
# with self.subTest("missing []"):
301-
# with self.assertRaisesRegex(ValueError, "An invalid Estimator pub-like was given"):
302-
# _ = est.run((qc, op)).result()
304+
with self.subTest("missing []"):
305+
with self.assertRaisesRegex(ValueError, "An invalid Estimator pub-like was given"):
306+
_ = est.run((qc, op)).result()
303307

304308
def test_run_numpy_params(self):
305309
"""Test for numpy array as parameter values"""
@@ -347,6 +351,31 @@ def test_precision(self):
347351
result = job.result()
348352
np.testing.assert_allclose(result[0].data.evs, [1.5555572817900956], rtol=self._rtol)
349353

354+
def test_diff_precision(self):
355+
"""Test for running different precisions at once"""
356+
estimator = EstimatorV2(options=self._options)
357+
pm = generate_preset_pass_manager(optimization_level=0, backend=self.backend)
358+
psi1 = pm.run(self.psi[0])
359+
hamiltonian1 = self.hamiltonian[0].apply_layout(psi1.layout)
360+
theta1 = self.theta[0]
361+
job = estimator.run(
362+
[(psi1, hamiltonian1, [theta1]), (psi1, hamiltonian1, [theta1], self._precision * 0.8)]
363+
)
364+
result = job.result()
365+
np.testing.assert_allclose(result[0].data.evs, [1.901141473854881], rtol=self._rtol)
366+
np.testing.assert_allclose(result[1].data.evs, [1.901141473854881], rtol=self._rtol)
367+
368+
def test_iter_pub(self):
369+
"""test for an iterable of pubs"""
370+
circuit = self.ansatz.assign_parameters([0, 1, 1, 2, 3, 5])
371+
pm = generate_preset_pass_manager(optimization_level=0, backend=self.backend)
372+
circuit = pm.run(circuit)
373+
estimator = EstimatorV2(options=self._options)
374+
observable = self.observable.apply_layout(circuit.layout)
375+
result = estimator.run(iter([(circuit, observable), (circuit, observable)])).result()
376+
np.testing.assert_allclose(result[0].data.evs, [-1.284366511861733], rtol=self._rtol)
377+
np.testing.assert_allclose(result[1].data.evs, [-1.284366511861733], rtol=self._rtol)
378+
350379

351380
if __name__ == "__main__":
352381
unittest.main()

test/terra/primitives/test_sampler_v2.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister
2323
from qiskit.circuit import Parameter
2424
from qiskit.circuit.library import RealAmplitudes, UnitaryGate
25-
from qiskit.primitives import PrimitiveResult, PubResult, StatevectorSampler
25+
from qiskit.primitives import PrimitiveResult, SamplerPubResult, StatevectorSampler
2626
from qiskit.primitives.containers import BitArray
2727
from qiskit.primitives.containers.data_bin import DataBin
2828
from qiskit.primitives.containers.sampler_pub import SamplerPub
@@ -93,10 +93,11 @@ def test_sampler_run(self):
9393
self.assertIsInstance(result, PrimitiveResult)
9494
self.assertIsInstance(result.metadata, dict)
9595
self.assertEqual(len(result), 1)
96-
self.assertIsInstance(result[0], PubResult)
96+
self.assertIsInstance(result[0], SamplerPubResult)
9797
self.assertIsInstance(result[0].data, DataBin)
9898
self.assertIsInstance(result[0].data.meas, BitArray)
9999
self._assert_allclose(result[0].data.meas, np.array(target))
100+
self.assertIn("simulator_metadata", result[0].metadata)
100101

101102
with self.subTest("single with param"):
102103
pqc, param_vals, target = self._cases[2]
@@ -108,10 +109,11 @@ def test_sampler_run(self):
108109
self.assertIsInstance(result, PrimitiveResult)
109110
self.assertIsInstance(result.metadata, dict)
110111
self.assertEqual(len(result), 1)
111-
self.assertIsInstance(result[0], PubResult)
112+
self.assertIsInstance(result[0], SamplerPubResult)
112113
self.assertIsInstance(result[0].data, DataBin)
113114
self.assertIsInstance(result[0].data.meas, BitArray)
114115
self._assert_allclose(result[0].data.meas, np.array(target))
116+
self.assertIn("simulator_metadata", result[0].metadata)
115117

116118
with self.subTest("multiple"):
117119
pqc, param_vals, target = self._cases[2]
@@ -125,10 +127,11 @@ def test_sampler_run(self):
125127
self.assertIsInstance(result, PrimitiveResult)
126128
self.assertIsInstance(result.metadata, dict)
127129
self.assertEqual(len(result), 1)
128-
self.assertIsInstance(result[0], PubResult)
130+
self.assertIsInstance(result[0], SamplerPubResult)
129131
self.assertIsInstance(result[0].data, DataBin)
130132
self.assertIsInstance(result[0].data.meas, BitArray)
131133
self._assert_allclose(result[0].data.meas, np.array([target, target, target]))
134+
self.assertIn("simulator_metadata", result[0].metadata)
132135

133136
def test_sampler_run_multiple_times(self):
134137
"""Test run() returns the same results if the same input is given."""
@@ -649,8 +652,8 @@ def test_iter_pub(self):
649652
result = sampler.run(iter([qc, qc2]), shots=self._shots).result()
650653
self.assertIsInstance(result, PrimitiveResult)
651654
self.assertEqual(len(result), 2)
652-
self.assertIsInstance(result[0], PubResult)
653-
self.assertIsInstance(result[1], PubResult)
655+
self.assertIsInstance(result[0], SamplerPubResult)
656+
self.assertIsInstance(result[1], SamplerPubResult)
654657
self._assert_allclose(result[0].data.meas, np.array({0: self._shots}))
655658
self._assert_allclose(result[1].data.meas, np.array({1: self._shots}))
656659

0 commit comments

Comments
 (0)