diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 941c733d2..d5ecb78de 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -10,7 +10,7 @@ on: jobs: python-packaging: name: 🐍 Packaging - uses: cda-tum/mqt-workflows/.github/workflows/reusable-python-packaging.yml@v1.1.5 + uses: cda-tum/mqt-workflows/.github/workflows/reusable-python-packaging.yml@v1.3 with: pure-python: true @@ -23,6 +23,8 @@ jobs: url: https://pypi.org/p/mqt.bench permissions: id-token: write + attestations: write + contents: read needs: [python-packaging] steps: - uses: actions/download-artifact@v4 @@ -30,6 +32,10 @@ jobs: pattern: cibw-* path: dist merge-multiple: true + - name: Generate artifact attestation for sdist and wheel(s) + uses: actions/attest-build-provenance@v1.4.1 + with: + subject-path: "dist/*" - uses: pypa/gh-action-pypi-publish@release/v1 upload_webserver: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e1bf129b..09e1a9b6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,19 +14,21 @@ concurrency: jobs: change-detection: name: 🔍 Change - uses: cda-tum/mqt-workflows/.github/workflows/reusable-change-detection.yml@v1.1.5 + uses: cda-tum/mqt-workflows/.github/workflows/reusable-change-detection.yml@v1.3 python-tests: name: 🐍 Test needs: change-detection if: fromJSON(needs.change-detection.outputs.run-python-tests) - uses: cda-tum/mqt-workflows/.github/workflows/reusable-python-ci.yml@v1.1.5 + uses: cda-tum/mqt-workflows/.github/workflows/reusable-python-ci.yml@v1.3 + with: + skip-testing-latest-python: true code-ql: name: 📝 CodeQL needs: change-detection if: fromJSON(needs.change-detection.outputs.run-code-ql) - uses: cda-tum/mqt-workflows/.github/workflows/reusable-code-ql-python.yml@v1.1.5 + uses: cda-tum/mqt-workflows/.github/workflows/reusable-code-ql-python.yml@v1.3 required-checks-pass: # This job does nothing and is only used for branch protection name: 🚦 Check diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3c9e9fa1b..10589e41b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ ci: repos: # Standard hooks - repo: https://github.com/pre-commit/pre-commit-hooks - rev: "v4.6.0" + rev: v4.6.0 hooks: - id: check-added-large-files - id: check-case-conflict @@ -28,9 +28,20 @@ repos: - id: mixed-line-ending - id: trailing-whitespace + # Clean jupyter notebooks + - repo: https://github.com/srstevenson/nb-clean + rev: 3.3.0 + hooks: + - id: nb-clean + args: + - --remove-empty-cells + - --preserve-cell-metadata + - raw_mimetype + - -- + # Handling unwanted unicode characters - repo: https://github.com/sirosen/texthooks - rev: "0.6.6" + rev: 0.6.7 hooks: - id: fix-ligatures - id: fix-smartquotes @@ -43,34 +54,13 @@ repos: - id: rst-directive-colons - id: rst-inline-touching-normal - # Clean jupyter notebooks - - repo: https://github.com/srstevenson/nb-clean - rev: "3.3.0" - hooks: - - id: nb-clean - # Check for spelling - - repo: https://github.com/codespell-project/codespell - rev: "v2.3.0" - hooks: - - id: codespell - args: ["-L", "wille,linz,fro"] - exclude: "mqt/bench/viewer/templates/legal.html" - - # Format configuration files with prettier - - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v4.0.0-alpha.8" - hooks: - - id: prettier - types_or: [yaml, markdown, html, css, javascript, json] - + # Python linting and formatting using ruff - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.5 + rev: v0.6.1 hooks: - id: ruff args: ["--fix", "--show-fixes"] - types_or: [python, pyi, jupyter] - id: ruff-format - types_or: [python, pyi, jupyter] # Also run Black on examples in the documentation - repo: https://github.com/adamchainz/blacken-docs @@ -79,11 +69,19 @@ repos: - id: blacken-docs additional_dependencies: [black==24.*] + # Format configuration files with prettier + - repo: https://github.com/rbubley/mirrors-prettier + rev: v3.3.3 + hooks: + - id: prettier + types_or: [yaml, markdown, html, css, scss, javascript, json] + + # Check static types with mypy - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.0 + rev: v1.11.1 hooks: - id: mypy - files: ^(src|tests) + files: ^(src/mqt|test/python) args: [] additional_dependencies: - pytket_qiskit @@ -97,6 +95,13 @@ repos: - types-tqdm - types-flask + # Check for spelling + - repo: https://github.com/crate-ci/typos + rev: v1.23.6 + hooks: + - id: typos + exclude: legal.html + # Catch common capitalization mistakes - repo: local hooks: @@ -108,7 +113,21 @@ repos: # Check best practices for scientific Python code - repo: https://github.com/scientific-python/cookie - rev: 2024.04.23 + rev: 2024.08.19 hooks: - id: sp-repo-review additional_dependencies: ["repo-review[cli]"] + + # Check JSON schemata + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.29.1 + hooks: + - id: check-dependabot + - id: check-github-workflows + - id: check-readthedocs + + # Check the pyproject.toml file + - repo: https://github.com/henryiii/validate-pyproject-schema-store + rev: 2024.08.19 + hooks: + - id: validate-pyproject diff --git a/noxfile.py b/noxfile.py index 959ea097a..711ec0c2d 100644 --- a/noxfile.py +++ b/noxfile.py @@ -16,7 +16,7 @@ nox.options.default_venv_backend = "uv|virtualenv" -PYTHON_ALL_VERSIONS = ["3.10", "3.11", "3.12"] +PYTHON_ALL_VERSIONS = ["3.10", "3.11", "3.12", "3.13"] BUILD_REQUIREMENTS = [ "setuptools>=66.1", diff --git a/pyproject.toml b/pyproject.toml index 93d994ada..ab2dde6ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ dynamic = ["version"] dependencies = [ "pytket-qiskit>=0.53.0", # manages the dependencies for qiskit and tket in a combined fashion "pytket>=1.29.0", # lowest version that supports the used pytket AutoRebase pass instead of auto_rebase + "qiskit!=1.2.0", # there is a bug in 1.2.0 that causes an error some benchmarks, see https://github.com/Qiskit/qiskit/issues/12969 "qiskit_optimization>=0.6", "qiskit_nature[pyscf]>=0.7", "qiskit_finance>=0.4.1", @@ -45,6 +46,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Intended Audience :: Science/Research", "Natural Language :: English", "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", @@ -92,15 +94,23 @@ log_cli_level = "INFO" xfail_strict = true filterwarnings = [ "error", - "ignore:.*pkg_resources.*:DeprecationWarning:", - "ignore:.*sre_.*:DeprecationWarning:", - "ignore:.*Rigetti.*:UserWarning:", - "ignore:.*Values in x.*:RuntimeWarning:", - "ignore:.*divide by zero encountered in det.*:RuntimeWarning:", - "ignore:.*invalid value encountered in det.*:RuntimeWarning:", - "ignore::DeprecationWarning:.*(docplex).*", - "ignore::SyntaxWarning:.*(docplex).*", - "ignore:.*The abstract Provider and ProviderV1 classes are deprecated.*:DeprecationWarning:qiskit.*", + 'ignore:.*pkg_resources.*:DeprecationWarning:', + 'ignore:.*sre_.*:DeprecationWarning:', + 'ignore:.*Rigetti.*:UserWarning:', + 'ignore:.*Values in x.*:RuntimeWarning:', + 'ignore:.*divide by zero encountered in det.*:RuntimeWarning:', + 'ignore:.*invalid value encountered in det.*:RuntimeWarning:', + 'ignore::DeprecationWarning:.*(docplex).*', + 'ignore::SyntaxWarning:.*(docplex).*', + 'ignore:.*The abstract Provider and ProviderV1 classes are deprecated.*:DeprecationWarning:qiskit.*', + 'ignore:.*qiskit.providers.models is deprecated since Qiskit 1.2*:DeprecationWarning:', + 'ignore:.*Treating CircuitInstruction as an iterable is deprecated legacy behavior since Qiskit 1.2*:DeprecationWarning:pytket.*', + 'ignore:.*qiskit.providers.models.* is deprecated since qiskit 1.2*:DeprecationWarning:qiskit.*', + 'ignore:.*qiskit.providers.models.* is deprecated as of qiskit 1.2*:DeprecationWarning:qiskit.*', + 'ignore:.*qiskit.primitives.* is deprecated as of qiskit 1.2*:DeprecationWarning:qiskit.*', + 'ignore:.*The class ``qiskit.qobj.pulse_qobj.PulseLibraryItem`` is deprecated as of qiskit 1.2.*:DeprecationWarning:qiskit.*', + 'ignore:.*The class ``qiskit.primitives.sampler.Sampler`` is deprecated as of qiskit 1.2*:DeprecationWarning:mqt.*', + 'ignore:.*The class ``qiskit.primitives.estimator.Estimator`` is deprecated as of qiskit 1.2*:DeprecationWarning:mqt.*', ] [tool.coverage] @@ -137,7 +147,6 @@ ignore_missing_imports = true [tool.ruff] line-length = 120 extend-include = ["*.ipynb"] -src = ["src"] preview = true unsafe-fixes = true @@ -202,3 +211,18 @@ isort.required-imports = ["from __future__ import annotations"] [tool.ruff.lint.pydocstyle] convention = "google" + + +[tool.typos] +default.extend-ignore-re = [ + '"id": ".*",', + "(?Rm)^.*(#|//)\\s*spellchecker:disable-line$", # ignore line + "(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on" # ignore block +] +[tool.typos.default.extend-words] +wille = "wille" +anc = "anc" +aer = "aer" +fom = "fom" +bench = "bench" +benchs = "benchs" diff --git a/src/mqt/bench/benchmark_generator.py b/src/mqt/bench/benchmark_generator.py index bbaac465d..dfadc77bd 100644 --- a/src/mqt/bench/benchmark_generator.py +++ b/src/mqt/bench/benchmark_generator.py @@ -27,12 +27,8 @@ from pytket.circuit import Circuit -if TYPE_CHECKING or sys.version_info >= (3, 10, 0): # pragma: no cover - from importlib import resources -else: - import importlib_resources as resources - from dataclasses import dataclass +from importlib import resources class Benchmark(TypedDict, total=False): @@ -359,11 +355,6 @@ def get_benchmark( Returns: Quantum Circuit Object representing the benchmark with the selected options, either as Qiskit::QuantumCircuit or Pytket::Circuit object (depending on the chosen compiler---while the algorithm level is always provided using Qiskit) """ - if "gate_set_name" in kwargs: - msg = "gate_set_name is deprecated and will be removed in a future release. Use provider_name instead." - warn(msg, DeprecationWarning, stacklevel=2) - provider_name = kwargs["gate_set_name"] - if benchmark_name not in utils.get_supported_benchmarks(): msg = f"Selected benchmark is not supported. Valid benchmarks are {utils.get_supported_benchmarks()}." raise ValueError(msg) diff --git a/src/mqt/bench/benchmarks/random.py b/src/mqt/bench/benchmarks/random.py index da7d05991..867a5b954 100644 --- a/src/mqt/bench/benchmarks/random.py +++ b/src/mqt/bench/benchmarks/random.py @@ -1,4 +1,4 @@ -"""Random benchmark definition.""" +"""Random benchmark definition.""" # noqa: A005 from __future__ import annotations diff --git a/src/mqt/bench/devices/calibration.py b/src/mqt/bench/devices/calibration.py index 8f6399d97..eea1cf81c 100644 --- a/src/mqt/bench/devices/calibration.py +++ b/src/mqt/bench/devices/calibration.py @@ -77,7 +77,7 @@ def get_two_qubit_gate_fidelity(self, gate_type: str, qubit1: int, qubit2: int) raise ValueError(msg) try: - return self.two_qubit_gate_fidelity[(qubit1, qubit2)][gate_type] + return self.two_qubit_gate_fidelity[qubit1, qubit2][gate_type] except KeyError: msg = f"Two-qubit fidelity for gate {gate_type} and qubits {qubit1} and {qubit2} not available." raise ValueError(msg) from None @@ -95,7 +95,7 @@ def get_two_qubit_gate_duration(self, gate_type: str, qubit1: int, qubit2: int) raise ValueError(msg) try: - return self.two_qubit_gate_duration[(qubit1, qubit2)][gate_type] + return self.two_qubit_gate_duration[qubit1, qubit2][gate_type] except KeyError: msg = f"Two-qubit duration for gate {gate_type} and qubits {qubit1} and {qubit2} not available." raise ValueError(msg) from None diff --git a/src/mqt/bench/devices/device.py b/src/mqt/bench/devices/device.py index f79e480af..436b665c0 100644 --- a/src/mqt/bench/devices/device.py +++ b/src/mqt/bench/devices/device.py @@ -140,7 +140,7 @@ def get_two_qubit_gates(self) -> set[str]: return { gate for qubit1, qubit2 in self.coupling_map - for gate in self.calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] + for gate in self.calibration.two_qubit_gate_fidelity[qubit1, qubit2] } def sanitize_device(self) -> None: diff --git a/src/mqt/bench/devices/ibm.py b/src/mqt/bench/devices/ibm.py index 0c6034e1e..62c04a631 100644 --- a/src/mqt/bench/devices/ibm.py +++ b/src/mqt/bench/devices/ibm.py @@ -8,10 +8,9 @@ if TYPE_CHECKING: from pathlib import Path - from qiskit.providers.models import BackendProperties + from qiskit.providers import BackendV2 from qiskit.transpiler import Target -from qiskit.providers import BackendV2 from mqt.bench.devices import Device, DeviceCalibration, Provider @@ -92,58 +91,15 @@ def import_backend(cls, path: Path) -> Device: edge = f"{qubit1}_{qubit2}" error = ibm_calibration["properties"][str(qubit1)]["eCX"][edge] - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] = {"cx": 1 - error} + calibration.two_qubit_gate_fidelity[qubit1, qubit2] = {"cx": 1 - error} # data in nanoseconds, convert to SI unit (seconds) duration = ibm_calibration["properties"][str(qubit1)]["tCX"][edge] * 1e-9 - calibration.two_qubit_gate_duration[(qubit1, qubit2)] = {"cx": duration} + calibration.two_qubit_gate_duration[qubit1, qubit2] = {"cx": duration} device.calibration = calibration return device - @classmethod - def __import_backend_properties(cls, backend_properties: BackendProperties) -> DeviceCalibration: - """Import calibration data from a Qiskit `BackendProperties` object. - - Arguments: - backend_properties: the Qiskit `BackendProperties` object. - - Returns: Collection of calibration data - """ - calibration = DeviceCalibration() - num_qubits = len(backend_properties.qubits) - - for qubit in range(num_qubits): - calibration.t1[qubit] = cast(float, backend_properties.t1(qubit)) - calibration.t2[qubit] = cast(float, backend_properties.t2(qubit)) - calibration.readout_fidelity[qubit] = 1 - cast(float, backend_properties.readout_error(qubit)) - calibration.readout_duration[qubit] = cast(float, backend_properties.readout_length(qubit)) - - calibration.single_qubit_gate_fidelity = {qubit: {} for qubit in range(num_qubits)} - calibration.single_qubit_gate_duration = {qubit: {} for qubit in range(num_qubits)} - for gate in backend_properties.gates: - # Skip `reset` gate as its error information is not exposed. - if gate.gate == "reset": - continue - - error: float = backend_properties.gate_error(gate.gate, gate.qubits) - duration: float = backend_properties.gate_length(gate.gate, gate.qubits) - if len(gate.qubits) == 1: - qubit = gate.qubits[0] - calibration.single_qubit_gate_fidelity[qubit][gate.gate] = 1 - error - calibration.single_qubit_gate_duration[qubit][gate.gate] = duration - elif len(gate.qubits) == 2: - qubit1, qubit2 = gate.qubits - if (qubit1, qubit2) not in calibration.two_qubit_gate_fidelity: - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] = {} - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)][gate.gate] = 1 - error - - if (qubit1, qubit2) not in calibration.two_qubit_gate_duration: - calibration.two_qubit_gate_duration[(qubit1, qubit2)] = {} - calibration.two_qubit_gate_duration[(qubit1, qubit2)][gate.gate] = duration - - return calibration - @classmethod def __import_target(cls, target: Target) -> DeviceCalibration: """Import calibration data from a Qiskit `Target` object. @@ -183,14 +139,14 @@ def __import_target(cls, target: Target) -> DeviceCalibration: calibration.single_qubit_gate_duration[qubit][instruction.name] = duration elif len(qargs) == 2: qubit1, qubit2 = qargs - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)][instruction.name] = 1 - error - calibration.two_qubit_gate_duration[(qubit1, qubit2)][instruction.name] = duration + calibration.two_qubit_gate_fidelity[qubit1, qubit2][instruction.name] = 1 - error + calibration.two_qubit_gate_duration[qubit1, qubit2][instruction.name] = duration return calibration @classmethod - def __import_backend_v2(cls, backend: BackendV2) -> Device: - """Import device data from a Qiskit `BackendV2` object. + def import_qiskit_backend(cls, backend: BackendV2) -> Device: + """Import device data from a Qiskit `Backend` object. Arguments: backend: the Qiskit `BackendV2` object. @@ -204,18 +160,3 @@ def __import_backend_v2(cls, backend: BackendV2) -> Device: device.coupling_map = backend.coupling_map.get_edges() device.calibration = cls.__import_target(backend.target) return device - - @classmethod - def import_qiskit_backend(cls, backend: BackendV2) -> Device: - """Import device data from a Qiskit `Backend` object. - - Arguments: - backend: the Qiskit `Backend` object. - - Returns: - Collection of device data - """ - if isinstance(backend, BackendV2): - return cls.__import_backend_v2(backend) - msg = f"Unsupported backend type {type(backend)}" - raise TypeError(msg) diff --git a/src/mqt/bench/devices/ionq.py b/src/mqt/bench/devices/ionq.py index 9b67c7eaf..fc7fce2a8 100644 --- a/src/mqt/bench/devices/ionq.py +++ b/src/mqt/bench/devices/ionq.py @@ -81,7 +81,7 @@ def import_backend(cls, path: Path) -> Device: calibration.t2[qubit] = ionq_calibration["timing"]["t2"] for qubit1, qubit2 in device.coupling_map: - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] = {"rxx": ionq_calibration["fidelity"]["2q"]["mean"]} - calibration.two_qubit_gate_duration[(qubit1, qubit2)] = {"rxx": ionq_calibration["timing"]["2q"]} + calibration.two_qubit_gate_fidelity[qubit1, qubit2] = {"rxx": ionq_calibration["fidelity"]["2q"]["mean"]} + calibration.two_qubit_gate_duration[qubit1, qubit2] = {"rxx": ionq_calibration["timing"]["2q"]} device.calibration = calibration return device diff --git a/src/mqt/bench/devices/iqm.py b/src/mqt/bench/devices/iqm.py index d62dd4465..5d2909f4a 100644 --- a/src/mqt/bench/devices/iqm.py +++ b/src/mqt/bench/devices/iqm.py @@ -92,20 +92,16 @@ def import_backend(cls, path: Path) -> Device: for qubit1, qubit2 in device.coupling_map: if (qubit1, qubit2) in calibration.two_qubit_gate_fidelity: continue # Skip reverse direction - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] = { + calibration.two_qubit_gate_fidelity[qubit1, qubit2] = { "cz": 1.0 - iqm_calibration["error"]["two_q"][str(qubit1) + "-" + str(qubit2)] } - calibration.two_qubit_gate_duration[(qubit1, qubit2)] = { + calibration.two_qubit_gate_duration[qubit1, qubit2] = { "cz": iqm_calibration["timing"]["two_q"] * 1e-9 # ns to s } # Same values for the reverse direction - calibration.two_qubit_gate_fidelity[(qubit2, qubit1)] = calibration.two_qubit_gate_fidelity[ - (qubit1, qubit2) - ] - calibration.two_qubit_gate_duration[(qubit2, qubit1)] = calibration.two_qubit_gate_duration[ - (qubit1, qubit2) - ] + calibration.two_qubit_gate_fidelity[qubit2, qubit1] = calibration.two_qubit_gate_fidelity[qubit1, qubit2] + calibration.two_qubit_gate_duration[qubit2, qubit1] = calibration.two_qubit_gate_duration[qubit1, qubit2] device.calibration = calibration return device diff --git a/src/mqt/bench/devices/oqc.py b/src/mqt/bench/devices/oqc.py index 7300bcfca..dbf330abf 100644 --- a/src/mqt/bench/devices/oqc.py +++ b/src/mqt/bench/devices/oqc.py @@ -97,7 +97,7 @@ def import_backend(cls, path: Path) -> Device: calibration.t2[qubit] = oqc_calibration["properties"]["one_qubit"][str(qubit)]["T2"] * 1e-6 for qubit1, qubit2 in device.coupling_map: - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] = dict.fromkeys( + calibration.two_qubit_gate_fidelity[qubit1, qubit2] = dict.fromkeys( ["ecr"], oqc_calibration["properties"]["two_qubit"][f"{qubit1}-{qubit2}"]["fECR"] ) device.calibration = calibration diff --git a/src/mqt/bench/devices/quantinuum.py b/src/mqt/bench/devices/quantinuum.py index 2c2095816..54e4a9b5c 100644 --- a/src/mqt/bench/devices/quantinuum.py +++ b/src/mqt/bench/devices/quantinuum.py @@ -72,7 +72,7 @@ def import_backend(cls, path: Path) -> Device: calibration.readout_fidelity[qubit] = quantinuum_calibration["fidelity"]["spam"]["mean"] for qubit1, qubit2 in device.coupling_map: - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] = { + calibration.two_qubit_gate_fidelity[qubit1, qubit2] = { "rzz": quantinuum_calibration["fidelity"]["2q"]["mean"] } device.calibration = calibration diff --git a/src/mqt/bench/devices/rigetti.py b/src/mqt/bench/devices/rigetti.py index 39403a2f1..c1c699eca 100644 --- a/src/mqt/bench/devices/rigetti.py +++ b/src/mqt/bench/devices/rigetti.py @@ -176,7 +176,7 @@ def import_backend(cls, path: Path) -> Device: fidelity["xx_plus_yy"] = -1.0 # Save the fidelity data for the two-qubit gate - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] = fidelity + calibration.two_qubit_gate_fidelity[qubit1, qubit2] = fidelity # If there are missing values, use the average cz_avg = sum(cz_lst) / len(cz_lst) @@ -187,16 +187,14 @@ def import_backend(cls, path: Path) -> Device: if qubit1 > qubit2: continue # Check if the fidelity data is missing (== -1) and set to average if so - if calibration.two_qubit_gate_fidelity[(qubit1, qubit2)]["cz"] < 0: - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)]["cz"] = cz_avg - if calibration.two_qubit_gate_fidelity[(qubit1, qubit2)]["cp"] < 0: - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)]["cp"] = cp_avg - if calibration.two_qubit_gate_fidelity[(qubit1, qubit2)]["xx_plus_yy"] < 0: - calibration.two_qubit_gate_fidelity[(qubit1, qubit2)]["xx_plus_yy"] = xx_plus_yy_avg + if calibration.two_qubit_gate_fidelity[qubit1, qubit2]["cz"] < 0: + calibration.two_qubit_gate_fidelity[qubit1, qubit2]["cz"] = cz_avg + if calibration.two_qubit_gate_fidelity[qubit1, qubit2]["cp"] < 0: + calibration.two_qubit_gate_fidelity[qubit1, qubit2]["cp"] = cp_avg + if calibration.two_qubit_gate_fidelity[qubit1, qubit2]["xx_plus_yy"] < 0: + calibration.two_qubit_gate_fidelity[qubit1, qubit2]["xx_plus_yy"] = xx_plus_yy_avg # Rigetti calibration data is symmetric, set same values for reverse edge - calibration.two_qubit_gate_fidelity[(qubit2, qubit1)] = calibration.two_qubit_gate_fidelity[ - (qubit1, qubit2) - ] + calibration.two_qubit_gate_fidelity[qubit2, qubit1] = calibration.two_qubit_gate_fidelity[qubit1, qubit2] device.calibration = calibration return device diff --git a/src/mqt/bench/evaluation/evaluation_visualization.ipynb b/src/mqt/bench/evaluation/evaluation_visualization.ipynb index 7e63de7e1..5216f62e0 100644 --- a/src/mqt/bench/evaluation/evaluation_visualization.ipynb +++ b/src/mqt/bench/evaluation/evaluation_visualization.ipynb @@ -247,14 +247,6 @@ "ax.set_xticklabels(labels)\n", "plt.savefig(\"results/violins.pdf\", format=\"pdf\", bbox_inches=\"tight\")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "238ae571", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/tests/devices/test_devices.py b/tests/devices/test_devices.py index 026894e83..4357531e7 100644 --- a/tests/devices/test_devices.py +++ b/tests/devices/test_devices.py @@ -32,8 +32,8 @@ def test_sanitized_devices(device: Device) -> None: for qubit1, qubit2 in device.coupling_map: assert (qubit1, qubit2) in device.calibration.two_qubit_gate_fidelity for gate in device.get_two_qubit_gates(): - assert gate in device.calibration.two_qubit_gate_fidelity[(qubit1, qubit2)] - assert device.calibration.two_qubit_gate_fidelity[(qubit1, qubit2)][gate] > 0 + assert gate in device.calibration.two_qubit_gate_fidelity[qubit1, qubit2] + assert device.calibration.two_qubit_gate_fidelity[qubit1, qubit2][gate] > 0 def test_device_calibration_errors() -> None: diff --git a/tests/devices/test_ibm_device_support.py b/tests/devices/test_ibm_device_support.py index 0cffb0c5e..0e04ed2f1 100644 --- a/tests/devices/test_ibm_device_support.py +++ b/tests/devices/test_ibm_device_support.py @@ -111,9 +111,3 @@ def test_get_ibmq_montreal_device() -> None: for gate in two_qubit_gates: assert 0 <= device.get_two_qubit_gate_fidelity(gate, q0, q1) <= 1 assert device.get_two_qubit_gate_duration(gate, q0, q1) >= 0 - - -def test_import_unsupported_backend() -> None: - """Test importing an unsupported backend type.""" - with pytest.raises(TypeError, match="Unsupported backend type "): - IBMProvider.import_qiskit_backend("V3") diff --git a/tests/test_bench.py b/tests/test_bench.py index a54c480c1..b70c3a11c 100644 --- a/tests/test_bench.py +++ b/tests/test_bench.py @@ -324,22 +324,6 @@ def test_routing() -> None: assert qc.depth() > 0 -def test_get_benchmark_deprecation_warning() -> None: - """Test the deprecation warning for gate_set_name in get_benchmark.""" - with pytest.warns( - DeprecationWarning, - match="gate_set_name is deprecated and will be removed in a future release. Use provider_name instead.", - ): - get_benchmark( - benchmark_name="dj", - level="mapped", - circuit_size=3, - compiler="tket", - device_name="oqc_lucy", - gate_set_name="oqc", - ) - - def test_unidirectional_coupling_map() -> None: """Test the unidirectional coupling map for the OQC Lucy device.""" qc = get_benchmark( @@ -737,7 +721,8 @@ def test_get_benchmark( if compiler == "tket": qc = tk_to_qiskit(qc) assert isinstance(qc, QuantumCircuit) - for instruction, _qargs, _cargs in qc.data: + for qc_instruction in qc.data: + instruction = qc_instruction.operation gate_type = instruction.name provider = get_provider_by_name(provider_name) assert gate_type in provider.get_native_gates() or gate_type == "barrier" diff --git a/tests/test_pregenerated_zip.py b/tests/test_pregenerated_zip.py index a80685b11..69dc2dae5 100644 --- a/tests/test_pregenerated_zip.py +++ b/tests/test_pregenerated_zip.py @@ -3,8 +3,7 @@ from __future__ import annotations import os -import sys -from typing import TYPE_CHECKING +from importlib import resources import pytest @@ -12,11 +11,6 @@ from mqt.bench.viewer import Server from mqt.bench.viewer.main import app -if TYPE_CHECKING or sys.version_info >= (3, 10, 0): # pragma: no cover - from importlib import resources -else: - import importlib_resources as resources - # only run test when executed on GitHub runner IN_GITHUB_ACTIONS = os.getenv("GITHUB_ACTIONS") == "true"