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

Update metadata of Primitives V2 #2206

Merged
merged 4 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion qiskit_aer/backends/aerbackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from qiskit.circuit import QuantumCircuit, ParameterExpression, Delay
from qiskit.compiler import assemble
from qiskit.providers import BackendV2 as Backend
from qiskit.providers.models import BackendStatus
from qiskit.providers.models.backendstatus import BackendStatus
from qiskit.pulse import Schedule, ScheduleBlock
from qiskit.qobj import QasmQobj, PulseQobj
from qiskit.result import Result
Expand Down
2 changes: 1 addition & 1 deletion qiskit_aer/noise/noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from qiskit.circuit import Instruction, Delay
from qiskit.providers import QubitProperties
from qiskit.providers.exceptions import BackendPropertyError
from qiskit.providers.models import BackendProperties
from qiskit.providers.models.backendproperties import BackendProperties
from qiskit.transpiler import PassManager
from qiskit.utils import apply_prefix
from .device.models import _excited_population, _truncate_t2_value
Expand Down
8 changes: 6 additions & 2 deletions qiskit_aer/primitives/estimator_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def _validate_pubs(self, pubs: list[EstimatorPub]):
)

def _run(self, pubs: list[EstimatorPub]) -> PrimitiveResult[PubResult]:
return PrimitiveResult([self._run_pub(pub) for pub in pubs])
return PrimitiveResult([self._run_pub(pub) for pub in pubs], metadata={"version": 2})

def _run_pub(self, pub: EstimatorPub) -> PubResult:
circuit = pub.circuit.copy()
Expand Down Expand Up @@ -151,5 +151,9 @@ def _run_pub(self, pub: EstimatorPub) -> PubResult:
evs = rng.normal(evs, precision, evs.shape)
return PubResult(
DataBin(evs=evs, stds=stds, shape=evs.shape),
metadata={"target_precision": precision, "simulator_metadata": result.metadata},
metadata={
"target_precision": precision,
"circuit_metadata": pub.circuit.metadata,
"simulator_metadata": result.metadata,
},
)
13 changes: 10 additions & 3 deletions qiskit_aer/primitives/sampler_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def _run(self, pubs: list[SamplerPub]) -> PrimitiveResult[SamplerPubResult]:
# reconstruct the result of pubs
for i, pub_result in zip(lst, pub_results):
results[i] = pub_result
return PrimitiveResult(results)
return PrimitiveResult(results, metadata={"version": 2})

def _run_pubs(self, pubs: list[SamplerPub], shots: int) -> list[SamplerPubResult]:
"""Compute results for pubs that all require the same value of ``shots``."""
Expand Down Expand Up @@ -192,6 +192,7 @@ def _run_pubs(self, pubs: list[SamplerPub], shots: int) -> list[SamplerPubResult
p_v.shape,
meas_info,
max_num_bytes,
pub.circuit.metadata,
result.metadata,
)
)
Expand All @@ -206,7 +207,8 @@ def _postprocess_pub(
shape: tuple[int, ...],
meas_info: list[_MeasureInfo],
max_num_bytes: int,
metadata: dict,
circuit_metadata: dict,
simulator_metadata: dict,
) -> SamplerPubResult:
"""Converts the memory data into an array of bit arrays with the shape of the pub."""
arrays = {
Expand All @@ -224,7 +226,12 @@ def _postprocess_pub(
item.creg_name: BitArray(arrays[item.creg_name], item.num_bits) for item in meas_info
}
return SamplerPubResult(
DataBin(**meas, shape=shape), metadata={"simulator_metadata": metadata}
DataBin(**meas, shape=shape),
metadata={
"shots": shots,
"circuit_metadata": circuit_metadata,
"simulator_metadata": simulator_metadata,
},
)


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
features:
- |
The metadata of Primitives V2 implementations,
i.e., :class:`.SamplerV2` and :class:`.EstimatorV2`,
has been updated to match that of IBM quantum devices.

* ``version`` and ``circuit_metadata`` are added for :class:`.SamplerV2` and :class:`.EstimatorV2`
* ``shots`` is added for :class:`.SamplerV2`

Note that metadata of :class:`.EstimatorV2` does not have ``shots`` because
the class computes expectation values with ``save_expectation_value`` instruction and shots are not used.
31 changes: 31 additions & 0 deletions test/terra/primitives/test_estimator_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,37 @@ def test_iter_pub(self):
np.testing.assert_allclose(result[0].data.evs, [-1.284366511861733], rtol=self._rtol)
np.testing.assert_allclose(result[1].data.evs, [-1.284366511861733], rtol=self._rtol)

def test_metadata(self):
"""Test for metadata"""
qc = QuantumCircuit(2)
qc2 = QuantumCircuit(2)
qc2.metadata = {"a": 1}
estimator = EstimatorV2(options=self._options)
pm = generate_preset_pass_manager(optimization_level=0, backend=self.backend)
qc, qc2 = pm.run([qc, qc2])
op = SparsePauliOp("ZZ").apply_layout(qc.layout)
op2 = SparsePauliOp("ZZ").apply_layout(qc2.layout)
result = estimator.run([(qc, op), (qc2, op2)], precision=0.1).result()

self.assertEqual(len(result), 2)
self.assertEqual(result.metadata, {"version": 2})

metadata = result[0].metadata
self.assertIsInstance(metadata["simulator_metadata"], dict)
del metadata["simulator_metadata"]
self.assertEqual(
metadata,
{"target_precision": 0.1, "circuit_metadata": qc.metadata},
)

metadata = result[1].metadata
self.assertIsInstance(metadata["simulator_metadata"], dict)
del metadata["simulator_metadata"]
self.assertEqual(
result[1].metadata,
{"target_precision": 0.1, "circuit_metadata": qc2.metadata},
)


if __name__ == "__main__":
unittest.main()
21 changes: 21 additions & 0 deletions test/terra/primitives/test_sampler_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,27 @@ def test_iter_pub(self):
self._assert_allclose(result[0].data.meas, np.array({0: self._shots}))
self._assert_allclose(result[1].data.meas, np.array({1: self._shots}))

def test_metadata(self):
"""Test for metadata"""
qc = QuantumCircuit(2)
qc.measure_all()
qc2 = qc.copy()
qc2.metadata = {"a": 1}
sampler = SamplerV2(**self._options)
result = sampler.run([(qc, None, 10), (qc2, None, 20)]).result()

self.assertEqual(len(result), 2)
self.assertEqual(result.metadata, {"version": 2})
metadata = result[0].metadata
self.assertIsInstance(metadata["simulator_metadata"], dict)
del metadata["simulator_metadata"]
self.assertEqual(metadata, {"shots": 10, "circuit_metadata": qc.metadata})

metadata = result[1].metadata
self.assertIsInstance(metadata["simulator_metadata"], dict)
del metadata["simulator_metadata"]
self.assertEqual(metadata, {"shots": 20, "circuit_metadata": qc2.metadata})

def test_seed(self):
"""Test for seed options"""
with self.subTest("empty"):
Expand Down
Loading