CUDA-Q backend for Qamomile.
This module provides transpiler, executor, and observable conversion for the CUDA-Q quantum computing platform.
All circuits are emitted through a unified CudaqKernelEmitter codegen
path, producing CudaqKernelArtifact instances. The artifact’s
ExecutionMode (STATIC or RUNNABLE) determines which CUDA-Q runtime
API is used for execution.
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 |
|---|---|
BoundCudaqKernelArtifact | CUDA-Q kernel artifact with bound parameter values. |
CudaqEmitPass | CUDA-Q-specific emission pass. |
CudaqExecutor | CUDA-Q quantum executor. |
CudaqKernelArtifact | Compiled CUDA-Q decorator-kernel artifact. |
CudaqKernelEmitter | Unified GateEmitter that generates @cudaq.kernel Python source code. |
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¶
BoundCudaqKernelArtifact [source]¶
class BoundCudaqKernelArtifactCUDA-Q kernel artifact with bound parameter values.
Used as the return type of CudaqExecutor.bind_parameters.
The executor dispatches to the appropriate CUDA-Q runtime API
based on execution_mode.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel_func | Any | The @cudaq.kernel decorated function. |
num_qubits | int | Number of qubits in the circuit. |
num_clbits | int | Number of classical bits in the circuit. |
param_values | list[float] | Bound parameter values in order. |
execution_mode | ExecutionMode | Execution mode inherited from the source artifact. |
Constructor¶
def __init__(
self,
kernel_func: Any,
num_qubits: int,
num_clbits: int,
param_values: list[float],
execution_mode: ExecutionMode = ExecutionMode.STATIC,
) -> NoneAttributes¶
execution_mode: ExecutionModekernel_func: Anynum_clbits: intnum_qubits: intparam_values: list[float]
CudaqEmitPass [source]¶
class CudaqEmitPass(StandardEmitPass[CudaqKernelArtifact])CUDA-Q-specific emission pass.
Uses a single CudaqKernelEmitter for all circuits. The emitter
generates @cudaq.kernel decorated Python source for both static
and runtime control flow circuits. The execution mode (STATIC or
RUNNABLE) is determined by a pre-scan of the operations.
Constructor¶
def __init__(
self,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
)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).
CudaqKernelArtifact [source]¶
class CudaqKernelArtifactCompiled CUDA-Q decorator-kernel artifact.
Wraps a @cudaq.kernel decorated function produced by
CudaqKernelEmitter. The execution_mode field determines
which CUDA-Q runtime APIs are valid for this artifact.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel_func | Any | The @cudaq.kernel decorated function, or None before finalize() is called. |
num_qubits | int | Number of qubits in the circuit. |
num_clbits | int | Number of classical bits in the circuit. |
source | str | Generated Python source code (for debugging). |
entry_source | str | Generated Python source for the entry-point kernel only. source may also include helper kernels emitted for cudaq.control. |
execution_mode | ExecutionMode | Whether this is a STATIC or RUNNABLE kernel. |
param_count | int | Number of variational parameters. |
Constructor¶
def __init__(
self,
kernel_func: Any,
num_qubits: int,
num_clbits: int,
source: str = '',
entry_source: str = '',
execution_mode: ExecutionMode = ExecutionMode.STATIC,
param_count: int = 0,
) -> NoneAttributes¶
entry_source: strexecution_mode: ExecutionModekernel_func: Anynum_clbits: intnum_qubits: intparam_count: intsource: str
CudaqKernelEmitter [source]¶
class CudaqKernelEmitterUnified GateEmitter that generates @cudaq.kernel Python source code.
Used for all CUDA-Q circuits. Gate calls are accumulated as Python
source lines forming a @cudaq.kernel decorated function. The
finalize() method compiles the source via exec() and populates
the artifact’s kernel_func.
The measurement_mode property controls measurement behaviour:
MeasurementMode.STATIC:emit_measureis a no-op;cudaq.sample()auto-measures all qubits.MeasurementMode.RUNNABLE:emit_measureemits explicitmz()calls for mid-circuit measurement variables.
Parameters:
| Name | Type | Description |
|---|---|---|
parametric | bool | Initial hint for parametricity. The emit pass overrides this after emission based on _param_count. |
Constructor¶
def __init__(self, parametric: bool = False) -> NoneAttributes¶
measurement_mode: MeasurementMode Return the current measurement mode.
Methods¶
append_gate¶
def append_gate(self, circuit: CudaqKernelArtifact, gate: Any, qubits: list[int]) -> NoneNo-op: not supported by CUDA-Q codegen path.
build_adjoint_helper¶
def build_adjoint_helper(self, num_targets: int, emit_body: Callable[[], None]) -> tuple[str, bool]Build a pure-device helper kernel for cudaq.adjoint.
Parameters:
| Name | Type | Description |
|---|---|---|
num_targets | int | Number of target qubit arguments accepted by the helper. |
emit_body | Callable[[], None] | Callback that emits the helper body into this emitter while qubit slots are mapped to helper arguments. |
Returns:
str — tuple[str, bool]: Helper function name, and whether the
bool — caller must pass the entry-point thetas parameter list.
Raises:
EmitError— Propagated fromemit_bodywhen the helper body cannot be emitted for CUDA-Q.
build_controlled_helper¶
def build_controlled_helper(self, num_targets: int, emit_body: Callable[[], None]) -> tuple[str, bool]Build a pure-device helper kernel for cudaq.control.
Parameters:
| Name | Type | Description |
|---|---|---|
num_targets | int | Number of target qubit arguments accepted by the helper. |
emit_body | Callable[[], None] | Callback that emits the helper body into this emitter while qubit slots are mapped to helper arguments. |
Returns:
str — tuple[str, bool]: Helper function name, and whether the
bool — caller must pass the entry-point thetas parameter list.
Raises:
EmitError— Propagated fromemit_bodywhen the helper body cannot be emitted for CUDA-Q.
circuit_to_gate¶
def circuit_to_gate(self, circuit: CudaqKernelArtifact, name: str = 'U') -> AnyNo-op: not supported by CUDA-Q codegen path.
create_circuit¶
def create_circuit(self, num_qubits: int, num_clbits: int) -> CudaqKernelArtifactStart building a @cudaq.kernel function.
Resets internal state and emits the q = cudaq.qvector(N)
allocation line.
Parameters:
| Name | Type | Description |
|---|---|---|
num_qubits | int | Number of qubits to allocate. |
num_clbits | int | Number of classical bits. |
Returns:
CudaqKernelArtifact — A new CudaqKernelArtifact with kernel_func=None
CudaqKernelArtifact — (populated by finalize()).
create_parameter¶
def create_parameter(self, name: str) -> CudaqExprReturn a CudaqExpr referencing thetas[i].
Returns an arithmetic-capable expression object so that
StandardEmitPass._evaluate_binop() can compose gate-angle
expressions (e.g. gamma * Jij) without triggering a
TypeError on raw string operands.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Symbolic parameter name. |
Returns:
CudaqExpr — CudaqExpr wrapping a source expression like
CudaqExpr — "thetas[0]".
emit_adjoint_kernel_call¶
def emit_adjoint_kernel_call(
self,
circuit: CudaqKernelArtifact,
helper_name: str,
target_indices: list[int],
uses_thetas: bool,
) -> NoneEmit a cudaq.adjoint call to a generated helper kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being emitted. The argument is accepted for GateEmitter symmetry and tracing subclasses. |
helper_name | str | Name of the generated helper function. |
target_indices | list[int] | Physical target qubit slots. |
uses_thetas | bool | Whether to pass the entry-point thetas parameter list to the helper. |
emit_barrier¶
def emit_barrier(self, circuit: CudaqKernelArtifact, qubits: list[int]) -> NoneNo-op: CUDA-Q does not support barrier instructions.
emit_ch¶
def emit_ch(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Hadamard via decomposition.
Mirrors the CH_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions. Inlined here (rather
than calling :func:emit_decomposition) so that the string-based
codegen produces the exact source contract expected by the tracing
test emitter, without double-recording primitive gate calls.
emit_controlled_kernel_call¶
def emit_controlled_kernel_call(
self,
circuit: CudaqKernelArtifact,
helper_name: str,
control_indices: list[int],
target_indices: list[int],
uses_thetas: bool,
) -> NoneEmit a cudaq.control call to a generated helper kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being emitted. The argument is accepted for GateEmitter symmetry and tracing subclasses. |
helper_name | str | Name of the generated helper function. |
control_indices | list[int] | Physical control qubit slots. |
target_indices | list[int] | Physical target qubit slots. |
uses_thetas | bool | Whether to pass the entry-point thetas parameter list to the helper. |
emit_cp¶
def emit_cp(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-Phase via decomposition.
Follows the shared CP_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions.
Inlined here because CudaqExpr angles require string-based codegen.
emit_crx¶
def emit_crx(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RX gate.
emit_cry¶
def emit_cry(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RY gate.
emit_crz¶
def emit_crz(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RZ gate.
emit_cx¶
def emit_cx(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit CNOT (controlled-X) gate.
emit_cy¶
def emit_cy(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Y via decomposition.
Mirrors the CY_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions. See
:meth:emit_ch for why this is inlined rather than delegating to
:func:emit_decomposition.
emit_cz¶
def emit_cz(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Z gate.
emit_else_start¶
def emit_else_start(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneEmit else: block.
emit_exp_pauli¶
def emit_exp_pauli(
self,
circuit: CudaqKernelArtifact,
qubit_indices: list[int],
pauli_str: str,
angle: float | Any,
) -> NoneEmit a native exp_pauli Pauli evolution term.
Implements exp(i * angle * P) for a single Pauli term P,
where pauli_str[k] acts on qubit_indices[k]. CUDA-Q applies
the j-th character of the word to the j-th qubit in the
passed list, so the word and qubit list share the same order and no
reversal is needed (verified against the Qiskit PauliEvolutionGate
reference for asymmetric multi-qubit terms such as X0 Z1).
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
qubit_indices | list[int] | Physical qubit slots pauli_str acts on, in natural (pauli_str[k] -> qubit_indices[k]) order. |
pauli_str | str | Pauli letters (X / Y / Z) for the term, one per entry in qubit_indices. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_for_loop_end¶
def emit_for_loop_end(self, circuit: CudaqKernelArtifact, context: Any) -> NoneNot supported: for-loops are unrolled by the transpiler.
emit_for_loop_start¶
def emit_for_loop_start(self, circuit: CudaqKernelArtifact, indexset: range) -> AnyNot supported: for-loops are unrolled by the transpiler.
emit_h¶
def emit_h(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Hadamard gate.
emit_if_end¶
def emit_if_end(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneClose if block by decreasing indentation.
emit_if_start¶
def emit_if_start(
self,
circuit: CudaqKernelArtifact,
clbit: int,
value: int = 1,
) -> dict[str, Any]Emit if __b{clbit}: and increase indentation.
emit_measure¶
def emit_measure(self, circuit: CudaqKernelArtifact, qubit: int, clbit: int) -> NoneEmit measurement, respecting the current mode.
In STATIC mode (measurement_mode == STATIC), this is a
no-op: cudaq.sample() auto-measures all qubits.
In RUNNABLE mode (measurement_mode == RUNNABLE), emits
explicit mz() to capture mid-circuit measurement results as
local variables for if / while conditions.
emit_multi_controlled_p¶
def emit_multi_controlled_p(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled phase rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary phase gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_rx¶
def emit_multi_controlled_rx(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RX rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RX gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_ry¶
def emit_multi_controlled_ry(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RY rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RY gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_rz¶
def emit_multi_controlled_rz(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RZ rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RZ gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_x¶
def emit_multi_controlled_x(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
) -> NoneEmit multi-controlled X using x.ctrl(c0, c1, ..., target).
emit_p¶
def emit_p(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit phase gate (R1).
emit_rx¶
def emit_rx(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RX rotation gate.
emit_ry¶
def emit_ry(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RY rotation gate.
emit_rz¶
def emit_rz(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RZ rotation gate.
emit_rzz¶
def emit_rzz(
self,
circuit: CudaqKernelArtifact,
qubit1: int,
qubit2: int,
angle: float | Any,
) -> NoneEmit RZZ via CNOT + RZ decomposition.
RZZ(q1, q2, theta) = CNOT(q1, q2) RZ(q2, theta) CNOT(q1, q2)
emit_s¶
def emit_s(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit S (phase) gate.
emit_sdg¶
def emit_sdg(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit S-dagger gate.
emit_swap¶
def emit_swap(self, circuit: CudaqKernelArtifact, qubit1: int, qubit2: int) -> NoneEmit SWAP gate.
emit_t¶
def emit_t(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit T gate.
emit_tdg¶
def emit_tdg(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit T-dagger gate.
emit_toffoli¶
def emit_toffoli(
self,
circuit: CudaqKernelArtifact,
control1: int,
control2: int,
target: int,
) -> NoneEmit Toffoli (CCX) gate.
Delegates to :meth:emit_multi_controlled_x so that all
multi-controlled X emission flows through a single canonical helper.
emit_while_end¶
def emit_while_end(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneClose while block by decreasing indentation.
emit_while_start¶
def emit_while_start(
self,
circuit: CudaqKernelArtifact,
clbit: int,
value: int = 1,
) -> dict[str, Any]Emit while __b{clbit}: and increase indentation.
emit_x¶
def emit_x(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-X gate.
emit_y¶
def emit_y(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-Y gate.
emit_z¶
def emit_z(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-Z gate.
finalize¶
def finalize(self, circuit: CudaqKernelArtifact, mode: ExecutionMode) -> CudaqKernelArtifactCompile accumulated source into a @cudaq.kernel function.
For RUNNABLE mode, appends return [__b0, __b1, ...] to
return per-shot logical clbit values. For STATIC mode,
generates a void function with no explicit terminal measurement.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | The artifact to finalize. |
mode | ExecutionMode | Execution mode determining the function signature. |
Returns:
CudaqKernelArtifact — The same artifact with kernel_func and source populated.
gate_controlled¶
def gate_controlled(self, gate: Any, num_controls: int) -> AnyNo-op: not supported by CUDA-Q codegen path.
gate_inverse¶
def gate_inverse(self, gate: Any) -> AnyReturn None because CUDA-Q source emission has no reusable inverse gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate | Any | Ignored reusable gate placeholder. |
Returns:
Any — Always None.
gate_power¶
def gate_power(self, gate: Any, power: int) -> AnyNo-op: not supported by CUDA-Q codegen path.
supports_for_loop¶
def supports_for_loop(self) -> boolReturn False: for-loops are unrolled by the transpiler.
supports_gate_inverse¶
def supports_gate_inverse(self) -> boolReturn False because CUDA-Q uses dedicated adjoint helper emission.
Returns:
bool — Always False.
supports_if_else¶
def supports_if_else(self) -> boolReturn True only in RUNNABLE mode (measurement-dependent branching).
supports_reusable_gates¶
def supports_reusable_gates(self) -> boolReturn False because CUDA-Q source emission has no reusable gate path.
Returns:
bool — Always False.
supports_while_loop¶
def supports_while_loop(self) -> boolReturn True only in RUNNABLE mode.
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
qamomile.cudaq.emitter¶
CUDA-Q emitter implementation.
This module provides a unified emitter for the CUDA-Q backend:
CudaqKernelEmitter: Generates@cudaq.kerneldecorated Python source code for all circuits. The emitter supports two execution modes:STATIC: Measurement-free kernels compatible with
cudaq.sample(),cudaq.get_state(), andcudaq.observe().RUNNABLE: Kernels with explicit mid-circuit measurements and a final
return mz(q), compatible withcudaq.run().
The execution mode is determined by the emit pass based on whether the circuit contains runtime measurement-dependent control flow.
Overview¶
| Class | Description |
|---|---|
CudaqExpr | Arithmetic-capable wrapper for CUDA-Q source expressions. |
CudaqKernelArtifact | Compiled CUDA-Q decorator-kernel artifact. |
CudaqKernelEmitter | Unified GateEmitter that generates @cudaq.kernel Python source code. |
ExecutionMode | Execution mode for a CUDA-Q kernel artifact. |
MeasurementMode | How a backend handles measurement operations. |
Classes¶
CudaqExpr [source]¶
class CudaqExprArithmetic-capable wrapper for CUDA-Q source expressions.
Enables operator-overload-based expression building in
StandardEmitPass._evaluate_binop(). Each arithmetic operation
returns a new CudaqExpr with a properly parenthesized string
representation. str(expr) yields the raw source expression
suitable for embedding directly in generated @cudaq.kernel code.
Parameters:
| Name | Type | Description |
|---|---|---|
expr | str | Source expression string (e.g. "thetas[0]"). |
Constructor¶
def __init__(self, expr: str) -> NoneCudaqKernelArtifact [source]¶
class CudaqKernelArtifactCompiled CUDA-Q decorator-kernel artifact.
Wraps a @cudaq.kernel decorated function produced by
CudaqKernelEmitter. The execution_mode field determines
which CUDA-Q runtime APIs are valid for this artifact.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel_func | Any | The @cudaq.kernel decorated function, or None before finalize() is called. |
num_qubits | int | Number of qubits in the circuit. |
num_clbits | int | Number of classical bits in the circuit. |
source | str | Generated Python source code (for debugging). |
entry_source | str | Generated Python source for the entry-point kernel only. source may also include helper kernels emitted for cudaq.control. |
execution_mode | ExecutionMode | Whether this is a STATIC or RUNNABLE kernel. |
param_count | int | Number of variational parameters. |
Constructor¶
def __init__(
self,
kernel_func: Any,
num_qubits: int,
num_clbits: int,
source: str = '',
entry_source: str = '',
execution_mode: ExecutionMode = ExecutionMode.STATIC,
param_count: int = 0,
) -> NoneAttributes¶
entry_source: strexecution_mode: ExecutionModekernel_func: Anynum_clbits: intnum_qubits: intparam_count: intsource: str
CudaqKernelEmitter [source]¶
class CudaqKernelEmitterUnified GateEmitter that generates @cudaq.kernel Python source code.
Used for all CUDA-Q circuits. Gate calls are accumulated as Python
source lines forming a @cudaq.kernel decorated function. The
finalize() method compiles the source via exec() and populates
the artifact’s kernel_func.
The measurement_mode property controls measurement behaviour:
MeasurementMode.STATIC:emit_measureis a no-op;cudaq.sample()auto-measures all qubits.MeasurementMode.RUNNABLE:emit_measureemits explicitmz()calls for mid-circuit measurement variables.
Parameters:
| Name | Type | Description |
|---|---|---|
parametric | bool | Initial hint for parametricity. The emit pass overrides this after emission based on _param_count. |
Constructor¶
def __init__(self, parametric: bool = False) -> NoneAttributes¶
measurement_mode: MeasurementMode Return the current measurement mode.
Methods¶
append_gate¶
def append_gate(self, circuit: CudaqKernelArtifact, gate: Any, qubits: list[int]) -> NoneNo-op: not supported by CUDA-Q codegen path.
build_adjoint_helper¶
def build_adjoint_helper(self, num_targets: int, emit_body: Callable[[], None]) -> tuple[str, bool]Build a pure-device helper kernel for cudaq.adjoint.
Parameters:
| Name | Type | Description |
|---|---|---|
num_targets | int | Number of target qubit arguments accepted by the helper. |
emit_body | Callable[[], None] | Callback that emits the helper body into this emitter while qubit slots are mapped to helper arguments. |
Returns:
str — tuple[str, bool]: Helper function name, and whether the
bool — caller must pass the entry-point thetas parameter list.
Raises:
EmitError— Propagated fromemit_bodywhen the helper body cannot be emitted for CUDA-Q.
build_controlled_helper¶
def build_controlled_helper(self, num_targets: int, emit_body: Callable[[], None]) -> tuple[str, bool]Build a pure-device helper kernel for cudaq.control.
Parameters:
| Name | Type | Description |
|---|---|---|
num_targets | int | Number of target qubit arguments accepted by the helper. |
emit_body | Callable[[], None] | Callback that emits the helper body into this emitter while qubit slots are mapped to helper arguments. |
Returns:
str — tuple[str, bool]: Helper function name, and whether the
bool — caller must pass the entry-point thetas parameter list.
Raises:
EmitError— Propagated fromemit_bodywhen the helper body cannot be emitted for CUDA-Q.
circuit_to_gate¶
def circuit_to_gate(self, circuit: CudaqKernelArtifact, name: str = 'U') -> AnyNo-op: not supported by CUDA-Q codegen path.
create_circuit¶
def create_circuit(self, num_qubits: int, num_clbits: int) -> CudaqKernelArtifactStart building a @cudaq.kernel function.
Resets internal state and emits the q = cudaq.qvector(N)
allocation line.
Parameters:
| Name | Type | Description |
|---|---|---|
num_qubits | int | Number of qubits to allocate. |
num_clbits | int | Number of classical bits. |
Returns:
CudaqKernelArtifact — A new CudaqKernelArtifact with kernel_func=None
CudaqKernelArtifact — (populated by finalize()).
create_parameter¶
def create_parameter(self, name: str) -> CudaqExprReturn a CudaqExpr referencing thetas[i].
Returns an arithmetic-capable expression object so that
StandardEmitPass._evaluate_binop() can compose gate-angle
expressions (e.g. gamma * Jij) without triggering a
TypeError on raw string operands.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Symbolic parameter name. |
Returns:
CudaqExpr — CudaqExpr wrapping a source expression like
CudaqExpr — "thetas[0]".
emit_adjoint_kernel_call¶
def emit_adjoint_kernel_call(
self,
circuit: CudaqKernelArtifact,
helper_name: str,
target_indices: list[int],
uses_thetas: bool,
) -> NoneEmit a cudaq.adjoint call to a generated helper kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being emitted. The argument is accepted for GateEmitter symmetry and tracing subclasses. |
helper_name | str | Name of the generated helper function. |
target_indices | list[int] | Physical target qubit slots. |
uses_thetas | bool | Whether to pass the entry-point thetas parameter list to the helper. |
emit_barrier¶
def emit_barrier(self, circuit: CudaqKernelArtifact, qubits: list[int]) -> NoneNo-op: CUDA-Q does not support barrier instructions.
emit_ch¶
def emit_ch(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Hadamard via decomposition.
Mirrors the CH_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions. Inlined here (rather
than calling :func:emit_decomposition) so that the string-based
codegen produces the exact source contract expected by the tracing
test emitter, without double-recording primitive gate calls.
emit_controlled_kernel_call¶
def emit_controlled_kernel_call(
self,
circuit: CudaqKernelArtifact,
helper_name: str,
control_indices: list[int],
target_indices: list[int],
uses_thetas: bool,
) -> NoneEmit a cudaq.control call to a generated helper kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being emitted. The argument is accepted for GateEmitter symmetry and tracing subclasses. |
helper_name | str | Name of the generated helper function. |
control_indices | list[int] | Physical control qubit slots. |
target_indices | list[int] | Physical target qubit slots. |
uses_thetas | bool | Whether to pass the entry-point thetas parameter list to the helper. |
emit_cp¶
def emit_cp(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-Phase via decomposition.
Follows the shared CP_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions.
Inlined here because CudaqExpr angles require string-based codegen.
emit_crx¶
def emit_crx(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RX gate.
emit_cry¶
def emit_cry(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RY gate.
emit_crz¶
def emit_crz(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RZ gate.
emit_cx¶
def emit_cx(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit CNOT (controlled-X) gate.
emit_cy¶
def emit_cy(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Y via decomposition.
Mirrors the CY_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions. See
:meth:emit_ch for why this is inlined rather than delegating to
:func:emit_decomposition.
emit_cz¶
def emit_cz(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Z gate.
emit_else_start¶
def emit_else_start(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneEmit else: block.
emit_exp_pauli¶
def emit_exp_pauli(
self,
circuit: CudaqKernelArtifact,
qubit_indices: list[int],
pauli_str: str,
angle: float | Any,
) -> NoneEmit a native exp_pauli Pauli evolution term.
Implements exp(i * angle * P) for a single Pauli term P,
where pauli_str[k] acts on qubit_indices[k]. CUDA-Q applies
the j-th character of the word to the j-th qubit in the
passed list, so the word and qubit list share the same order and no
reversal is needed (verified against the Qiskit PauliEvolutionGate
reference for asymmetric multi-qubit terms such as X0 Z1).
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
qubit_indices | list[int] | Physical qubit slots pauli_str acts on, in natural (pauli_str[k] -> qubit_indices[k]) order. |
pauli_str | str | Pauli letters (X / Y / Z) for the term, one per entry in qubit_indices. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_for_loop_end¶
def emit_for_loop_end(self, circuit: CudaqKernelArtifact, context: Any) -> NoneNot supported: for-loops are unrolled by the transpiler.
emit_for_loop_start¶
def emit_for_loop_start(self, circuit: CudaqKernelArtifact, indexset: range) -> AnyNot supported: for-loops are unrolled by the transpiler.
emit_h¶
def emit_h(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Hadamard gate.
emit_if_end¶
def emit_if_end(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneClose if block by decreasing indentation.
emit_if_start¶
def emit_if_start(
self,
circuit: CudaqKernelArtifact,
clbit: int,
value: int = 1,
) -> dict[str, Any]Emit if __b{clbit}: and increase indentation.
emit_measure¶
def emit_measure(self, circuit: CudaqKernelArtifact, qubit: int, clbit: int) -> NoneEmit measurement, respecting the current mode.
In STATIC mode (measurement_mode == STATIC), this is a
no-op: cudaq.sample() auto-measures all qubits.
In RUNNABLE mode (measurement_mode == RUNNABLE), emits
explicit mz() to capture mid-circuit measurement results as
local variables for if / while conditions.
emit_multi_controlled_p¶
def emit_multi_controlled_p(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled phase rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary phase gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_rx¶
def emit_multi_controlled_rx(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RX rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RX gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_ry¶
def emit_multi_controlled_ry(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RY rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RY gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_rz¶
def emit_multi_controlled_rz(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RZ rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RZ gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_x¶
def emit_multi_controlled_x(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
) -> NoneEmit multi-controlled X using x.ctrl(c0, c1, ..., target).
emit_p¶
def emit_p(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit phase gate (R1).
emit_rx¶
def emit_rx(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RX rotation gate.
emit_ry¶
def emit_ry(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RY rotation gate.
emit_rz¶
def emit_rz(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RZ rotation gate.
emit_rzz¶
def emit_rzz(
self,
circuit: CudaqKernelArtifact,
qubit1: int,
qubit2: int,
angle: float | Any,
) -> NoneEmit RZZ via CNOT + RZ decomposition.
RZZ(q1, q2, theta) = CNOT(q1, q2) RZ(q2, theta) CNOT(q1, q2)
emit_s¶
def emit_s(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit S (phase) gate.
emit_sdg¶
def emit_sdg(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit S-dagger gate.
emit_swap¶
def emit_swap(self, circuit: CudaqKernelArtifact, qubit1: int, qubit2: int) -> NoneEmit SWAP gate.
emit_t¶
def emit_t(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit T gate.
emit_tdg¶
def emit_tdg(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit T-dagger gate.
emit_toffoli¶
def emit_toffoli(
self,
circuit: CudaqKernelArtifact,
control1: int,
control2: int,
target: int,
) -> NoneEmit Toffoli (CCX) gate.
Delegates to :meth:emit_multi_controlled_x so that all
multi-controlled X emission flows through a single canonical helper.
emit_while_end¶
def emit_while_end(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneClose while block by decreasing indentation.
emit_while_start¶
def emit_while_start(
self,
circuit: CudaqKernelArtifact,
clbit: int,
value: int = 1,
) -> dict[str, Any]Emit while __b{clbit}: and increase indentation.
emit_x¶
def emit_x(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-X gate.
emit_y¶
def emit_y(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-Y gate.
emit_z¶
def emit_z(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-Z gate.
finalize¶
def finalize(self, circuit: CudaqKernelArtifact, mode: ExecutionMode) -> CudaqKernelArtifactCompile accumulated source into a @cudaq.kernel function.
For RUNNABLE mode, appends return [__b0, __b1, ...] to
return per-shot logical clbit values. For STATIC mode,
generates a void function with no explicit terminal measurement.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | The artifact to finalize. |
mode | ExecutionMode | Execution mode determining the function signature. |
Returns:
CudaqKernelArtifact — The same artifact with kernel_func and source populated.
gate_controlled¶
def gate_controlled(self, gate: Any, num_controls: int) -> AnyNo-op: not supported by CUDA-Q codegen path.
gate_inverse¶
def gate_inverse(self, gate: Any) -> AnyReturn None because CUDA-Q source emission has no reusable inverse gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate | Any | Ignored reusable gate placeholder. |
Returns:
Any — Always None.
gate_power¶
def gate_power(self, gate: Any, power: int) -> AnyNo-op: not supported by CUDA-Q codegen path.
supports_for_loop¶
def supports_for_loop(self) -> boolReturn False: for-loops are unrolled by the transpiler.
supports_gate_inverse¶
def supports_gate_inverse(self) -> boolReturn False because CUDA-Q uses dedicated adjoint helper emission.
Returns:
bool — Always False.
supports_if_else¶
def supports_if_else(self) -> boolReturn True only in RUNNABLE mode (measurement-dependent branching).
supports_reusable_gates¶
def supports_reusable_gates(self) -> boolReturn False because CUDA-Q source emission has no reusable gate path.
Returns:
bool — Always False.
supports_while_loop¶
def supports_while_loop(self) -> boolReturn True only in RUNNABLE mode.
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
MeasurementMode [source]¶
class MeasurementMode(Enum)How a backend handles measurement operations.
Attributes¶
NATIVERUNNABLESTATIC
qamomile.cudaq.observable¶
CUDA-Q observable support.
This module provides conversion from qamomile.observable.Hamiltonian
to CUDA-Q SpinOperator for use with cudaq.observe.
Overview¶
| Function | Description |
|---|---|
hamiltonian_to_cudaq_spin_op | Convert qamomile.observable.Hamiltonian to cudaq.SpinOperator. |
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)qamomile.cudaq.transpiler¶
CUDA-Q backend transpiler implementation.
This module provides CudaqTranspiler for converting Qamomile QKernels into CUDA-Q decorator-kernel artifacts, along with CudaqEmitPass and CudaqExecutor.
All circuits (static and runtime) are emitted through a single
CudaqKernelEmitter codegen path. The emitter produces
CudaqKernelArtifact instances whose execution_mode determines
whether cudaq.sample() / cudaq.observe() / cudaq.get_state()
(STATIC) or cudaq.run() (RUNNABLE) is used for execution.
Overview¶
| Function | Description |
|---|---|
evaluate_binop | Evaluate a BinOp and store the result in bindings. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, MOD, POW, MIN). |
BoundCudaqKernelArtifact | CUDA-Q kernel artifact with bound parameter values. |
CallBlockOperation | |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CompositeGateType | Registry of known composite gate types. |
ControlledUOperation | Base class for controlled-U operations. |
CudaqEmitPass | CUDA-Q-specific emission pass. |
CudaqExecutor | CUDA-Q quantum executor. |
CudaqKernelArtifact | Compiled CUDA-Q decorator-kernel artifact. |
CudaqKernelEmitter | Unified GateEmitter that generates @cudaq.kernel Python source code. |
CudaqTranspiler | CUDA-Q transpiler for qamomile.circuit module. |
EmitError | Error during backend code emission. |
EmitPass | Base class for backend-specific emission passes. |
ExecutionMode | Execution mode for a CUDA-Q kernel artifact. |
ExpvalOp | Expectation value operation. |
ForItemsOperation | Represents iteration over dict/iterable items. |
ForOperation | Represents a for loop operation. |
GateOperation | Quantum gate operation. |
GateOperationType | |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
InverseBlockOperation | Represent an inverse qkernel/block as a first-class IR operation. |
MeasureOperation | |
MeasureQFixedOperation | Measure a quantum fixed-point number. |
MeasureVectorOperation | Measure a vector of qubits. |
MeasurementMode | How a backend handles measurement operations. |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
ReturnOperation | Explicit return operation marking the end of a block with return values. |
RuntimeClassicalExpr | A classical expression known to require runtime evaluation. |
SegmentationPass | Segment a block into a strategy-specific executable program plan. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
Transpiler | Base class for backend-specific transpilers. |
Value | A typed SSA value in the IR. |
WhileOperation | Represents a while loop operation. |
Functions¶
evaluate_binop [source]¶
def evaluate_binop(emit_pass: 'StandardEmitPass', op: BinOp, bindings: dict[str, Any]) -> NoneEvaluate a BinOp and store the result in bindings.
Tries the shared fold_classical_op first for a clean concrete
fold (which already encapsulates the runtime-parameter guard).
Falls back to creating backend Parameter symbols and doing
symbolic arithmetic when one or both operands are runtime
parameters — that’s the path that lets rx(q, gamma * 2) produce
a circuit with a single Parameter("gamma") * 2 expression rather
than baking in a placeholder.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
When slice_of is set, this array is a strided view over another
array. Element accesses on a sliced ArrayValue resolve to
physical slots on the root parent via the affine map
parent_index = slice_start + slice_step * view_local_index,
applied recursively along slice_of chains. The emit-time
resolver walks this chain to produce the final qubit index; passes
that substitute or clone values must treat slice_of /
slice_start / slice_step as Value references that need to
track through the same mapping as parent_array.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
slice_of: 'ArrayValue | None' = None,
slice_start: 'Value | None' = None,
slice_step: 'Value | None' = None,
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]slice_of: ‘ArrayValue | None’slice_start: ‘Value | None’slice_step: ‘Value | None’type: Tuuid: str
Methods¶
is_slice¶
def is_slice(self) -> boolReturn True if this array is a strided view of another array.
Returns:
bool — True iff slice_of is non-None.
next_version¶
def next_version(self) -> ArrayValue[T]BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, MOD, POW, MIN).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
BoundCudaqKernelArtifact [source]¶
class BoundCudaqKernelArtifactCUDA-Q kernel artifact with bound parameter values.
Used as the return type of CudaqExecutor.bind_parameters.
The executor dispatches to the appropriate CUDA-Q runtime API
based on execution_mode.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel_func | Any | The @cudaq.kernel decorated function. |
num_qubits | int | Number of qubits in the circuit. |
num_clbits | int | Number of classical bits in the circuit. |
param_values | list[float] | Bound parameter values in order. |
execution_mode | ExecutionMode | Execution mode inherited from the source artifact. |
Constructor¶
def __init__(
self,
kernel_func: Any,
num_qubits: int,
num_clbits: int,
param_values: list[float],
execution_mode: ExecutionMode = ExecutionMode.STATIC,
) -> NoneAttributes¶
execution_mode: ExecutionModekernel_func: Anynum_clbits: intnum_qubits: intparam_values: list[float]
CallBlockOperation [source]¶
class CallBlockOperation(Operation)Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
block: Block | None = None,
) -> NoneAttributes¶
block: Block | Noneoperation_kind: OperationKindsignature: Signature
Methods¶
is_self_reference_to¶
def is_self_reference_to(self, block: Block) -> boolReturn True if this call points to the given block (self-ref).
CompositeGateOperation [source]¶
class CompositeGateOperation(Operation)Represents a composite gate (QPE, QFT, etc.) as a single operation.
CompositeGate allows representing complex multi-gate operations as a single atomic operation in the IR. This enables:
Resource estimation without full implementation
Backend-native conversion (e.g., Qiskit’s QPE)
User-defined complex gates
The operands structure is:
operands[0:num_control_qubits]: Control qubits (if any)
operands[num_control_qubits:num_control_qubits+num_target_qubits]: Target qubits
operands[num_control_qubits+num_target_qubits:]: Parameters
The results structure:
results[0:num_control_qubits]: Control qubits (returned)
results[num_control_qubits:]: Target qubits (returned)
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
gate_type: CompositeGateType = CompositeGateType.CUSTOM,
num_control_qubits: int = 0,
num_target_qubits: int = 0,
custom_name: str = '',
resource_metadata: ResourceMetadata | None = None,
has_implementation: bool = True,
implementation_block: Block | None = None,
composite_gate_instance: Any = None,
strategy_name: str | None = None,
) -> NoneAttributes¶
composite_gate_instance: Anycontrol_qubits: list[‘Value’] Get the control qubit operands.custom_name: strgate_type: CompositeGateTypehas_implementation: boolimplementation: Block | None Get the implementation block, if any.implementation_block: Block | Nonename: str Human-readable name of this composite gate.num_control_qubits: intnum_target_qubits: intoperation_kind: OperationKind Return the operation kind (always QUANTUM).parameters: list[‘Value’] Get the parameter operands (angles, etc.).resource_metadata: ResourceMetadata | Nonesignature: Signature Return the operation signature.strategy_name: str | Nonetarget_qubits: list[‘Value’] Get the target qubit operands.
CompositeGateType [source]¶
class CompositeGateType(enum.Enum)Registry of known composite gate types.
Attributes¶
CUSTOMIQFTQFTQPE
ControlledUOperation [source]¶
class ControlledUOperation(Operation)Base class for controlled-U operations.
Two concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands; optionalcontrol_indicesselects a subset of the control vector to act as controls (the rest pass through).
All isinstance(op, ControlledUOperation) checks match every subclass.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: int | Value = 1,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.num_controls: int | Valueoperation_kind: OperationKindparam_operands: list[Value] Get parameter operands (non-qubit, non-block).power: int | Valuesignature: Signaturetarget_operands: list[Value] Get the target qubit values (arguments to U).
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationCudaqEmitPass [source]¶
class CudaqEmitPass(StandardEmitPass[CudaqKernelArtifact])CUDA-Q-specific emission pass.
Uses a single CudaqKernelEmitter for all circuits. The emitter
generates @cudaq.kernel decorated Python source for both static
and runtime control flow circuits. The execution mode (STATIC or
RUNNABLE) is determined by a pre-scan of the operations.
Constructor¶
def __init__(
self,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
)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).
CudaqKernelArtifact [source]¶
class CudaqKernelArtifactCompiled CUDA-Q decorator-kernel artifact.
Wraps a @cudaq.kernel decorated function produced by
CudaqKernelEmitter. The execution_mode field determines
which CUDA-Q runtime APIs are valid for this artifact.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel_func | Any | The @cudaq.kernel decorated function, or None before finalize() is called. |
num_qubits | int | Number of qubits in the circuit. |
num_clbits | int | Number of classical bits in the circuit. |
source | str | Generated Python source code (for debugging). |
entry_source | str | Generated Python source for the entry-point kernel only. source may also include helper kernels emitted for cudaq.control. |
execution_mode | ExecutionMode | Whether this is a STATIC or RUNNABLE kernel. |
param_count | int | Number of variational parameters. |
Constructor¶
def __init__(
self,
kernel_func: Any,
num_qubits: int,
num_clbits: int,
source: str = '',
entry_source: str = '',
execution_mode: ExecutionMode = ExecutionMode.STATIC,
param_count: int = 0,
) -> NoneAttributes¶
entry_source: strexecution_mode: ExecutionModekernel_func: Anynum_clbits: intnum_qubits: intparam_count: intsource: str
CudaqKernelEmitter [source]¶
class CudaqKernelEmitterUnified GateEmitter that generates @cudaq.kernel Python source code.
Used for all CUDA-Q circuits. Gate calls are accumulated as Python
source lines forming a @cudaq.kernel decorated function. The
finalize() method compiles the source via exec() and populates
the artifact’s kernel_func.
The measurement_mode property controls measurement behaviour:
MeasurementMode.STATIC:emit_measureis a no-op;cudaq.sample()auto-measures all qubits.MeasurementMode.RUNNABLE:emit_measureemits explicitmz()calls for mid-circuit measurement variables.
Parameters:
| Name | Type | Description |
|---|---|---|
parametric | bool | Initial hint for parametricity. The emit pass overrides this after emission based on _param_count. |
Constructor¶
def __init__(self, parametric: bool = False) -> NoneAttributes¶
measurement_mode: MeasurementMode Return the current measurement mode.
Methods¶
append_gate¶
def append_gate(self, circuit: CudaqKernelArtifact, gate: Any, qubits: list[int]) -> NoneNo-op: not supported by CUDA-Q codegen path.
build_adjoint_helper¶
def build_adjoint_helper(self, num_targets: int, emit_body: Callable[[], None]) -> tuple[str, bool]Build a pure-device helper kernel for cudaq.adjoint.
Parameters:
| Name | Type | Description |
|---|---|---|
num_targets | int | Number of target qubit arguments accepted by the helper. |
emit_body | Callable[[], None] | Callback that emits the helper body into this emitter while qubit slots are mapped to helper arguments. |
Returns:
str — tuple[str, bool]: Helper function name, and whether the
bool — caller must pass the entry-point thetas parameter list.
Raises:
EmitError— Propagated fromemit_bodywhen the helper body cannot be emitted for CUDA-Q.
build_controlled_helper¶
def build_controlled_helper(self, num_targets: int, emit_body: Callable[[], None]) -> tuple[str, bool]Build a pure-device helper kernel for cudaq.control.
Parameters:
| Name | Type | Description |
|---|---|---|
num_targets | int | Number of target qubit arguments accepted by the helper. |
emit_body | Callable[[], None] | Callback that emits the helper body into this emitter while qubit slots are mapped to helper arguments. |
Returns:
str — tuple[str, bool]: Helper function name, and whether the
bool — caller must pass the entry-point thetas parameter list.
Raises:
EmitError— Propagated fromemit_bodywhen the helper body cannot be emitted for CUDA-Q.
circuit_to_gate¶
def circuit_to_gate(self, circuit: CudaqKernelArtifact, name: str = 'U') -> AnyNo-op: not supported by CUDA-Q codegen path.
create_circuit¶
def create_circuit(self, num_qubits: int, num_clbits: int) -> CudaqKernelArtifactStart building a @cudaq.kernel function.
Resets internal state and emits the q = cudaq.qvector(N)
allocation line.
Parameters:
| Name | Type | Description |
|---|---|---|
num_qubits | int | Number of qubits to allocate. |
num_clbits | int | Number of classical bits. |
Returns:
CudaqKernelArtifact — A new CudaqKernelArtifact with kernel_func=None
CudaqKernelArtifact — (populated by finalize()).
create_parameter¶
def create_parameter(self, name: str) -> CudaqExprReturn a CudaqExpr referencing thetas[i].
Returns an arithmetic-capable expression object so that
StandardEmitPass._evaluate_binop() can compose gate-angle
expressions (e.g. gamma * Jij) without triggering a
TypeError on raw string operands.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Symbolic parameter name. |
Returns:
CudaqExpr — CudaqExpr wrapping a source expression like
CudaqExpr — "thetas[0]".
emit_adjoint_kernel_call¶
def emit_adjoint_kernel_call(
self,
circuit: CudaqKernelArtifact,
helper_name: str,
target_indices: list[int],
uses_thetas: bool,
) -> NoneEmit a cudaq.adjoint call to a generated helper kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being emitted. The argument is accepted for GateEmitter symmetry and tracing subclasses. |
helper_name | str | Name of the generated helper function. |
target_indices | list[int] | Physical target qubit slots. |
uses_thetas | bool | Whether to pass the entry-point thetas parameter list to the helper. |
emit_barrier¶
def emit_barrier(self, circuit: CudaqKernelArtifact, qubits: list[int]) -> NoneNo-op: CUDA-Q does not support barrier instructions.
emit_ch¶
def emit_ch(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Hadamard via decomposition.
Mirrors the CH_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions. Inlined here (rather
than calling :func:emit_decomposition) so that the string-based
codegen produces the exact source contract expected by the tracing
test emitter, without double-recording primitive gate calls.
emit_controlled_kernel_call¶
def emit_controlled_kernel_call(
self,
circuit: CudaqKernelArtifact,
helper_name: str,
control_indices: list[int],
target_indices: list[int],
uses_thetas: bool,
) -> NoneEmit a cudaq.control call to a generated helper kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being emitted. The argument is accepted for GateEmitter symmetry and tracing subclasses. |
helper_name | str | Name of the generated helper function. |
control_indices | list[int] | Physical control qubit slots. |
target_indices | list[int] | Physical target qubit slots. |
uses_thetas | bool | Whether to pass the entry-point thetas parameter list to the helper. |
emit_cp¶
def emit_cp(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-Phase via decomposition.
Follows the shared CP_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions.
Inlined here because CudaqExpr angles require string-based codegen.
emit_crx¶
def emit_crx(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RX gate.
emit_cry¶
def emit_cry(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RY gate.
emit_crz¶
def emit_crz(
self,
circuit: CudaqKernelArtifact,
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RZ gate.
emit_cx¶
def emit_cx(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit CNOT (controlled-X) gate.
emit_cy¶
def emit_cy(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Y via decomposition.
Mirrors the CY_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions. See
:meth:emit_ch for why this is inlined rather than delegating to
:func:emit_decomposition.
emit_cz¶
def emit_cz(self, circuit: CudaqKernelArtifact, control: int, target: int) -> NoneEmit controlled-Z gate.
emit_else_start¶
def emit_else_start(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneEmit else: block.
emit_exp_pauli¶
def emit_exp_pauli(
self,
circuit: CudaqKernelArtifact,
qubit_indices: list[int],
pauli_str: str,
angle: float | Any,
) -> NoneEmit a native exp_pauli Pauli evolution term.
Implements exp(i * angle * P) for a single Pauli term P,
where pauli_str[k] acts on qubit_indices[k]. CUDA-Q applies
the j-th character of the word to the j-th qubit in the
passed list, so the word and qubit list share the same order and no
reversal is needed (verified against the Qiskit PauliEvolutionGate
reference for asymmetric multi-qubit terms such as X0 Z1).
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
qubit_indices | list[int] | Physical qubit slots pauli_str acts on, in natural (pauli_str[k] -> qubit_indices[k]) order. |
pauli_str | str | Pauli letters (X / Y / Z) for the term, one per entry in qubit_indices. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_for_loop_end¶
def emit_for_loop_end(self, circuit: CudaqKernelArtifact, context: Any) -> NoneNot supported: for-loops are unrolled by the transpiler.
emit_for_loop_start¶
def emit_for_loop_start(self, circuit: CudaqKernelArtifact, indexset: range) -> AnyNot supported: for-loops are unrolled by the transpiler.
emit_h¶
def emit_h(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Hadamard gate.
emit_if_end¶
def emit_if_end(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneClose if block by decreasing indentation.
emit_if_start¶
def emit_if_start(
self,
circuit: CudaqKernelArtifact,
clbit: int,
value: int = 1,
) -> dict[str, Any]Emit if __b{clbit}: and increase indentation.
emit_measure¶
def emit_measure(self, circuit: CudaqKernelArtifact, qubit: int, clbit: int) -> NoneEmit measurement, respecting the current mode.
In STATIC mode (measurement_mode == STATIC), this is a
no-op: cudaq.sample() auto-measures all qubits.
In RUNNABLE mode (measurement_mode == RUNNABLE), emits
explicit mz() to capture mid-circuit measurement results as
local variables for if / while conditions.
emit_multi_controlled_p¶
def emit_multi_controlled_p(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled phase rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary phase gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_rx¶
def emit_multi_controlled_rx(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RX rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RX gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_ry¶
def emit_multi_controlled_ry(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RY rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RY gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_rz¶
def emit_multi_controlled_rz(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
angle: float | Any,
) -> NoneEmit a multi-controlled RZ rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | Artifact currently being built. |
control_indices | list[int] | Physical control qubit indices. If empty, this method emits an ordinary RZ gate. |
target_idx | int | Physical target qubit index. |
angle | float | Any | Rotation angle or CUDA-Q source expression. |
emit_multi_controlled_x¶
def emit_multi_controlled_x(
self,
circuit: CudaqKernelArtifact,
control_indices: list[int],
target_idx: int,
) -> NoneEmit multi-controlled X using x.ctrl(c0, c1, ..., target).
emit_p¶
def emit_p(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit phase gate (R1).
emit_rx¶
def emit_rx(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RX rotation gate.
emit_ry¶
def emit_ry(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RY rotation gate.
emit_rz¶
def emit_rz(self, circuit: CudaqKernelArtifact, qubit: int, angle: float | Any) -> NoneEmit RZ rotation gate.
emit_rzz¶
def emit_rzz(
self,
circuit: CudaqKernelArtifact,
qubit1: int,
qubit2: int,
angle: float | Any,
) -> NoneEmit RZZ via CNOT + RZ decomposition.
RZZ(q1, q2, theta) = CNOT(q1, q2) RZ(q2, theta) CNOT(q1, q2)
emit_s¶
def emit_s(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit S (phase) gate.
emit_sdg¶
def emit_sdg(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit S-dagger gate.
emit_swap¶
def emit_swap(self, circuit: CudaqKernelArtifact, qubit1: int, qubit2: int) -> NoneEmit SWAP gate.
emit_t¶
def emit_t(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit T gate.
emit_tdg¶
def emit_tdg(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit T-dagger gate.
emit_toffoli¶
def emit_toffoli(
self,
circuit: CudaqKernelArtifact,
control1: int,
control2: int,
target: int,
) -> NoneEmit Toffoli (CCX) gate.
Delegates to :meth:emit_multi_controlled_x so that all
multi-controlled X emission flows through a single canonical helper.
emit_while_end¶
def emit_while_end(self, circuit: CudaqKernelArtifact, context: dict[str, Any]) -> NoneClose while block by decreasing indentation.
emit_while_start¶
def emit_while_start(
self,
circuit: CudaqKernelArtifact,
clbit: int,
value: int = 1,
) -> dict[str, Any]Emit while __b{clbit}: and increase indentation.
emit_x¶
def emit_x(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-X gate.
emit_y¶
def emit_y(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-Y gate.
emit_z¶
def emit_z(self, circuit: CudaqKernelArtifact, qubit: int) -> NoneEmit Pauli-Z gate.
finalize¶
def finalize(self, circuit: CudaqKernelArtifact, mode: ExecutionMode) -> CudaqKernelArtifactCompile accumulated source into a @cudaq.kernel function.
For RUNNABLE mode, appends return [__b0, __b1, ...] to
return per-shot logical clbit values. For STATIC mode,
generates a void function with no explicit terminal measurement.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | CudaqKernelArtifact | The artifact to finalize. |
mode | ExecutionMode | Execution mode determining the function signature. |
Returns:
CudaqKernelArtifact — The same artifact with kernel_func and source populated.
gate_controlled¶
def gate_controlled(self, gate: Any, num_controls: int) -> AnyNo-op: not supported by CUDA-Q codegen path.
gate_inverse¶
def gate_inverse(self, gate: Any) -> AnyReturn None because CUDA-Q source emission has no reusable inverse gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate | Any | Ignored reusable gate placeholder. |
Returns:
Any — Always None.
gate_power¶
def gate_power(self, gate: Any, power: int) -> AnyNo-op: not supported by CUDA-Q codegen path.
supports_for_loop¶
def supports_for_loop(self) -> boolReturn False: for-loops are unrolled by the transpiler.
supports_gate_inverse¶
def supports_gate_inverse(self) -> boolReturn False because CUDA-Q uses dedicated adjoint helper emission.
Returns:
bool — Always False.
supports_if_else¶
def supports_if_else(self) -> boolReturn True only in RUNNABLE mode (measurement-dependent branching).
supports_reusable_gates¶
def supports_reusable_gates(self) -> boolReturn False because CUDA-Q source emission has no reusable gate path.
Returns:
bool — Always False.
supports_while_loop¶
def supports_while_loop(self) -> boolReturn True only in RUNNABLE mode.
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. |
EmitError [source]¶
class EmitError(QamomileCompileError)Error during backend code emission.
Constructor¶
def __init__(self, message: str, operation: str | None = None)Attributes¶
operation
EmitPass [source]¶
class EmitPass(Pass[ProgramPlan, ExecutableProgram[T]], Generic[T])Base class for backend-specific emission passes.
Subclasses implement _emit_quantum_segment() to generate backend-specific quantum circuits.
Input: ProgramPlan Output: ExecutableProgram with compiled segments
Constructor¶
def __init__(
self,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
)Initialize with optional parameter bindings.
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | None | Values to bind parameters to. If not provided, parameters must be bound at execution time. |
parameters | list[str] | None | List of parameter names to preserve as backend parameters. |
Attributes¶
bindingsname: strparameters
Methods¶
run¶
def run(self, input: ProgramPlan) -> ExecutableProgram[T]Emit backend code from a program plan.
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
ExpvalOp [source]¶
class ExpvalOp(Operation)Expectation value operation.
This operation computes the expectation value <psi|H|psi> where psi is the quantum state and H is the Hamiltonian observable.
The operation bridges quantum and classical computation:
Input: quantum state (qubits) + Observable reference
Output: classical Float (expectation value)
Example IR:
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
hamiltonian: Value Alias for observable (deprecated, use observable instead).observable: Value The Observable parameter operand.operation_kind: OperationKind ExpvalOp is HYBRID - bridges quantum state to classical value.output: Value The expectation value result.qubits: Value The quantum register operand.signature: Signature
ForItemsOperation [source]¶
class ForItemsOperation(HasNestedOps, Operation)Represents iteration over dict/iterable items.
Example:
for (i, j), Jij in qmc.items(ising):
bodyConstructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
key_vars: list[str] = list(),
value_var: str = '',
key_is_vector: bool = False,
key_var_values: tuple[Value, ...] | None = None,
value_var_value: Value | None = None,
operations: list[Operation] = list(),
) -> NoneAttributes¶
key_is_vector: boolkey_var_values: tuple[Value, ...] | Nonekey_vars: list[str]operation_kind: OperationKindoperations: list[Operation]signature: Signaturevalue_var: strvalue_var_value: Value | None
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Include the per-key/value Value fields for cloning/substitution.
Same rationale as ForOperation.all_input_values: keep the IR
identity fields in lockstep with body references so UUID-keyed
lookups stay valid after inline cloning.
nested_op_lists¶
def nested_op_lists(self) -> list[list[Operation]]rebuild_nested¶
def rebuild_nested(self, new_lists: list[list[Operation]]) -> Operationreplace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationForOperation [source]¶
class ForOperation(HasNestedOps, Operation)Represents a for loop operation.
Example:
for i in range(start, stop, step):
bodyConstructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
loop_var: str = '',
loop_var_value: Value | None = None,
operations: list[Operation] = list(),
) -> NoneAttributes¶
loop_var: strloop_var_value: Value | Noneoperation_kind: OperationKindoperations: list[Operation]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Include loop_var_value so cloning/substitution stays consistent.
Without this override, UUIDRemapper would clone every body
reference to the loop variable to a fresh UUID, but leave
loop_var_value pointing at the un-cloned original — emit-time
UUID-keyed lookups for the loop variable would then miss.
nested_op_lists¶
def nested_op_lists(self) -> list[list[Operation]]rebuild_nested¶
def rebuild_nested(self, new_lists: list[list[Operation]]) -> Operationreplace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationGateOperation [source]¶
class GateOperation(Operation)Quantum gate operation.
For rotation gates (RX, RY, RZ, P, CP, RZZ), the angle parameter is
stored as the last element of operands. Use the theta
property for typed read access and the rotation / fixed factory
class-methods for type-safe construction.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
gate_type: GateOperationType | None = None,
) -> NoneAttributes¶
gate_type: GateOperationType | Noneoperation_kind: OperationKindqubit_operands: list[Value] Qubit operands (excluding the theta parameter if present).signature: Signaturetheta: Value | None Angle parameter for rotation gates, orNonefor fixed gates.
Methods¶
fixed¶
@classmethod
def fixed(
cls,
gate_type: GateOperationType,
qubits: list[Value],
results: list[Value],
) -> 'GateOperation'Create a fixed gate (H, X, CX, SWAP, …) with no angle parameter.
rotation¶
@classmethod
def rotation(
cls,
gate_type: GateOperationType,
qubits: list[Value],
theta: Value,
results: list[Value],
) -> 'GateOperation'Create a rotation gate (RX, RY, RZ, P, CP, RZZ) with an angle.
GateOperationType [source]¶
class GateOperationType(enum.Enum)Attributes¶
CPCXCZHPRXRYRZRZZSSDGSWAPTTDGTOFFOLIXYZ
HasNestedOps [source]¶
class HasNestedOpsMixin for operations that contain nested operation lists.
Subclasses implement nested_op_lists() and rebuild_nested()
so that generic passes can recurse into control flow without
isinstance chains.
Methods¶
nested_op_lists¶
def nested_op_lists(self) -> list[list[Operation]]Return all nested operation lists in this control flow op.
rebuild_nested¶
def rebuild_nested(self, new_lists: list[list[Operation]]) -> OperationReturn a copy with nested operation lists replaced.
new_lists must have the same length/order as nested_op_lists().
IfOperation [source]¶
class IfOperation(HasNestedOps, Operation)Represents an if-else conditional operation.
Example:
if condition:
true_body
else:
false_bodyConstructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
true_operations: list[Operation] = list(),
false_operations: list[Operation] = list(),
phi_ops: list[PhiOp] = list(),
) -> NoneAttributes¶
condition: Valuefalse_operations: list[Operation]operation_kind: OperationKindphi_ops: list[PhiOp]signature: Signaturetrue_operations: list[Operation]
Methods¶
nested_op_lists¶
def nested_op_lists(self) -> list[list[Operation]]rebuild_nested¶
def rebuild_nested(self, new_lists: list[list[Operation]]) -> OperationInverseBlockOperation [source]¶
class InverseBlockOperation(Operation)Represent an inverse qkernel/block as a first-class IR operation.
The operation stores both the original forward block and a Qamomile-built
inverse implementation block. Emitters may use source_block with a
backend-native inverse/adjoint primitive, then fall back to
implementation_block when native inversion is unavailable.
Operands are ordered as control qubits, target quantum operands, then
classical/object parameters. Results mirror the quantum operand layout:
control results first, then one target result per target operand. Vector
target operands therefore count as one operand/result while contributing
their scalar width to num_target_qubits.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
num_control_qubits: int = 0,
num_target_qubits: int = 0,
custom_name: str = '',
source_block: Block | None = None,
implementation_block: Block | None = None,
) -> NoneAttributes¶
control_qubits: list[‘Value’] Return control quantum operands.custom_name: strimplementation_block: Block | Nonename: str Return a human-readable inverse operation name.num_control_qubits: intnum_target_qubits: intoperation_kind: OperationKind Return the operation kind.parameters: list[‘Value’] Return classical/object parameter operands.signature: Signature Return the operation signature.source_block: Block | Nonetarget_qubits: list[‘Value’] Return target quantum operands.
MeasureOperation [source]¶
class MeasureOperation(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
MeasureQFixedOperation [source]¶
class MeasureQFixedOperation(Operation)Measure a quantum fixed-point number.
This operation measures all qubits in a QFixed register and produces a Float result. During transpilation, this is lowered to individual MeasureOperations plus a DecodeQFixedOperation.
operands: [QFixed value (contains qubit_values in params)] results: [Float value]
Encoding:
For QPE phase (int_bits=0): float_value = 0.b0b1b2... = b00.5 + b10.25 + b2*0.125 + ...
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
num_bits: int = 0,
int_bits: int = 0,
) -> NoneAttributes¶
int_bits: intnum_bits: intoperation_kind: OperationKindsignature: Signature
MeasureVectorOperation [source]¶
class MeasureVectorOperation(Operation)Measure a vector of qubits.
Takes a Vector[Qubit] (ArrayValue) and produces a Vector[Bit] (ArrayValue). This operation measures all qubits in the vector as a single operation.
operands: [ArrayValue of qubits] results: [ArrayValue of bits]
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
MeasurementMode [source]¶
class MeasurementMode(Enum)How a backend handles measurement operations.
Attributes¶
NATIVERUNNABLESTATIC
PauliEvolveOp [source]¶
class PauliEvolveOp(Operation)Pauli evolution operation: exp(-i * gamma * H).
This operation applies the time evolution of a Pauli Hamiltonian to a quantum register.
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
evolved_qubits: Value The evolved quantum register result.gamma: Value The evolution time parameter.observable: Value The Observable parameter operand.operation_kind: OperationKind PauliEvolveOp is QUANTUM - transforms quantum state.qubits: Value The quantum register operand.signature: Signature
ReturnOperation [source]¶
class ReturnOperation(Operation)Explicit return operation marking the end of a block with return values.
This operation represents an explicit return statement in the IR. It takes the values to be returned as operands and produces no results (it is a terminal operation that transfers control flow back to the caller).
operands: [Value, ...] - The values to return (may be empty for void returns) results: [] - Always empty (terminal operation)
Example:
A function that returns two values (a UInt and a Float):
ReturnOperation(
operands=[uint_value, float_value],
results=[],
)
The signature would be:
operands=[ParamHint("return_0", UIntType()), ParamHint("return_1", FloatType())]
results=[]Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Return CLASSICAL as this is a control flow operation without quantum effects.signature: Signature Return the signature with operands for each return value and no results.
RuntimeClassicalExpr [source]¶
class RuntimeClassicalExpr(Operation)A classical expression known to require runtime evaluation.
Lowered from CompOp / CondOp / NotOp / BinOp by
ClassicalLoweringPass when the op’s operand dataflow traces back
to a MeasureOperation (i.e. cannot be folded at compile-time, by
emit-time loop unrolling, or by compile_time_if_lowering). Backend
emit translates this 1:1 to a backend-native runtime expression
(e.g. qiskit.circuit.classical.expr.Expr).
Operand convention:
Binary kinds (EQ/NEQ/LT/LE/GT/GE/AND/OR/ADD/SUB/MUL/DIV/FLOORDIV/MOD/POW):
operands = [lhs, rhs].Unary kind (NOT):
operands = [val].Result:
results = [output_value].
The single-node + unified-kind shape (vs four parallel subclasses)
keeps the backend dispatch a single match op.kind instead of four
parallel hooks, and makes the IR self-documenting: a single
RuntimeClassicalExpr instance signals “runtime evaluation
required” regardless of which classical family it came from.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: RuntimeOpKind | None = None,
) -> NoneAttributes¶
kind: RuntimeOpKind | Noneoperation_kind: OperationKindsignature: Signature
SegmentationPass [source]¶
class SegmentationPass(Pass[Block, ProgramPlan])Segment a block into a strategy-specific executable program plan.
This pass:
Materializes return operations (syncs output_values from ReturnOperation)
Splits the operation list into quantum and classical segments
Builds a ProgramPlan via the configured segmentation strategy
Input: Block (typically ANALYZED or AFFINE) Output: ProgramPlan
Constructor¶
def __init__(self, strategy: SegmentationStrategy | None = None) -> NoneAttributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> ProgramPlanSegment the block into a ProgramPlan.
StandardEmitPass [source]¶
class StandardEmitPass(EmitPass[T], Generic[T])Standard emit pass implementation using GateEmitter protocol.
This class provides the orchestration logic for circuit emission while delegating backend-specific operations to a GateEmitter.
Subclasses (QiskitEmitPass, CudaqEmitPass) override specific methods
to provide native backend support. The thin wrappers here delegate to
module functions in emit_support/ by default.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_emitter | GateEmitter[T] | Backend-specific gate emitter |
bindings | dict[str, Any] | None | Parameter bindings for the circuit |
parameters | list[str] | None | List of parameter names to preserve as backend parameters |
composite_emitters | list[CompositeGateEmitter[T]] | None | Optional list of CompositeGateEmitter for native implementations |
Constructor¶
def __init__(
self,
gate_emitter: GateEmitter[T],
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
composite_emitters: list[CompositeGateEmitter[T]] | None = None,
)Transpiler [source]¶
class Transpiler(ABC, Generic[T])Base class for backend-specific transpilers.
Provides the full compilation pipeline from QKernel to executable program.
Usage:
transpiler = QiskitTranspiler()
Option 1: Full pipeline¶
executable = transpiler.compile(kernel, bindings={“theta”: 0.5}) results = executable.run(transpiler.executor())
Option 2: Step-by-step¶
block = transpiler.to_block(kernel) substituted = transpiler.substitute(block) affine = transpiler.inline(substituted) validated = transpiler.affine_validate(affine) folded = transpiler.constant_fold(validated, bindings={“theta”: 0.5}) analyzed = transpiler.analyze(folded) plan = transpiler.plan(analyzed) executable = transpiler.emit(plan, bindings={“theta”: 0.5})
Option 3: Just get the circuit (no execution)¶
circuit = transpiler.to_circuit(kernel, bindings={“theta”: 0.5})
With configuration (strategy overrides)¶
config = TranspilerConfig.with_strategies({“qft”: “approximate”}) transpiler = QiskitTranspiler(config=config)
Attributes¶
MAX_UNROLL_DEPTH: intconfig: TranspilerConfig Get the transpiler configuration.
Methods¶
affine_validate¶
def affine_validate(self, block: Block) -> BlockPass 1.5: Validate affine type semantics.
This is a safety net to catch affine type violations that may have bypassed frontend checks. Validates that quantum values are used at most once.
analyze¶
def analyze(self, block: Block) -> BlockPass 2: Validate and analyze dependencies.
classical_lowering¶
def classical_lowering(self, block: Block) -> BlockPass 2.25: Lower measurement-derived classical ops.
Identifies CompOp / CondOp / NotOp / BinOp
instances whose operand dataflow traces back to a measurement and
rewrites them to RuntimeClassicalExpr. Compile-time-foldable
and emit-time-foldable (loop-bound, parameter-bound) classical
ops are left unchanged.
Runs after analyze so the measurement-taint analysis has the
full dependency graph available, and before
validate_symbolic_shapes / plan / emit so downstream
passes can rely on the cleaner IR (in particular: future
segmentation work can dispatch on RuntimeClassicalExpr type
instead of the BitType-only heuristic).
constant_fold¶
def constant_fold(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockPass 1.5: Fold constant expressions.
Evaluates BinOp operations when all operands are constants
or bound parameters. This prevents quantum segment splitting
from parametric expressions like phase * 2.
emit¶
def emit(
self,
separated: ProgramPlan,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
) -> ExecutableProgram[T]Pass 4: Generate backend-specific code.
Parameters:
| Name | Type | Description |
|---|---|---|
separated | ProgramPlan | The separated program to emit |
bindings | dict[str, Any] | None | Parameter values to bind at compile time |
parameters | list[str] | None | Parameter names to preserve as backend parameters |
executor¶
def executor(self, **kwargs: Any = {}) -> QuantumExecutor[T]Create a quantum executor for this backend.
inline¶
def inline(self, block: Block) -> BlockPass 1: Inline all CallBlockOperations.
lower_compile_time_ifs¶
def lower_compile_time_ifs(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockPass 1.75: Lower compile-time resolvable IfOperations.
Evaluates IfOperation conditions (including expression-derived conditions via CompOp/CondOp/NotOp) and replaces resolved ones with selected-branch operations. Phi outputs are substituted with selected-branch values throughout the block.
This prevents SegmentationPass from seeing classical-only compile-time IfOperations that would otherwise split quantum segments.
partial_eval¶
def partial_eval(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockPass 1.75: Fold constants and lower compile-time control flow.
plan¶
def plan(self, block: Block) -> ProgramPlanPass 3: Lower and split into a program plan.
Validates C→Q→C pattern with single quantum segment.
resolve_parameter_shapes¶
def resolve_parameter_shapes(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockPass 0.75: Resolve symbolic Vector parameter shape dims.
Qamomile circuits are compile-time fixed-structure. Parameter
Vector[Float] / Vector[UInt] inputs carry symbolic
{name}_dim{i} shape Values so frontend code like
arr.shape[0] returns a usable handle. This pass looks at
bindings and, for every parameter array that has a concrete
binding, substitutes those symbolic dims with constants so that
downstream loop-bound resolution sees fixed lengths.
Parameters without a concrete binding are left as-is; their symbolic dims are harmless as long as no compile-time structure decision depends on them (the library QAOA pattern).
set_config¶
def set_config(self, config: TranspilerConfig) -> NoneSet the transpiler configuration.
Parameters:
| Name | Type | Description |
|---|---|---|
config | TranspilerConfig | Transpiler configuration to use |
slice_borrow_check¶
def slice_borrow_check(self, block: Block) -> BlockPass 1.9: Post-fold slice-view linearity checker.
Runs after :meth:partial_eval has resolved slice bounds to
concrete values. Catches the slice-view linearity violations
that the trace-time frontend check cannot detect on its own —
specifically, slices whose bounds were symbolic at trace
time (so the frontend bulk-borrow tracker had to skip them)
and aliasing scenarios that only become visible once those
bounds are folded to constants:
A view whose newly-concrete coverage overlaps another live view of the same root parent.
A view whose newly-concrete coverage hits a slot that was consumed by a destructive view operation earlier in the block.
A view that reaches the end of the block while still recorded as the owner of the parent’s slots (i.e. it was never used or never released).
Direct element borrows (q[i]) emit no IR operation, so the
IR-level pass cannot observe them; the trace-time validation
in :func:func_to_block._validate_returned_arrays covers that
path.
The pass is a pass-through for the IR — it only raises on violations and leaves the block unchanged on success.
strip_slice_ops¶
def strip_slice_ops(self, block: Block) -> BlockPass 1.95: Remove SliceArrayOperation nodes from the block.
PartialEvaluationPass keeps these declarative ops through
constant folding so :meth:slice_borrow_check can use them
as view-declaration markers. Once the linearity check has run,
segmentation and downstream passes expect a classical-op-free
quantum stream — this pass performs that cleanup.
substitute¶
def substitute(self, block: Block) -> BlockPass 0.5: Apply substitutions (optional).
This pass replaces CallBlockOperation targets and sets strategy names on CompositeGateOperations based on config.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | Block to transform |
Returns:
Block — Block with substitutions applied
to_block¶
def to_block(
self,
kernel: QKernel,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
) -> BlockConvert a QKernel to a Block.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel | QKernel | The QKernel to convert |
bindings | dict[str, Any] | None | Concrete values to bind at trace time (resolves array shapes) |
parameters | list[str] | None | Names to keep as unbound parameters |
When bindings or parameters are provided, uses kernel.build() to properly resolve array shapes from the bound data. Otherwise uses the cached hierarchical block for efficiency.
to_circuit¶
def to_circuit(self, kernel: QKernel, bindings: dict[str, Any] | None = None) -> TCompile and extract just the quantum circuit.
This is a convenience method for when you just want the backend circuit without the full executable.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel | QKernel | The QKernel to compile |
bindings | dict[str, Any] | None | Parameter values to bind |
Returns:
T — Backend-specific quantum circuit
transpile¶
def transpile(
self,
kernel: QKernel,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
) -> ExecutableProgram[T]Full compilation pipeline from QKernel to executable.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel | QKernel | The QKernel to compile |
bindings | dict[str, Any] | None | Parameter values to bind (also resolves array shapes). Names in bindings and parameters must be disjoint — a name is either compile-time bound or runtime symbolic, never both. |
parameters | list[str] | None | Parameter names to preserve as backend parameters |
Returns:
ExecutableProgram[T] — ExecutableProgram ready for execution
Raises:
ValueError— If a name appears in bothbindingsandparameters. A name being in both is ambiguous (placeholder value vs runtime symbol) and used to silently miscompile control-flow predicates that depended on parameter-array elements; rejecting the overlap up front keeps the contract unambiguous.QamomileCompileError— If compilation fails (validation, dependency errors)
Pipeline:
to_block: Convert QKernel to Block
substitute: Apply substitutions (if configured)
resolve_parameter_shapes: Constant-fold symbolic Vector param dims
inline: Inline CallBlockOperations
affine_validate: Validate affine type semantics
partial_eval: Fold constants and lower compile-time control flow
analyze: Validate and analyze dependencies
validate_symbolic_shapes: Reject unresolved parameter shape dims
plan: Build ProgramPlan (segment into C->Q->C steps)
emit: Generate backend-specific code
unroll_recursion¶
def unroll_recursion(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockFixed-point loop of inline ↔ partial_eval for self-recursive kernels.
Each iteration unrolls one layer of self-referential
CallBlockOperation and then folds the base-case
IfOperation via partial_eval. Terminates when no
CallBlockOperation remains (success), when every residual call
is trapped inside an operation-owned block where partial_eval
cannot fold it (control / inverse of a recursive kernel — raises a
targeted error, see below), or when MAX_UNROLL_DEPTH is reached
(genuinely non-terminating top-level recursion — raises).
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to unroll. May be HIERARCHICAL (still containing self-referential CallBlockOperations) or already AFFINE (returned unchanged). |
bindings | dict[str, Any] | None | Compile-time bindings used by partial_eval to fold the base-case condition. Defaults to None, meaning no bindings are applied. |
Returns:
Block — The fully unrolled, AFFINE block once no
CallBlockOperation remains. Returned unchanged when the
input already has no calls.
Raises:
FrontendTransformError— If every remainingCallBlockOperationis trapped inside aControlledUOperation.block/InverseBlockOperationblock (a self-recursive kernel was passed toqmc.control/qmc.inverse), or if a genuinely non-terminating top-level recursion does not converge withinMAX_UNROLL_DEPTHiterations. The two cases carry distinct, cause-specific messages.
validate_symbolic_shapes¶
def validate_symbolic_shapes(self, block: Block) -> BlockPass 2.5: Reject unresolved parameter shape dims in loop bounds.
Runs after analyze so dependency info is complete. Raises
QamomileCompileError with an actionable message when a
gamma_dim0-style symbolic Value reaches a ForOperation
bound without being folded to a constant by
ParameterShapeResolutionPass.
Value [source]¶
class Value(_MetadataValueMixin, Generic[T])A typed SSA value in the IR.
The name field is display-only: it labels the value for
visualization and error messages and has no role in identity. Identity
is carried by uuid (per-version) and logical_id (across
versions).
An empty string (name="") is the anonymous marker used by
auto-generated tmp values (arithmetic results, comparison results,
coerced constants). Name-based readers must guard with truthiness
(if value.name and value.name in bindings: ...) so anonymous values
never collide on a shared empty key. User-supplied parameter names and
array names continue to be non-empty.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
) -> NoneAttributes¶
element_indices: tuple[Value, ...]logical_id: strmetadata: ValueMetadataname: strparent_array: ArrayValue | Nonetype: Tuuid: strversion: int
Methods¶
is_array_element¶
def is_array_element(self) -> boolnext_version¶
def next_version(self) -> Value[T]Create a new Value with incremented version and fresh UUID.
Metadata is intentionally preserved across versions so that
parameter bindings and constant annotations remain accessible
after the value is updated (e.g. by a gate application or a
classical operation). The logical_id also stays the same:
it identifies the same logical variable across SSA versions,
independently of backend resource allocation. This applies to
every Value regardless of its type (Qubit, Float,
Bit, ...) -- it is not specific to qubits.
WhileOperation [source]¶
class WhileOperation(HasNestedOps, Operation)Represents a while loop operation.
Only measurement-backed conditions are supported: the condition must
be a Bit value produced by qmc.measure(). Non-measurement
conditions (classical variables, constants, comparisons) are rejected
by ValidateWhileContractPass before reaching backend emit.
Example::
bit = qmc.measure(q)
while bit:
q = qmc.h(q)
bit = qmc.measure(q)Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
operations: list[Operation] = list(),
max_iterations: int | None = None,
) -> NoneAttributes¶
max_iterations: int | Noneoperation_kind: OperationKindoperations: list[Operation]signature: Signature
Methods¶
nested_op_lists¶
def nested_op_lists(self) -> list[list[Operation]]rebuild_nested¶
def rebuild_nested(self, new_lists: list[list[Operation]]) -> Operation