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

♻️ BackendV2 migration of MQT DDSIM Qiskit backends #267

Merged
merged 115 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
95b5eeb
BackendV2 migration of Qasmsimulator
andresbar98 Jul 24, 2023
b6ef98e
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 24, 2023
c17f69c
qasmsimulator file renamed
andresbar98 Jul 25, 2023
7d4a1fe
backend_migration
andresbar98 Jul 25, 2023
cd72fa6
Included the remaining multi-controlled gates and modified some featu…
andresbar98 Aug 1, 2023
1c81a2e
modified test and QasmSimulatorFile
andresbar98 Aug 1, 2023
fd031e0
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 1, 2023
a79eb0d
more changes
andresbar98 Aug 1, 2023
2f2b268
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 1, 2023
8b12671
more changes to custom gate classes
andresbar98 Aug 2, 2023
57f65e5
Merge branch 'backend_migration' of https://github.com/andresbar98/mq…
andresbar98 Aug 2, 2023
d2ec824
More changes to qasmsimulator.py, statevectorsimulator.py and their c…
andresbar98 Aug 2, 2023
b16a2c6
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 2, 2023
d283920
more changes to qasmsimulator.py/Explicitely initializing QuantumCirc…
andresbar98 Aug 2, 2023
26f43c1
1
andresbar98 Aug 2, 2023
4855dca
more changes
andresbar98 Aug 2, 2023
5e59c8e
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 2, 2023
a255651
changed some test files, some of them were calling attributes of back…
andresbar98 Aug 3, 2023
d63d6ea
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 3, 2023
b1c3774
added header to result object in qasmsimulator.py
andresbar98 Aug 3, 2023
4b7f740
merge
andresbar98 Aug 3, 2023
9c2354c
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 3, 2023
378e659
recuperated experiment header information that was previously deleted
andresbar98 Aug 6, 2023
bab5a2c
merging
andresbar98 Aug 6, 2023
2e0248c
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 6, 2023
34018ab
Change the usage of keyword arguments in the class definitions
andresbar98 Aug 6, 2023
b7b46eb
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 6, 2023
05bc5dd
Merge branch 'main' into backend_migration
hillmich Aug 8, 2023
68240fb
Merge branch 'cda-tum:main' into backend_migration
andresbar98 Aug 8, 2023
c976612
Removed logger and reset is now supported gate
andresbar98 Aug 8, 2023
85caf9e
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 8, 2023
166a99a
🔥 remove deprecated `configuration` method and member
burgholzer Aug 8, 2023
9b1bbf9
🩹 properly return `None` for `max_circuits`
burgholzer Aug 8, 2023
4cd02e4
🩹 properly use properties for target
burgholzer Aug 8, 2023
20cf1f3
🔥 remove debugging code
burgholzer Aug 8, 2023
74c22d5
♻️ simplify constructors
burgholzer Aug 8, 2023
77eb8e7
🔥 remove the superfluous `_validate` method
burgholzer Aug 8, 2023
07ceecf
🔥 remove logger from `Job`
burgholzer Aug 8, 2023
b88b050
♻️ simplify constructor
burgholzer Aug 8, 2023
cd05ad1
🔥 `status()` is no longer required in `BackendV2`
burgholzer Aug 8, 2023
c6762e7
🔥 remove useless tests
burgholzer Aug 8, 2023
3120715
♻️ significantly simplify Provider
burgholzer Aug 8, 2023
449d7a3
🚨 better typing
burgholzer Aug 8, 2023
2585544
♻️ add dedicated target handling
burgholzer Aug 8, 2023
b419554
♻️ refactor QASM Simulator tests to use pytest
burgholzer Aug 8, 2023
e59506b
🚨 better typing
burgholzer Aug 8, 2023
42dd45d
✅ add tests for multi-qubit gate support
burgholzer Aug 8, 2023
6cb6e31
🩹 add `MCXGate` to definitions
burgholzer Aug 8, 2023
6b35974
✅ add tests for target gate set support
burgholzer Aug 8, 2023
91c3f49
♻️ simplify Job class and better typing
burgholzer Aug 9, 2023
726130e
🔥 remove unnecessary check
burgholzer Aug 9, 2023
c94b3c6
🩹 fix name of seed option
burgholzer Aug 9, 2023
5055902
♻️ simplify handling of simulator
burgholzer Aug 9, 2023
68ba5ea
migration to BackendV2 of unitarysimulator.py
andresbar98 Aug 13, 2023
653e89f
Removed useless tests from test_unitary_simulator.py
andresbar98 Aug 13, 2023
53033df
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 13, 2023
16eb3d6
Merge branch 'cda-tum:main' into backend_migration
andresbar98 Aug 13, 2023
c95986b
Removed old configuration call
andresbar98 Aug 13, 2023
18b1d68
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 13, 2023
2f807f5
Recover header object/ Build it on a different file
andresbar98 Aug 16, 2023
ed55644
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 16, 2023
57aa2ea
Minor changes to UnitarySimulatorBackend
andresbar98 Aug 16, 2023
10c40ff
Restored old configuration calls for backends that haven't been modified
andresbar98 Aug 16, 2023
e99d0c6
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 16, 2023
3414971
Fixed small error in usage.ipynb
andresbar98 Aug 16, 2023
d745245
Modified job handling
andresbar98 Aug 16, 2023
bff5212
Merge branch 'cda-tum:main' into backend_migration
andresbar98 Aug 16, 2023
477dac4
Merge branch 'backend_migration' of https://github.com/andresbar98/mq…
andresbar98 Aug 16, 2023
31336ce
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 16, 2023
94be19a
Fixed error using |: function
andresbar98 Aug 16, 2023
2c50dc6
Merge branch 'backend_migration' of https://github.com/andresbar98/mq…
andresbar98 Aug 16, 2023
1725398
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 16, 2023
0b83fdc
Fixed problem with header.py
andresbar98 Aug 17, 2023
0b7ad80
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 17, 2023
f5d553a
Fixed error in test_target
andresbar98 Aug 20, 2023
5838886
Fixed small error
andresbar98 Aug 24, 2023
c26fc88
⬆️🪝 update pre-commit hooks (#282)
pre-commit-ci[bot] Aug 22, 2023
ddd69a3
Manually merged commits from main branch
andresbar98 Aug 24, 2023
bdddec3
Merge branch 'main' into backend_migration
andresbar98 Aug 24, 2023
cb12537
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 24, 2023
77cd493
Fixed python typing
andresbar98 Aug 25, 2023
2aa10a8
Merge branch 'backend_migration' of https://github.com/andresbar98/mq…
andresbar98 Aug 25, 2023
84a959a
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 25, 2023
a05eb66
Migration of pathqasmsim and pathstatevectorsim
andresbar98 Aug 25, 2023
72edcf3
Merge branch 'backend_migration' of https://github.com/andresbar98/mq…
andresbar98 Aug 25, 2023
812d7c2
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 25, 2023
e9d9ef7
Fixed small typo
andresbar98 Aug 25, 2023
72875c7
Fixed small typo
andresbar98 Aug 25, 2023
9336ff9
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 25, 2023
c761ba6
Migration of HybridQasmSim and HybridStateVectorSim
andresbar98 Aug 26, 2023
4bca1ec
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 26, 2023
0f79433
Fixed typos
andresbar98 Aug 26, 2023
3b0f21b
FIxed more typos
andresbar98 Aug 26, 2023
fb4e540
♻️ Refactor simulator backends
burgholzer Aug 26, 2023
cc62e82
✅ improve tests
burgholzer Aug 26, 2023
4f8c6a7
🧪 make tests that should fail fail again
burgholzer Aug 26, 2023
0f7eea5
🔀 main
burgholzer Aug 28, 2023
8c54447
🩹 post-merge fixes
burgholzer Aug 28, 2023
e739943
🚨 fix mypy warnings
burgholzer Aug 28, 2023
8cbdb4e
Added test for multiple circuits in a job
andresbar98 Aug 30, 2023
3209a64
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 30, 2023
df75872
Fixed small error
andresbar98 Aug 30, 2023
2484a1e
Fixed small error
andresbar98 Aug 30, 2023
643bff0
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 30, 2023
49f32c4
Merge branch 'cda-tum:main' into backend_migration
andresbar98 Aug 30, 2023
ac677af
Fixed old check warning
andresbar98 Sep 1, 2023
f2a50ff
Attribute error check for GlobalPhaseGate
andresbar98 Sep 1, 2023
6ad8119
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 1, 2023
d9db534
Attribute error check for CSGate
andresbar98 Sep 1, 2023
3efbd56
Fixed Attribute error in some recent gates/Fixed error with _validate…
andresbar98 Sep 2, 2023
2f60039
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 2, 2023
208d3c4
Small changes to test_target
andresbar98 Sep 5, 2023
f3c5801
Update test/python/test_target.py
andresbar98 Sep 5, 2023
f067f8e
Update test/python/test_target.py
andresbar98 Sep 5, 2023
fd2dc2f
Merge branch 'main' into backend_migration
burgholzer Sep 6, 2023
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
157 changes: 135 additions & 22 deletions mqt/ddsim/qasmsimulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,53 @@
from typing import Dict, List, Union

from qiskit import QiskitError, QuantumCircuit
from qiskit.compiler import assemble
from qiskit.providers import BackendV1, Options
from qiskit.circuit import Parameter
from qiskit.circuit.library import (
MCMT,
GlobalPhaseGate,
MCPhaseGate,
MCXGrayCode,
MCXRecursive,
MCXVChain,
Measure,
RXGate,
RYGate,
RZGate,
)
from qiskit.providers import BackendV2, Options
from qiskit.providers.models import BackendConfiguration, BackendStatus
from qiskit.qobj import PulseQobj, QasmQobj, QasmQobjExperiment, Qobj
from qiskit.qobj import PulseQobj, QasmQobj
from qiskit.result import Result
from qiskit.transpiler import Target

from mqt.ddsim import CircuitSimulator, __version__
from mqt.ddsim.job import DDSIMJob

logger = logging.getLogger(__name__)
hillmich marked this conversation as resolved.
Show resolved Hide resolved


class QasmSimulatorBackend(BackendV1):
# Need to define new class for mcrx, mcry and mcrz. They cannot be found in qiskit.circuit.library


class MCRXGate(MCMT):
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
def __init__(self, num_ctrl_qubits=None, theta=None):
super().__init__(gate=RXGate(theta), num_ctrl_qubits=num_ctrl_qubits, num_target_qubits=1)
QuantumCircuit.__init__(self)


class MCRYGate(MCMT):
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
def __init__(self, num_ctrl_qubits=None, theta=None):
super().__init__(gate=RYGate(theta), num_ctrl_qubits=num_ctrl_qubits, num_target_qubits=1)
QuantumCircuit.__init__(self)


class MCRZGate(MCMT):
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
def __init__(self, num_ctrl_qubits=None, theta=None):
super().__init__(gate=RZGate(theta), num_ctrl_qubits=num_ctrl_qubits, num_target_qubits=1)
QuantumCircuit.__init__(self)


class QasmSimulatorBackend(BackendV2):
"""Python interface to MQT DDSIM"""

SHOW_STATE_VECTOR = False
Expand All @@ -35,7 +69,7 @@ def _default_options(cls) -> Options:
approximation_strategy="fidelity",
)

