2020-10-14 03:45:49 +08:00
|
|
|
# This code is part of Qiskit.
|
|
|
|
#
|
|
|
|
# (C) Copyright IBM 2018, 2019.
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
|
|
|
# pylint: disable=invalid-name
|
|
|
|
"""
|
2023-10-26 10:20:27 +08:00
|
|
|
Aer simulator backend utils
|
2020-10-14 03:45:49 +08:00
|
|
|
"""
|
|
|
|
import os
|
|
|
|
from math import log2
|
2023-11-21 12:00:10 +08:00
|
|
|
|
|
|
|
import psutil
|
2020-10-14 03:45:49 +08:00
|
|
|
from qiskit.circuit import QuantumCircuit
|
2021-08-24 06:32:20 +08:00
|
|
|
from qiskit.qobj import QasmQobjInstruction
|
2021-12-11 05:29:21 +08:00
|
|
|
from qiskit.result import ProbDistribution
|
|
|
|
from qiskit.quantum_info import Clifford
|
2023-11-21 12:00:10 +08:00
|
|
|
|
2021-12-11 05:29:21 +08:00
|
|
|
from .compatibility import Statevector, DensityMatrix, StabilizerState, Operator, SuperOp
|
|
|
|
|
2024-05-21 09:55:03 +08:00
|
|
|
# pylint: disable=import-error, no-name-in-module, abstract-method
|
|
|
|
from .controller_wrappers import aer_initialize_libraries
|
|
|
|
|
2020-10-14 03:45:49 +08:00
|
|
|
# Available system memory
|
2023-11-21 12:00:10 +08:00
|
|
|
SYSTEM_MEMORY_GB = psutil.virtual_memory().total / (1024**3)
|
2020-10-14 03:45:49 +08:00
|
|
|
|
|
|
|
# Max number of qubits for complex double statevector
|
|
|
|
# given available system memory
|
|
|
|
MAX_QUBITS_STATEVECTOR = int(log2(SYSTEM_MEMORY_GB * (1024**3) / 16))
|
|
|
|
|
|
|
|
# Location where we put external libraries that will be
|
|
|
|
# loaded at runtime by the simulator extension
|
|
|
|
LIBRARY_DIR = os.path.dirname(__file__)
|
2024-05-21 09:55:03 +08:00
|
|
|
aer_initialize_libraries(LIBRARY_DIR)
|
2020-10-14 03:45:49 +08:00
|
|
|
|
2021-08-24 06:32:20 +08:00
|
|
|
LEGACY_METHOD_MAP = {
|
|
|
|
"statevector_cpu": ("statevector", "CPU"),
|
|
|
|
"statevector_gpu": ("statevector", "GPU"),
|
|
|
|
"statevector_thrust": ("statevector", "Thrust"),
|
|
|
|
"density_matrix_cpu": ("density_matrix", "CPU"),
|
|
|
|
"density_matrix_gpu": ("density_matrix", "GPU"),
|
|
|
|
"density_matrix_thrust": ("density_matrix", "Thrust"),
|
|
|
|
"unitary_cpu": ("unitary", "CPU"),
|
|
|
|
"unitary_gpu": ("unitary", "GPU"),
|
|
|
|
"unitary_thrust": ("unitary", "Thrust"),
|
|
|
|
}
|
|
|
|
|
2021-11-09 02:54:05 +08:00
|
|
|
BASIS_GATES = {
|
|
|
|
"statevector": sorted(
|
|
|
|
[
|
|
|
|
"u1",
|
|
|
|
"u2",
|
|
|
|
"u3",
|
|
|
|
"u",
|
|
|
|
"p",
|
|
|
|
"r",
|
|
|
|
"rx",
|
|
|
|
"ry",
|
|
|
|
"rz",
|
|
|
|
"id",
|
|
|
|
"x",
|
|
|
|
"y",
|
|
|
|
"z",
|
|
|
|
"h",
|
|
|
|
"s",
|
|
|
|
"sdg",
|
|
|
|
"sx",
|
|
|
|
"sxdg",
|
|
|
|
"t",
|
|
|
|
"tdg",
|
|
|
|
"swap",
|
|
|
|
"cx",
|
|
|
|
"cy",
|
|
|
|
"cz",
|
|
|
|
"csx",
|
|
|
|
"cp",
|
|
|
|
"cu",
|
|
|
|
"cu1",
|
|
|
|
"cu2",
|
|
|
|
"cu3",
|
|
|
|
"rxx",
|
|
|
|
"ryy",
|
|
|
|
"rzz",
|
|
|
|
"rzx",
|
|
|
|
"ccx",
|
2024-03-28 10:29:17 +08:00
|
|
|
"ccz",
|
2024-05-28 12:39:49 +08:00
|
|
|
"crx",
|
|
|
|
"cry",
|
|
|
|
"crz",
|
2021-11-09 02:54:05 +08:00
|
|
|
"cswap",
|
|
|
|
"mcx",
|
|
|
|
"mcy",
|
|
|
|
"mcz",
|
|
|
|
"mcsx",
|
|
|
|
"mcp",
|
|
|
|
"mcphase",
|
|
|
|
"mcu",
|
|
|
|
"mcu1",
|
|
|
|
"mcu2",
|
|
|
|
"mcu3",
|
|
|
|
"mcrx",
|
|
|
|
"mcry",
|
|
|
|
"mcrz",
|
|
|
|
"mcr",
|
|
|
|
"mcswap",
|
|
|
|
"unitary",
|
|
|
|
"diagonal",
|
|
|
|
"multiplexer",
|
2022-12-03 05:26:38 +08:00
|
|
|
"initialize",
|
|
|
|
"pauli",
|
|
|
|
"mcx_gray",
|
|
|
|
"ecr",
|
2024-06-17 09:41:55 +08:00
|
|
|
"store",
|
2021-11-09 02:54:05 +08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
"density_matrix": sorted(
|
|
|
|
[
|
|
|
|
"u1",
|
|
|
|
"u2",
|
|
|
|
"u3",
|
|
|
|
"u",
|
|
|
|
"p",
|
|
|
|
"r",
|
|
|
|
"rx",
|
|
|
|
"ry",
|
|
|
|
"rz",
|
|
|
|
"id",
|
|
|
|
"x",
|
|
|
|
"y",
|
|
|
|
"z",
|
|
|
|
"h",
|
|
|
|
"s",
|
|
|
|
"sdg",
|
|
|
|
"sx",
|
|
|
|
"sxdg",
|
|
|
|
"t",
|
|
|
|
"tdg",
|
|
|
|
"swap",
|
|
|
|
"cx",
|
|
|
|
"cy",
|
|
|
|
"cz",
|
|
|
|
"cp",
|
|
|
|
"cu1",
|
|
|
|
"rxx",
|
|
|
|
"ryy",
|
|
|
|
"rzz",
|
|
|
|
"rzx",
|
2022-12-03 05:26:38 +08:00
|
|
|
"ccx",
|
|
|
|
"unitary",
|
|
|
|
"diagonal",
|
|
|
|
"pauli",
|
|
|
|
"ecr",
|
2021-11-09 02:54:05 +08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
"matrix_product_state": sorted(
|
|
|
|
[
|
|
|
|
"u1",
|
|
|
|
"u2",
|
|
|
|
"u3",
|
|
|
|
"u",
|
|
|
|
"p",
|
|
|
|
"cp",
|
|
|
|
"cx",
|
|
|
|
"cy",
|
|
|
|
"cz",
|
|
|
|
"id",
|
|
|
|
"x",
|
|
|
|
"y",
|
|
|
|
"z",
|
|
|
|
"h",
|
|
|
|
"s",
|
|
|
|
"sdg",
|
|
|
|
"sx",
|
|
|
|
"sxdg",
|
2023-03-14 04:19:06 +08:00
|
|
|
"t",
|
2021-11-09 02:54:05 +08:00
|
|
|
"tdg",
|
|
|
|
"swap",
|
|
|
|
"ccx",
|
|
|
|
"unitary",
|
|
|
|
"roerror",
|
|
|
|
"pauli",
|
|
|
|
"r",
|
|
|
|
"rx",
|
|
|
|
"ry",
|
|
|
|
"rz",
|
|
|
|
"rxx",
|
|
|
|
"ryy",
|
|
|
|
"rzz",
|
|
|
|
"rzx",
|
|
|
|
"csx",
|
|
|
|
"cswap",
|
|
|
|
"diagonal",
|
|
|
|
"initialize",
|
2024-05-29 12:05:44 +08:00
|
|
|
"ecr",
|
2024-06-17 09:41:55 +08:00
|
|
|
"store",
|
2021-11-09 02:54:05 +08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
"stabilizer": sorted(
|
|
|
|
[
|
|
|
|
"id",
|
|
|
|
"x",
|
|
|
|
"y",
|
|
|
|
"z",
|
|
|
|
"h",
|
|
|
|
"s",
|
|
|
|
"sdg",
|
|
|
|
"sx",
|
|
|
|
"sxdg",
|
|
|
|
"cx",
|
|
|
|
"cy",
|
|
|
|
"cz",
|
|
|
|
"swap",
|
|
|
|
"pauli",
|
2023-08-22 12:01:19 +08:00
|
|
|
"ecr",
|
2023-09-19 13:51:36 +08:00
|
|
|
"rz",
|
2024-06-17 09:41:55 +08:00
|
|
|
"store",
|
2021-11-09 02:54:05 +08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
"extended_stabilizer": sorted(
|
|
|
|
[
|
|
|
|
"cx",
|
|
|
|
"cz",
|
|
|
|
"id",
|
|
|
|
"x",
|
|
|
|
"y",
|
|
|
|
"z",
|
|
|
|
"h",
|
|
|
|
"s",
|
|
|
|
"sdg",
|
|
|
|
"sx",
|
|
|
|
"sxdg",
|
|
|
|
"swap",
|
|
|
|
"u0",
|
|
|
|
"t",
|
|
|
|
"tdg",
|
|
|
|
"u1",
|
|
|
|
"p",
|
|
|
|
"ccx",
|
|
|
|
"ccz",
|
|
|
|
"pauli",
|
2024-05-29 12:05:44 +08:00
|
|
|
"ecr",
|
2024-05-28 12:39:49 +08:00
|
|
|
"rz",
|
2024-06-17 09:41:55 +08:00
|
|
|
"store",
|
2021-11-09 02:54:05 +08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
"unitary": sorted(
|
|
|
|
[
|
|
|
|
"u1",
|
|
|
|
"u2",
|
|
|
|
"u3",
|
|
|
|
"u",
|
|
|
|
"p",
|
|
|
|
"r",
|
|
|
|
"rx",
|
|
|
|
"ry",
|
|
|
|
"rz",
|
|
|
|
"id",
|
|
|
|
"x",
|
|
|
|
"y",
|
|
|
|
"z",
|
|
|
|
"h",
|
|
|
|
"s",
|
|
|
|
"sdg",
|
|
|
|
"sx",
|
|
|
|
"sxdg",
|
|
|
|
"t",
|
|
|
|
"tdg",
|
|
|
|
"swap",
|
|
|
|
"cx",
|
|
|
|
"cy",
|
|
|
|
"cz",
|
|
|
|
"csx",
|
|
|
|
"cp",
|
|
|
|
"cu",
|
|
|
|
"cu1",
|
|
|
|
"cu2",
|
|
|
|
"cu3",
|
|
|
|
"rxx",
|
|
|
|
"ryy",
|
|
|
|
"rzz",
|
|
|
|
"rzx",
|
|
|
|
"ccx",
|
2024-03-28 10:29:17 +08:00
|
|
|
"ccz",
|
2021-11-09 02:54:05 +08:00
|
|
|
"cswap",
|
2024-05-28 12:39:49 +08:00
|
|
|
"crx",
|
|
|
|
"cry",
|
|
|
|
"crz",
|
2021-11-09 02:54:05 +08:00
|
|
|
"mcx",
|
|
|
|
"mcy",
|
|
|
|
"mcz",
|
|
|
|
"mcsx",
|
|
|
|
"mcp",
|
|
|
|
"mcphase",
|
|
|
|
"mcu",
|
|
|
|
"mcu1",
|
|
|
|
"mcu2",
|
|
|
|
"mcu3",
|
|
|
|
"mcrx",
|
|
|
|
"mcry",
|
|
|
|
"mcrz",
|
|
|
|
"mcr",
|
|
|
|
"mcswap",
|
|
|
|
"unitary",
|
|
|
|
"diagonal",
|
|
|
|
"multiplexer",
|
|
|
|
"pauli",
|
2022-12-03 05:26:38 +08:00
|
|
|
"ecr",
|
2024-06-17 09:41:55 +08:00
|
|
|
"store",
|
2021-11-09 02:54:05 +08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
"superop": sorted(
|
|
|
|
[
|
|
|
|
"u1",
|
|
|
|
"u2",
|
|
|
|
"u3",
|
|
|
|
"u",
|
|
|
|
"p",
|
|
|
|
"r",
|
|
|
|
"rx",
|
|
|
|
"ry",
|
|
|
|
"rz",
|
|
|
|
"id",
|
|
|
|
"x",
|
|
|
|
"y",
|
|
|
|
"z",
|
|
|
|
"h",
|
|
|
|
"s",
|
|
|
|
"sdg",
|
|
|
|
"sx",
|
|
|
|
"sxdg",
|
|
|
|
"t",
|
|
|
|
"tdg",
|
|
|
|
"swap",
|
|
|
|
"cx",
|
|
|
|
"cy",
|
|
|
|
"cz",
|
|
|
|
"cp",
|
|
|
|
"cu1",
|
|
|
|
"rxx",
|
|
|
|
"ryy",
|
2023-01-30 10:57:34 +08:00
|
|
|
"rzz",
|
|
|
|
"rzx",
|
|
|
|
"ccx",
|
|
|
|
"unitary",
|
|
|
|
"diagonal",
|
|
|
|
"pauli",
|
2024-06-17 09:41:55 +08:00
|
|
|
"store",
|
2023-01-30 10:57:34 +08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
"tensor_network": sorted(
|
|
|
|
[
|
|
|
|
"u1",
|
|
|
|
"u2",
|
|
|
|
"u3",
|
|
|
|
"u",
|
|
|
|
"p",
|
|
|
|
"r",
|
|
|
|
"rx",
|
|
|
|
"ry",
|
|
|
|
"rz",
|
|
|
|
"id",
|
|
|
|
"x",
|
|
|
|
"y",
|
|
|
|
"z",
|
|
|
|
"h",
|
|
|
|
"s",
|
|
|
|
"sdg",
|
|
|
|
"sx",
|
|
|
|
"sxdg",
|
|
|
|
"t",
|
|
|
|
"tdg",
|
|
|
|
"swap",
|
|
|
|
"cx",
|
|
|
|
"cy",
|
|
|
|
"cz",
|
|
|
|
"csx",
|
|
|
|
"cp",
|
|
|
|
"cu",
|
|
|
|
"cu1",
|
|
|
|
"cu2",
|
|
|
|
"cu3",
|
|
|
|
"rxx",
|
|
|
|
"ryy",
|
|
|
|
"rzz",
|
|
|
|
"rzx",
|
|
|
|
"ccx",
|
2024-03-28 10:29:17 +08:00
|
|
|
"ccz",
|
2023-01-30 10:57:34 +08:00
|
|
|
"cswap",
|
2024-05-28 12:39:49 +08:00
|
|
|
"crx",
|
|
|
|
"cry",
|
|
|
|
"crz",
|
2023-01-30 10:57:34 +08:00
|
|
|
"mcx",
|
|
|
|
"mcy",
|
|
|
|
"mcz",
|
|
|
|
"mcsx",
|
|
|
|
"mcp",
|
|
|
|
"mcphase",
|
|
|
|
"mcu",
|
|
|
|
"mcu1",
|
|
|
|
"mcu2",
|
|
|
|
"mcu3",
|
|
|
|
"mcrx",
|
|
|
|
"mcry",
|
|
|
|
"mcrz",
|
|
|
|
"mcr",
|
|
|
|
"mcswap",
|
|
|
|
"unitary",
|
|
|
|
"diagonal",
|
|
|
|
"multiplexer",
|
|
|
|
"initialize",
|
|
|
|
"pauli",
|
|
|
|
"mcx_gray",
|
2024-05-29 12:05:44 +08:00
|
|
|
"ecr",
|
2024-06-17 09:41:55 +08:00
|
|
|
"store",
|
2021-11-09 02:54:05 +08:00
|
|
|
]
|
2023-03-14 04:19:06 +08:00
|
|
|
),
|
2021-11-09 02:54:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
# Automatic method basis gates are the union of statevector,
|
|
|
|
# density matrix, and stabilizer methods
|
|
|
|
BASIS_GATES[None] = BASIS_GATES["automatic"] = sorted(
|
|
|
|
set(BASIS_GATES["statevector"])
|
|
|
|
.union(BASIS_GATES["stabilizer"])
|
|
|
|
.union(BASIS_GATES["density_matrix"])
|
|
|
|
.union(BASIS_GATES["matrix_product_state"])
|
|
|
|
.union(BASIS_GATES["unitary"])
|
2023-01-30 10:57:34 +08:00
|
|
|
.union(BASIS_GATES["superop"])
|
|
|
|
.union(BASIS_GATES["tensor_network"])
|
2023-03-14 04:19:06 +08:00
|
|
|
)
|
2021-11-09 02:54:05 +08:00
|
|
|
|
2020-10-14 03:45:49 +08:00
|
|
|
|
2023-03-09 00:21:15 +08:00
|
|
|
def cpp_execute_qobj(controller, qobj):
|
2021-03-31 09:53:20 +08:00
|
|
|
"""Execute qobj on C++ controller wrapper"""
|
2020-10-14 03:45:49 +08:00
|
|
|
|
|
|
|
# Location where we put external libraries that will be
|
|
|
|
# loaded at runtime by the simulator extension
|
2021-03-31 09:53:20 +08:00
|
|
|
qobj.config.library_dir = LIBRARY_DIR
|
|
|
|
return controller(qobj)
|
2020-10-14 03:45:49 +08:00
|
|
|
|
|
|
|
|
2023-03-09 00:21:15 +08:00
|
|
|
def cpp_execute_circuits(controller, aer_circuits, noise_model, config):
|
|
|
|
"""Execute aer circuits on C++ controller wrapper"""
|
|
|
|
|
|
|
|
# Location where we put external libraries that will be
|
|
|
|
# loaded at runtime by the simulator extension
|
|
|
|
config.library_dir = LIBRARY_DIR
|
|
|
|
|
|
|
|
noise_model = noise_model.to_dict(serializable=True) if noise_model else {}
|
|
|
|
|
|
|
|
return controller.execute(aer_circuits, noise_model, config)
|
|
|
|
|
|
|
|
|
2023-12-08 21:47:38 +08:00
|
|
|
def available_methods(methods, devices):
|
|
|
|
"""Check available simulation methods"""
|
2020-10-14 03:45:49 +08:00
|
|
|
|
|
|
|
valid_methods = []
|
2023-12-08 21:47:38 +08:00
|
|
|
for method in methods:
|
|
|
|
if method == "tensor_network":
|
|
|
|
if "GPU" in devices:
|
|
|
|
valid_methods.append(method)
|
|
|
|
else:
|
|
|
|
valid_methods.append(method)
|
2021-08-24 06:32:20 +08:00
|
|
|
return tuple(valid_methods)
|
2021-04-01 02:16:44 +08:00
|
|
|
|
|
|
|
|
2023-12-08 21:47:38 +08:00
|
|
|
def available_devices(controller):
|
|
|
|
"""return available simulation devices"""
|
|
|
|
dev = controller.available_devices()
|
|
|
|
return tuple(dev)
|
2021-08-24 06:32:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
def add_final_save_instruction(qobj, state):
|
|
|
|
"""Add final save state instruction to all experiments in a qobj."""
|
|
|
|
|
|
|
|
def save_inst(num_qubits):
|
|
|
|
"""Return n-qubit save statevector inst"""
|
|
|
|
return QasmQobjInstruction(
|
|
|
|
name=f"save_{state}",
|
|
|
|
qubits=list(range(num_qubits)),
|
|
|
|
label=f"{state}",
|
|
|
|
snapshot_type="single",
|
|
|
|
)
|
|
|
|
|
|
|
|
for exp in qobj.experiments:
|
|
|
|
num_qubits = exp.config.n_qubits
|
|
|
|
exp.instructions.append(save_inst(num_qubits))
|
|
|
|
|
|
|
|
return qobj
|
|
|
|
|
|
|
|
|
2023-03-09 00:21:15 +08:00
|
|
|
def add_final_save_op(aer_circuits, state):
|
|
|
|
"""Add final save state op to all experiments in a qobj."""
|
|
|
|
|
|
|
|
for aer_circuit in aer_circuits:
|
|
|
|
num_qubits = aer_circuit.num_qubits
|
|
|
|
aer_circuit.save_state(list(range(num_qubits)), f"save_{state}", "single", state)
|
|
|
|
|
|
|
|
return aer_circuits
|
|
|
|
|
|
|
|
|
2021-08-24 06:32:20 +08:00
|
|
|
def map_legacy_method_options(qobj):
|
|
|
|
"""Map legacy method names of qasm simulator to aer simulator options"""
|
|
|
|
method = getattr(qobj.config, "method", None)
|
|
|
|
if method in LEGACY_METHOD_MAP:
|
|
|
|
qobj.config.method, qobj.config.device = LEGACY_METHOD_MAP[method]
|
|
|
|
return qobj
|
2021-12-11 05:29:21 +08:00
|
|
|
|
|
|
|
|
2023-03-09 00:21:15 +08:00
|
|
|
def map_legacy_method_config(config):
|
|
|
|
"""Map legacy method names of qasm simulator to aer simulator options"""
|
|
|
|
method = config.method
|
|
|
|
if method in LEGACY_METHOD_MAP:
|
|
|
|
config.method, config.device = LEGACY_METHOD_MAP[method]
|
|
|
|
return config
|
|
|
|
|
|
|
|
|
2021-12-11 05:29:21 +08:00
|
|
|
def format_save_type(data, save_type, save_subtype):
|
|
|
|
"""Format raw simulator result data based on save type."""
|
|
|
|
init_fns = {
|
|
|
|
"save_statevector": Statevector,
|
|
|
|
"save_density_matrix": DensityMatrix,
|
|
|
|
"save_unitary": Operator,
|
|
|
|
"save_superop": SuperOp,
|
|
|
|
"save_stabilizer": (lambda data: StabilizerState(Clifford.from_dict(data))),
|
|
|
|
"save_clifford": Clifford.from_dict,
|
|
|
|
"save_probabilities_dict": ProbDistribution,
|
|
|
|
}
|
|
|
|
|
|
|
|
# Non-handled cases return raw data
|
|
|
|
if save_type not in init_fns:
|
|
|
|
return data
|
|
|
|
|
|
|
|
if save_subtype in ["list", "c_list"]:
|
2023-03-14 04:19:06 +08:00
|
|
|
|
2021-12-11 05:29:21 +08:00
|
|
|
def func(data):
|
|
|
|
init_fn = init_fns[save_type]
|
|
|
|
return [init_fn(i) for i in data]
|
2023-03-14 04:19:06 +08:00
|
|
|
|
2021-12-11 05:29:21 +08:00
|
|
|
else:
|
|
|
|
func = init_fns[save_type]
|
|
|
|
|
|
|
|
# Conditional save
|
|
|
|
if save_subtype[:2] == "c_":
|
|
|
|
return {key: func(val) for key, val in data.items()}
|
|
|
|
|
|
|
|
return func(data)
|
2021-12-17 03:28:27 +08:00
|
|
|
|
|
|
|
|
|
|
|
def circuit_optypes(circuit):
|
|
|
|
"""Return set of all operation types and parent types in a circuit."""
|
|
|
|
if not isinstance(circuit, QuantumCircuit):
|
|
|
|
return set()
|
|
|
|
optypes = set()
|
|
|
|
for inst, _, _ in circuit._data:
|
|
|
|
optypes.update(type(inst).mro())
|
|
|
|
optypes.discard(object)
|
|
|
|
return optypes
|