Skip to content

Commit

Permalink
Stop using circuit metadata to internaly manage simulation results
Browse files Browse the repository at this point in the history
This fixes `AerSimulator` to use circuit metadata to maintain mapping
from input and output of an executor call. This fixes an issue
Qiskit#1723.
  • Loading branch information
hhorii committed Apr 5, 2023
1 parent 1b866c6 commit 0d0c1ef
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 22 deletions.
14 changes: 8 additions & 6 deletions qiskit_aer/backends/aer_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

import itertools
from copy import copy
from typing import List
from typing import List, Dict

from qiskit.circuit import QuantumCircuit, Clbit, ParameterExpression
from qiskit.extensions import Initialize
Expand Down Expand Up @@ -364,7 +364,7 @@ def generate_aer_config(
return config


def assemble_circuit(circuit: QuantumCircuit):
def assemble_circuit(circuit: QuantumCircuit, metadata: Dict):
"""assemble circuit object mapped to AER::Circuit"""

num_qubits = circuit.num_qubits
Expand All @@ -391,8 +391,8 @@ def assemble_circuit(circuit: QuantumCircuit):
global_phase=global_phase,
)

if circuit.metadata is not None:
header.metadata = circuit.metadata
if metadata is not None:
header.metadata = metadata

qubit_indices = {qubit: idx for idx, qubit in enumerate(circuit.qubits)}
clbit_indices = {clbit: idx for idx, clbit in enumerate(circuit.clbits)}
Expand Down Expand Up @@ -588,7 +588,7 @@ def _assemble_op(aer_circ, inst, qubit_indices, clbit_indices, is_conditional, c
raise AerError(f"unknown instruction: {name}")


def assemble_circuits(circuits: List[QuantumCircuit]) -> List[AerCircuit]:
def assemble_circuits(circuits: List[QuantumCircuit], metadata_list: Dict) -> List[AerCircuit]:
"""converts a list of Qiskit circuits into circuits mapped AER::Circuit
Args:
Expand All @@ -611,4 +611,6 @@ def assemble_circuits(circuits: List[QuantumCircuit]) -> List[AerCircuit]:
# Generate AerCircuit from the input circuit
aer_qc_list = assemble_circuits(circuits=[qc])
"""
return [assemble_circuit(circuit) for circuit in circuits]
return [
assemble_circuit(circuit, metadata) for circuit, metadata in zip(circuits, metadata_list)
]
20 changes: 4 additions & 16 deletions qiskit_aer/backends/aerbackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,19 +423,10 @@ def _execute_circuits_job(self, circuits, noise_model, config, job_id="", format
# Start timer
start = time.time()

# Take metadata from headers of experiments to work around JSON serialization error
metadata_list = []
for idx, circ in enumerate(circuits):
metadata_list.append(circ.metadata)
# TODO: we test for True-like on purpose here to condition against both None and {},
# which allows us to support versions of Terra before and after QuantumCircuit.metadata
# accepts None as a valid value. This logic should be revisited after terra>=0.24.0 is
# required.
if circ.metadata:
circ.metadata = {"metadata_index": idx}

# Run simulation
aer_circuits = assemble_circuits(circuits)
aer_circuits = assemble_circuits(
circuits, [{"metadata_index": idx} for idx in range(len(circuits))]
)
output = self._execute_circuits(aer_circuits, noise_model, config)

# Validate output
Expand All @@ -460,10 +451,7 @@ def _execute_circuits_job(self, circuits, noise_model, config, job_id="", format
and "metadata_index" in result["header"]["metadata"]
):
metadata_index = result["header"]["metadata"]["metadata_index"]
result["header"]["metadata"] = metadata_list[metadata_index]

for circ, metadata in zip(circuits, metadata_list):
circ.metadata = metadata
result["header"]["metadata"] = circuits[metadata_index].metadata

# Add execution time
output["time_taken"] = time.time() - start
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fixes:
- |
Previously :class:`~.AerSimulator` modifies circuit metadata to maintain
consistency between input and output of simulation with side effect of
unexpected view of metadata from applicatiln in simiulation. This fix
avoids using circuit metadata to maintain consistency internaly and then
always provides consistent view of metadata to application.
18 changes: 18 additions & 0 deletions test/terra/backends/aer_simulator/test_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,21 @@ def test_partial_result_a_single_invalid_circuit(self):
self.assertEqual(result.status, "PARTIAL COMPLETED")
self.assertTrue(hasattr(result.results[1].data, "counts"))
self.assertFalse(hasattr(result.results[0].data, "counts"))

def test_metadata_protected(self):
"""Test metadata is consitently viewed from users"""

qc = QuantumCircuit(2)
qc.metadata = {"foo": "bar", "object": object}

circuits = [qc.copy() for _ in range(5)]

backend = self.backend()
job = backend.run(circuits)

for circuit in circuits:
self.assertTrue("foo" in circuit.metadata)
self.assertEqual(circuit.metadata["foo"], "bar")
self.assertEqual(circuit.metadata["object"], object)

job.result()

0 comments on commit 0d0c1ef

Please sign in to comment.