def __init__(self, configuration=None, provider=None):
def __init__(self, provider=None, name=None, description=None, online_date=None, backend_version=None):
conf = {
"backend_name": "qasm_simulator",
"backend_version": __version__,
Expand Down Expand Up @@ -94,7 +128,6 @@ def __init__(self, configuration=None, provider=None):
"rzx",
"xx_minus_yy",
"xx_plus_yy",
"snapshot",
],
"memory": False,
"n_qubits": 64,
Expand All @@ -104,7 +137,55 @@ def __init__(self, configuration=None, provider=None):
"open_pulse": False,
"gates": [],
}
super().__init__(configuration=configuration or BackendConfiguration.from_dict(conf), provider=provider)

custom_name_mapping_dict = {
"gphase": GlobalPhaseGate(Parameter("ϴ")),
"u0": GlobalPhaseGate(Parameter("ϴ")),
"mcphase": MCPhaseGate,
"mcx_gray": MCXGrayCode,
"mcx_recursive": MCXRecursive,
"mcx_vchain": MCXVChain,
"mcrx": MCRXGate,
"mcry": MCRYGate,
"mcrz": MCRZGate,
}

super().__init__(
provider=provider,
name=name or "qasm_simulator",
description=description or "MQT DDSIM C++ simulator",
online_date=online_date or None,
backend_version=backend_version or __version__,
)

