From c1079f49e5499b6eb5b4a58d0e5fc2772de11254 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 26 Aug 2024 22:58:08 +0200 Subject: [PATCH 01/17] =?UTF-8?q?=F0=9F=91=A5=20add=20Tom=20as=20contribut?= =?UTF-8?q?or?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- README.md | 1 + pyproject.toml | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 33a2bb31..0fa74879 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,7 @@ The contributors to this tool are: - Thomas Grurl - Peter-Jan H.S. Derks - Timo Hillmann +- Tom Peham ## Acknowledgements diff --git a/pyproject.toml b/pyproject.toml index f150c37e..77c549f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,8 @@ authors = [ { name = "Lucas Berent", email = "lucas.berent@tum.de" }, { name = "Lukas Burgholzer", email = "lukas.burgholzer@tum.de" }, { name = "Peter-Jan H.S. Derks", email = "peter-janderks@hotmail.com" }, - { name = "Timo Hillmann", email = "timo.hillmann@rwth-aachen.de"} + { name = "Timo Hillmann", email = "timo.hillmann@rwth-aachen.de"}, + { name = "Tom Peham", email = "tom.peham@tum.de" }, ] keywords = ["MQT", "quantum-computing", "error-correction", "MaxSAT", "QLDPC"] license = { file = "LICENSE" } @@ -32,6 +33,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Development Status :: 5 - Production/Stable", "Typing :: Typed", ] From 02d8e8df9fc30d182dd184c5ddb0285d96778c23 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 26 Aug 2024 23:10:05 +0200 Subject: [PATCH 02/17] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20update=20pre-commit?= =?UTF-8?q?=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .pre-commit-config.yaml | 17 +++++++---------- pyproject.toml | 1 - 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 53a9739b..98eec9d6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: # 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 @@ -58,13 +58,11 @@ repos: # Python linting and formatting using ruff - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.7 + rev: v0.6.2 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 @@ -75,7 +73,7 @@ repos: # Check static types with mypy - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.1 + rev: v1.11.2 hooks: - id: mypy files: ^(src/mqt|test/python) @@ -85,11 +83,10 @@ repos: - numpy - pytest - pytest-mock - - numba # Check for spelling - repo: https://github.com/crate-ci/typos - rev: v1.23.6 + rev: v1.24.1 hooks: - id: typos @@ -127,14 +124,14 @@ 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 + rev: 0.29.2 hooks: - id: check-dependabot - id: check-github-workflows @@ -142,6 +139,6 @@ repos: # Check the pyproject.toml file - repo: https://github.com/henryiii/validate-pyproject-schema-store - rev: 2024.08.08 + rev: 2024.08.26 hooks: - id: validate-pyproject diff --git a/pyproject.toml b/pyproject.toml index 77c549f7..bf9fda8a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -186,7 +186,6 @@ ignore_missing_imports = true [tool.ruff] line-length = 120 -src = ["src"] namespace-packages = ["mqt"] preview = true unsafe-fixes = true From c4a0d40e6b6729bdc5391df05fa55925fb80f6ec Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 26 Aug 2024 23:29:41 +0200 Subject: [PATCH 03/17] =?UTF-8?q?=F0=9F=9A=A8=20address=20mypy=20warnings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .../simulators/analog_tannergraph_decoding.py | 2 +- .../simulators/memory_experiment_v2.py | 2 +- .../simulators/simulation.py | 14 ++--- src/mqt/qecc/cc_decoder/decoder.py | 2 +- src/mqt/qecc/codes/css_code.py | 4 +- src/mqt/qecc/ft_stateprep/simulation.py | 31 ++++------ src/mqt/qecc/ft_stateprep/state_prep.py | 62 +++++++++---------- test/python/ft_stateprep/test_simulation.py | 6 +- test/python/ft_stateprep/test_stateprep.py | 36 +++++------ 9 files changed, 75 insertions(+), 84 deletions(-) diff --git a/src/mqt/qecc/analog_information_decoding/simulators/analog_tannergraph_decoding.py b/src/mqt/qecc/analog_information_decoding/simulators/analog_tannergraph_decoding.py index 90b54dd9..a85807fe 100644 --- a/src/mqt/qecc/analog_information_decoding/simulators/analog_tannergraph_decoding.py +++ b/src/mqt/qecc/analog_information_decoding/simulators/analog_tannergraph_decoding.py @@ -90,7 +90,7 @@ def _set_analog_syndrome(self, analog_syndrome: NDArray[np.float64]) -> None: def decode(self, analog_syndrome: NDArray[np.float64]) -> NDArray[np.int32]: """Decode a given analog syndrome.""" self._set_analog_syndrome(analog_syndrome) - return self.bposd_decoder.decode(simulation_utils.get_binary_from_analog(analog_syndrome)) # type: ignore[no-any-return] + return self.bposd_decoder.decode(simulation_utils.get_binary_from_analog(analog_syndrome)) class AtdSimulator: diff --git a/src/mqt/qecc/analog_information_decoding/simulators/memory_experiment_v2.py b/src/mqt/qecc/analog_information_decoding/simulators/memory_experiment_v2.py index 1ded3773..233fda65 100644 --- a/src/mqt/qecc/analog_information_decoding/simulators/memory_experiment_v2.py +++ b/src/mqt/qecc/analog_information_decoding/simulators/memory_experiment_v2.py @@ -158,4 +158,4 @@ def decode_multiround( # correct in the commit and tentative region as the last round stabilizer is perfect decoded = (np.cumsum(space_correction, 1) % 2)[:, -1] - return decoded.astype(np.int32), syndrome, analog_syndr, bp_iter # type: ignore[return-value] + return decoded.astype(np.int32), syndrome, analog_syndr, bp_iter diff --git a/src/mqt/qecc/analog_information_decoding/simulators/simulation.py b/src/mqt/qecc/analog_information_decoding/simulators/simulation.py index 1fbc9402..c46a8d47 100644 --- a/src/mqt/qecc/analog_information_decoding/simulators/simulation.py +++ b/src/mqt/qecc/analog_information_decoding/simulators/simulation.py @@ -238,9 +238,9 @@ def _get_noisy_syndrome( z_syndrome_w_err = get_noisy_analog_syndrome(perfect_syndr=z_syndrome, sigma=self.sigma_z) else: # usual pauli error channel syndrome error x_syndrome_err = generate_syndr_err(channel_probs=self.x_syndr_error_channel) - x_syndrome_w_err = (x_syndrome + x_syndrome_err) % 2 # type: ignore[assignment] # only occurs due to reused var name + x_syndrome_w_err = (x_syndrome + x_syndrome_err) % 2 z_syndrome_err = generate_syndr_err(channel_probs=self.z_syndr_error_channel) - z_syndrome_w_err = (z_syndrome + z_syndrome_err) % 2 # type: ignore[assignment] # only occurs due to reused var name + z_syndrome_w_err = (z_syndrome + z_syndrome_err) % 2 else: x_syndrome_w_err = np.copy(x_syndrome) z_syndrome_w_err = np.copy(z_syndrome) @@ -354,7 +354,7 @@ def _decode_ss_with_meta( meta_bin = (meta_pcm @ get_binary_from_analog(syndrome_w_err)) % 2 meta_syndr = get_signed_from_binary(meta_bin) # for AI decoder we need {-1,+1} syndrome as input else: - meta_syndr = (meta_pcm @ syndrome_w_err) % 2 # type: ignore[assignment] # only occurs due to reused var name + meta_syndr = (meta_pcm @ syndrome_w_err) % 2 ss_syndr = np.hstack((syndrome_w_err, meta_syndr)) # only first n bit are data, the other are virtual nodes and can be discarded for estimate @@ -383,7 +383,7 @@ def _ss_analog_tg_decoding( meta_syndr = (meta_pcm @ bin_syndr) % 2 ss_syndr = np.hstack((bin_syndr, meta_syndr)) # only first n bit are data, return them - return decoder.decode(ss_syndr)[: self.n] # type: ignore[no-any-return] + return decoder.decode(ss_syndr)[: self.n] def _two_stage_decoding( self, x_syndrome_w_err: NDArray[np.float64], z_syndrome_w_err: NDArray[np.float64] @@ -483,7 +483,7 @@ def _analog_tg_decoding( analog_channel = get_virtual_check_init_vals(analog_syndrome, sigma) decoder.update_channel_probs(np.hstack((bit_err_channel, analog_channel))) # only first n bit are data so only return those - return decoder.decode(hard_syndrome)[: self.n] # type: ignore[no-any-return] + return decoder.decode(hard_syndrome)[: self.n] def _single_stage_setup( self, @@ -505,11 +505,11 @@ def _single_stage_setup( if self.z_meta and self.Mz is not None: self.ss_z_pcm = build_single_stage_pcm(self.Hz, self.Mz) else: - self.ss_z_pcm = None # type: ignore[assignment] + self.ss_z_pcm = None if self.x_meta and self.Mx is not None: self.ss_x_pcm = build_single_stage_pcm(self.Hx, self.Mx) else: - self.ss_x_pcm = None # type: ignore[assignment] + self.ss_x_pcm = None # X-checks := (Hx|Mx) => Influenced by Z-syndrome error rate # ss_x_bpd used to decode X bit errors using Z-side check matrices diff --git a/src/mqt/qecc/cc_decoder/decoder.py b/src/mqt/qecc/cc_decoder/decoder.py index d7f36e94..a43427a1 100644 --- a/src/mqt/qecc/cc_decoder/decoder.py +++ b/src/mqt/qecc/cc_decoder/decoder.py @@ -164,7 +164,7 @@ def simulate_error_rate(code: ColorCode, error_rate: float, nr_sims: int, solver for logical in range(len(code.L)): if (code.L[logical] @ residual % 2).any(): logical_errors[logical] += 1 - wt = np.sum(residual) # compute the min weight of a logical error + wt: int = np.sum(residual) # compute the min weight of a logical error if min_wt_logicals[logical] == -1 or wt < min_wt_logicals[logical]: min_wt_logicals[logical] = int(wt) break diff --git a/src/mqt/qecc/codes/css_code.py b/src/mqt/qecc/codes/css_code.py index 91f186a0..ae144d99 100644 --- a/src/mqt/qecc/codes/css_code.py +++ b/src/mqt/qecc/codes/css_code.py @@ -96,7 +96,7 @@ def _compute_logical(m1: npt.NDArray[np.int8] | None, m2: npt.NDArray[np.int8] | return logs if m2 is None: - return mod2.nullspace(m1).astype(np.int8) # type: ignore[no-any-return] + return mod2.nullspace(m1).astype(np.int8) ker_m1 = mod2.nullspace(m1) # compute the kernel basis of m1 im_m2_transp = mod2.row_basis(m2) # compute the image basis of m2 @@ -220,7 +220,7 @@ def from_code_name(code_name: str, distance: int | None = None) -> CSSCode: if code_name == "surface": if distance is None: distance = 3 - code_name += "_%d" % distance + code_name += f"_{distance}" if code_name in paths: hx = np.load(paths[code_name] / "hx.npy") diff --git a/src/mqt/qecc/ft_stateprep/simulation.py b/src/mqt/qecc/ft_stateprep/simulation.py index 41342368..f89509b7 100644 --- a/src/mqt/qecc/ft_stateprep/simulation.py +++ b/src/mqt/qecc/ft_stateprep/simulation.py @@ -51,11 +51,11 @@ def __init__( self.zero_state = zero_state # Store which measurements are X, Z or data measurements. # The indices refer to the indices of the measurements in the stim circuit. - self.x_verification_measurements = [] # type: list[int] - self.z_verification_measurements = [] # type: list[int] - self.x_measurements = [] # type: list[int] - self.z_measurements = [] # type: list[int] - self.data_measurements = [] # type: list[int] + self.x_verification_measurements: list[int] = [] + self.z_verification_measurements: list[int] = [] + self.x_measurements: list[int] = [] + self.z_measurements: list[int] = [] + self.data_measurements: list[int] = [] self.parallel_gates = parallel_gates self.n_measurements = 0 self.stim_circ = stim.Circuit() @@ -98,10 +98,6 @@ def to_stim_circ(self) -> stim.Circuit: - Two-qubit gates are followed by a two-qubit Pauli error with probability p/15. - Measurements flip with a probability of 2/3 p. - Qubit are initialized in the -1 Eigenstate with probability 2/3 p. - - Args: - circ: The QuantumCircuit to convert. - p: The error rate. """ initialized = [False for _ in self.circ.qubits] stim_circuit = stim.Circuit() @@ -115,10 +111,9 @@ def idle_error(used_qubits: list[int]) -> None: dag = circuit_to_dag(self.circ) layers = dag.layers() - used_qubits = [] # type: list[int] - + used_qubits: list[int] = [] targets = set() - measured = defaultdict(int) # type: defaultdict[int, int] + measured: defaultdict[int, int] = defaultdict(int) for layer in layers: layer_circ = dag_to_circuit(layer["graph"]) @@ -181,7 +176,7 @@ def idle_error(used_qubits: list[int]) -> None: return stim_circuit - def measure_stabilizers(self) -> stim.Circuit: + def measure_stabilizers(self) -> None: """Measure the stabilizers of the code. An ancilla is used for each measurement. @@ -295,7 +290,7 @@ def _simulate_batch(self, shots: int = 1024) -> tuple[int, int]: corrected = state + estimates num_discarded = detection_events.shape[0] - filtered_events.shape[0] - num_logical_errors = np.sum( + num_logical_errors: int = np.sum( np.any(corrected @ observables.T % 2 != 0, axis=1) ) # number of non-commuting corrected states return num_logical_errors, num_discarded @@ -348,8 +343,8 @@ def __init__(self, code: CSSCode, init_luts: bool = True) -> None: init_luts: Whether to initialize the lookup tables at object creation. """ self.code = code - self.x_lut = {} # type: dict[bytes, npt.NDArray[np.int8]] - self.z_lut = {} # type: dict[bytes, npt.NDArray[np.int8]] + self.x_lut: dict[bytes, npt.NDArray[np.int8]] = {} + self.z_lut: dict[bytes, npt.NDArray[np.int8]] = {} if init_luts: self.generate_x_lut() self.generate_z_lut() @@ -403,9 +398,9 @@ def _generate_lut(checks: npt.NDArray[np.int_]) -> dict[bytes, npt.NDArray[np.in n_qubits = checks.shape[1] syndromes = defaultdict(list) - lut = {} # type: dict[bytes, npt.NDArray[np.int8]] + lut: dict[bytes, npt.NDArray[np.int8]] = {} for i in range(2**n_qubits): - state = np.array(list(np.binary_repr(i).zfill(n_qubits))).astype(np.int8) # type: npt.NDArray[np.int_] + state: npt.NDArray[np.int_] = np.array(list(np.binary_repr(i).zfill(n_qubits))).astype(np.int8) syndrome = checks @ state % 2 syndromes[syndrome.astype(np.int8).tobytes()].append(state) diff --git a/src/mqt/qecc/ft_stateprep/state_prep.py b/src/mqt/qecc/ft_stateprep/state_prep.py index e7abf1d3..9d8e5ba4 100644 --- a/src/mqt/qecc/ft_stateprep/state_prep.py +++ b/src/mqt/qecc/ft_stateprep/state_prep.py @@ -18,7 +18,6 @@ logger = logging.getLogger(__name__) - if TYPE_CHECKING: # pragma: no cover from collections.abc import Callable @@ -78,7 +77,6 @@ def compute_fault_set( """Compute the fault set of the state. Args: - state: The stabilizer state to compute the fault set for. num_errors: The number of independent errors to propagate through the circuit. x_errors: If True, compute the fault set for X errors. If False, compute the fault set for Z errors. reduce: If True, reduce the fault set by the stabilizers of the code to reduce weights. @@ -86,7 +84,9 @@ def compute_fault_set( Returns: The fault set of the state. """ - faults = self.x_fault_sets[num_errors] if x_errors else self.z_fault_sets[num_errors] # type: npt.NDArray[np.int8] | None + faults: npt.NDArray[np.int8] | None = ( + self.x_fault_sets[num_errors] if x_errors else self.z_fault_sets[num_errors] + ) if faults is not None: return faults @@ -104,7 +104,7 @@ def compute_fault_set( faults = np.unique(faults, axis=0) if x_errors and self.x_fault_sets_unreduced[1] is None: - non_propagated_single_errors = np.eye(self.num_qubits, dtype=np.int8) # type: npt.NDArray[np.int8] + non_propagated_single_errors = np.eye(self.num_qubits, dtype=np.int8) self.x_fault_sets_unreduced[1] = np.vstack((faults, non_propagated_single_errors)) elif not x_errors and self.z_fault_sets[1] is None: non_propagated_single_errors = np.eye(self.num_qubits, dtype=np.int8) @@ -168,7 +168,7 @@ def combine_faults( next_faults = fault_sets_unreduced[i + 1] assert next_faults is not None fault_sets_unreduced[i + 1] = np.vstack((next_faults, combined)) - fault_sets = [None for _ in range(self.max_errors + 1)] # type: list[None | npt.NDArray[np.int8]] + fault_sets: list[npt.NDArray[np.int8] | None] = [None for _ in range(self.max_errors + 1)] stabs = self.x_checks if x_errors else self.z_checks for num_errors in range(1, self.max_errors + 1): fs = fault_sets_unreduced[num_errors] @@ -188,10 +188,10 @@ def _set_max_errors(self) -> None: self.max_z_errors = ( (self.code.z_distance - 1) // 2 if not self.error_detection_code else self.code.z_distance // 2 ) - self.x_fault_sets = [None for _ in range(self.max_errors + 1)] # type: list[npt.NDArray[np.int8] | None] - self.z_fault_sets = [None for _ in range(self.max_errors + 1)] # type: list[npt.NDArray[np.int8] | None] - self.x_fault_sets_unreduced = [None for _ in range(self.max_errors + 1)] # type: list[npt.NDArray[np.int8] | None] - self.z_fault_sets_unreduced = [None for _ in range(self.max_errors + 1)] # type: list[npt.NDArray[np.int8] | None] + self.x_fault_sets: list[npt.NDArray[np.int8] | None] = [None for _ in range(self.max_errors + 1)] + self.z_fault_sets: list[npt.NDArray[np.int8] | None] = [None for _ in range(self.max_errors + 1)] + self.x_fault_sets_unreduced: list[npt.NDArray[np.int8] | None] = [None for _ in range(self.max_errors + 1)] + self.z_fault_sets_unreduced: list[npt.NDArray[np.int8] | None] = [None for _ in range(self.max_errors + 1)] def heuristic_prep_circuit(code: CSSCode, optimize_depth: bool = True, zero_state: bool = True) -> StatePrepCircuit: @@ -218,16 +218,16 @@ def is_reduced() -> bool: costs -= np.sum(checks, axis=0) np.fill_diagonal(costs, 1) - used_qubits = [] # type: list[np.int_] - cnots = [] # type: list[tuple[int, int]] + used_qubits: list[np.int_] = [] + cnots: list[tuple[int, int]] = [] while not is_reduced(): - m = np.zeros((checks.shape[1], checks.shape[1]), dtype=bool) # type: npt.NDArray[np.bool_] + m = np.zeros((checks.shape[1], checks.shape[1]), dtype=bool) m[used_qubits, :] = True m[:, used_qubits] = True costs_unused = np.ma.array(costs, mask=m) # type: ignore[no-untyped-call] if np.all(costs_unused >= 0) or len(used_qubits) == checks.shape[1]: # no more reductions possible - if used_qubits == []: # local minimum => get out by making matrix triangular + if not used_qubits: # local minimum => get out by making matrix triangular logging.warning("Local minimum reached. Making matrix triangular.") checks = mod2.reduced_row_echelon(checks)[0] costs = np.array([ @@ -329,7 +329,7 @@ def _generate_circ_with_bounded_depth( def _generate_circ_with_bounded_gates( checks: npt.NDArray[np.int8], max_cnots: int, zero_state: bool = True -) -> QuantumCircuit: +) -> QuantumCircuit | None: """Find the gate optimal circuit for a given check matrix and maximum depth.""" n = checks.shape[1] columns = np.array([ @@ -591,7 +591,7 @@ def gate_optimal_verification_stabilizers( A list of stabilizers to verify the state preparation circuit. """ max_errors = sp_circ.max_errors - layers = [[] for _ in range(max_errors)] # type: list[list[npt.NDArray[np.int8]]] + layers: list[list[npt.NDArray[np.int8]]] = [[] for _ in range(max_errors)] if max_ancillas is None: max_ancillas = sp_circ.max_z_measurements if x_errors else sp_circ.max_x_measurements @@ -618,8 +618,8 @@ def gate_optimal_verification_stabilizers( # Minimal CNOT solution must be achievable with these num_anc = max_ancillas checks = sp_circ.z_checks if x_errors else sp_circ.x_checks - min_cnots = np.min(np.sum(checks, axis=1)) - max_cnots = np.sum(checks) + min_cnots: int = np.min(np.sum(checks, axis=1)) + max_cnots: int = np.sum(checks) logging.info( f"Finding verification stabilizers for {num_errors} errors with {min_cnots} to {max_cnots} CNOTs using {num_anc} ancillas" @@ -700,7 +700,7 @@ def _verification_circuit( full_fault_tolerance: bool = True, ) -> QuantumCircuit: logging.info("Finding verification stabilizers for the state preparation circuit") - layers_1 = verification_stabs_fun(sp_circ, sp_circ.zero_state) # type: ignore[call-arg] + layers_1 = verification_stabs_fun(sp_circ, sp_circ.zero_state, None) measurements_1 = [measurement for layer in layers_1 for measurement in layer] if full_fault_tolerance: @@ -793,7 +793,7 @@ def heuristic_verification_stabilizers( """ logging.info("Finding verification stabilizers using heuristic method") max_errors = sp_circ.max_errors - layers = [[] for _ in range(max_errors)] # type: list[list[npt.NDArray[np.int8]]] + layers: list[list[npt.NDArray[np.int8]]] = [[] for _ in range(max_errors)] sp_circ.compute_fault_sets() fault_sets = ( sp_circ.combine_faults(additional_faults, x_errors) @@ -825,13 +825,10 @@ def _set_cover( n: int, cands: set[frozenset[int]], mapping: dict[frozenset[int], list[npt.NDArray[np.int8]]] ) -> set[frozenset[int]]: universe = set(range(n)) - cover = set() # type: set[frozenset[int]] - - def sort_key(stab: frozenset[int], universe: set[int] = universe) -> tuple[int, np.int_]: - return (len(stab & universe), -np.sum(mapping[stab])) + cover: set[frozenset[int]] = set() while universe: - best = max(cands, key=sort_key) + best = max(cands, key=lambda stab: (len(stab & universe), -np.sum(mapping[stab]))) # type: ignore[operator] cover.add(best) universe -= best return cover @@ -840,8 +837,8 @@ def sort_key(stab: frozenset[int], universe: set[int] = universe) -> tuple[int, def _extend_covering_sets( candidate_sets: set[frozenset[int]], size_limit: int, mapping: dict[frozenset[int], list[npt.NDArray[np.int8]]] ) -> set[frozenset[int]]: - to_remove = set() # type: set[frozenset[int]] - to_add = set() # type: set[frozenset[int]] + to_remove: set[frozenset[int]] = set() + to_add: set[frozenset[int]] = set() for c1 in candidate_sets: for c2 in candidate_sets: if len(to_add) >= size_limit: @@ -986,7 +983,7 @@ def _measure_ft_stabs( def _vars_to_stab( measurement: list[z3.BoolRef | bool], generators: npt.NDArray[np.int8] -) -> npt.NDArray[z3.BoolRef | bool]: # type: ignore[type-var] +) -> npt.NDArray[z3.BoolRef | bool]: measurement_stab = _symbolic_scalar_mult(generators[0], measurement[0]) for i, scalar in enumerate(measurement[1:]): measurement_stab = _symbolic_vector_add(measurement_stab, _symbolic_scalar_mult(generators[i + 1], scalar)) @@ -1007,7 +1004,6 @@ def verification_stabilizers( fault_set: The set of errors to verify. num_anc: The maximum number of ancilla qubits to use. num_cnots: The maximumg number of CNOT gates to use. - num_errors: The number of errors occur in the state prep circuit. x_errors: If True, the errors are X errors. Otherwise, the errors are Z errors. """ # Measurements are written as sums of generators @@ -1040,7 +1036,7 @@ def verification_stabilizers( # Extract stabilizer measurements from model actual_measurements = [] for m in measurement_vars: - v = np.zeros(sp_circ.num_qubits, dtype=np.int8) # type: npt.NDArray[np.int8] + v = np.zeros(sp_circ.num_qubits, dtype=np.int8) for g in range(n_gens): if model[m[g]]: v += gens[g] @@ -1136,7 +1132,7 @@ def _column_addition_constraint( col_add_vars: npt.NDArray[z3.BoolRef], ) -> z3.BoolRef: assert len(columns.shape) == 3 - max_depth = col_add_vars.shape[0] # type: ignore[unreachable] + max_depth = col_add_vars.shape[0] n_cols = col_add_vars.shape[2] constraints = [] @@ -1170,7 +1166,7 @@ def _column_addition_constraint( def _final_matrix_constraint(columns: npt.NDArray[z3.BoolRef | bool]) -> z3.BoolRef: assert len(columns.shape) == 3 - return z3.PbEq( # type: ignore[unreachable] + return z3.PbEq( [(z3.Not(z3.Or(list(columns[-1, :, col]))), 1) for col in range(columns.shape[2])], columns.shape[2] - columns.shape[1], ) @@ -1179,11 +1175,11 @@ def _final_matrix_constraint(columns: npt.NDArray[z3.BoolRef | bool]) -> z3.Bool def _propagate_error(dag: DagCircuit, node: DAGNode, x_errors: bool = True) -> PauliList: """Propagates a Pauli error through a circuit beginning from control of node.""" control = node.qargs[0]._index # noqa: SLF001 - error = np.array([0] * dag.num_qubits(), dtype=np.int8) # type: npt.NDArray[np.int8] + error: npt.NDArray[np.int8] = np.array([0] * dag.num_qubits(), dtype=np.int8) error[control] = 1 # propagate error through circuit via bfs q = deque([node]) - visited = set() # type: set[DAGNode] + visited: set[DAGNode] = set() while q: node = q.popleft() if node in visited or isinstance(node, DAGOutNode): diff --git a/test/python/ft_stateprep/test_simulation.py b/test/python/ft_stateprep/test_simulation.py index d053589a..03fe2c3e 100644 --- a/test/python/ft_stateprep/test_simulation.py +++ b/test/python/ft_stateprep/test_simulation.py @@ -67,7 +67,7 @@ def test_lut(steane_code: CSSCode) -> None: assert len(lut.x_lut) != 0 assert lut.x_lut is lut.z_lut # Code is self dual so luts should be the same - error_1 = np.zeros(steane_code.n, dtype=np.int8) # type: ignore[var-annotated] + error_1 = np.zeros(steane_code.n, dtype=np.int8) error_1[0] = 1 error_w1 = (steane_code.Hx[0] + error_1) % 2 @@ -76,7 +76,7 @@ def test_lut(steane_code: CSSCode) -> None: assert steane_code.stabilizer_eq_x_error(estimate_1, error_1) assert steane_code.stabilizer_eq_z_error(estimate_1, error_1) - error_2 = np.zeros(steane_code.n, dtype=np.int8) # type: ignore[var-annotated] + error_2 = np.zeros(steane_code.n, dtype=np.int8) error_2[0] = 1 error_2[1] = 1 error_w2 = (steane_code.Hx[0] + error_2) % 2 @@ -87,7 +87,7 @@ def test_lut(steane_code: CSSCode) -> None: assert not steane_code.stabilizer_eq_x_error(estimate_2, error_2) assert np.sum(estimate_2) == 1 - error_3 = np.ones((steane_code.n), dtype=np.int8) # type: ignore[var-annotated] + error_3 = np.ones((steane_code.n), dtype=np.int8) error_w3 = (steane_code.Hx[0] + error_3) % 2 syndrome_3 = steane_code.get_x_syndrome(error_w3) estimate_3 = lut.decode_x(syndrome_3.astype(np.int8)) diff --git a/test/python/ft_stateprep/test_stateprep.py b/test/python/ft_stateprep/test_stateprep.py index 5bb2ab17..2fbb991c 100644 --- a/test/python/ft_stateprep/test_stateprep.py +++ b/test/python/ft_stateprep/test_stateprep.py @@ -90,7 +90,7 @@ def color_code_d5_sp(cc_4_8_8_code: CSSCode) -> StatePrepCircuit: def eq_span(a: npt.NDArray[np.int_], b: npt.NDArray[np.int_]) -> bool: """Check if two matrices have the same row space.""" - return a.shape == b.shape and mod2.rank(np.vstack((a, b))) == mod2.rank(a) == mod2.rank(b) + return (a.shape == b.shape) and (int(mod2.rank(np.vstack((a, b)))) == int(mod2.rank(a)) == int(mod2.rank(b))) def in_span(m: npt.NDArray[np.int_], v: npt.NDArray[np.int_]) -> bool: @@ -117,14 +117,14 @@ def test_heuristic_prep_consistent(code: CSSCode, request) -> None: # type: ign sp_circ = heuristic_prep_circuit(code) circ = sp_circ.circ - max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[arg-type] + max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[operator] assert circ.num_qubits == code.n assert circ.num_nonlocal_gates() <= max_cnots x, z = get_stabs(circ) - assert eq_span(code.Hx, x) # type: ignore[arg-type] - assert eq_span(np.vstack((code.Hz, code.Lz)), z) # type: ignore[arg-type] + assert eq_span(code.Hx, x) + assert eq_span(np.vstack((code.Hz, code.Lz)), z) @pytest.mark.parametrize("code", ["steane_code", "css_4_2_2_code", "css_6_2_2_code"]) @@ -136,14 +136,14 @@ def test_gate_optimal_prep_consistent(code: CSSCode, request) -> None: # type: assert sp_circ.zero_state circ = sp_circ.circ - max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[arg-type] + max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[operator] assert circ.num_qubits == code.n assert circ.num_nonlocal_gates() <= max_cnots x, z = get_stabs(circ) - assert eq_span(code.Hx, x) # type: ignore[arg-type] - assert eq_span(np.vstack((code.Hz, code.Lz)), z) # type: ignore[arg-type] + assert eq_span(code.Hx, x) + assert eq_span(np.vstack((code.Hz, code.Lz)), z) @pytest.mark.parametrize("code", ["steane_code", "css_4_2_2_code", "css_6_2_2_code"]) @@ -154,14 +154,14 @@ def test_depth_optimal_prep_consistent(code: CSSCode, request) -> None: # type: sp_circ = depth_optimal_prep_circuit(code, max_timeout=3) assert sp_circ is not None circ = sp_circ.circ - max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[arg-type] + max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[operator] assert circ.num_qubits == code.n assert circ.num_nonlocal_gates() <= max_cnots x, z = get_stabs(circ) - assert eq_span(code.Hx, x) # type: ignore[arg-type] - assert eq_span(np.vstack((code.Hz, code.Lz)), z) # type: ignore[arg-type] + assert eq_span(code.Hx, x) + assert eq_span(np.vstack((code.Hz, code.Lz)), z) @pytest.mark.parametrize("code", ["steane_code", "css_4_2_2_code", "css_6_2_2_code"]) @@ -174,14 +174,14 @@ def test_plus_state_gate_optimal(code: CSSCode, request) -> None: # type: ignor assert not sp_circ_plus.zero_state circ_plus = sp_circ_plus.circ - max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[arg-type] + max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[operator] assert circ_plus.num_qubits == code.n assert circ_plus.num_nonlocal_gates() <= max_cnots x, z = get_stabs(circ_plus) - assert eq_span(code.Hz, z) # type: ignore[arg-type] - assert eq_span(np.vstack((code.Hx, code.Lx)), x) # type: ignore[arg-type] + assert eq_span(code.Hz, z) + assert eq_span(np.vstack((code.Hx, code.Lx)), x) sp_circ_zero = gate_optimal_prep_circuit(code, max_timeout=5, zero_state=True) @@ -210,14 +210,14 @@ def test_plus_state_heuristic(code: CSSCode, request) -> None: # type: ignore[n assert not sp_circ_plus.zero_state circ_plus = sp_circ_plus.circ - max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[arg-type] + max_cnots = np.sum(code.Hx) + np.sum(code.Hz) # type: ignore[operator] assert circ_plus.num_qubits == code.n assert circ_plus.num_nonlocal_gates() <= max_cnots x, z = get_stabs(circ_plus) - assert eq_span(code.Hz, z) # type: ignore[arg-type] - assert eq_span(np.vstack((code.Hx, code.Lx)), x) # type: ignore[arg-type] + assert eq_span(code.Hz, z) + assert eq_span(np.vstack((code.Hx, code.Lx)), x) sp_circ_zero = heuristic_prep_circuit(code, zero_state=True) circ_zero = sp_circ_zero.circ @@ -378,7 +378,7 @@ def test_not_full_ft_opt_cc5(color_code_d5_sp: StatePrepCircuit) -> None: assert len(non_detected) == 0 # Check that circuit is correct - n_cnots = np.sum(ver_stabs_1) + np.sum(ver_stabs_2) + n_cnots = np.sum(ver_stabs_1) + np.sum(ver_stabs_2) # type: ignore[operator] circ_ver = gate_optimal_verification_circuit(circ, max_ancillas=3, max_timeout=5, full_fault_tolerance=True) assert circ_ver.num_qubits > circ.num_qubits + 5 # overhead from the flags assert circ_ver.num_nonlocal_gates() > n_cnots + circ.circ.num_nonlocal_gates() # Overhead from Flag CNOTS @@ -412,7 +412,7 @@ def test_not_full_ft_heuristic_cc5(color_code_d5_sp: StatePrepCircuit) -> None: # Check that circuit is correct circ_ver = heuristic_verification_circuit(circ, full_fault_tolerance=False) - n_cnots = np.sum(ver_stabs_1) + np.sum(ver_stabs_2) + n_cnots = np.sum(ver_stabs_1) + np.sum(ver_stabs_2) # type: ignore[operator] assert circ_ver.num_qubits == circ.num_qubits + len(ver_stabs_1) + len(ver_stabs_2) assert circ_ver.num_nonlocal_gates() == n_cnots + circ.circ.num_nonlocal_gates() From 0d76eedb57deb87343421bb602f8ab6507464164 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 26 Aug 2024 23:38:33 +0200 Subject: [PATCH 04/17] =?UTF-8?q?=F0=9F=94=A7=20update=20project=20configu?= =?UTF-8?q?ration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- noxfile.py | 10 +++++----- pyproject.toml | 22 +++++++--------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/noxfile.py b/noxfile.py index 7202a446..08f41892 100644 --- a/noxfile.py +++ b/noxfile.py @@ -18,7 +18,7 @@ nox.options.sessions = ["lint", "tests"] -PYTHON_ALL_VERSIONS = ["3.8", "3.9", "3.10", "3.11", "3.12"] +PYTHON_ALL_VERSIONS = ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] # The following lists all the build requirements for building the package. # Note that this includes transitive build dependencies of package dependencies, @@ -26,9 +26,9 @@ # and get better caching performance. This only concerns dependencies that are # not available via wheels on PyPI (i.e., only as source distributions). BUILD_REQUIREMENTS = [ - "scikit-build-core[pyproject]>=0.8.1", + "scikit-build-core[pyproject]>=0.10.1", "setuptools_scm>=7", - "pybind11>=2.12", + "pybind11>=2.13", "wheel>=0.40", # transitive dependency of pytest on Windows "Cython>=3; python_version > '3.11'", # required to build ldpc on Python 3.12+ "numpy>=1.26,<2; python_version > '3.11'", # required to build ldpc on Python 3.12+ @@ -73,7 +73,7 @@ def _run_tests( session.install(*BUILD_REQUIREMENTS, *install_args, env=env) install_arg = f"-ve.[{','.join(_extras)}]" - session.install("--no-build-isolation", install_arg, *install_args, env=env) + session.install("--no-build-isolation", "--reinstall-package", "mqt.qecc", install_arg, *install_args, env=env) session.run("pytest", *run_args, *posargs, env=env) @@ -104,7 +104,7 @@ def docs(session: nox.Session) -> None: serve = args.builder == "html" and session.interactive extra_installs = ["sphinx-autobuild"] if serve else [] session.install(*BUILD_REQUIREMENTS, *extra_installs) - session.install("--no-build-isolation", "-ve.[docs]") + session.install("--no-build-isolation", "-ve.[docs]", "--reinstall-package", "mqt.qecc") session.chdir("docs") if args.builder == "linkcheck": diff --git a/pyproject.toml b/pyproject.toml index bf9fda8a..ca1047b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["scikit-build-core>=0.8.1", "setuptools-scm>=7", "pybind11>=2.12"] +requires = ["scikit-build-core>=0.10.1", "setuptools-scm>=7", "pybind11>=2.13"] build-backend = "scikit_build_core.build" [project] @@ -89,23 +89,22 @@ Discussions = "https://github.com/cda-tum/mqt-qecc/discussions" [tool.scikit-build] # Protect the configuration against future changes in scikit-build-core -minimum-version = "0.8.1" +minimum-version = "build-system.requires" # Set the wheel install directory wheel.install-dir = "mqt/qecc" -# Set required CMake and Ninja versions -cmake.version = ">=3.19" +# Set required Ninja version ninja.version = ">=1.10" # Setuptools-style build caching in a local directory -build-dir = "build/{wheel_tag}" +build-dir = "build/{build_type}" # Explicitly set the package directory wheel.packages = ["src/mqt"] # Only build the Python bindings target -cmake.targets = ["pyqecc"] +build.targets = ["pyqecc"] # Only install the Python package component install.components = ["mqt-qecc_Python"] @@ -281,13 +280,6 @@ aer = "aer" anc = "anc" -[tool.repo-review] -ignore = [ - "PC160", # "Uses codespell" -> switched to https://github.com/crate-ci/typos - "PC180", # "Uses prettier" -> switched to different prettier-mirror that is not recognized by the check -] - - [tool.cibuildwheel] build = "cp3*" skip = "*-musllinux*" @@ -303,9 +295,9 @@ environment = { DEPLOY = "ON" } environment = { MACOSX_DEPLOYMENT_TARGET = "11.0" } [tool.cibuildwheel.windows] -before-build = "uv pip install delvewheel>=1.4.0" +before-build = "uv pip install delvewheel>=1.7.3" repair-wheel-command = "delvewheel repair -v -w {dest_dir} {wheel} --namespace-pkg mqt" -environment = { CMAKE_ARGS = "-T ClangCL" } +environment = { CMAKE_ARGS = "-T ClangCL", SKBUILD_CMAKE_ARGS="--fresh" } [[tool.cibuildwheel.overrides]] select = "cp312-*" From 9e3ed58620b1bde73b8f9112f1c937094b8587c2 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 00:01:01 +0200 Subject: [PATCH 05/17] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20update=20MQT=20Core?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- cmake/ExternalDependencies.cmake | 4 ++-- include/ecc/Ecc.hpp | 6 ++---- include/ecc/Id.hpp | 4 ++-- include/ecc/Q18Surface.hpp | 4 ++-- include/ecc/Q3Shor.hpp | 8 ++++---- include/ecc/Q5Laflamme.hpp | 6 +++--- include/ecc/Q7Steane.hpp | 8 ++++---- include/ecc/Q9Shor.hpp | 4 ++-- include/ecc/Q9Surface.hpp | 4 ++-- src/ecc/CMakeLists.txt | 8 ++++++-- src/ecc/Ecc.cpp | 2 +- src/ecc/Q18Surface.cpp | 8 ++++---- src/ecc/Q3Shor.cpp | 8 ++++---- src/ecc/Q5Laflamme.cpp | 8 ++++---- src/ecc/Q7Steane.cpp | 10 +++++----- src/ecc/Q9Shor.cpp | 10 +++++----- src/ecc/Q9Surface.cpp | 8 ++++---- src/python/bindings.cpp | 2 +- test/test_ecc_functionality.cpp | 6 +++--- 19 files changed, 60 insertions(+), 58 deletions(-) diff --git a/cmake/ExternalDependencies.cmake b/cmake/ExternalDependencies.cmake index cd28d503..cea7dab8 100644 --- a/cmake/ExternalDependencies.cmake +++ b/cmake/ExternalDependencies.cmake @@ -20,9 +20,9 @@ if(BUILD_MQT_QECC_BINDINGS) endif() # cmake-format: off -set(MQT_CORE_VERSION 2.5.1 +set(MQT_CORE_VERSION 2.6.1 CACHE STRING "MQT Core version") -set(MQT_CORE_REV "35e06ca3067ca3cf36bda1f0c38edf5bd7456fb6" +set(MQT_CORE_REV "5be1c3ec4efb773d0330298621704e876afa7c16" CACHE STRING "MQT Core identifier (tag, branch or commit hash)") set(MQT_CORE_REPO_OWNER "cda-tum" CACHE STRING "MQT Core repository owner (change when using a fork)") diff --git a/include/ecc/Ecc.hpp b/include/ecc/Ecc.hpp index 7555bd7a..35a7fd37 100644 --- a/include/ecc/Ecc.hpp +++ b/include/ecc/Ecc.hpp @@ -1,17 +1,15 @@ #pragma once #include "Definitions.hpp" -#include "QuantumComputation.hpp" -#include "operations/OpType.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/OpType.hpp" #include #include #include -#include #include #include #include -#include #include namespace ecc { diff --git a/include/ecc/Id.hpp b/include/ecc/Id.hpp index 9c473e6d..0ace9505 100644 --- a/include/ecc/Id.hpp +++ b/include/ecc/Id.hpp @@ -1,8 +1,8 @@ #pragma once #include "Ecc.hpp" -#include "QuantumComputation.hpp" -#include "operations/Operation.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/include/ecc/Q18Surface.hpp b/include/ecc/Q18Surface.hpp index 125331e8..4d564d9a 100644 --- a/include/ecc/Q18Surface.hpp +++ b/include/ecc/Q18Surface.hpp @@ -1,8 +1,8 @@ #pragma once #include "Ecc.hpp" -#include "QuantumComputation.hpp" -#include "operations/Operation.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/include/ecc/Q3Shor.hpp b/include/ecc/Q3Shor.hpp index 5eb6bc87..c8eda9a9 100644 --- a/include/ecc/Q3Shor.hpp +++ b/include/ecc/Q3Shor.hpp @@ -2,10 +2,10 @@ #include "Definitions.hpp" #include "Ecc.hpp" -#include "QuantumComputation.hpp" -#include "operations/Control.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/Control.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/include/ecc/Q5Laflamme.hpp b/include/ecc/Q5Laflamme.hpp index 092af904..87e2cbb0 100644 --- a/include/ecc/Q5Laflamme.hpp +++ b/include/ecc/Q5Laflamme.hpp @@ -1,9 +1,9 @@ #pragma once #include "Ecc.hpp" -#include "QuantumComputation.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/include/ecc/Q7Steane.hpp b/include/ecc/Q7Steane.hpp index 7a645183..7377976f 100644 --- a/include/ecc/Q7Steane.hpp +++ b/include/ecc/Q7Steane.hpp @@ -2,10 +2,10 @@ #include "Definitions.hpp" #include "Ecc.hpp" -#include "QuantumComputation.hpp" -#include "operations/Control.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/Control.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/include/ecc/Q9Shor.hpp b/include/ecc/Q9Shor.hpp index 3e622e9d..5e511099 100644 --- a/include/ecc/Q9Shor.hpp +++ b/include/ecc/Q9Shor.hpp @@ -1,8 +1,8 @@ #pragma once #include "Ecc.hpp" -#include "QuantumComputation.hpp" -#include "operations/Operation.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/include/ecc/Q9Surface.hpp b/include/ecc/Q9Surface.hpp index eeb41f2f..77c537ce 100644 --- a/include/ecc/Q9Surface.hpp +++ b/include/ecc/Q9Surface.hpp @@ -1,8 +1,8 @@ #pragma once #include "Ecc.hpp" -#include "QuantumComputation.hpp" -#include "operations/Operation.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/src/ecc/CMakeLists.txt b/src/ecc/CMakeLists.txt index 6748c95e..45bcf018 100644 --- a/src/ecc/CMakeLists.txt +++ b/src/ecc/CMakeLists.txt @@ -13,8 +13,12 @@ if(NOT TARGET ${PROJECT_NAME}-ecc) Q9Surface.cpp Q18Surface.cpp) - target_link_libraries(${PROJECT_NAME}-ecc PUBLIC MQT::Core) - target_link_libraries(${PROJECT_NAME}-ecc PRIVATE MQT::ProjectOptions MQT::ProjectWarnings) + target_link_libraries( + ${PROJECT_NAME}-ecc + PUBLIC MQT::CoreIR + PRIVATE MQT::ProjectOptions MQT::ProjectWarnings) + + target_include_directories(${PROJECT_NAME}-ecc PUBLIC ${MQT_QECC_INCLUDE_BUILD_DIR}) # add MQT alias add_library(MQT::QECCFramework ALIAS ${PROJECT_NAME}-ecc) diff --git a/src/ecc/Ecc.cpp b/src/ecc/Ecc.cpp index d42618ca..2a1a168d 100644 --- a/src/ecc/Ecc.cpp +++ b/src/ecc/Ecc.cpp @@ -1,6 +1,6 @@ #include "ecc/Ecc.hpp" -#include "QuantumComputation.hpp" +#include "ir/QuantumComputation.hpp" #include #include diff --git a/src/ecc/Q18Surface.cpp b/src/ecc/Q18Surface.cpp index 36cf911d..ff44ba5d 100644 --- a/src/ecc/Q18Surface.cpp +++ b/src/ecc/Q18Surface.cpp @@ -1,10 +1,10 @@ #include "ecc/Q18Surface.hpp" #include "ecc/Ecc.hpp" -#include "operations/Control.hpp" -#include "operations/NonUnitaryOperation.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" +#include "ir/operations/Control.hpp" +#include "ir/operations/NonUnitaryOperation.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/src/ecc/Q3Shor.cpp b/src/ecc/Q3Shor.cpp index f03f3b83..42490cca 100644 --- a/src/ecc/Q3Shor.cpp +++ b/src/ecc/Q3Shor.cpp @@ -2,10 +2,10 @@ #include "Definitions.hpp" #include "ecc/Ecc.hpp" -#include "operations/NonUnitaryOperation.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" -#include "operations/StandardOperation.hpp" +#include "ir/operations/NonUnitaryOperation.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" +#include "ir/operations/StandardOperation.hpp" #include #include diff --git a/src/ecc/Q5Laflamme.cpp b/src/ecc/Q5Laflamme.cpp index 999933f2..1e40ef5b 100644 --- a/src/ecc/Q5Laflamme.cpp +++ b/src/ecc/Q5Laflamme.cpp @@ -1,10 +1,10 @@ #include "ecc/Q5Laflamme.hpp" #include "ecc/Ecc.hpp" -#include "operations/NonUnitaryOperation.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" -#include "operations/StandardOperation.hpp" +#include "ir/operations/NonUnitaryOperation.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" +#include "ir/operations/StandardOperation.hpp" #include #include diff --git a/src/ecc/Q7Steane.cpp b/src/ecc/Q7Steane.cpp index 36ae0eb7..6eb077b9 100644 --- a/src/ecc/Q7Steane.cpp +++ b/src/ecc/Q7Steane.cpp @@ -2,11 +2,11 @@ #include "Definitions.hpp" #include "ecc/Ecc.hpp" -#include "operations/Control.hpp" -#include "operations/NonUnitaryOperation.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" -#include "operations/StandardOperation.hpp" +#include "ir/operations/Control.hpp" +#include "ir/operations/NonUnitaryOperation.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" +#include "ir/operations/StandardOperation.hpp" #include #include diff --git a/src/ecc/Q9Shor.cpp b/src/ecc/Q9Shor.cpp index eda8518f..4ba521c8 100644 --- a/src/ecc/Q9Shor.cpp +++ b/src/ecc/Q9Shor.cpp @@ -1,11 +1,11 @@ #include "ecc/Q9Shor.hpp" #include "ecc/Ecc.hpp" -#include "operations/Control.hpp" -#include "operations/NonUnitaryOperation.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" -#include "operations/StandardOperation.hpp" +#include "ir/operations/Control.hpp" +#include "ir/operations/NonUnitaryOperation.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" +#include "ir/operations/StandardOperation.hpp" #include #include diff --git a/src/ecc/Q9Surface.cpp b/src/ecc/Q9Surface.cpp index 86683751..43224507 100644 --- a/src/ecc/Q9Surface.cpp +++ b/src/ecc/Q9Surface.cpp @@ -1,10 +1,10 @@ #include "ecc/Q9Surface.hpp" #include "ecc/Ecc.hpp" -#include "operations/Control.hpp" -#include "operations/NonUnitaryOperation.hpp" -#include "operations/OpType.hpp" -#include "operations/Operation.hpp" +#include "ir/operations/Control.hpp" +#include "ir/operations/NonUnitaryOperation.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/Operation.hpp" #include #include diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index d05faa81..22ebe471 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -6,7 +6,6 @@ #include "Decoder.hpp" #include "DecodingRunInformation.hpp" #include "DecodingSimulator.hpp" -#include "QuantumComputation.hpp" #include "UFDecoder.hpp" #include "UFHeuristic.hpp" #include "ecc/Ecc.hpp" @@ -17,6 +16,7 @@ #include "ecc/Q7Steane.hpp" #include "ecc/Q9Shor.hpp" #include "ecc/Q9Surface.hpp" +#include "ir/QuantumComputation.hpp" #include "python/qiskit/QuantumCircuit.hpp" #include diff --git a/test/test_ecc_functionality.cpp b/test/test_ecc_functionality.cpp index a20148a1..819639fe 100644 --- a/test/test_ecc_functionality.cpp +++ b/test/test_ecc_functionality.cpp @@ -1,5 +1,4 @@ #include "Definitions.hpp" -#include "QuantumComputation.hpp" #include "dd/Package.hpp" #include "dd/Simulation.hpp" #include "ecc/Id.hpp" @@ -9,8 +8,9 @@ #include "ecc/Q7Steane.hpp" #include "ecc/Q9Shor.hpp" #include "ecc/Q9Surface.hpp" -#include "operations/NonUnitaryOperation.hpp" -#include "operations/OpType.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/NonUnitaryOperation.hpp" +#include "ir/operations/OpType.hpp" #include #include From ff1353912adc8d91c1d2e9afa1b60d0c65fffba6 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 00:02:09 +0200 Subject: [PATCH 06/17] =?UTF-8?q?=F0=9F=9A=A8=20fix=20deprecation=20warnin?= =?UTF-8?q?gs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- src/mqt/qecc/ecc_qiskit_wrapper.py | 2 +- src/mqt/qecc/ft_stateprep/simulation.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mqt/qecc/ecc_qiskit_wrapper.py b/src/mqt/qecc/ecc_qiskit_wrapper.py index 4f3f89a2..058cdea5 100644 --- a/src/mqt/qecc/ecc_qiskit_wrapper.py +++ b/src/mqt/qecc/ecc_qiskit_wrapper.py @@ -167,7 +167,7 @@ def main() -> None: circ = load(open_qasm_file) - if not any(gate[0].name == "measure" for gate in circ.data): + if not any(gate.operation.name == "measure" for gate in circ.data): print("Warning: No measurement gates found in the circuit. Adding measurement gates to all qubits.") # noqa: T201 circ.measure_all() diff --git a/src/mqt/qecc/ft_stateprep/simulation.py b/src/mqt/qecc/ft_stateprep/simulation.py index f89509b7..6759632d 100644 --- a/src/mqt/qecc/ft_stateprep/simulation.py +++ b/src/mqt/qecc/ft_stateprep/simulation.py @@ -123,8 +123,8 @@ def idle_error(used_qubits: list[int]) -> None: used_qubits = [] for gate in layer_circ.data: - if gate[0].name == "h": - qubit = self.circ.find_bit(gate[1][0])[0] + if gate.operation.name == "h": + qubit = self.circ.find_bit(gate.qubits[0])[0] ctrls.append(qubit) if initialized[qubit]: stim_circuit.append_operation("H", [qubit]) @@ -134,9 +134,9 @@ def idle_error(used_qubits: list[int]) -> None: else: used_qubits.append(qubit) - elif gate[0].name == "cx": - ctrl = self.circ.find_bit(gate[1][0])[0] - target = self.circ.find_bit(gate[1][1])[0] + elif gate.operation.name == "cx": + ctrl = self.circ.find_bit(gate.qubits[0])[0] + target = self.circ.find_bit(gate.qubits[1])[0] targets.add(target) if not initialized[ctrl]: if ctrl in ctrls: @@ -156,8 +156,8 @@ def idle_error(used_qubits: list[int]) -> None: else: used_qubits.extend([ctrl, target]) - elif gate[0].name == "measure": - anc = self.circ.find_bit(gate[1][0])[0] + elif gate.operation.name == "measure": + anc = self.circ.find_bit(gate.qubits[0])[0] stim_circuit.append_operation("X_ERROR", [anc], [2 * self.p / 3]) stim_circuit.append_operation("MR", [anc]) if anc in targets: From dac870acb9dad1dc936fe47de69b362c9c3ccc9f Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 00:04:57 +0200 Subject: [PATCH 07/17] =?UTF-8?q?=F0=9F=94=A7=F0=9F=9A=A8=20restore=20prop?= =?UTF-8?q?er=20warning=20filters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ca1047b2..4442677b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -146,11 +146,13 @@ addopts = ["-ra", "--strict-markers", "--strict-config", "--showlocals"] log_cli_level = "INFO" xfail_strict = true filterwarnings = [ -# "error", # temporary fix until https://github.com/quantumgizmos/ldpc/pull/42 is merged and released + "error", "ignore:.*pkg_resources.*:DeprecationWarning:", "ignore:.*The retworkx package is deprecated*:DeprecationWarning:pymatching", 'ignore:.*Qiskit with Python 3.8.*:DeprecationWarning:', 'ignore:.*qiskit.providers.provider.Provider.*:DeprecationWarning:', + 'ignore:.*invalid escape sequence.*:DeprecationWarning:', + 'ignore:.*invalid escape sequence.*:SyntaxWarning:', ] [tool.coverage] From dc0af4774cb8f542be6249e5e0a4ad9f30ecb137 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 00:08:07 +0200 Subject: [PATCH 08/17] =?UTF-8?q?=F0=9F=94=A7=20widen=20CMake=20version=20?= =?UTF-8?q?support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0144839..c05e0585 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.19...3.28) +cmake_minimum_required(VERSION 3.19...3.30) project( mqt-qecc From 376284077fef51f1d57011ad049520c8570ce83a Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 00:38:04 +0200 Subject: [PATCH 09/17] =?UTF-8?q?=F0=9F=94=A7=20explicit=20Python=203.13?= =?UTF-8?q?=20free=20threading=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- pyproject.toml | 3 ++- src/python/bindings.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4442677b..a1b04d66 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -287,8 +287,9 @@ build = "cp3*" skip = "*-musllinux*" archs = "auto64" test-command = "python -c \"from mqt import qecc\"" -test-skip = "*-macosx_arm64-*" +test-skip = ["cp38-macosx_arm64", "cp313*"] # skip testing on Python 3.13 until our dependencies are ready build-frontend = "build[uv]" +free-threaded-support = true [tool.cibuildwheel.linux] environment = { DEPLOY = "ON" } diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index 22ebe471..100352d5 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -86,7 +86,7 @@ py::dict applyEcc(const py::object& circ, const std::string& eccName, const size return py::dict("circ"_a = oss.str()); } -PYBIND11_MODULE(pyqecc, m) { +PYBIND11_MODULE(pyqecc, m, py::mod_gil_not_used()) { // In this function the exposed python functions are defined. // Additionally, the required parameters are described. m.doc() = "pybind11 for the MQT QECC quantum error-correcting codes tool"; From e279a85e178a39405c359edcf121db0b0d61c248 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 00:49:42 +0200 Subject: [PATCH 10/17] =?UTF-8?q?=F0=9F=9A=A8=20fix=20clang-tidy=20warning?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- include/DecodingSimulator.hpp | 25 +++++++++----------- include/ecc/Ecc.hpp | 2 ++ src/DecodingSimulator.cpp | 29 ++++++++++++++++------- test/test_originalUfd.cpp | 43 ++++++++++++++++++----------------- 4 files changed, 56 insertions(+), 43 deletions(-) diff --git a/include/DecodingSimulator.hpp b/include/DecodingSimulator.hpp index 326a124f..8cc2d3ac 100644 --- a/include/DecodingSimulator.hpp +++ b/include/DecodingSimulator.hpp @@ -1,18 +1,16 @@ -// -// Created by luca on 09/08/22. -// +#pragma once -#ifndef QECC_DECODINGSIMULATOR_HPP -#define QECC_DECODINGSIMULATOR_HPP - -#include "Decoder.hpp" -#include "UFHeuristic.hpp" +#include "Code.hpp" +#include +#include +#include +#include #include -#include -using json = nlohmann::json; -enum DecoderType { +using json = nlohmann::basic_json<>; + +enum DecoderType : std::uint8_t { UfHeuristic, UfDecoder }; @@ -25,7 +23,8 @@ enum DecoderType { } throw std::invalid_argument("Invalid decodinger type: " + status); } -NLOHMANN_JSON_SERIALIZE_ENUM(DecoderType, {{UfHeuristic, "UF_HEURISTIC"}, // NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) +// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,misc-include-cleaner) +NLOHMANN_JSON_SERIALIZE_ENUM(DecoderType, {{UfHeuristic, "UF_HEURISTIC"}, {UfDecoder, "UF_DECODER"}}) class DecodingSimulator { @@ -72,5 +71,3 @@ class DecodingSimulator { std::size_t nrSamples, const DecoderType& decoderType); }; - -#endif // QECC_DECODINGSIMULATOR_HPP diff --git a/include/ecc/Ecc.hpp b/include/ecc/Ecc.hpp index 35a7fd37..6dbcaee0 100644 --- a/include/ecc/Ecc.hpp +++ b/include/ecc/Ecc.hpp @@ -7,9 +7,11 @@ #include #include #include +#include #include #include #include +#include #include namespace ecc { diff --git a/src/DecodingSimulator.cpp b/src/DecodingSimulator.cpp index e5431e28..5ac32117 100644 --- a/src/DecodingSimulator.cpp +++ b/src/DecodingSimulator.cpp @@ -1,12 +1,25 @@ -// -// Created by luca on 09/08/22. -// #include "DecodingSimulator.hpp" +#include "Code.hpp" +#include "Decoder.hpp" #include "DecodingRunInformation.hpp" #include "UFDecoder.hpp" +#include "UFHeuristic.hpp" +#include "Utils.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include std::string generateOutFileName(const std::string& filepath) { auto t = std::time(nullptr); @@ -34,12 +47,12 @@ void DecodingSimulator::simulateWER(const std::string& rawDataOutputFilepath, if (rawOut) { auto dataFileName = generateOutFileName(rawDataOutputFilepath); rawDataOutput.open(dataFileName); - std::cout << "Writing raw data to " << dataFileName << std::endl; + std::cout << "Writing raw data to " << dataFileName << '\n'; } if (statsOut) { auto jsonFileName = generateOutFileName(statsOutputFilepath); statisticsOutstr.open(jsonFileName); - std::cout << "Writing stats output to " << jsonFileName << std::endl; + std::cout << "Writing stats output to " << jsonFileName << '\n'; statisticsOutstr << "{ \"runs\" : [ "; statisticsOutstr << R"({ "run": { "physicalErrRate":)" << minPhysicalErrRate << ", \"data\": [ "; } @@ -108,13 +121,13 @@ void DecodingSimulator::simulateAverageRuntime(const std::string& rawDataOutputF std::ofstream dataOutStream; if (rawOut) { - std::cout << "writing raw data to " << rawDataOutputFilepath << std::endl; + std::cout << "writing raw data to " << rawDataOutputFilepath << '\n'; finalRawOut.open(generateOutFileName(rawDataOutputFilepath)); finalRawOut.rdbuf()->pubsetbuf(nullptr, 0); } if (infoOut) { - std::cout << "writing statistics to " << decodingInfoOutfilePath << std::endl; + std::cout << "writing statistics to " << decodingInfoOutfilePath << '\n'; dataOutStream.open(generateOutFileName(decodingInfoOutfilePath)); dataOutStream.rdbuf()->pubsetbuf(nullptr, 0); } @@ -165,7 +178,7 @@ void DecodingSimulator::simulateAverageRuntime(const std::string& rawDataOutputF avgSampleRuns = {}; } } catch (std::exception& e) { - std::cerr << "Exception occurred " << e.what() << std::endl; + std::cerr << "Exception occurred " << e.what() << '\n'; } if (rawOut) { const json j = avgSampleRunsPerCode; diff --git a/test/test_originalUfd.cpp b/test/test_originalUfd.cpp index bb4373b3..7a6604c4 100644 --- a/test/test_originalUfd.cpp +++ b/test/test_originalUfd.cpp @@ -6,8 +6,12 @@ #include "Codes.hpp" #include "UFDecoder.hpp" +#include "Utils.hpp" +#include #include +#include +#include class OriginalUFDtest : public testing::TestWithParam> {}; class UniquelyCorrectableErrTestOriginal : public OriginalUFDtest {}; @@ -41,8 +45,8 @@ TEST_P(UniquelyCorrectableErrTestOriginal, SteaneCodeDecodingTestEstim) { auto code = SteaneXCode(); UFDecoder decoder; decoder.setCode(code); - std::cout << "code: " << std::endl - << code << std::endl; + std::cout << "code:\n" + << code << '\n'; const std::vector err = GetParam(); auto syndr = code.getXSyndrome(err); @@ -53,23 +57,20 @@ TEST_P(UniquelyCorrectableErrTestOriginal, SteaneCodeDecodingTestEstim) { const auto& estim = decodingResult.estimBoolVector; const auto& estimIdx = decodingResult.estimNodeIdxVector; gf2Vec estim2(err.size()); - std::cout << "estiIdxs: "; + std::cout << "\nestiIdxs: "; for (auto idx : estimIdx) { estim2.at(idx) = true; std::cout << idx; } - std::cout << std::endl; const gf2Vec sol = GetParam(); - std::cout << "Estim: " << std::endl; + std::cout << "\nEstim:\n"; Utils::printGF2vector(estim); - std::cout << std::endl; - std::cout << "EstimIdx: "; + std::cout << "\nEstimIdx: "; Utils::printGF2vector(estim2); - std::cout << std::endl; - std::cout << "Sol: "; + std::cout << "\nSol: "; Utils::printGF2vector(sol); - std::cout << std::endl; + std::cout << '\n'; EXPECT_TRUE(sol == estim); EXPECT_TRUE(sol == estim2); } @@ -81,8 +82,8 @@ TEST_P(InCorrectableErrTestOriginal, SteaneCodeDecodingTestEstim) { auto code = SteaneXCode(); UFDecoder decoder; decoder.setCode(code); - std::cout << "code: " << std::endl - << code << std::endl; + std::cout << "code:\n" + << code << '\n'; std::vector err = GetParam(); auto syndr = code.getXSyndrome(err); @@ -91,7 +92,7 @@ TEST_P(InCorrectableErrTestOriginal, SteaneCodeDecodingTestEstim) { const auto& estim = decodingResult.estimBoolVector; const auto& estimIdx = decodingResult.estimNodeIdxVector; gf2Vec estim2(err.size()); - std::cout << "estiIdxs: "; + std::cout << "\nestiIdxs: "; for (auto idx : estimIdx) { estim2.at(idx) = true; std::cout << idx; @@ -103,11 +104,11 @@ TEST_P(InCorrectableErrTestOriginal, SteaneCodeDecodingTestEstim) { const gf2Vec sol = GetParam(); - std::cout << "Estim: " << std::endl; + std::cout << "Estim: \n"; Utils::printGF2vector(estim); - std::cout << "EstimIdx: " << std::endl; + std::cout << "EstimIdx: \n"; Utils::printGF2vector(estim2); - std::cout << "Sol: " << std::endl; + std::cout << "Sol: \n"; Utils::printGF2vector(sol); EXPECT_FALSE(sol == estim); EXPECT_FALSE(sol == estim2); @@ -120,10 +121,10 @@ TEST_P(UpToStabCorrectableErrTestOriginal, SteaneCodeDecodingTest) { auto code = SteaneCode(); UFDecoder decoder; decoder.setCode(code); - std::cout << "code: " << std::endl - << code << std::endl; + std::cout << "code:\n" + << code << '\n'; std::vector err = GetParam(); - std::cout << "err :" << std::endl; + std::cout << "err:\n"; Utils::printGF2vector(err); auto syndr = code.getXSyndrome(err); decoder.decode(syndr); @@ -131,12 +132,12 @@ TEST_P(UpToStabCorrectableErrTestOriginal, SteaneCodeDecodingTest) { const auto& estim = decodingResult.estimBoolVector; const auto& estimIdx = decodingResult.estimNodeIdxVector; gf2Vec estim2(err.size()); - std::cout << "estiIdxs: "; + std::cout << "\nestiIdxs: "; for (auto idx : estimIdx) { estim2.at(idx) = true; std::cout << idx; } - std::cout << std::endl; + std::cout << '\n'; std::vector residualErr(err.size()); for (size_t i = 0; i < err.size(); i++) { residualErr.at(i) = (err[i] != estim[i]); From f207871497cb31b57d6f4c326dba7ee543efd23f Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 00:50:34 +0200 Subject: [PATCH 11/17] =?UTF-8?q?=F0=9F=A9=B9=20fix=20duplicate=20files=20?= =?UTF-8?q?in=20wheel=20warnings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index a1b04d66..2d1bfb53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -185,6 +185,10 @@ module = ["qiskit.*", "qecsim.*","qiskit_aer.*", "matplotlib.*", "scipy.*", "ldp ignore_missing_imports = true +[tool.check-wheel-contents] +ignore = ["W002"] # Triggers on __init__.py's and duplicate data files + + [tool.ruff] line-length = 120 namespace-packages = ["mqt"] From 96fed4d9f2802f91644de6c622bc1c5a53b60703 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 01:00:00 +0200 Subject: [PATCH 12/17] =?UTF-8?q?=F0=9F=94=A7=20minimum=20required=20pybin?= =?UTF-8?q?d11=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- cmake/ExternalDependencies.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/ExternalDependencies.cmake b/cmake/ExternalDependencies.cmake index cea7dab8..6fcfb1c8 100644 --- a/cmake/ExternalDependencies.cmake +++ b/cmake/ExternalDependencies.cmake @@ -16,7 +16,7 @@ if(BUILD_MQT_QECC_BINDINGS) endif() # add pybind11 library - find_package(pybind11 CONFIG REQUIRED) + find_package(pybind11 2.13 CONFIG REQUIRED) endif() # cmake-format: off From 61115ce62d47f4c87a7c3d31c5ff9e5900d737dd Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 09:45:11 +0200 Subject: [PATCH 13/17] =?UTF-8?q?=F0=9F=A9=B9=F0=9F=8F=81=20fix=20windows?= =?UTF-8?q?=20compilation=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- src/DecodingSimulator.cpp | 2 +- src/Utils.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DecodingSimulator.cpp b/src/DecodingSimulator.cpp index 5ac32117..232def83 100644 --- a/src/DecodingSimulator.cpp +++ b/src/DecodingSimulator.cpp @@ -138,7 +138,7 @@ void DecodingSimulator::simulateAverageRuntime(const std::string& rawDataOutputF DecodingRunInformation info; for (const auto& file : std::filesystem::directory_iterator(codesPath)) { - codePaths.emplace_back(file.path()); + codePaths.emplace_back(file.path().string()); } try { for (const auto& currPath : codePaths) { diff --git a/src/Utils.cpp b/src/Utils.cpp index eb02bf0e..98cb466d 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -187,7 +187,7 @@ void Utils::printTimePerSampleRun(const std::map& codePaths) { for (const auto& file : std::filesystem::directory_iterator(inPath)) { - codePaths.emplace_back(file.path()); + codePaths.emplace_back(file.path().string()); } } From 49095c28affa99227797f17f918d3c56a72af93d Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 10:09:41 +0200 Subject: [PATCH 14/17] =?UTF-8?q?=F0=9F=94=A5=20drop=20Python=203.8=20supp?= =?UTF-8?q?ort?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- noxfile.py | 2 +- pyproject.toml | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/noxfile.py b/noxfile.py index 08f41892..7a61564b 100644 --- a/noxfile.py +++ b/noxfile.py @@ -18,7 +18,7 @@ nox.options.sessions = ["lint", "tests"] -PYTHON_ALL_VERSIONS = ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] +PYTHON_ALL_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13"] # The following lists all the build requirements for building the package. # Note that this includes transitive build dependencies of package dependencies, diff --git a/pyproject.toml b/pyproject.toml index 2d1bfb53..005e5258 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,6 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -37,7 +36,7 @@ classifiers = [ "Development Status :: 5 - Production/Stable", "Typing :: Typed", ] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [ "z3-solver>=4.12,<4.14", "qecsim", @@ -149,7 +148,6 @@ filterwarnings = [ "error", "ignore:.*pkg_resources.*:DeprecationWarning:", "ignore:.*The retworkx package is deprecated*:DeprecationWarning:pymatching", - 'ignore:.*Qiskit with Python 3.8.*:DeprecationWarning:', 'ignore:.*qiskit.providers.provider.Provider.*:DeprecationWarning:', 'ignore:.*invalid escape sequence.*:DeprecationWarning:', 'ignore:.*invalid escape sequence.*:SyntaxWarning:', @@ -167,7 +165,7 @@ report.exclude_also = [ [tool.mypy] files = ["src/mqt", "test/python"] mypy_path = ["$MYPY_CONFIG_FILE_DIR/src"] -python_version = "3.8" +python_version = "3.9" warn_unused_configs = true enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] strict = true From c11df37e7cf3bea377ebb0902f405018f59a363c Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 27 Aug 2024 10:10:21 +0200 Subject: [PATCH 15/17] =?UTF-8?q?=F0=9F=93=8C=20fix=20a=20couple=20of=20de?= =?UTF-8?q?pendency=20bounds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 005e5258..3fe59442 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,13 +44,14 @@ dependencies = [ "numpy>=1.26,<2; python_version > '3.11'", # some of our dependencies are not yet compatible with numpy 2.0 "numpy>=1.24,<2; python_version <= '3.11'", # some of our dependencies are not yet compatible with numpy 2.0 "qiskit[qasm3-import]>=1.0.0", - "qiskit-aer>=0.14.0", + "qiskit-aer>=0.15.0", "stim >= 1.13.0", "multiprocess >= 0.70.16", "bposd>=1.6", "numba>=0.59; python_version > '3.11'", "numpy>=0.57; python_version <= '3.11'", - "pymatching>=2", + "pymatching>=2.2; python_version > '3.11'", + "pymatching>=2; python_version <= '3.11'", ] dynamic = ["version"] From f08558de7b5e9b763d7f77bd2d031357925dbd31 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Wed, 28 Aug 2024 10:19:19 +0200 Subject: [PATCH 16/17] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20update=20actions=20i?= =?UTF-8?q?n=20workflows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .github/workflows/cd.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/reusable-python-packaging.yml | 2 +- .github/workflows/update-mqt-core.yml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 20a339a2..2db8b96b 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -31,7 +31,7 @@ jobs: path: dist merge-multiple: true - name: Generate artifact attestation for sdist and wheel(s) - uses: actions/attest-build-provenance@v1.4.0 + uses: actions/attest-build-provenance@v1.4.2 with: subject-path: "dist/*" - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02bf4765..04e7f8a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ 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 cpp-tests: name: 🇨‌ Test diff --git a/.github/workflows/reusable-python-packaging.yml b/.github/workflows/reusable-python-packaging.yml index f6a5f3fd..b2985efa 100644 --- a/.github/workflows/reusable-python-packaging.yml +++ b/.github/workflows/reusable-python-packaging.yml @@ -49,7 +49,7 @@ jobs: - if: runner.os == 'macOS' uses: yezz123/setup-uv@v4 - name: Build wheels - uses: pypa/cibuildwheel@v2.19 + uses: pypa/cibuildwheel@v2.20 - name: Verify clean directory run: git diff --exit-code shell: bash diff --git a/.github/workflows/update-mqt-core.yml b/.github/workflows/update-mqt-core.yml index a76522ea..4f48ee10 100644 --- a/.github/workflows/update-mqt-core.yml +++ b/.github/workflows/update-mqt-core.yml @@ -21,6 +21,6 @@ concurrency: jobs: update-mqt-core: name: ⬆️ Update MQT Core - uses: cda-tum/mqt-workflows/.github/workflows/reusable-mqt-core-update.yml@v1.1.5 + uses: cda-tum/mqt-workflows/.github/workflows/reusable-mqt-core-update.yml@v1.3 with: - update-to-head: ${{ fromJSON(github.event.inputs.update-to-head) || false }} + update-to-head: ${{ github.event.inputs.update-to-head || false }} From ca3d56c04d18ff81a24f2b8156e24ac4e9cee5b6 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Wed, 28 Aug 2024 10:23:02 +0200 Subject: [PATCH 17/17] =?UTF-8?q?=F0=9F=94=A7=20adjust=20CI=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .github/workflows/reusable-python-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-python-ci.yml b/.github/workflows/reusable-python-ci.yml index 78c25682..ab2538b7 100644 --- a/.github/workflows/reusable-python-ci.yml +++ b/.github/workflows/reusable-python-ci.yml @@ -41,14 +41,14 @@ jobs: fail-fast: false matrix: runs-on: [ubuntu-latest] - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12"] include: - runs-on: macos-13 - python-version: "3.8" + python-version: "3.9" - runs-on: macos-13 python-version: "3.12" - runs-on: macos-14 - python-version: "3.10" + python-version: "3.9" - runs-on: macos-14 python-version: "3.12" steps: