Download qsharp/TensorRoll.qs from Snapkitty/tensor-roll: direct link, hf CLI and curl.
- Browser
- Download file 4.28 kB
-
https://huggingface.co/Snapkitty/tensor-roll/resolve/main/qsharp/TensorRoll.qs
- Command line
-
hf download hf://Snapkitty/tensor-roll/qsharp/TensorRoll.qs
-
curl -L -o TensorRoll.qs https://huggingface.co/Snapkitty/tensor-roll/resolve/main/qsharp/TensorRoll.qs
4.28 kB
| // Tensor Roll — Recursive CUDA-Q Model Quantizer | |
| // Copyright (C) 2026 SnapKitty Collective | |
| // SPDX-License-Identifier: AGPL-3.0-or-later | |
| // | |
| // Genuine Q# operations for the tensor_roll kernel family. | |
| // These mirror cudaq/tensor_roll_kernels.py across the process/IR boundary | |
| // documented in docs/BOUNDARIES.md: CUDA-Q kernels emit QIR/MLIR on the | |
| // CUDA-Q side; this Q# source is the equivalent family expressed for the | |
| // Q# toolchain. There is no direct CUDA-Q <-> Q# linkage — the boundary is | |
| // a real serialized artifact (QIR bitcode / measurement-counts JSON), | |
| // never an invented API. | |
| // | |
| // NOTE: not compiled or executed in this repository's test environment | |
| // (no Q# toolchain present). Every execution claim in tensor-roll refers | |
| // to the classical qsim-classical simulator, explicitly labeled as such. | |
| namespace TensorRoll { | |
| open Microsoft.Quantum.Canon; | |
| open Microsoft.Quantum.Intrinsic; | |
| open Microsoft.Quantum.Measurement; | |
| open Microsoft.Quantum.Math; | |
| open Microsoft.Quantum.Convert; | |
| open Microsoft.Quantum.Arrays; | |
| /// Encodes a classical tensor block into a qubit register (angle encoding). | |
| operation EncodeTensorBlock(block : Double[], register : Qubit[]) : Unit { | |
| let n = Length(block) < Length(register) ? Length(block) | Length(register); | |
| for i in 0..n - 1 { | |
| Ry(2.0 * ArcTan(block[i]), register[i]); | |
| } | |
| } | |
| /// Applies per-qubit RY rotations — the "roll" of the register. | |
| operation RollRegister(register : Qubit[], angles : Double[]) : Unit { | |
| for i in 0..Length(register) - 1 { | |
| Ry(angles[i % Length(angles)], register[i]); | |
| } | |
| } | |
| /// Nearest-neighbour CNOT ladder over the register. | |
| operation EntangleRoll(register : Qubit[]) : Unit { | |
| for i in 0..Length(register) - 2 { | |
| Controlled X([register[i]], register[i + 1]); | |
| } | |
| } | |
| /// Recursive kernel: each level rotates and entangles the active subset, | |
| /// measures the outer qubit, resets it, and recurses on the remainder. | |
| /// Q# operations may call themselves — this is genuine recursion. | |
| /// Returns one measurement Result per recursion level. | |
| operation RecursiveRoll(register : Qubit[], angles : Double[], depth : Int) : Result[] { | |
| if depth <= 0 or Length(register) == 0 { | |
| return []; | |
| } | |
| RollRegister(register, angles); | |
| EntangleRoll(register); | |
| let outer = register[Length(register) - 1]; | |
| let outcome = MResetZ(outer); | |
| let rest = RecursiveRoll(register[0..Length(register) - 2], angles, depth - 1); | |
| return [outcome] + rest; | |
| } | |
| /// Measures the register in the Z basis, resetting each qubit. | |
| operation MeasureRoll(register : Qubit[]) : Result[] { | |
| mutable results = []; | |
| for q in register { | |
| set results += [MResetZ(q)]; | |
| } | |
| return results; | |
| } | |
| /// Classical reconstruction of amplitude estimates from measurement counts. | |
| /// Reconstruction is classical by construction — this function executes on | |
| /// the classical host, never on the quantum processor. | |
| function ReconstructBlock(counts : (Result[], Int)[], nQubits : Int) : Double[] { | |
| mutable total = 0; | |
| for (_, c) in counts { | |
| set total += c; | |
| } | |
| let dim = 1 <<< nQubits; | |
| mutable amps = [0.0, size = dim]; | |
| for (bits, c) in counts { | |
| mutable idx = 0; | |
| for b in bits { | |
| set idx = idx * 2 + (b == One ? 1 | 0); | |
| } | |
| if idx < dim and total > 0 { | |
| set amps w/= idx <- Sqrt(IntAsDouble(c) / IntAsDouble(total)); | |
| } | |
| } | |
| return amps; | |
| } | |
| @EntryPoint() | |
| operation Main() : Unit { | |
| // Small demonstration block; mirrors the 8x8-block smoke test that | |
| // tensor-roll qkernel runs classically via qsim. | |
| let block = [0.1, 0.4, 0.2, 0.8]; | |
| use register = Qubit[4]; | |
| EncodeTensorBlock(block, register); | |
| let rolled = RecursiveRoll(register, [0.3, 0.6, 0.2, 0.9], 2); | |
| let tail = MeasureRoll(register); | |
| Message($"recursive outcomes: {rolled}"); | |
| Message($"tail outcomes: {tail}"); | |
| ResetAll(register); | |
| } | |
| } | |