self.target = Target.from_configuration(
basis_gates=conf["basis_gates"],
coupling_map=None,
num_qubits=64,
custom_name_mapping=custom_name_mapping_dict,
)

self.target.add_instruction(Measure())
self._configuration = BackendConfiguration.from_dict(conf)

def target(self):
return self.target

def configuration(self):
warnings.warn(
"The configuration() method is deprecated and will be removed in a "
"future release. Instead you should access these attributes directly "
"off the object or via the .target attribute. You can refer to qiskit "
"backend interface transition guide for the exact changes: "
"https://qiskit.org/documentation/apidoc/providers.html#backendv1-backendv2",
DeprecationWarning,
stacklevel=1,
)

return self._configuration

def max_circuits(self):
return 1000000000

def run(self, quantum_circuits: Union[QuantumCircuit, List[QuantumCircuit]], **options) -> DDSIMJob:
if isinstance(quantum_circuits, (QasmQobj, PulseQobj)):
Expand All @@ -120,42 +201,42 @@ def run(self, quantum_circuits: Union[QuantumCircuit, List[QuantumCircuit]], **o
warnings.warn("Option %s is not used by this backend" % key, UserWarning, stacklevel=2)
else:
out_options[key] = options[key]
circuit_qobj = assemble(quantum_circuits, self, **out_options)

job_id = str(uuid.uuid4())
local_job = DDSIMJob(self, job_id, self._run_job, circuit_qobj, **options)
local_job = DDSIMJob(self, job_id, self._run_job, quantum_circuits, **options)
local_job.submit()
return local_job

def _run_job(self, job_id, qobj_instance: Qobj, **options) -> Result:
self._validate(qobj_instance)
def _run_job(self, job_id, quantum_circuits: list, **options) -> Result:
self._validate(quantum_circuits)

start = time.time()
result_list = [self.run_experiment(qobj_exp, **options) for qobj_exp in qobj_instance.experiments]
result_list = [self.run_experiment(q_circ, **options) for q_circ in quantum_circuits]
end = time.time()

result = {
"backend_name": self.configuration().backend_name,
"backend_version": self.configuration().backend_version,
"qobj_id": qobj_instance.qobj_id,
"backend_name": self.name,
"backend_version": self.backend_version,
"qobj_id": None,
"job_id": job_id,
"results": result_list,
"status": "COMPLETED",
"success": True,
"time_taken": (end - start),
"header": qobj_instance.header.to_dict(),
"header": {"backend_name": self.name, "backend_version": self.backend_version},
}

return Result.from_dict(result)

def run_experiment(self, qobj_experiment: QasmQobjExperiment, **options) -> Dict:
def run_experiment(self, q_circ: QuantumCircuit, **options) -> Dict:
start_time = time.time()
approximation_step_fidelity = options.get("approximation_step_fidelity", 1.0)
approximation_steps = options.get("approximation_steps", 1)
approximation_strategy = options.get("approximation_strategy", "fidelity")
seed = options.get("seed", -1)

sim = CircuitSimulator(
qobj_experiment,
q_circ,
approximation_step_fidelity=approximation_step_fidelity,
approximation_steps=approximation_steps,
approximation_strategy=approximation_strategy,
Expand All @@ -165,16 +246,48 @@ def run_experiment(self, qobj_experiment: QasmQobjExperiment, **options) -> Dict
end_time = time.time()
counts_hex = {hex(int(result, 2)): count for result, count in counts.items()}

qubit_labels = []
clbit_labels = []
qreg_sizes = []
creg_sizes = []

for qreg in q_circ.qregs:
qreg_sizes.append([qreg.name, qreg.size])
for j in range(qreg.size):
qubit_labels.append([qreg.name, j])

for creg in q_circ.cregs:
creg_sizes.append([creg.name, creg.size])
for j in range(creg.size):
clbit_labels.append([creg.name, j])

metadata = q_circ.metadata
if metadata is None:
metadata = {}

header_dict = {
"clbit_labels": clbit_labels,
"qubit_labels": qubit_labels,
"creg_sizes": creg_sizes,
"qreg_sizes": qreg_sizes,
"n_qubits": q_circ.num_qubits,
"memory_slots": q_circ.num_clbits,
"name": q_circ.name,
"global_phase": q_circ.global_phase,
"metadata": metadata,
}

result = {
"header": qobj_experiment.header.to_dict(),
"name": qobj_experiment.header.name,
"header": header_dict,
"name": q_circ.name,
"status": "DONE",
"time_taken": end_time - start_time,
"seed": options.get("seed", -1),
"shots": options.get("shots", 1024),
"data": {"counts": counts_hex},
"success": True,
}

if self.SHOW_STATE_VECTOR:
result["data"]["statevector"] = sim.get_vector()
return result
Expand All @@ -188,8 +301,8 @@ def status(self) -> BackendStatus:
BackendStatus: the status of the backend.
"""
return BackendStatus(
backend_name=self.name(),
backend_version=self.configuration().backend_version,
backend_name=self.name,
backend_version=self.backend_version,
operational=True,
pending_jobs=0,
status_msg="",
Expand Down
80 changes: 8 additions & 72 deletions mqt/ddsim/statevectorsimulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import logging

from qiskit.providers.models import BackendConfiguration

from mqt.ddsim import __version__
from mqt.ddsim.qasmsimulator import QasmSimulatorBackend

Expand All @@ -15,76 +13,14 @@ class StatevectorSimulatorBackend(QasmSimulatorBackend):

SHOW_STATE_VECTOR = True

def __init__(self, configuration=None, provider=None):
conf = {
"backend_name": "statevector_simulator",
"backend_version": __version__,
"url": "https://github.com/cda-tum/mqt-ddsim",
"simulator": True,
"local": True,
"description": "MQT DDSIM C++ simulator",
"basis_gates": [
"gphase",
"id",
"u0",
"u1",
"u2",
"u3",
"cu3",
"x",
"cx",
"ccx",
"mcx_gray",
"mcx_recursive",
"mcx_vchain",
"y",
"cy",
"z",
"cz",
"h",
"ch",
"s",
"sdg",
"t",
"tdg",
"rx",
"crx",
"mcrx",
"ry",
"cry",
"mcry",
"rz",
"crz",
"mcrz",
"p",
"cp",
"cu1",
"mcphase",
"sx",
"csx",
"sxdg",
"swap",
"cswap",
"iswap",
"dcx",
"ecr",
"rxx",
"ryy",
"rzz",
"rzx",
"xx_minus_yy",
"xx_plus_yy",
"snapshot",
],
"memory": False,
"n_qubits": 64,
"coupling_map": None,
"conditional": False,
"max_shots": 1000000000,
"open_pulse": False,
"gates": [],
}
super().__init__(configuration=configuration or BackendConfiguration.from_dict(conf), provider=provider)
def __init__(self, provider=None, name=None, description=None, online_date=None, backend_version=None):
super().__init__(
provider=provider,
name=name or "statevector_simulator",
description=description or "MQT DDSIM C++ simulator",
online_date=online_date or None,
backend_version=backend_version or __version__,
)

def _validate(self, _quantum_circuit):
return
9 changes: 4 additions & 5 deletions test/python/simulator/test_qasm_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ def setUp(self):
)
self.circuit.name = "test"

def test_target(self):
"""Test backend.target"""
return self.backend.target

def test_configuration(self):
"""Test backend.configuration()."""
return self.backend.configuration()

def test_properties(self):
"""Test backend.properties()."""
properties = self.backend.properties()
assert properties is None

def test_status(self):
"""Test backend.status()."""
return self.backend.status()
Expand Down
9 changes: 4 additions & 5 deletions test/python/simulator/test_statevector_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ def setUp(self):
self.q_circuit.h(qr[0])
self.q_circuit.cx(qr[0], qr[1])

def test_target(self):
"""Test backend.target"""
return self.backend.target

def test_configuration(self):
"""Test backend.configuration()."""
return self.backend.configuration()

def test_properties(self):
"""Test backend.properties()."""
properties = self.backend.properties()
assert properties is None

def test_status(self):
"""Test backend.status()."""
return self.backend.status()
Expand Down
2 changes: 1 addition & 1 deletion test/python/test_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ def test_backends(self):
def test_get_backend(self):
"""Test getting a backend from the provider."""
backend = self.provider.get_backend(name=self.backend_name)
assert backend.name() == self.backend_name
assert backend.name == self.backend_name