mirror of https://github.com/Qiskit/qiskit-aer.git
Fix AerCompiler to use custom pass manager to decompose control flow ops (#2095)
* Fix AerCompiler to use basis_gates built from input circuit * use custom pass manager to decompose dontrol flow ops * remove unused import
This commit is contained in:
parent
c0420ea7b5
commit
cf510a2a45
|
@ -36,7 +36,10 @@ from qiskit.circuit.controlflow import (
|
|||
SwitchCaseOp,
|
||||
CASE_DEFAULT,
|
||||
)
|
||||
from qiskit.compiler import transpile
|
||||
from qiskit.transpiler import PassManager
|
||||
from qiskit.transpiler.passes import Decompose
|
||||
|
||||
|
||||
from qiskit.qobj import QobjExperimentHeader
|
||||
from qiskit_aer.aererror import AerError
|
||||
from qiskit_aer.noise import NoiseModel
|
||||
|
@ -67,13 +70,11 @@ class AerCompiler:
|
|||
def __init__(self):
|
||||
self._last_flow_id = -1
|
||||
|
||||
def compile(self, circuits, basis_gates=None, optypes=None):
|
||||
def compile(self, circuits, optypes=None):
|
||||
"""compile a circuit that have control-flow instructions.
|
||||
|
||||
Args:
|
||||
circuits (QuantumCircuit or list): The QuantumCircuits to be compiled
|
||||
basis_gates (list): basis gates to decompose sub-circuits
|
||||
(default: None).
|
||||
optypes (list): list of instruction type sets for each circuit
|
||||
(default: None).
|
||||
|
||||
|
@ -92,17 +93,14 @@ class AerCompiler:
|
|||
# Make a shallow copy incase we modify it
|
||||
compiled_optypes = list(optypes)
|
||||
if isinstance(circuits, list):
|
||||
basis_gates = basis_gates + ["mark", "jump"]
|
||||
compiled_circuits = []
|
||||
for idx, circuit in enumerate(circuits):
|
||||
# Resolve initialize
|
||||
circuit = self._inline_initialize(circuit, compiled_optypes[idx])
|
||||
if self._is_dynamic(circuit, compiled_optypes[idx]):
|
||||
compiled_circ = transpile(
|
||||
self._inline_circuit(circuit, None, None),
|
||||
basis_gates=basis_gates,
|
||||
optimization_level=0,
|
||||
)
|
||||
pm = PassManager([Decompose(["mark", "jump"])])
|
||||
compiled_circ = pm.run(self._inline_circuit(circuit, None, None))
|
||||
|
||||
compiled_circuits.append(compiled_circ)
|
||||
# Recompute optype for compiled circuit
|
||||
compiled_optypes[idx] = circuit_optypes(compiled_circ)
|
||||
|
@ -214,7 +212,6 @@ class AerCompiler:
|
|||
)
|
||||
else:
|
||||
ret._append(instruction)
|
||||
|
||||
return ret
|
||||
|
||||
def _convert_jump_conditional(self, cond_tuple, bit_map):
|
||||
|
@ -272,7 +269,9 @@ class AerCompiler:
|
|||
inlined_body = self._inline_circuit(body, continue_label, break_label, inner_bit_map)
|
||||
if loop_parameter is not None:
|
||||
inlined_body = inlined_body.assign_parameters({loop_parameter: index})
|
||||
parent.append(inlined_body, qargs, cargs)
|
||||
# parent.append(inlined_body, qargs, cargs)
|
||||
for inst in inlined_body:
|
||||
parent.append(inst, qargs, cargs)
|
||||
parent.append(AerMark(continue_label, len(qargs), len(cargs)), qargs, cargs)
|
||||
|
||||
if inlined_body is not None:
|
||||
|
@ -323,7 +322,8 @@ class AerCompiler:
|
|||
)
|
||||
parent.append(AerJump(break_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
parent.append(AerMark(loop_start_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
parent.append(inlined_body, qargs, cargs)
|
||||
for inst in inlined_body:
|
||||
parent.append(inst, qargs, cargs)
|
||||
parent.append(AerJump(continue_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
parent.append(AerMark(break_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
|
||||
|
@ -371,9 +371,9 @@ class AerCompiler:
|
|||
)
|
||||
parent.append(AerJump(if_else_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
parent.append(AerMark(if_true_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
parent.append(
|
||||
self._inline_circuit(true_body, continue_label, break_label, true_bit_map), qargs, cargs
|
||||
)
|
||||
child = self._inline_circuit(true_body, continue_label, break_label, true_bit_map)
|
||||
for inst in child.data:
|
||||
parent.append(inst, qargs, cargs)
|
||||
|
||||
if false_body:
|
||||
false_bit_map = {
|
||||
|
@ -385,11 +385,9 @@ class AerCompiler:
|
|||
}
|
||||
parent.append(AerJump(if_end_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
parent.append(AerMark(if_else_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
parent.append(
|
||||
self._inline_circuit(false_body, continue_label, break_label, false_bit_map),
|
||||
qargs,
|
||||
cargs,
|
||||
)
|
||||
child = self._inline_circuit(false_body, continue_label, break_label, false_bit_map)
|
||||
for inst in child.data:
|
||||
parent.append(inst, qargs, cargs)
|
||||
|
||||
parent.append(AerMark(if_end_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
|
||||
|
@ -468,23 +466,21 @@ class AerCompiler:
|
|||
|
||||
for case_data in case_data_list:
|
||||
parent.append(AerMark(case_data.label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
parent.append(
|
||||
self._inline_circuit(
|
||||
child = self._inline_circuit(
|
||||
case_data.body, continue_label, break_label, case_data.bit_map
|
||||
),
|
||||
qargs,
|
||||
cargs,
|
||||
)
|
||||
for inst in child.data:
|
||||
parent.append(inst, qargs, cargs)
|
||||
parent.append(AerJump(switch_end_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
|
||||
parent.append(AerMark(switch_end_label, len(qargs), len(mark_cargs)), qargs, mark_cargs)
|
||||
|
||||
|
||||
def compile_circuit(circuits, basis_gates=None, optypes=None):
|
||||
def compile_circuit(circuits, optypes=None):
|
||||
"""
|
||||
compile a circuit that have control-flow instructions
|
||||
"""
|
||||
return AerCompiler().compile(circuits, basis_gates, optypes)
|
||||
return AerCompiler().compile(circuits, optypes)
|
||||
|
||||
|
||||
BACKEND_RUN_ARG_TYPES = {
|
||||
|
|
|
@ -517,9 +517,7 @@ class AerBackend(Backend, ABC):
|
|||
optypes = [circuit_optypes(circ) for circ in circuits]
|
||||
|
||||
# Compile Qasm3 instructions
|
||||
circuits, optypes = compile_circuit(
|
||||
circuits, basis_gates=self.configuration().basis_gates, optypes=optypes
|
||||
)
|
||||
circuits, optypes = compile_circuit(circuits, optypes=optypes)
|
||||
|
||||
# run option noise model
|
||||
circuits, noise_model, run_options = self._assemble_noise_model(
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
fixes:
|
||||
- |
|
||||
When the circuit is a dynamic circuit, the input circuit was not correctly
|
||||
transpiled in AerCompiler that causes wrong noise simulation result,
|
||||
because some gates noise to be applied were transpiled to other gates.
|
||||
|
||||
This fix uses custom pass manager to decompose only jump and mark ops
|
||||
Aer uses internally.
|
Loading…
Reference in New Issue