CUDA-Q backend for Qamomile.
Design intent: this package concretizes circuit’s abstract IR through an
internal CudaqMaterializer and exposes only the transpiler, executor, and
observable conversion. Source-generation machinery and artifact wrappers are
implementation details rather than a second public compilation API.
Public symbols are exported lazily so that a mere import qamomile.cudaq
does not fail in environments where the cudaq package is absent. Accessing
any public symbol (e.g. qamomile.cudaq.CudaqTranspiler) will raise an
:class:ImportError with actionable install guidance when cudaq is not
available.
Overview¶
| Function | Description |
|---|---|
hamiltonian_to_cudaq_spin_op | Convert qamomile.observable.Hamiltonian to cudaq.SpinOperator. |
| Class | Description |
|---|---|
CudaqExecutor | CUDA-Q quantum executor. |
CudaqTranspiler | CUDA-Q transpiler for qamomile.circuit module. |
ExecutionMode | Execution mode for a CUDA-Q kernel artifact. |
Functions¶
hamiltonian_to_cudaq_spin_op [source]¶
def hamiltonian_to_cudaq_spin_op(hamiltonian: qm_o.Hamiltonian) -> AnyConvert qamomile.observable.Hamiltonian to cudaq.SpinOperator.
Parameters:
| Name | Type | Description |
|---|---|---|
hamiltonian | qm_o.Hamiltonian | The qamomile Hamiltonian to convert. |
Returns:
Any — A CUDA-Q SpinOperator built from cudaq.spin primitives.
Example:
import qamomile.observable as qm_o
from qamomile.cudaq.observable import hamiltonian_to_cudaq_spin_op
H = qm_o.Z(0) * qm_o.Z(1) + 0.5 * (qm_o.X(0) + qm_o.X(1))
spin_op = hamiltonian_to_cudaq_spin_op(H)Classes¶
CudaqExecutor [source]¶
class CudaqExecutor(QuantumExecutor[CudaqKernelArtifact])CUDA-Q quantum executor.
Supports sampling via cudaq.sample / cudaq.run and expectation
value estimation via cudaq.observe. Dispatches to the appropriate
CUDA-Q runtime API based on the artifact’s execution_mode:
STATICartifacts (no mid-circuit measurement or runtime control flow) support both sampling (cudaq.sample) and expectation-value estimation (cudaq.observe).RUNNABLEartifacts (mid-circuit measurement or measurement-dependent control flow such asif bit:/while bit:) support sampling only, viacudaq.run.
Expectation-value estimation is therefore static-only: calling
:meth:estimate on a RUNNABLE artifact raises TypeError because
cudaq.observe cannot consume a kernel that requires cudaq.run.
See :meth:estimate for the full rationale.
Parameters:
| Name | Type | Description |
|---|---|---|
target | str | None | CUDA-Q target name (e.g., "qpp-cpu"). If None, uses the default CUDA-Q target. |
Constructor¶
def __init__(self, target: str | None = None)Methods¶
bind_parameters¶
def bind_parameters(
self,
circuit: Any,
bindings: dict[str, Any],
parameter_metadata: ParameterMetadata,
) -> BoundCudaqKernelArtifactBind parameters to a circuit for execution.
Returns a BoundCudaqKernelArtifact with the execution mode
inherited from the source artifact.
estimate¶
def estimate(
self,
circuit: Any,
hamiltonian: 'qm_o.Hamiltonian',
params: Sequence[float] | None = None,
) -> floatEstimate an expectation value using cudaq.observe.
Expectation-value estimation on the CUDA-Q backend is static-only.
It is supported exclusively for STATIC-mode artifacts, which are
evaluated with cudaq.observe(). RUNNABLE-mode artifacts (a
kernel containing mid-circuit measurement or measurement-dependent
control flow such as if bit: / while bit:) are emitted for
cudaq.run(), and cudaq.observe() cannot consume them. Such
artifacts therefore raise TypeError rather than silently returning
a meaningless value.
This is a CUDA-Q API limitation, not merely a Qamomile gap:
cudaq.observe() evaluates the analytic expectation value of a
deterministic state-preparation kernel and has no execution path for a
kernel that requires the per-shot cudaq.run() runtime. There is no
safe alternative that preserves the exact-expectation contract of this
method, so the TypeError path is intentional. Under the current
affine model a single Qamomile kernel also cannot be both RUNNABLE
and carry a terminal qmc.expval (reusing a measured qubit is
rejected), so the ExecutableProgram.run expval path does not reach
this guard; it is reached only when estimate is called directly on
a RUNNABLE artifact.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | Any | A CUDA-Q artifact (CudaqKernelArtifact or BoundCudaqKernelArtifact). Must be STATIC-mode; RUNNABLE-mode artifacts are rejected. |
hamiltonian | qm_o.Hamiltonian | The observable to measure. A qamomile.observable.Hamiltonian is converted to a CUDA-Q SpinOperator; an already-converted operator is used as-is. |
params | Sequence[float] | None | Values for the kernel’s runtime parameters slots, in declared parameter order. Compile- time-bound parameters are already baked into the artifact and are not included here. Defaults to None for a non-parametric or already-bound (BoundCudaqKernelArtifact) kernel. |
Returns:
float — The estimated expectation value <psi|H|psi>.
Raises:
TypeError— Ifcircuitis aRUNNABLE-mode artifact, sincecudaq.observe()only accepts static state-preparation kernels (see the static-only note above).
Example:
>>> transpiler = CudaqTranspiler()
>>> exe = transpiler.transpile(static_ansatz, bindings={"H": H})
>>> executor = transpiler.executor()
>>> value = executor.estimate(exe.get_first_circuit(), H)execute¶
def execute(self, circuit: Any, shots: int) -> dict[str, int]Execute circuit and return canonical big-endian bitstring counts.
Dispatches based on execution_mode:
STATIC: usescudaq.sample()on the decorator kernel.RUNNABLE: usescudaq.run()on the runnable kernel.
Both paths return bitstrings in big-endian format (highest qubit
index = leftmost bit). An artifact without quantum or classical bits
returns {"": shots} without calling the CUDA-Q runtime.
CudaqTranspiler [source]¶
class CudaqTranspiler(Transpiler[CudaqKernelArtifact])CUDA-Q transpiler for qamomile.circuit module.
Converts Qamomile QKernels into CUDA-Q decorator-kernel artifacts.
Example:
from qamomile.cudaq import CudaqTranspiler
import qamomile.circuit as qm
@qm.qkernel
def bell_state(q0: qm.Qubit, q1: qm.Qubit) -> tuple[qm.Bit, qm.Bit]:
q0 = qm.h(q0)
q0, q1 = qm.cx(q0, q1)
return qm.measure(q0), qm.measure(q1)
transpiler = CudaqTranspiler()
executable = transpiler.transpile(bell_state)Methods¶
executor¶
def executor(self, target: str | None = None) -> CudaqExecutorCreate a CUDA-Q executor.
Parameters:
| Name | Type | Description |
|---|---|---|
target | str | None | CUDA-Q target name (e.g., "qpp-cpu"). If None, uses the default CUDA-Q target. |
ExecutionMode [source]¶
class ExecutionMode(enum.Enum)Execution mode for a CUDA-Q kernel artifact.
Determines which CUDA-Q runtime API is used for execution:
STATIC: Compatible withcudaq.sample(),cudaq.get_state(), andcudaq.observe(). The kernel has no explicit terminal measurements and no return value.RUNNABLE: Compatible withcudaq.run(). The kernel has explicit mid-circuit measurements and returnsmz(q)(list[bool]).
Attributes¶
RUNNABLESTATIC