Skip to content
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
29 changes: 29 additions & 0 deletions qiskit/providers/aer/backends/aerbackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,30 @@ def _run(self, qobj, job_id='', format_result=True):
# Start timer
start = time.time()

# Take metadata from headers of experiments to work around JSON serialization error
metadata_list = []
metadata_index = 0
for expr in qobj.experiments:
if hasattr(expr.header, "metadata"):
metadata_copy = expr.header.metadata.copy()
metadata_list.append(metadata_copy)
expr.header.metadata.clear()
if "id" in metadata_copy:
expr.header.metadata["id"] = metadata_copy["id"]
Comment thread
mtreinish marked this conversation as resolved.
expr.header.metadata["metadata_index"] = metadata_index
metadata_index += 1

# Run simulation
output = self._execute(qobj)

# Recover metadata
metadata_index = 0
for expr in qobj.experiments:
if hasattr(expr.header, "metadata"):
expr.header.metadata.clear()
expr.header.metadata.update(metadata_list[metadata_index])
metadata_index += 1

# Validate output
if not isinstance(output, dict):
logger.error("%s: simulation failed.", self.name())
Expand All @@ -305,6 +326,14 @@ def _run(self, qobj, job_id='', format_result=True):
output["backend_name"] = self.name()
output["backend_version"] = self.configuration().backend_version

# Push metadata to experiment headers
for result in output["results"]:
if ("header" in result and
"metadata" in result["header"] and
"metadata_index" in result["header"]["metadata"]):
metadata_index = result["header"]["metadata"]["metadata_index"]
result["header"]["metadata"] = metadata_list[metadata_index]

# Add execution time
output["time_taken"] = time.time() - start

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
fixes:
- |
Fixed a potential issue with running simulations on circuits that have the
:attr:`.QuantumCircuit.metadata` attribute set. The :attr:`~.QuantumCircuit.metadata`
attribute can be any python dictionary and previously qiskit-aer would attempt to
JSON serialize the contents of the attribute to process it with the rest of the rest
of the circuit input, even if the contents were not JSON serializable. This no longer
occurs as the :attr:`.QuantumCircuit.metadata` attribute is not used to run the
simulation so now the contents are no serialized and instead are directly attached
to the :class:`qiskit.result.Result` object without attempting to JSON serialize
the contents.
Fixed `#1435 <https://github.com/Qiskit/qiskit-aer/issues/1435>`__
104 changes: 104 additions & 0 deletions test/terra/backends/aer_simulator/test_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2019, 2020, 2021, 2022.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
AerSimulator Integration Tests
"""
from math import sqrt
from ddt import ddt
from qiskit import transpile, QuantumCircuit
from test.terra.reference import ref_algorithms

from test.terra.backends.simulator_test_case import (
SimulatorTestCase, supported_methods)


@ddt
class TestMetadata(SimulatorTestCase):
"""AerSimulator algorithm tests in the default basis"""

@supported_methods(
['automatic', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
def test_single_circuit_metadata(self, method, device):
"""Test circuits with object metadata."""
backend = self.backend(method=method, device=device)
metadata = {1: object}
circuit = QuantumCircuit(1, name='circ0', metadata=metadata.copy())
result = backend.run(circuit).result()
self.assertSuccess(result)
self.assertEqual(result.results[0].header.metadata, metadata)
self.assertEqual(circuit.metadata, metadata)

@supported_methods(
['automatic', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
def test_three_circuit_metadata(self, method, device):
"""Test circuits with object metadata."""
backend = self.backend(method=method, device=device)

metadata0 = {0: object}
circuit0 = QuantumCircuit(1, name='circ0', metadata=metadata0.copy())

metadata1 = {1: object}
circuit1 = QuantumCircuit(1, name='circ1', metadata=metadata1.copy())

metadata2 = {2: object}
circuit2 = QuantumCircuit(1, name='circ2', metadata=metadata2.copy())

result = backend.run([circuit0, circuit1, circuit2]).result()
self.assertSuccess(result)
self.assertEqual(len(result.results), 3)
self.assertEqual(result.results[0].header.metadata, metadata0)
self.assertEqual(result.results[1].header.metadata, metadata1)
self.assertEqual(result.results[2].header.metadata, metadata2)
self.assertEqual(circuit0.metadata, metadata0)
self.assertEqual(circuit1.metadata, metadata1)
self.assertEqual(circuit2.metadata, metadata2)

@supported_methods(
['automatic', 'statevector', 'density_matrix', 'matrix_product_state'])
def test_three_parameterized_circuit_metadata(self, method, device):
"""Test circuits with object metadata."""
backend = self.backend(method=method, device=device)

metadata0 = {0: object}
circuit0 = QuantumCircuit(1, name='circ0', metadata=metadata0.copy())
circuit0.ry(0.1, 0)
circuit0.measure_all()

metadata1 = {1: object}
circuit1 = QuantumCircuit(1, name='circ1', metadata=metadata1.copy())
circuit1.ry(0.1, 0)
circuit1.measure_all()

metadata2 = {2: object}
circuit2 = QuantumCircuit(1, name='circ2', metadata=metadata2.copy())
circuit2.ry(0.1, 0)
circuit2.measure_all()

parameterizations=[[[[0, 0], [0, 1]]],
[[[0, 0], [0, 1, 2]]],
[]]

result = backend.run([circuit0, circuit1, circuit2],
parameterizations=parameterizations).result()
self.assertSuccess(result)
self.assertEqual(len(result.results), 6)
self.assertEqual(result.results[0].header.metadata, metadata0)
self.assertEqual(result.results[1].header.metadata, metadata0)
self.assertEqual(result.results[2].header.metadata, metadata1)
self.assertEqual(result.results[3].header.metadata, metadata1)
self.assertEqual(result.results[4].header.metadata, metadata1)
self.assertEqual(result.results[5].header.metadata, metadata2)
self.assertEqual(circuit0.metadata, metadata0)
self.assertEqual(circuit1.metadata, metadata1)
self.assertEqual(circuit2.metadata, metadata2)
Comment thread
hhorii marked this conversation as resolved.