Download cudaq/tensor_roll_kernels.py from Snapkitty/tensor-roll: direct link, hf CLI and curl.
- Browser
- Download file 4.5 kB
-
https://huggingface.co/Snapkitty/tensor-roll/resolve/main/cudaq/tensor_roll_kernels.py
- Command line
-
hf download hf://Snapkitty/tensor-roll/cudaq/tensor_roll_kernels.py
-
curl -L -o tensor_roll_kernels.py https://huggingface.co/Snapkitty/tensor-roll/resolve/main/cudaq/tensor_roll_kernels.py
4.5 kB
| # Tensor Roll — Recursive CUDA-Q Model Quantizer | |
| # Copyright (C) 2026 SnapKitty Collective | |
| # SPDX-License-Identifier: AGPL-3.0-or-later | |
| """Real CUDA-Q kernels for the tensor_roll family. | |
| Target: NVIDIA CUDA-Q Python API (>= 0.8). Execute with a simulator | |
| target (``cudaq.set_target("qpp-cpu")``) or on QPU/GPU hardware. | |
| These kernels are NOT executed by the tensor-roll CLI on machines without | |
| the CUDA-Q toolchain (see docs/BOUNDARIES.md). The classical state-vector | |
| simulator in tensor_roll/qsim.py mirrors this family's semantics so the | |
| pipeline is measurable everywhere; every qsim report is labeled | |
| ``qsim-classical`` and never claims QPU execution. | |
| Conceptual mapping (classical -> quantum descent): | |
| C = A x B (CUDA GEMM, classical baseline) | |
| TensorRoll(A, B) (dispatch boundary in tensor_roll/core.py) | |
| |- classical region -> CUDA GEMM | |
| -- candidate region -> tensor_roll kernels below -> measurement | |
| -> classical reconstruction | |
| """ | |
| try: | |
| import cudaq | |
| from cudaq import spin | |
| _HAS_CUDAQ = True | |
| except ImportError: # pragma: no cover - toolchain absent on most machines | |
| _HAS_CUDAQ = False | |
| if _HAS_CUDAQ: | |
| def tensor_roll_encode(qubits: cudaq.qview, angles: list[float]): | |
| """Angle-encode a tensor block: RY(2*atan(x_i)) per qubit.""" | |
| for q in range(qubits.size()): | |
| ry(2.0 * angles[q], qubits[q]) | |
| def tensor_roll_rotate(qubits: cudaq.qview, angles: list[float]): | |
| """Per-qubit RY rotations (the 'roll' of the register).""" | |
| for q in range(qubits.size()): | |
| ry(angles[q], qubits[q]) | |
| def tensor_roll_entangle(qubits: cudaq.qview): | |
| """Nearest-neighbour CNOT ladder.""" | |
| for q in range(qubits.size() - 1): | |
| x.ctrl(qubits[q], qubits[q + 1]) | |
| def tensor_roll_measure(qubits: cudaq.qview): | |
| """Measure the full register in the Z basis.""" | |
| mz(qubits) | |
| def tensor_roll_recursive(qubits: cudaq.qview, angles: list[float], | |
| depth: int): | |
| """Recursive kernel: each level rotates + entangles a shrinking | |
| active qubit subset, then measures it. Implemented iteratively over | |
| levels (CUDA-Q kernels unroll statically); depth selects how many | |
| levels execute.""" | |
| n = qubits.size() | |
| for level in range(depth): | |
| # active subset shrinks with depth: n, n-1, ... | |
| for q in range(n): | |
| if q < n - level: | |
| ry(angles[q], qubits[q]) | |
| for q in range(n - 1): | |
| if q < n - 1 - level: | |
| x.ctrl(qubits[q], qubits[q + 1]) | |
| if level < depth - 1: | |
| # mid-circuit measurement of the outer qubit, then reset | |
| # for the next recursion level | |
| mz(qubits[n - 1 - level]) | |
| reset(qubits[n - 1 - level]) | |
| mz(qubits) | |
| def tensor_roll_reconstruct(counts_register: cudaq.qview): | |
| """Measurement kernel whose counts are classically post-processed | |
| into amplitude estimates (see tensor_roll/qsim.py for the estimator). | |
| Reconstruction itself is classical by construction.""" | |
| mz(counts_register) | |
| def run_smoke(n_qubits: int = 4, shots: int = 1024) -> dict: | |
| """Execute the kernel family on the qpp-cpu simulator target and return | |
| a real invocation summary. Requires the CUDA-Q toolchain.""" | |
| if not _HAS_CUDAQ: | |
| raise RuntimeError( | |
| "CUDA-Q toolchain not installed (pip install cudaq). " | |
| "This machine cannot execute these kernels; use the " | |
| "qsim-classical path (tensor-roll qkernel) instead.") | |
| import math | |
| cudaq.set_target("qpp-cpu") | |
| angles = [2.0 * math.atan(0.1 * (i + 1)) for i in range(n_qubits)] | |
| def _smoke_entry(n_qubits: int, angles: list[float], depth: int): | |
| qubits = cudaq.qvector(n_qubits) | |
| tensor_roll_encode(qubits, angles) | |
| tensor_roll_recursive(qubits, angles, depth) | |
| counts = cudaq.sample(_smoke_entry, n_qubits, angles, 2, | |
| shots_count=shots) | |
| return {"counts": {k: int(v) for k, v in counts.items()}, | |
| "shots": shots, "target": cudaq.get_target().name} | |
| if __name__ == "__main__": | |
| try: | |
| print(run_smoke()) | |
| except RuntimeError as e: | |
| print(f"unavailable: {e}") | |