From 90cab774eaf5f1eeb8e446ff516ce6975fbcfc4c Mon Sep 17 00:00:00 2001 From: viiccwen Date: Mon, 25 May 2026 15:29:16 +0000 Subject: [PATCH] docs: add missing QDP Python API docstrings --- qdp/qdp-python/qumat_qdp/api.py | 22 +++++++++ qdp/qdp-python/qumat_qdp/backend.py | 10 ++++ qdp/qdp-python/qumat_qdp/tensor.py | 19 ++++++++ qdp/qdp-python/qumat_qdp/triton_amd.py | 63 ++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) diff --git a/qdp/qdp-python/qumat_qdp/api.py b/qdp/qdp-python/qumat_qdp/api.py index e1e8b20e3a..c593e5d41b 100644 --- a/qdp/qdp-python/qumat_qdp/api.py +++ b/qdp/qdp-python/qumat_qdp/api.py @@ -102,14 +102,31 @@ def __init__(self, device_id: int = 0) -> None: self._backend_name: str = "rust" def qubits(self, n: int) -> QdpBenchmark: + """Set the number of qubits for benchmarked encodings. + + :param n: Number of qubits in each encoded output state. + :returns: This builder for fluent chaining. + """ self._num_qubits = n return self def encoding(self, method: str) -> QdpBenchmark: + """Set the encoding method to benchmark. + + :param method: Encoding name, for example ``"amplitude"``, + ``"angle"``, ``"basis"``, ``"iqp"``, or ``"iqp-z"``. + :returns: This builder for fluent chaining. + """ self._encoding_method = method return self def batches(self, total: int, size: int = 64) -> QdpBenchmark: + """Set the number and size of benchmark batches. + + :param total: Number of timed batches to process. + :param size: Number of vectors in each batch. + :returns: This builder for fluent chaining. + """ self._total_batches = total self._batch_size = size return self @@ -119,6 +136,11 @@ def prefetch(self, n: int) -> QdpBenchmark: return self def warmup(self, n: int) -> QdpBenchmark: + """Set the number of warmup batches run before timing. + + :param n: Number of batches to execute before measurements begin. + :returns: This builder for fluent chaining. + """ self._warmup_batches = n return self diff --git a/qdp/qdp-python/qumat_qdp/backend.py b/qdp/qdp-python/qumat_qdp/backend.py index ea889fed87..098662d889 100644 --- a/qdp/qdp-python/qumat_qdp/backend.py +++ b/qdp/qdp-python/qumat_qdp/backend.py @@ -92,4 +92,14 @@ def encode( num_qubits: int, encoding_method: str = "amplitude", ) -> Any: + """Encode input samples with the configured backend. + + :param data: Input samples accepted by the selected backend. + :param num_qubits: Number of qubits in the output state vector. + :param encoding_method: Encoding strategy, such as ``"amplitude"``, + ``"angle"``, ``"basis"``, ``"iqp"``, ``"iqp-z"``, or + ``"phase"`` when supported by the backend. + :returns: Backend-native encoded tensor or tensor-like result. + :raises ValueError: If the backend does not support ``encoding_method``. + """ return self._engine_adapter.encode(data, num_qubits, encoding_method) diff --git a/qdp/qdp-python/qumat_qdp/tensor.py b/qdp/qdp-python/qumat_qdp/tensor.py index 4c8b26680a..c9d651a73e 100644 --- a/qdp/qdp-python/qumat_qdp/tensor.py +++ b/qdp/qdp-python/qumat_qdp/tensor.py @@ -30,6 +30,14 @@ class QdpTensor: backend: str def __dlpack__(self, stream: int | None = None) -> Any: + """Return a DLPack capsule for the wrapped backend tensor. + + :param stream: Optional consumer stream to pass through to the wrapped + tensor's ``__dlpack__`` implementation. + :returns: A DLPack capsule representing ``value``. + :raises RuntimeError: If the wrapped value does not implement + ``__dlpack__``. + """ if not hasattr(self.value, "__dlpack__"): raise RuntimeError( f"Backend '{self.backend}' returned object without __dlpack__ support: " @@ -40,6 +48,12 @@ def __dlpack__(self, stream: int | None = None) -> Any: return self.value.__dlpack__(stream=stream) def __dlpack_device__(self) -> Any: + """Return the DLPack device descriptor for the wrapped tensor. + + :returns: The ``(device_type, device_id)`` tuple reported by ``value``. + :raises RuntimeError: If the wrapped value does not implement + ``__dlpack_device__``. + """ if not hasattr(self.value, "__dlpack_device__"): raise RuntimeError( f"Backend '{self.backend}' returned object without __dlpack_device__ support: " @@ -48,6 +62,11 @@ def __dlpack_device__(self) -> Any: return self.value.__dlpack_device__() def to_torch(self) -> Any: + """Convert the wrapped tensor to a PyTorch tensor via DLPack. + + :returns: A ``torch.Tensor`` sharing storage with the backend tensor + when the backend's DLPack producer supports zero-copy exchange. + """ import torch return torch.from_dlpack(self) diff --git a/qdp/qdp-python/qumat_qdp/triton_amd.py b/qdp/qdp-python/qumat_qdp/triton_amd.py index 8bcbd5d025..678fb49a55 100644 --- a/qdp/qdp-python/qumat_qdp/triton_amd.py +++ b/qdp/qdp-python/qumat_qdp/triton_amd.py @@ -47,6 +47,11 @@ def _is_rocm_runtime() -> bool: def is_triton_amd_available() -> bool: + """Return whether the Triton AMD backend appears usable. + + :returns: ``True`` when PyTorch reports a ROCm device, Triton imports, and + the active Triton target is HIP or cannot be queried reliably. + """ if not _is_rocm_runtime() or triton_mod is None: return False try: @@ -148,6 +153,10 @@ def __post_init__(self) -> None: ) def check_runtime(self) -> None: + """Validate that the process can use the Triton AMD backend. + + :raises RuntimeError: If PyTorch ROCm support or Triton is unavailable. + """ if not _is_rocm_runtime(): raise RuntimeError( "Triton AMD backend unavailable: no PyTorch ROCm device detected." @@ -230,6 +239,14 @@ def _pair_indices(self, num_qubits: int) -> Any: return pairs def encode_amplitude(self, data: Any, num_qubits: int) -> Any: + """Encode real-valued samples as normalized amplitudes. + + :param data: One- or two-dimensional samples with width at most + ``2**num_qubits``. + :param num_qubits: Number of qubits in the encoded state. + :returns: Complex tensor of shape ``(batch, 2**num_qubits)``. + :raises ValueError: If the sample width exceeds the state length. + """ torch_mod = self._require_torch() x = self._to_2d(data, dtype=self._real_dtype()) batch, sample_size = x.shape @@ -250,6 +267,14 @@ def encode_amplitude(self, data: Any, num_qubits: int) -> Any: return amp.to(self._complex_dtype()) def encode_angle(self, data: Any, num_qubits: int) -> Any: + """Encode samples with product-state angle encoding. + + :param data: One- or two-dimensional angle samples with exactly + ``num_qubits`` values per sample. + :param num_qubits: Number of qubits in the encoded state. + :returns: Complex tensor of shape ``(batch, 2**num_qubits)``. + :raises ValueError: If the sample width is not ``num_qubits``. + """ torch_mod = self._require_torch() real_dtype = self._real_dtype() angles = self._to_2d(data, dtype=real_dtype) @@ -273,6 +298,14 @@ def encode_angle(self, data: Any, num_qubits: int) -> Any: return amp.to(self._complex_dtype()) def encode_basis(self, data: Any, num_qubits: int) -> Any: + """Encode integer basis-state indices as one-hot quantum states. + + :param data: One-dimensional indices or a two-dimensional column of + indices in ``[0, 2**num_qubits - 1]``. + :param num_qubits: Number of qubits in the encoded state. + :returns: Complex one-hot tensor of shape ``(batch, 2**num_qubits)``. + :raises ValueError: If indices are empty, malformed, or out of range. + """ torch_mod = self._require_torch() idx = torch_mod.as_tensor(data, device=self._device(), dtype=torch_mod.int64) if idx.ndim == 2: @@ -352,6 +385,17 @@ def encode_iqp( *, enable_zz: bool = True, ) -> Any: + """Encode samples with the IQP feature map. + + :param data: IQP parameters. With ``enable_zz=True``, each sample must + contain ``num_qubits + num_qubits * (num_qubits - 1) // 2`` values; + otherwise each sample must contain ``num_qubits`` values. + :param num_qubits: Number of qubits in the encoded state. + :param enable_zz: Include pairwise ZZ interactions when ``True``. + :returns: Complex tensor of shape ``(batch, 2**num_qubits)``. + :raises ValueError: If the parameter width does not match the IQP + variant. + """ torch_mod = self._require_torch() real_dtype = self._real_dtype() params = self._to_2d(data, dtype=real_dtype) @@ -443,6 +487,14 @@ def _encode_phase_triton(self, phases: Any, num_qubits: int) -> Any: return out def encode_phase(self, data: Any, num_qubits: int) -> Any: + """Encode samples as equal-magnitude states with data-dependent phase. + + :param data: One- or two-dimensional phase samples with exactly + ``num_qubits`` values per sample. + :param num_qubits: Number of qubits in the encoded state. + :returns: Complex tensor of shape ``(batch, 2**num_qubits)``. + :raises ValueError: If the sample width is not ``num_qubits``. + """ torch_mod = self._require_torch() real_dtype = self._real_dtype() phases = self._to_2d(data, dtype=real_dtype) @@ -473,6 +525,17 @@ def encode( num_qubits: int, encoding_method: str = "amplitude", ) -> Any: + """Encode input samples using a named Triton AMD encoding. + + :param data: Input samples for the selected encoding method. + :param num_qubits: Number of qubits in the encoded state. + :param encoding_method: One of ``"amplitude"``, ``"angle"``, + ``"basis"``, ``"iqp"``, ``"iqp-z"``, or ``"phase"``. + :returns: Complex tensor of shape ``(batch, 2**num_qubits)``. + :raises RuntimeError: If the Triton AMD runtime is unavailable. + :raises ValueError: If ``encoding_method`` is unsupported or inputs are + invalid for the selected encoder. + """ self.check_runtime() method = encoding_method.lower()