Download src/cpsc/channel.py from Snapkitty/cpsc-qft: direct link, hf CLI and curl.
- Browser
- Download file 5.76 kB
-
https://huggingface.co/Snapkitty/cpsc-qft/resolve/main/src/cpsc/channel.py
- Command line
-
hf download hf://Snapkitty/cpsc-qft/src/cpsc/channel.py
-
curl -L -o channel.py https://huggingface.co/Snapkitty/cpsc-qft/resolve/main/src/cpsc/channel.py
5.76 kB
| # ******************************************************************************* | |
| # Copyright (c) 2026 Ahmad Ali Parr and others. | |
| # | |
| # This program and the accompanying materials are made available under the | |
| # terms of the CPSC Eclipse Strict Copyleft License, Version 1.0, which is | |
| # available in LICENSES/CPSC-ESCL-1.0.txt, or, at your option, under the | |
| # GNU Affero General Public License, Version 3 only, which is available in | |
| # LICENSES/AGPL-3.0.txt. Both options are strict copyleft. There is no | |
| # classpath exception and no permissive relicensing. | |
| # | |
| # SPDX-License-Identifier: LicenseRef-CPSC-ESCL-1.0 OR AGPL-3.0-only | |
| # ******************************************************************************* | |
| """Channel-space evolution: exponentiate H only inside the allowed sector.""" | |
| from __future__ import annotations | |
| import numpy as np | |
| from cpsc.hamiltonian import magnetization_of, parity_of, transverse_ising | |
| def sector_basis( | |
| n: int, | |
| *, | |
| parity: int, | |
| magnetization: int | None = None, | |
| ) -> list[int]: | |
| basis: list[int] = [] | |
| for b in range(1 << n): | |
| if parity_of(b, n) != parity: | |
| continue | |
| if magnetization is not None and magnetization_of(b, n) != magnetization: | |
| continue | |
| basis.append(b) | |
| return basis | |
| def evolve_in_sector( | |
| n: int, | |
| initial_basis: int, | |
| *, | |
| time: float, | |
| j: float = 1.0, | |
| lam: float = 0.0, | |
| conserve_magnetization: bool = False, | |
| ) -> np.ndarray: | |
| """Return the full-space statevector of the sector-restricted evolution. | |
| Z-parity completeness holds only at lambda = 0. For lambda != 0 the | |
| symmetry is prod X. Magnetization pruning is refused unless lambda == 0. | |
| """ | |
| if not 0 <= initial_basis < (1 << n): | |
| raise ValueError("initial basis out of range") | |
| parity = parity_of(initial_basis, n) | |
| mag = magnetization_of(initial_basis, n) if conserve_magnetization else None | |
| if conserve_magnetization and lam != 0.0: | |
| raise ValueError( | |
| "magnetization is not a symmetry of the transverse field; " | |
| "refusing a completeness-breaking projection" | |
| ) | |
| allowed = sector_basis(n, parity=parity, magnetization=mag) | |
| h = transverse_ising(n, j=j, lam=lam) | |
| index = {b: i for i, b in enumerate(allowed)} | |
| block = np.zeros((len(allowed), len(allowed)), dtype=np.complex128) | |
| for a in allowed: | |
| for b in allowed: | |
| block[index[a], index[b]] = h[a, b] | |
| evals, evecs = np.linalg.eigh(block) | |
| phase = np.exp(-1j * evals * time) | |
| u = (evecs * phase) @ evecs.conj().T | |
| psi0 = np.zeros(len(allowed), dtype=np.complex128) | |
| psi0[index[initial_basis]] = 1.0 | |
| evolved = u @ psi0 | |
| full = np.zeros(1 << n, dtype=np.complex128) | |
| for b, amp in zip(allowed, evolved): | |
| full[b] = amp | |
| return full | |
| def leakage(state: np.ndarray, n: int, parity: int) -> float: | |
| """Probability mass on the wrong Z-parity sector.""" | |
| wrong = 0.0 | |
| for b, amp in enumerate(state): | |
| if parity_of(b, n) != parity: | |
| wrong += float(np.abs(amp) ** 2) | |
| return wrong | |
| def apply_prod_x(state: np.ndarray, n: int) -> np.ndarray: | |
| out = np.zeros_like(state) | |
| mask = (1 << n) - 1 | |
| for basis, amp in enumerate(state): | |
| out[basis ^ mask] += amp | |
| return out | |
| def even_cat(n: int, basis: int) -> np.ndarray: | |
| """Normalized +1 eigenstate of prod X built from a computational seed.""" | |
| state = np.zeros(1 << n, dtype=np.complex128) | |
| state[basis] = 1.0 / np.sqrt(2.0) | |
| state[basis ^ ((1 << n) - 1)] += 1.0 / np.sqrt(2.0) | |
| return state | |
| def z_parity_leakage(state: np.ndarray, n: int, parity: int) -> float: | |
| return leakage(state, n, parity) | |
| def x_parity_leakage(state: np.ndarray, n: int, seed_basis: int) -> float: | |
| """Mass outside the even prod-X sector.""" | |
| del seed_basis | |
| flipped = apply_prod_x(state, n) | |
| projected = 0.5 * (state + flipped) | |
| return float(max(0.0, 1.0 - np.vdot(projected, projected).real)) | |
| def _apply_rx(state: np.ndarray, n: int, qubit: int, angle: float) -> np.ndarray: | |
| cos = np.cos(angle) | |
| sin = np.sin(angle) | |
| out = np.zeros_like(state) | |
| bit = 1 << qubit | |
| for basis, amp in enumerate(state): | |
| if amp == 0: | |
| continue | |
| out[basis] += cos * amp | |
| out[basis ^ bit] += -1j * sin * amp | |
| return out | |
| def _apply_rzz(state: np.ndarray, n: int, q1: int, q2: int, angle: float) -> np.ndarray: | |
| out = state.copy() | |
| for basis in range(state.shape[0]): | |
| z1 = 1.0 if ((basis >> q1) & 1) == 0 else -1.0 | |
| z2 = 1.0 if ((basis >> q2) & 1) == 0 else -1.0 | |
| out[basis] *= np.exp(1j * angle * z1 * z2) | |
| return out | |
| def evolve_trotter( | |
| n: int, | |
| initial_basis: int, | |
| gates, | |
| *, | |
| time: float, | |
| steps: int, | |
| j: float, | |
| lam: float, | |
| conserve_magnetization: bool, | |
| ) -> np.ndarray: | |
| """First-order Trotter product of the admitted local terms.""" | |
| if conserve_magnetization: | |
| state = np.zeros(1 << n, dtype=np.complex128) | |
| state[initial_basis] = 1.0 | |
| else: | |
| state = even_cat(n, initial_basis) | |
| dt = time / steps | |
| for _ in range(steps): | |
| for gate in gates: | |
| if gate.kind == "magnetization": | |
| a, b = gate.qubits | |
| state = _apply_rzz(state, n, a, b, j * dt) | |
| elif gate.kind in {"illegal", "transverse"}: | |
| state = _apply_rx(state, n, gate.qubits[0], lam * dt) | |
| elif gate.kind == "parity_even": | |
| for q in gate.qubits: | |
| state = _apply_rx(state, n, q, lam * dt) | |
| elif gate.kind == "phase": | |
| continue | |
| else: | |
| raise ValueError(f"no evolution rule for {gate.kind}") | |
| return state | |