From 99cb745cbfb1894205a9a0398d82249e477f0a07 Mon Sep 17 00:00:00 2001 From: Naoki Kanazawa Date: Mon, 9 Sep 2024 21:49:31 +0900 Subject: [PATCH] switch pylint to ruff --- gem_suite/__init__.py | 8 +++++ gem_suite/analysis.py | 12 ++----- gem_suite/experiments.py | 16 +++------ gem_suite/gem_core.pyi | 9 +++-- gem_suite/plaquettes.py | 21 +++++++---- gem_suite/sub_analysis/__init__.py | 8 +++++ gem_suite/sub_analysis/operators.py | 24 ++++--------- pyproject.toml | 21 +++++++++++ requirements-dev.txt | 5 --- tests/utils.py | 55 ++++++++--------------------- tox.ini | 27 ++++++++++---- 11 files changed, 105 insertions(+), 101 deletions(-) delete mode 100644 requirements-dev.txt diff --git a/gem_suite/__init__.py b/gem_suite/__init__.py index 5f9849d..6b91387 100644 --- a/gem_suite/__init__.py +++ b/gem_suite/__init__.py @@ -13,3 +13,11 @@ from .plaquettes import PlaquetteLattice from .experiments import GemExperiment +from .analysis import GemAnalysis + + +__all__ = [ + "PlaquetteLattice", + "GemExperiment", + "GemAnalysis", +] diff --git a/gem_suite/analysis.py b/gem_suite/analysis.py index f8f838b..1f0179d 100644 --- a/gem_suite/analysis.py +++ b/gem_suite/analysis.py @@ -90,9 +90,7 @@ def _run_analysis( # Check if lattice object exists. # The lattice information is necessary for decoding experiment outcomes. if self._plaquettes is None: - plaquette_qubit_map = experiment_data.metadata.get( - "plaquette_qubit_map", None - ) + plaquette_qubit_map = experiment_data.metadata.get("plaquette_qubit_map", None) connectivity = experiment_data.metadata.get("connectivity", None) if plaquette_qubit_map is None or connectivity is None: raise RuntimeError( @@ -101,9 +99,7 @@ def _run_analysis( "This analysis cannot be performed because of " "the missing lattice information to decode bitstrings." ) - lattice = PyHeavyHexLattice.from_plaquettes( - plaquette_qubit_map, connectivity - ) + lattice = PyHeavyHexLattice.from_plaquettes(plaquette_qubit_map, connectivity) self._plaquettes = PlaquetteLattice(lattice) # Decode count dictionaries and build intermediate data collection. @@ -194,9 +190,7 @@ def _run_analysis( } dot = visualize_plaquette_with_noise(p_map, noise_map) fig_data.append( - FigureData( - dot_to_mplfigure(dot, "neato", 300), name="plaquette_quality" - ) + FigureData(dot_to_mplfigure(dot, "neato", 300), name="plaquette_quality") ) return analysis_results, fig_data diff --git a/gem_suite/experiments.py b/gem_suite/experiments.py index 7c0461e..2e36126 100644 --- a/gem_suite/experiments.py +++ b/gem_suite/experiments.py @@ -51,9 +51,7 @@ def __init__( RuntimeError: When plaquettes are selected by index but backend is not provided. """ if not isinstance(plaquettes, PlaquetteLattice): - plaquettes = PlaquetteLattice.from_backend(backend).filter( - includes=plaquettes - ) + plaquettes = PlaquetteLattice.from_backend(backend).filter(includes=plaquettes) qubits = [q.index for q in plaquettes.qubits()] super().__init__( physical_qubits=qubits, @@ -161,12 +159,8 @@ def parameterized_circuits(self) -> tuple[QuantumCircuit, ...]: def circuits(self) -> list[QuantumCircuit]: circs_bound = [] - for tmp_circ, param in product( - self.parameterized_circuits(), self.parameters() - ): - assigned = tmp_circ.assign_parameters( - {self.parameter: param}, inplace=False - ) + for tmp_circ, param in product(self.parameterized_circuits(), self.parameters()): + assigned = tmp_circ.assign_parameters({self.parameter: param}, inplace=False) assigned.metadata["theta"] = np.round(param / np.pi, 5) circs_bound.append(assigned) return circs_bound @@ -174,7 +168,5 @@ def circuits(self) -> list[QuantumCircuit]: def _metadata(self) -> dict[str, Any]: metadata = super()._metadata() metadata["connectivity"] = self.plaquettes.connectivity() - metadata["plaquette_qubit_map"] = { - p.index: p.qubits for p in self.plaquettes.plaquettes() - } + metadata["plaquette_qubit_map"] = {p.index: p.qubits for p in self.plaquettes.plaquettes()} return metadata diff --git a/gem_suite/gem_core.pyi b/gem_suite/gem_core.pyi index 70a5577..fed4f37 100644 --- a/gem_suite/gem_core.pyi +++ b/gem_suite/gem_core.pyi @@ -9,7 +9,6 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -"""This file contsins Python annotation for PyO3 classes and functions.""" from typing import Callable @@ -39,7 +38,9 @@ class PyHeavyHexLattice: def __init__(self, coupling_map: list[tuple[int, int]]) -> PyHeavyHexLattice: ... @classmethod def from_plaquettes( - plaquette_qubits_map: dict[int, list[int]], connectivity: list[tuple[int, int]] + cls, + plaquette_qubits_map: dict[int, list[int]], + connectivity: list[tuple[int, int]], ) -> PyHeavyHexLattice: ... def qubit_graph_dot(self) -> str: ... def plaquette_graph_dot(self) -> str: ... @@ -49,7 +50,9 @@ class PyHeavyHexLattice: def connectivity(self) -> list[tuple[int, int]]: ... def filter(self, includes: list[int]) -> PyHeavyHexLattice: ... def build_gate_schedule(self, index: int) -> list[list[PyScheduledGate]]: ... - def decode_outcomes_fb(self, counts: dict[str, int], return_counts: bool) -> tuple[ + def decode_outcomes_fb( + self, counts: dict[str, int], return_counts: bool + ) -> tuple[ dict[str, int] | None, list[float], list[float], diff --git a/gem_suite/plaquettes.py b/gem_suite/plaquettes.py index f05c598..8d62f57 100644 --- a/gem_suite/plaquettes.py +++ b/gem_suite/plaquettes.py @@ -13,8 +13,7 @@ from __future__ import annotations -from collections import namedtuple -from typing import Iterator, Callable +from typing import Iterator, Callable, NamedTuple import numpy as np from pymatching import Matching @@ -25,8 +24,18 @@ from gem_suite.gem_core import PyHeavyHexLattice, PyQubit, PyPlaquette, PyScheduledGate from .plot_utils import dot_to_mplfigure -ScheduledGate = namedtuple("ScheduledGate", ["q0", "q1", "group"]) -DecodeOutcome = namedtuple("DecodeOutcome", ["w_ops", "zxz_ops", "f", "g"]) + +class ScheduledGate(NamedTuple): + q0: int + q1: int + group: str + + +class DecodeOutcome(NamedTuple): + w_ops: list[float] + zxz_ops: list[float] + f: tuple[float, float] + g: tuple[float, float] class PlaquetteLattice: @@ -138,9 +147,7 @@ def decode_outcomes( elif decoder == "pymatching": hvec, dims = self._core.check_matrix_csc() data = np.ones(len(hvec[0])) - solver = _build_batch_decoder( - csc_matrix((data, hvec), dims, dtype=np.bool_) - ) + solver = _build_batch_decoder(csc_matrix((data, hvec), dims, dtype=np.bool_)) out = self._core.decode_outcomes_pm(solver, counts, return_counts) outcome = DecodeOutcome(*out[1:]) else: diff --git a/gem_suite/sub_analysis/__init__.py b/gem_suite/sub_analysis/__init__.py index a006065..d724916 100644 --- a/gem_suite/sub_analysis/__init__.py +++ b/gem_suite/sub_analysis/__init__.py @@ -17,3 +17,11 @@ analyze_clifford_limit, ) from .magnetization import analyze_magnetization + + +__all__ = [ + "analyze_operators", + "analyze_individual_bonds", + "analyze_clifford_limit", + "analyze_magnetization", +] diff --git a/gem_suite/sub_analysis/operators.py b/gem_suite/sub_analysis/operators.py index cee16cd..957c7aa 100644 --- a/gem_suite/sub_analysis/operators.py +++ b/gem_suite/sub_analysis/operators.py @@ -76,25 +76,19 @@ def analyze_operators( yvals_w_nominal = unp.nominal_values(yvals_w) yvals_w_std = unp.std_devs(yvals_w) - yvals_w_std = np.where( - np.isclose(yvals_w_std, 0.0), np.finfo(float).eps, yvals_w_std - ) + yvals_w_std = np.where(np.isclose(yvals_w_std, 0.0), np.finfo(float).eps, yvals_w_std) w_weights = 1 / yvals_w_std w_weights = np.clip(w_weights, 0.0, np.percentile(w_weights, 90)) yvals_zxz_nominal = unp.nominal_values(yvals_zxz) yvals_zxz_std = unp.std_devs(yvals_zxz) - yvals_zxz_std = np.where( - np.isclose(yvals_zxz_std, 0.0), np.finfo(float).eps, yvals_zxz_std - ) + yvals_zxz_std = np.where(np.isclose(yvals_zxz_std, 0.0), np.finfo(float).eps, yvals_zxz_std) zxz_weights = 1 / yvals_zxz_std zxz_weights = np.clip(zxz_weights, 0.0, np.percentile(zxz_weights, 90)) def multi_residuals(params): r_w = (w_model(xvals, params[0]) - yvals_w_nominal) * w_weights - r_zxz = ( - zxz_model(xvals, params[0], params[1]) - yvals_zxz_nominal - ) * zxz_weights + r_zxz = (zxz_model(xvals, params[0], params[1]) - yvals_zxz_nominal) * zxz_weights return np.concatenate([r_w, r_zxz]) if ret := fit_util( @@ -298,9 +292,7 @@ def analyze_clifford_limit( return [] plaquettes = sorted(plaquettes, key=lambda p: p.index) bond_to_qubits = dict( - enumerate( - sorted([q for q in qubits if q.role == "Bond"], key=lambda q: q.index) - ) + enumerate(sorted([q for q in qubits if q.role == "Bond"], key=lambda q: q.index)) ) # pylint: disable=invalid-name for wi, plaquette in enumerate(plaquettes): @@ -314,12 +306,8 @@ def analyze_clifford_limit( # Take bond qubits in this plaquette if bond_qubit.index not in sub_qubits: continue - filtered_data = clif_data[ - (clif_data.name == "zxz") & (clif_data.component == bond_bit) - ] - zxz_val = ufloat( - np.average(filtered_data.value), np.std(filtered_data.value) - ) + filtered_data = clif_data[(clif_data.name == "zxz") & (clif_data.component == bond_bit)] + zxz_val = ufloat(np.average(filtered_data.value), np.std(filtered_data.value)) all_obs.append(zxz_val) if any(o < 0 for o in all_obs): value = None diff --git a/pyproject.toml b/pyproject.toml index 18030b8..6e4f57c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,3 +13,24 @@ authors = [ [tool.setuptools.packages.find] include = ["gem_suite", "gem_suite.*"] + +[tool.black] +line-length = 100 +target-version = ['py38', 'py39', 'py310', 'py311'] + +[tool.ruff] +line-length = 105 +src = ["gem_suite", "setup.py", "tests"] +target-version = "py38" + +[tool.ruff.lint] +select = [ + "E", # pycodestyle + "F", # pyflakes + "UP", # pyupgrade + "PYI", # flake8-pyi + "Q", # flake8-quotes +] + +[tool.ruff.lint.per-file-ignores] +"*.pyi" = ["F403", "F405", "PYI001", "PYI002"] diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 94dd462..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,5 +0,0 @@ -black -stestr -astroid==2.14.2 -pylint==2.16.2 -qiskit_ibm_runtime diff --git a/tests/utils.py b/tests/utils.py index 41ff593..5975c04 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -20,9 +20,7 @@ # pylint: disable=too-many-locals, disable=invalid-name def process_counts_debug( counts: dict[str, int] -) -> tuple[ - dict[str, int], list[float], list[float], tuple[float, float], tuple[float, float] -]: +) -> tuple[dict[str, int], list[float], list[float], tuple[float, float], tuple[float, float]]: """Generate reference decoded outcomes. Cheat sheet: @@ -126,39 +124,17 @@ def process_counts_debug( if syndromes[1] == 1: syndrome_sum[1] += count_num # Add up bond correlation - bond_sum[0] += ( - count_num if bond_bits[0] ^ site_bits[0] ^ site_bits[1] else -count_num - ) - bond_sum[1] += ( - count_num if bond_bits[1] ^ site_bits[0] ^ site_bits[2] else -count_num - ) - bond_sum[2] += ( - count_num if bond_bits[2] ^ site_bits[1] ^ site_bits[3] else -count_num - ) - bond_sum[3] += ( - count_num if bond_bits[3] ^ site_bits[2] ^ site_bits[4] else -count_num - ) - bond_sum[4] += ( - count_num if bond_bits[4] ^ site_bits[3] ^ site_bits[5] else -count_num - ) - bond_sum[5] += ( - count_num if bond_bits[5] ^ site_bits[4] ^ site_bits[5] else -count_num - ) - bond_sum[6] += ( - count_num if bond_bits[6] ^ site_bits[4] ^ site_bits[6] else -count_num - ) - bond_sum[7] += ( - count_num if bond_bits[7] ^ site_bits[5] ^ site_bits[7] else -count_num - ) - bond_sum[8] += ( - count_num if bond_bits[8] ^ site_bits[6] ^ site_bits[8] else -count_num - ) - bond_sum[9] += ( - count_num if bond_bits[9] ^ site_bits[7] ^ site_bits[9] else -count_num - ) - bond_sum[10] += ( - count_num if bond_bits[10] ^ site_bits[8] ^ site_bits[9] else -count_num - ) + bond_sum[0] += count_num if bond_bits[0] ^ site_bits[0] ^ site_bits[1] else -count_num + bond_sum[1] += count_num if bond_bits[1] ^ site_bits[0] ^ site_bits[2] else -count_num + bond_sum[2] += count_num if bond_bits[2] ^ site_bits[1] ^ site_bits[3] else -count_num + bond_sum[3] += count_num if bond_bits[3] ^ site_bits[2] ^ site_bits[4] else -count_num + bond_sum[4] += count_num if bond_bits[4] ^ site_bits[3] ^ site_bits[5] else -count_num + bond_sum[5] += count_num if bond_bits[5] ^ site_bits[4] ^ site_bits[5] else -count_num + bond_sum[6] += count_num if bond_bits[6] ^ site_bits[4] ^ site_bits[6] else -count_num + bond_sum[7] += count_num if bond_bits[7] ^ site_bits[5] ^ site_bits[7] else -count_num + bond_sum[8] += count_num if bond_bits[8] ^ site_bits[6] ^ site_bits[8] else -count_num + bond_sum[9] += count_num if bond_bits[9] ^ site_bits[7] ^ site_bits[9] else -count_num + bond_sum[10] += count_num if bond_bits[10] ^ site_bits[8] ^ site_bits[9] else -count_num # Hardcoded decoder # There are three check variables (, , ) to solve. decode_in_out = { @@ -219,12 +195,9 @@ def calculate_f_and_g(dist): out_g = 1 / num_data**3 * (m4 - m2**2) std_f = ( - m4 / num_shots - - (m2 - m1**2) ** 2 * (num_shots - 3) / num_shots / (num_shots - 1) - ) ** 0.5 - std_g = ( - m8 / num_shots - std_f**4 * (num_shots - 3) / num_shots / (num_shots - 1) + m4 / num_shots - (m2 - m1**2) ** 2 * (num_shots - 3) / num_shots / (num_shots - 1) ) ** 0.5 + std_g = (m8 / num_shots - std_f**4 * (num_shots - 3) / num_shots / (num_shots - 1)) ** 0.5 std_f /= num_data std_g /= num_data**3 diff --git a/tox.ini b/tox.ini index 89bfde6..3de5af8 100644 --- a/tox.ini +++ b/tox.ini @@ -1,26 +1,41 @@ [tox] minversion = 4.0 envlist = py38, py39, py310, py311, py312, lint -skipsdist = True +isolated_build = true [testenv] usedevelop = True install_command = pip install -U {opts} {packages} setenv = VIRTUAL_ENV={envdir} + LANGUAGE=en_US + RUST_DEBUG=1 deps = - setuptools_rust + setuptools-rust -r{toxinidir}/requirements.txt - -r{toxinidir}/requirements-dev.txt + stestr>=4.1 + qiskit_ibm_runtime commands = stestr run {posargs} [testenv:lint] -envdir = .tox/lint +basepython = python3 +package = editable +skip_install = true +deps = + black~=22.0 + ruff +allowlist_externals = cargo commands = - black --check {posargs} gem_suite tests - pylint -rn gem_suite/ tests/ + black --check {posargs} gem_suite tests setup.py + cargo fmt --check + ruff check gem_suite tests setup.py + cargo clippy -- -D warnings [testenv:black] +basepython = python3 +skip_install = true +deps = + black~=22.0 commands = black {posargs} gem_suite tests [pycodestyle]