qamomile.circuit.transpiler.capabilities¶
Backend capability definitions for transpiler optimization.
Overview¶
| Class | Description |
|---|---|
BackendCapability | Capabilities that a backend may support natively. |
CapableBackend | Protocol for backends that declare their capabilities. |
Classes¶
BackendCapability [source]¶
class BackendCapability(enum.Flag)Capabilities that a backend may support natively.
Use these flags to indicate which composite gates and features a backend supports, allowing the transpiler to use native implementations when available.
Attributes¶
BASIC_COMPOSITECLASSICAL_FEEDFORWARDDYNAMIC_CIRCUITSFOR_LOOPFULL_COMPOSITEFULL_CONTROL_FLOWNATIVE_IQFTNATIVE_QFTNATIVE_QPENONEWHILE_LOOP
CapableBackend [source]¶
class CapableBackend(Protocol)Protocol for backends that declare their capabilities.
Implement this protocol in backend-specific EmitPass classes to enable capability-based optimizations.
Attributes¶
capabilities: BackendCapability Return the capabilities this backend supports.
Methods¶
has_capability¶
def has_capability(self, cap: BackendCapability) -> boolCheck if this backend has a specific capability.
Parameters:
| Name | Type | Description |
|---|---|---|
cap | BackendCapability | The capability to check for. |
Returns:
bool — True if the backend has the capability, False otherwise.
qamomile.circuit.transpiler.classical_executor¶
Classical segment executor for Python-based classical operations.
Overview¶
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
ClassicalExecutor | Executes classical segments in Python. |
ClassicalSegment | A segment of pure classical operations. |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CondOp | Conditional logical operation (AND, OR). |
DecodeQFixedOperation | Decode measured bits to float (classical operation). |
DictValue | A dictionary value stored as stable ordered entries. |
ExecutionContext | Holds global state during program execution. |
ExecutionError | Error during program execution. |
ForItemsOperation | Represents iteration over dict/iterable items. |
ForOperation | Represents a for loop operation. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
NotOp | |
PhiOp | SSA Phi function: merge point after conditional branch. |
TupleValue | A tuple of IR values for structured data. |
Value | A typed SSA value in the IR. |
WhileOperation | Represents a while loop operation. |
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
ClassicalExecutor [source]¶
class ClassicalExecutorExecutes classical segments in Python.
Methods¶
execute¶
def execute(self, segment: ClassicalSegment, context: ExecutionContext) -> dict[str, Any]Execute classical operations and return outputs.
Interprets the operations list directly using Python.
ClassicalSegment [source]¶
class ClassicalSegment(Segment)A segment of pure classical operations.
Contains arithmetic, comparisons, and control flow. Will be executed directly in Python.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
kind: SegmentKind
CompOp [source]¶
class CompOp(BinaryOperationBase)Comparison operation (EQ, NEQ, LT, LE, GT, GE).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CompOpKind | None = None,
) -> NoneAttributes¶
kind: CompOpKind | Noneoperation_kind: OperationKindsignature: Signature
CondOp [source]¶
class CondOp(BinaryOperationBase)Conditional logical operation (AND, OR).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CondOpKind | None = None,
) -> NoneAttributes¶
kind: CondOpKind | Noneoperation_kind: OperationKindsignature: Signature
DecodeQFixedOperation [source]¶
class DecodeQFixedOperation(Operation)Decode measured bits to float (classical operation).
This operation converts a sequence of classical bits from qubit measurements into a floating-point number using fixed-point encoding.
The decoding formula:
float_value = Σ bit[i] * 2^(int_bits - 1 - i)
For QPE phase (int_bits=0): float_value = 0.b0b1b2... = b00.5 + b10.25 + b2*0.125 + ...
Example:
bits = [1, 0, 1] with int_bits=0
→ 0.101 (binary) = 0.5 + 0.125 = 0.625operands: [ArrayValue of bits (vec[bit])] results: [Float value]
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
DictValue [source]¶
class DictValue(_MetadataValueMixin)A dictionary value stored as stable ordered entries.
Constructor¶
def __init__(
self,
name: str,
entries: tuple[tuple[TupleValue | Value, Value], ...] = tuple(),
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
) -> NoneAttributes¶
entries: tuple[tuple[TupleValue | Value, Value], ...]logical_id: strmetadata: ValueMetadataname: strtype: DictTypeuuid: str
Methods¶
is_constant¶
def is_constant(self) -> boolnext_version¶
def next_version(self) -> DictValueExecutionContext [source]¶
class ExecutionContextHolds global state during program execution.
Constructor¶
def __init__(self, initial_bindings: dict[str, Any] | None = None)Methods¶
copy¶
def copy(self) -> 'ExecutionContext'Clone the execution context.
get¶
def get(self, key: str) -> Anyget_many¶
def get_many(self, keys: list[str]) -> dict[str, Any]has¶
def has(self, key: str) -> boolset¶
def set(self, key: str, value: Any) -> Noneupdate¶
def update(self, values: dict[str, Any]) -> NoneExecutionError [source]¶
class ExecutionError(QamomileCompileError)Error during program execution.
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]) -> OperationHasNestedOps [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]]) -> OperationNotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
PhiOp [source]¶
class PhiOp(Operation)SSA Phi function: merge point after conditional branch.
This operation selects one of two values based on a condition. Used to merge values from different branches of an if-else statement.
Example:
if condition:
x = x + 1 # true_value
else:
x = x + 2 # false_value
# x is now PhiOp(condition, true_value, false_value)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
condition: Valuefalse_value: Valueoperation_kind: OperationKindoutput: Valuesignature: Signaturetrue_value: Value
TupleValue [source]¶
class TupleValue(_MetadataValueMixin)A tuple of IR values for structured data.
Constructor¶
def __init__(
self,
name: str,
elements: tuple[Value, ...] = tuple(),
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
) -> NoneAttributes¶
elements: tuple[Value, ...]logical_id: strmetadata: ValueMetadataname: strtype: ‘TupleType’uuid: str
Methods¶
is_constant¶
def is_constant(self) -> boolnext_version¶
def next_version(self) -> TupleValueValue [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]]) -> Operationqamomile.circuit.transpiler.compile_check¶
Overview¶
| Function | Description |
|---|---|
is_block_compilable | Check if a Block is compilable. |
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
Functions¶
is_block_compilable [source]¶
def is_block_compilable(block: Block) -> boolCheck if a Block is compilable.
A Block is considered compilable if all its operations are compilable. This function checks each operation in the block’s operations list.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The Block to check. |
Returns: bool: True if the block is compilable, False otherwise.
Classes¶
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
qamomile.circuit.transpiler.compiled_segments¶
Compiled segment structures for transpiled quantum circuits.
Overview¶
| Class | Description |
|---|---|
ClassicalSegment | A segment of pure classical operations. |
CompiledClassicalSegment | A classical segment ready for Python execution. |
CompiledExpvalSegment | A compiled expectation value segment with concrete Hamiltonian. |
CompiledQuantumSegment | A quantum segment with emitted backend circuit. |
ExpvalSegment | A segment for expectation value computation. |
ParameterMetadata | Metadata for all parameters in a compiled segment. |
QuantumSegment | A segment of pure quantum operations. |
Classes¶
ClassicalSegment [source]¶
class ClassicalSegment(Segment)A segment of pure classical operations.
Contains arithmetic, comparisons, and control flow. Will be executed directly in Python.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
kind: SegmentKind
CompiledClassicalSegment [source]¶
class CompiledClassicalSegmentA classical segment ready for Python execution.
Constructor¶
def __init__(self, segment: ClassicalSegment) -> NoneAttributes¶
segment: ClassicalSegment
CompiledExpvalSegment [source]¶
class CompiledExpvalSegmentA compiled expectation value segment with concrete Hamiltonian.
This segment computes <psi|H|psi> where psi is the quantum state from a quantum circuit and H is a qamomile.observable.Hamiltonian.
Constructor¶
def __init__(
self,
segment: ExpvalSegment,
hamiltonian: 'qm_o.Hamiltonian',
quantum_segment_index: int = 0,
result_ref: str = '',
qubit_map: dict[int, int] = dict(),
) -> NoneAttributes¶
hamiltonian: ‘qm_o.Hamiltonian’quantum_segment_index: intqubit_map: dict[int, int]result_ref: strsegment: ExpvalSegment
CompiledQuantumSegment [source]¶
class CompiledQuantumSegment(Generic[T])A quantum segment with emitted backend circuit.
Constructor¶
def __init__(
self,
segment: QuantumSegment,
circuit: T,
qubit_map: QubitMap = dict(),
clbit_map: ClbitMap = dict(),
measurement_qubit_map: dict[int, int] = dict(),
parameter_metadata: ParameterMetadata = ParameterMetadata(),
) -> NoneAttributes¶
circuit: Tclbit_map: ClbitMapmeasurement_qubit_map: dict[int, int]parameter_metadata: ParameterMetadataqubit_map: QubitMapsegment: QuantumSegment
ExpvalSegment [source]¶
class ExpvalSegment(Segment)A segment for expectation value computation.
Represents computing <psi|H|psi> where psi is the quantum state and H is a Hamiltonian observable.
This segment bridges a quantum circuit (state preparation) to a classical expectation value.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
hamiltonian_value: Value | None = None,
qubits_value: Value | None = None,
result_ref: str = '',
) -> NoneAttributes¶
hamiltonian_value: Value | Nonekind: SegmentKindqubits_value: Value | Noneresult_ref: str
ParameterMetadata [source]¶
class ParameterMetadataMetadata for all parameters in a compiled segment.
Tracks parameter information for runtime binding.
Constructor¶
def __init__(self, parameters: list[ParameterInfo] = list()) -> NoneAttributes¶
parameters: list[ParameterInfo]
Methods¶
get_array_names¶
def get_array_names(self) -> set[str]Get unique array/scalar parameter names.
get_ordered_params¶
def get_ordered_params(self) -> list[Any]Get backend parameter objects in definition order.
Useful for backends that require positional parameter binding (e.g., QURI Parts).
Returns:
list[Any] — List of backend_param objects in the order they were defined.
Example:
# For QURI Parts that uses positional binding:
param_values = [bindings[p.name] for p in metadata.parameters]
bound_circuit = circuit.bind_parameters(param_values)get_param_by_name¶
def get_param_by_name(self, name: str) -> ParameterInfo | NoneGet parameter info by full name.
to_binding_dict¶
def to_binding_dict(self, bindings: dict[str, Any]) -> dict[Any, Any]Convert indexed bindings to backend parameter bindings.
Transforms user-provided bindings (with indexed names like “gammas[0]”) into a dictionary mapping backend parameter objects to values. Useful for backends that use dict-based parameter binding (e.g., Qiskit).
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | Dictionary mapping parameter names to values. e.g., {“gammas[0]”: 0.1, “gammas[1]”: 0.2, “theta”: 0.5} |
Returns:
dict[Any, Any] — Dictionary mapping backend_param objects to values.
Example:
# For Qiskit that uses dict-based binding:
qiskit_bindings = metadata.to_binding_dict(bindings)
bound_circuit = circuit.assign_parameters(qiskit_bindings)QuantumSegment [source]¶
class QuantumSegment(Segment)A segment of pure quantum operations.
Contains quantum gates and qubit allocations. Will be emitted to a quantum circuit.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
qubit_values: list[Value] = list(),
num_qubits: int = 0,
) -> NoneAttributes¶
kind: SegmentKindnum_qubits: intqubit_values: list[Value]
qamomile.circuit.transpiler.decompositions¶
Shared gate decomposition recipes for backend emitters.
This module defines the canonical decomposition of controlled gates (CH, CY,
CP, CRY, CRZ) into primitive operations (RY, RZ, CNOT, S, SDG). Each recipe
is a frozen sequence of :class:DecompStep instances that encode:
Which primitive gate to apply,
Which qubit role receives the gate (
"control"or"target"),An optional angle expression (e.g.
"theta/2","-pi/4").
The recipes are the single source of truth for how Qamomile decomposes controlled gates when a backend cannot use a native controlled-U operation.
Why data-only (no shared execution helper)¶
Each backend has its own emission dialect:
Qiskit uses native
circuit.ch()/circuit.cy()and never needs this decomposition.QURI Parts represents angles as parametric dicts (name -> coefficient); primitive
emit_*methods take those dicts, not plain floats, so a generic “loop over the recipe and callemitter.emit_ry(angle)” helper does not compose.CUDA-Q emits Python source as strings. A generic helper that calls
self.emit_ryinteracts poorly with the tracing test emitter, which wraps everyemit_*method and would double-record each call.
Because no single helper absorbs all three styles cleanly, backends inline
their decomposition using their own idiomatic emission, and reference the
recipe constants below from the emit_ch / emit_cy / ... docstrings to
document equivalence. When changing a recipe, update the constant here and
ensure every backend’s inline implementation matches.
Overview¶
| Class | Description |
|---|---|
DecompStep | A single step in a decomposition recipe. |
PrimitiveGate | Gate primitives used in decomposition recipes. |
Constants¶
CH_DECOMPOSITION:list[DecompStep]CP_DECOMPOSITION:list[DecompStep]CRY_DECOMPOSITION:list[DecompStep]CRZ_DECOMPOSITION:list[DecompStep]CY_DECOMPOSITION:list[DecompStep]
Classes¶
DecompStep [source]¶
class DecompStepA single step in a decomposition recipe.
Constructor¶
def __init__(self, gate: PrimitiveGate, target: str, angle: str | None = None) -> NoneAttributes¶
angle: str | Nonegate: PrimitiveGatetarget: str
PrimitiveGate [source]¶
class PrimitiveGate(Enum)Gate primitives used in decomposition recipes.
Attributes¶
CNOTRYRZSSDG
qamomile.circuit.transpiler.emit_context¶
Typed bindings container for the emit pipeline.
Background — what was wrong with the bare dict[str, Any]:
The pre-EmitContext design used a single bindings: dict[str, Any]
threaded through every emit-pipeline function. That dict served at least
seven distinct semantic purposes simultaneously:
User-supplied kernel parameters (keyed by parameter name).
Loop iteration variables (keyed by loop_var name; pushed on entry, restored on exit).
Emit-time-computed intermediates —
BinOp/CompOp/CondOp/NotOpresults (keyed by Value UUID after Fix B; originally also keyed by Value name, which collided across tmps).Phi-output aliases (keyed by phi-output UUID; written by
register_classical_phi_aliases).Backend runtime expressions (e.g.
qiskit.circuit.classical.expr.Exprfor compound runtime if-conditions).Array data (keyed by array name; bound iterables passed by user).
Dict data (keyed by dict name; bound iterables passed by user).
Pauli observables (keyed by observable name).
This overloading was the structural cause of every name-collision bug
class seen in this codebase: "bit_tmp" chained predicates,
j_phi_4 phi aliases, the inline-pass DictValue drop, and the
type-blind bool(...) coercion in resolve_operand. Each was
patched locally; the structural overloading remained.
What EmitContext does (root-cause fix):
EmitContext is a dict subclass — flat [key] access still
works for migration compatibility. On top of dict semantics, every
binding kind has a separate, semantically-typed slot with the
appropriate identity key:
_params— user parameters, keyed by name (user-facing)._loop_vars— loop iteration variables, keyed by Value UUID._values— emit-time intermediates, keyed by UUID._runtime_exprs— backend Expr objects, keyed by UUID._array_data— array bindings, keyed byArrayValue.uuid._dict_data— dict bindings, keyed byDictValue.uuid._observables— Pauli observables, keyed byValue.uuid.
The key invariant: after the migration, the dict-baseclass writes
disappear. All writers go through typed setters (push_loop_var,
set_array_data, etc.); all readers go through typed getters.
EmitContext retains dict-protocol read-compat for legacy callers
during migration, but new code should never touch ctx[key].
Identity policy:
UUID: everything compiler-internal (loop vars, intermediates, runtime exprs, array/dict/observable bindings).
Name: only at the user-API boundary (parameter names supplied by
transpile(bindings={...})).
This eliminates the name-collision bug class entirely: empty/duplicate names cannot resolve to anything because lookups never go through the name path.
Overview¶
| Class | Description |
|---|---|
EmitContext | Bindings container with semantic slots, dict-compatible. |
Classes¶
EmitContext [source]¶
class EmitContext(dict)Bindings container with semantic slots, dict-compatible.
All emit-pipeline functions that take bindings: dict[str, Any]
accept an EmitContext unchanged because it inherits from dict.
Use the typed methods (bind_param, set_value, etc.) when
writing new code so the slot tracking stays accurate; existing
ctx[key] = value writes still work but bypass the slots.
Slots:
_params: User-supplied kernel parameters, keyed by parameter
name. Stable across the run. Name-keyed because the user
supplies parameters by name at the public API boundary.
_loop_vars: Currently-bound loop iteration variables, keyed by
ForOperation.loop_var_value.uuid /
ForItemsOperation.value_var_value.uuid etc. Pushed on
loop entry, restored on exit. UUID-keyed so identical
user-chosen variable names in nested or sibling loops never
collide.
_values: Emit-time-computed intermediate values (BinOp
results, CompOp/CondOp/NotOp results, phi
aliases), keyed by Value UUID.
_runtime_exprs: Backend runtime-expression objects (e.g. Qiskit
expr.Expr for compound classical conditions), keyed by
Value UUID.
_array_data: Bound array data (e.g. Vector[Float] parameter
values), keyed by ArrayValue.uuid.
_dict_data: Bound dict data (e.g. Dict[Tuple[UInt, UInt], Float]
ising coefficients), keyed by DictValue.uuid.
_observables: Bound Pauli observables (used by PauliEvolveOp
and gate counting), keyed by observable Value UUID.
Example:
>>> ctx = EmitContext.from_user_bindings({"theta": 0.5, "n": 3})
>>> ctx["theta"] # dict-style read still works
0.5
>>> ctx.bind_param("phi", 1.5)
>>> "phi" in ctx and ctx["phi"] == 1.5
True
>>> ctx.set_value(some_uuid, 42)
>>> ctx[some_uuid] == 42 and some_uuid in ctx._values
TrueConstructor¶
def __init__(self, *args: Any = (), **kwargs: Any = {}) -> NoneMethods¶
bind_param¶
def bind_param(self, name: str, value: Any) -> NoneRegister a kernel parameter binding (by name).
bind_params¶
def bind_params(self, params: dict[str, Any]) -> NoneRegister multiple kernel parameter bindings.
copy¶
def copy(self) -> 'EmitContext'Return a shallow copy preserving all semantic slots.
The dict baseclass copy() returns a plain dict, dropping
the slot-tracking metadata. Loop unrollers call bindings.copy()
to make a per-iteration child scope; without this override the
child would lose the params/loop_vars/values/runtime_exprs
partitioning and become a flat dict, defeating the whole point of
EmitContext. We override to return an EmitContext with
slot dicts independently copied so child mutations (e.g. pushing
a new loop var) don’t bleed back to the parent.
describe¶
def describe(self) -> strReturn a multi-line summary suitable for debug printing.
from_user_bindings¶
@classmethod
def from_user_bindings(cls, user_bindings: dict[str, Any] | None) -> 'EmitContext'Build an EmitContext seeded with user-supplied parameters.
Parameters:
| Name | Type | Description |
|---|---|---|
user_bindings | dict[str, Any] | None | The dict passed by the user to transpile(); None is treated as empty. |
Returns:
'EmitContext' — A fresh EmitContext with all entries registered as parameters.
get_array_data¶
def get_array_data(self, uuid: str) -> AnyGet array data by ArrayValue.uuid, or None.
get_dict_data¶
def get_dict_data(self, uuid: str) -> AnyGet dict data by DictValue.uuid, or None.
get_loop_var¶
def get_loop_var(self, uuid: str) -> AnyGet a loop variable binding by Value UUID, or None if absent.
get_observable¶
def get_observable(self, uuid: str) -> AnyGet a Pauli observable by Value UUID, or None.
get_runtime_expr¶
def get_runtime_expr(self, uuid: str) -> AnyGet a backend runtime expression by Value UUID, or None.
iter_values¶
def iter_values(self) -> Iterator[tuple[str, Any]]Iterate over UUID-keyed emit-time intermediates only.
push_loop_var¶
def push_loop_var(self, uuid: str, value: Any, display_name: str | None = None) -> NoneBind a loop iteration variable, keyed by Value UUID.
Parameters:
| Name | Type | Description |
|---|---|---|
uuid | str | loop_var_value.uuid (or per-key/value UUID for ForItemsOperation). Different loops with identical user-chosen names (e.g. nested for i) get distinct UUIDs and therefore never collide here. |
value | Any | The bound iteration value (int / Hamiltonian item / etc.). |
display_name | str | None | Reserved for future debug-only use. Currently unused — loop variables are looked up exclusively by UUID, so the display name is never written into the bindings dict. Defaults to None. |
Note: this adds a binding to the existing context. Loop unrollers typically copy the parent context first so the binding is local to one iteration; this method does not copy.
set_array_data¶
def set_array_data(self, uuid: str, data: Any, display_name: str | None = None) -> NoneBind array data by ArrayValue.uuid.
Parameters:
| Name | Type | Description |
|---|---|---|
uuid | str | The array Value’s UUID. |
data | Any | The bound iterable / sequence / Vector handle. |
display_name | str | None | Migration shim — also writes the flat-dict view under the array’s user-facing name. Remove once Phase 3 of #7 lands. |
set_dict_data¶
def set_dict_data(self, uuid: str, data: Any, display_name: str | None = None) -> NoneBind dict data by DictValue.uuid.
Parameters:
| Name | Type | Description |
|---|---|---|
uuid | str | The dict Value’s UUID. |
data | Any | The bound dict / iterable. |
display_name | str | None | Migration shim — see set_array_data. |
set_observable¶
def set_observable(self, uuid: str, observable: Any, display_name: str | None = None) -> NoneBind a Pauli observable by Value UUID.
Parameters:
| Name | Type | Description |
|---|---|---|
uuid | str | The observable Value’s UUID. |
observable | Any | A qm_o.Hamiltonian (or backend-equivalent). |
display_name | str | None | Migration shim — see set_array_data. |
set_runtime_expr¶
def set_runtime_expr(self, uuid: str, expr: Any) -> NoneBind a backend runtime expression by Value UUID.
Backends (e.g. Qiskit) call this when they construct a
runtime-evaluable expression for a classical predicate that
wasn’t compile-time-foldable. _emit_if / _emit_while
consult the runtime-expr slot first when resolving conditions.
set_value¶
def set_value(self, uuid: str, value: Any) -> NoneBind an emit-time-computed intermediate by Value UUID.
Use for BinOp / CompOp / CondOp / NotOp results,
phi aliases, and other UUID-identified intermediates.
qamomile.circuit.transpiler.errors¶
Compilation error classes for Qamomile transpiler.
Overview¶
| Class | Description |
|---|---|
AffineTypeError | Base class for affine type violations. |
DependencyError | Error when quantum operation depends on non-parameter classical value. |
EmitError | Error during backend code emission. |
EntrypointValidationError | Error when a top-level transpilation entrypoint has unsupported I/O. |
ExecutionError | Error during program execution. |
FrontendTransformError | Error during frontend AST-to-builder lowering. |
InliningError | Error during inline pass (inlining CallBlockOperations). |
OperandResolutionInfo | Detailed information about a single operand that failed to resolve. |
QamomileCompileError | Base class for all Qamomile compilation errors. |
QubitAliasError | Same qubit used multiple times in one operation. |
QubitConsumedError | Qubit handle used after being consumed by a previous operation. |
QubitIndexResolutionError | Error when qubit indices cannot be resolved during emission. |
QubitRebindError | Quantum variable reassigned from a different quantum source. |
ResolutionFailureReason | Categorizes why qubit index resolution failed. |
SeparationError | Error during quantum/classical separation. |
UnreturnedBorrowError | Borrowed array element not returned before array use. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Classes¶
AffineTypeError [source]¶
class AffineTypeError(QamomileCompileError)Base class for affine type violations.
Affine types enforce that quantum resources (qubits) are used at most once. This prevents common errors such as reusing a consumed qubit or aliasing.
Constructor¶
def __init__(
self,
message: str,
handle_name: str | None = None,
operation_name: str | None = None,
first_use_location: str | None = None,
)Attributes¶
first_use_locationhandle_nameoperation_name
DependencyError [source]¶
class DependencyError(QamomileCompileError)Error when quantum operation depends on non-parameter classical value.
This error indicates that the program requires JIT compilation which is not yet supported.
Constructor¶
def __init__(
self,
message: str,
quantum_op: str | None = None,
classical_value: str | None = None,
)Attributes¶
classical_valuequantum_op
EmitError [source]¶
class EmitError(QamomileCompileError)Error during backend code emission.
Constructor¶
def __init__(self, message: str, operation: str | None = None)Attributes¶
operation
EntrypointValidationError [source]¶
class EntrypointValidationError(ValidationError)Error when a top-level transpilation entrypoint has unsupported I/O.
ExecutionError [source]¶
class ExecutionError(QamomileCompileError)Error during program execution.
FrontendTransformError [source]¶
class FrontendTransformError(QamomileCompileError)Error during frontend AST-to-builder lowering.
InliningError [source]¶
class InliningError(QamomileCompileError)Error during inline pass (inlining CallBlockOperations).
OperandResolutionInfo [source]¶
class OperandResolutionInfoDetailed information about a single operand that failed to resolve.
Constructor¶
def __init__(
self,
operand_name: str,
operand_uuid: str,
is_array_element: bool,
parent_array_name: str | None,
element_indices_names: list[str],
failure_reason: ResolutionFailureReason,
failure_details: str,
) -> NoneAttributes¶
element_indices_names: list[str]failure_details: strfailure_reason: ResolutionFailureReasonis_array_element: booloperand_name: stroperand_uuid: strparent_array_name: str | None
QamomileCompileError [source]¶
class QamomileCompileError(Exception)Base class for all Qamomile compilation errors.
QubitAliasError [source]¶
class QubitAliasError(AffineTypeError)Same qubit used multiple times in one operation.
Operations like cx() require distinct qubits for control and target. Using the same qubit in both positions is physically impossible and indicates a programming error.
Example of incorrect code:
q1, q2 = qm.cx(q, q) # ERROR: same qubit as control and target
Correct code:
q1, q2 = qm.cx(control, target) # Use distinct qubits
QubitConsumedError [source]¶
class QubitConsumedError(AffineTypeError)Qubit handle used after being consumed by a previous operation.
Each qubit handle can only be used once. After a gate operation, you must reassign the result to use the new handle.
Example of incorrect code:
q1 = qm.h(q) q2 = qm.x(q) # ERROR: q was already consumed by h()
Correct code:
q = qm.h(q) # Reassign to capture new handle q = qm.x(q) # Use the reassigned handle
QubitIndexResolutionError [source]¶
class QubitIndexResolutionError(EmitError)Error when qubit indices cannot be resolved during emission.
This error provides detailed diagnostic information about why qubit index resolution failed and suggests remediation steps.
Constructor¶
def __init__(
self,
gate_type: str,
operand_infos: list[OperandResolutionInfo],
available_bindings_keys: list[str],
available_qubit_map_keys: list[str],
)Attributes¶
available_bindings_keysavailable_qubit_map_keysgate_typeoperand_infos
QubitRebindError [source]¶
class QubitRebindError(AffineTypeError)Quantum variable reassigned from a different quantum source.
When a quantum variable is reassigned, the RHS must consume the same variable (self-update pattern). Reassigning from a different quantum variable silently discards the original quantum state.
Example of incorrect code:
a = qm.h(b) # ERROR: ‘a’ was quantum, now overwritten from ‘b’ a = b # ERROR: ‘a’ was quantum, now overwritten from ‘b’
Correct patterns:
a = qm.h(a) # Self-update (OK) new = qm.h(b) # New binding (OK, ‘new’ wasn’t quantum before)
ResolutionFailureReason [source]¶
class ResolutionFailureReason(Enum)Categorizes why qubit index resolution failed.
Attributes¶
ARRAY_ELEMENT_NOT_IN_QUBIT_MAPDIRECT_UUID_NOT_FOUNDINDEX_NOT_NUMERICNESTED_ARRAY_RESOLUTION_FAILEDSYMBOLIC_INDEX_NOT_BOUNDUNKNOWN
SeparationError [source]¶
class SeparationError(QamomileCompileError)Error during quantum/classical separation.
UnreturnedBorrowError [source]¶
class UnreturnedBorrowError(AffineTypeError)Borrowed array element not returned before array use.
When you borrow an element from a qubit array, you must return it (write it back) before using other elements or the array itself.
Example of incorrect code:
q0 = qubits[0] q0 = qm.h(q0) q1 = qubits[1] # ERROR: q0 not returned yet
Correct code:
q0 = qubits[0] q0 = qm.h(q0) qubits[0] = q0 # Return the borrowed element q1 = qubits[1] # Now safe to borrow another
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
qamomile.circuit.transpiler.executable¶
Executable program structure for compiled quantum-classical programs.
Overview¶
| Class | Description |
|---|---|
ClassicalExecutor | Executes classical segments in Python. |
CompiledClassicalSegment | A classical segment ready for Python execution. |
CompiledExpvalSegment | A compiled expectation value segment with concrete Hamiltonian. |
CompiledQuantumSegment | A quantum segment with emitted backend circuit. |
ExecutableProgram | A fully compiled program ready for execution. |
ExecutionContext | Holds global state during program execution. |
ExecutionError | Error during program execution. |
ExpvalJob | Job for expectation value computation. |
ParameterInfo | Information about a single unbound parameter in the circuit. |
ParameterMetadata | Metadata for all parameters in a compiled segment. |
ProgramPlan | Execution plan for a hybrid quantum/classical program. |
QuantumExecutor | Abstract base class for quantum backend execution. |
RunJob | Job for single execution. |
SampleJob | Job for sampling execution (multiple shots). |
Classes¶
ClassicalExecutor [source]¶
class ClassicalExecutorExecutes classical segments in Python.
Methods¶
execute¶
def execute(self, segment: ClassicalSegment, context: ExecutionContext) -> dict[str, Any]Execute classical operations and return outputs.
Interprets the operations list directly using Python.
CompiledClassicalSegment [source]¶
class CompiledClassicalSegmentA classical segment ready for Python execution.
Constructor¶
def __init__(self, segment: ClassicalSegment) -> NoneAttributes¶
segment: ClassicalSegment
CompiledExpvalSegment [source]¶
class CompiledExpvalSegmentA compiled expectation value segment with concrete Hamiltonian.
This segment computes <psi|H|psi> where psi is the quantum state from a quantum circuit and H is a qamomile.observable.Hamiltonian.
Constructor¶
def __init__(
self,
segment: ExpvalSegment,
hamiltonian: 'qm_o.Hamiltonian',
quantum_segment_index: int = 0,
result_ref: str = '',
qubit_map: dict[int, int] = dict(),
) -> NoneAttributes¶
hamiltonian: ‘qm_o.Hamiltonian’quantum_segment_index: intqubit_map: dict[int, int]result_ref: strsegment: ExpvalSegment
CompiledQuantumSegment [source]¶
class CompiledQuantumSegment(Generic[T])A quantum segment with emitted backend circuit.
Constructor¶
def __init__(
self,
segment: QuantumSegment,
circuit: T,
qubit_map: QubitMap = dict(),
clbit_map: ClbitMap = dict(),
measurement_qubit_map: dict[int, int] = dict(),
parameter_metadata: ParameterMetadata = ParameterMetadata(),
) -> NoneAttributes¶
circuit: Tclbit_map: ClbitMapmeasurement_qubit_map: dict[int, int]parameter_metadata: ParameterMetadataqubit_map: QubitMapsegment: QuantumSegment
ExecutableProgram [source]¶
class ExecutableProgram(Generic[T])A fully compiled program ready for execution.
Contains compiled quantum, classical, and expectation-value segments.
Use sample() for multi-shot execution or run() for single
execution.
Example:
executable = transpiler.compile(kernel)
# Sample: multiple shots, returns counts
job = executable.sample(executor, shots=1000)
result = job.result() # SampleResult with counts
# Run: single shot, returns typed result
job = executable.run(executor)
result = job.result() # Returns kernel's return typeConstructor¶
def __init__(
self,
plan: ProgramPlan | None = None,
compiled_quantum: list[CompiledQuantumSegment[T]] = list(),
compiled_classical: list[CompiledClassicalSegment] = list(),
compiled_expval: list[CompiledExpvalSegment] = list(),
output_refs: list[str] = list(),
num_output_bits: int = 0,
) -> NoneAttributes¶
compiled_classical: list[CompiledClassicalSegment]compiled_expval: list[CompiledExpvalSegment]compiled_quantum: list[CompiledQuantumSegment[T]]has_parameters: bool Check if this program has unbound parameters.num_output_bits: intoutput_refs: list[str]parameter_names: list[str] Get list of parameter names that need binding.plan: ProgramPlan | Nonequantum_circuit: T Get the single quantum circuit.
Methods¶
get_circuits¶
def get_circuits(self) -> list[T]Get all quantum circuits in execution order.
get_first_circuit¶
def get_first_circuit(self) -> T | NoneGet the first quantum circuit, or None if no quantum segments.
run¶
def run(
self,
executor: QuantumExecutor[T],
bindings: dict[str, Any] | None = None,
) -> RunJob[Any] | ExpvalJobExecute once and return single result.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
RunJob[Any] | ExpvalJob — RunJob that resolves to the kernel’s return type, or
RunJob[Any] | ExpvalJob — ExpvalJob if the program contains expectation value computation.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.run(executor, bindings={"gamma": [0.5]})
result = job.result()
print(result) # 0.25 (for QFixed) or (0, 1) (for bits)sample¶
def sample(
self,
executor: QuantumExecutor[T],
shots: int = 1024,
bindings: dict[str, Any] | None = None,
) -> SampleJob[Any]Execute with multiple shots and return counts.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
shots | int | Number of shots to run. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
SampleJob[Any] — SampleJob that resolves to SampleResult with results.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.sample(executor, shots=1000, bindings={"gamma": [0.5]})
result = job.result()
print(result.results) # [(0.25, 500), (0.75, 500)]ExecutionContext [source]¶
class ExecutionContextHolds global state during program execution.
Constructor¶
def __init__(self, initial_bindings: dict[str, Any] | None = None)Methods¶
copy¶
def copy(self) -> 'ExecutionContext'Clone the execution context.
get¶
def get(self, key: str) -> Anyget_many¶
def get_many(self, keys: list[str]) -> dict[str, Any]has¶
def has(self, key: str) -> boolset¶
def set(self, key: str, value: Any) -> Noneupdate¶
def update(self, values: dict[str, Any]) -> NoneExecutionError [source]¶
class ExecutionError(QamomileCompileError)Error during program execution.
ExpvalJob [source]¶
class ExpvalJob(Job[float])Job for expectation value computation.
Returns a single float representing <psi|H|psi>.
Constructor¶
def __init__(self, exp_val: float)Initialize expval job.
Parameters:
| Name | Type | Description |
|---|---|---|
exp_val | float | The computed expectation value |
Methods¶
result¶
def result(self) -> floatReturn the expectation value.
status¶
def status(self) -> JobStatusReturn job status.
ParameterInfo [source]¶
class ParameterInfoInformation about a single unbound parameter in the circuit.
Constructor¶
def __init__(
self,
name: str,
array_name: str,
index: int | None,
backend_param: Any,
source_ref: str | None = None,
) -> NoneAttributes¶
array_name: strbackend_param: Anyindex: int | Nonename: strsource_ref: str | None
ParameterMetadata [source]¶
class ParameterMetadataMetadata for all parameters in a compiled segment.
Tracks parameter information for runtime binding.
Constructor¶
def __init__(self, parameters: list[ParameterInfo] = list()) -> NoneAttributes¶
parameters: list[ParameterInfo]
Methods¶
get_array_names¶
def get_array_names(self) -> set[str]Get unique array/scalar parameter names.
get_ordered_params¶
def get_ordered_params(self) -> list[Any]Get backend parameter objects in definition order.
Useful for backends that require positional parameter binding (e.g., QURI Parts).
Returns:
list[Any] — List of backend_param objects in the order they were defined.
Example:
# For QURI Parts that uses positional binding:
param_values = [bindings[p.name] for p in metadata.parameters]
bound_circuit = circuit.bind_parameters(param_values)get_param_by_name¶
def get_param_by_name(self, name: str) -> ParameterInfo | NoneGet parameter info by full name.
to_binding_dict¶
def to_binding_dict(self, bindings: dict[str, Any]) -> dict[Any, Any]Convert indexed bindings to backend parameter bindings.
Transforms user-provided bindings (with indexed names like “gammas[0]”) into a dictionary mapping backend parameter objects to values. Useful for backends that use dict-based parameter binding (e.g., Qiskit).
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | Dictionary mapping parameter names to values. e.g., {“gammas[0]”: 0.1, “gammas[1]”: 0.2, “theta”: 0.5} |
Returns:
dict[Any, Any] — Dictionary mapping backend_param objects to values.
Example:
# For Qiskit that uses dict-based binding:
qiskit_bindings = metadata.to_binding_dict(bindings)
bound_circuit = circuit.assign_parameters(qiskit_bindings)ProgramPlan [source]¶
class ProgramPlanExecution plan for a hybrid quantum/classical program.
Structure:
[Optional] Classical preprocessing (parameter computation, etc.)
Single quantum segment (REQUIRED)
[Optional] Expval segment OR classical postprocessing
This plan enforces Qamomile’s current execution model: all quantum operations must be in a single quantum circuit.
Constructor¶
def __init__(
self,
steps: list[ProgramStep] = list(),
abi: ProgramABI = ProgramABI(),
boundaries: list[HybridBoundary] = list(),
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
abi: ProgramABIboundaries: list[HybridBoundary]parameters: dict[str, Value]steps: list[ProgramStep]
QuantumExecutor [source]¶
class QuantumExecutor(ABC, Generic[T])Abstract base class for quantum backend execution.
To implement a custom executor:
execute() [Required] Execute circuit and return bitstring counts as dict[str, int]. Keys are bitstrings in big-endian format (e.g., “011” means q2=0, q1=1, q0=1).
bind_parameters() [Optional] Bind parameter values to parametric circuits. Override if your executor supports parametric circuits (e.g., QAOA variational circuits). Use ParameterMetadata.to_binding_dict() for easy conversion.
estimate() [Optional] Compute expectation values <psi|H|psi>. Override if your executor supports estimation primitives (e.g., Qiskit Estimator, QURI Parts).
Example (Minimal): class MyExecutor(QuantumExecutor[QuantumCircuit]): def init(self): from qiskit_aer import AerSimulator self.backend = AerSimulator()
def execute(self, circuit, shots):
from qiskit import transpile
if circuit.num_clbits == 0:
circuit = circuit.copy()
circuit.measure_all()
transpiled = transpile(circuit, self.backend)
return self.backend.run(transpiled, shots=shots).result().get_counts()Example (With Parameter Binding): def bind_parameters(self, circuit, bindings, metadata): # metadata.to_binding_dict() converts indexed names to backend params return circuit.assign_parameters(metadata.to_binding_dict(bindings))
Methods¶
bind_parameters¶
def bind_parameters(
self,
circuit: T,
bindings: dict[str, Any],
parameter_metadata: ParameterMetadata,
) -> TBind parameter values to the circuit.
Default implementation returns the circuit unchanged. Override for backends that support parametric circuits.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The parameterized circuit |
bindings | dict[str, Any] | Dict mapping parameter names (indexed format) to values. e.g., {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
parameter_metadata | ParameterMetadata | Metadata about circuit parameters |
Returns:
T — New circuit with parameters bound
estimate¶
def estimate(
self,
circuit: T,
hamiltonian: 'qm_o.Hamiltonian',
params: Sequence[float] | None = None,
) -> floatEstimate the expectation value of a Hamiltonian.
This method computes <psi|H|psi> where psi is the quantum state prepared by the circuit and H is the Hamiltonian.
Backends can override this method to provide optimized implementations using their native estimator primitives.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The quantum circuit (state preparation ansatz) |
hamiltonian | 'qm_o.Hamiltonian' | The qamomile.observable.Hamiltonian to measure |
params | Sequence[float] | None | Optional parameter values for parametric circuits |
Returns:
float — The estimated expectation value
Raises:
NotImplementedError— If the executor does not support estimation
execute¶
def execute(self, circuit: T, shots: int) -> dict[str, int]Execute the circuit and return bitstring counts.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The quantum circuit to execute |
shots | int | Number of measurement shots |
Returns:
dict[str, int] — Dictionary mapping bitstrings to counts.
dict[str, int] — {“00”: 512, “11”: 512}
RunJob [source]¶
class RunJob(Job[T], Generic[T])Job for single execution.
Returns a single result value matching the kernel’s return type.
Constructor¶
def __init__(self, raw_counts: dict[str, int], result_converter: Callable[[str], T])Initialize run job.
Parameters:
| Name | Type | Description |
|---|---|---|
raw_counts | dict[str, int] | Bitstring counts from executor (should have single entry) |
result_converter | Callable[[str], T] | Function to convert bitstring to typed result |
Methods¶
result¶
def result(self) -> TReturn the single result.
status¶
def status(self) -> JobStatusReturn job status.
SampleJob [source]¶
class SampleJob(Job[SampleResult[T]], Generic[T])Job for sampling execution (multiple shots).
Returns a SampleResult containing counts for each unique result.
Constructor¶
def __init__(
self,
raw_counts: dict[str, int],
result_converter: Callable[[dict[str, int]], list[tuple[T, int]]],
shots: int,
)Initialize sample job.
Parameters:
| Name | Type | Description |
|---|---|---|
raw_counts | dict[str, int] | Bitstring counts from executor (e.g., {“00”: 512, “11”: 512}) |
result_converter | Callable[[dict[str, int]], list[tuple[T, int]]] | Function to convert raw counts to typed results |
shots | int | Number of shots executed |
Methods¶
result¶
def result(self) -> SampleResult[T]Return the sample result.
status¶
def status(self) -> JobStatusReturn job status.
qamomile.circuit.transpiler.execution_context¶
Execution context for quantum-classical program execution.
Overview¶
| Class | Description |
|---|---|
ExecutionContext | Holds global state during program execution. |
Classes¶
ExecutionContext [source]¶
class ExecutionContextHolds global state during program execution.
Constructor¶
def __init__(self, initial_bindings: dict[str, Any] | None = None)Methods¶
copy¶
def copy(self) -> 'ExecutionContext'Clone the execution context.
get¶
def get(self, key: str) -> Anyget_many¶
def get_many(self, keys: list[str]) -> dict[str, Any]has¶
def has(self, key: str) -> boolset¶
def set(self, key: str, value: Any) -> Noneupdate¶
def update(self, values: dict[str, Any]) -> Noneqamomile.circuit.transpiler.gate_emitter¶
GateEmitter protocol for backend-agnostic gate emission.
This module defines the GateEmitter protocol that backends implement to emit individual quantum gates. The StandardEmitPass uses this protocol to orchestrate circuit generation without backend-specific code.
Overview¶
| Function | Description |
|---|---|
default_combine_symbolic | Default combine_symbolic for backends with arithmetic-capable Parameters. |
| Class | Description |
|---|---|
BinOpKind | |
GateEmitter | Protocol for backend-specific gate emission. |
GateKind | Classification of gates for emission. |
GateSpec | Specification for a gate type. |
MeasurementMode | How a backend handles measurement operations. |
Constants¶
GATE_SPECS:dict[GateKind, GateSpec]
Functions¶
default_combine_symbolic [source]¶
def default_combine_symbolic(kind: 'BinOpKind', lhs: Any, rhs: Any) -> AnyDefault combine_symbolic for backends with arithmetic-capable Parameters.
Performs Python operator dispatch on the operands. Used by
evaluate_binop whenever the active emitter does not define its
own combine_symbolic method — the typical case for Qiskit
(ParameterExpression overloads __add__ etc.) and CUDA-Q
parameters. Backends whose Parameter type lacks Python operators
(e.g. QURI Parts) define their own combine_symbolic on the
emitter class to return a backend-native symbolic representation
instead.
Parameters:
| Name | Type | Description |
|---|---|---|
kind | 'BinOpKind' | The BinOpKind to apply. |
lhs | Any | Left operand (numeric or backend Parameter / expression). |
rhs | Any | Right operand (same shape). |
Returns:
Any — lhs OP rhs for the matching operator. 0.0 / 0 for
Any — division-by-zero in the symbolic path so the caller can finish
Any — emission without aborting on a numerically degenerate case.
Any — None for unrecognised kind values, which the caller
Any — treats as a no-op.
Classes¶
BinOpKind [source]¶
class BinOpKind(enum.Enum)Attributes¶
ADDDIVFLOORDIVMULPOWSUB
GateEmitter [source]¶
class GateEmitter(Protocol[T])Protocol for backend-specific gate emission.
Each backend implements this protocol to emit individual gates to their circuit representation.
Type parameter T is the backend’s circuit type (e.g., QuantumCircuit).
Attributes¶
measurement_mode: MeasurementMode Return the measurement mode for this backend.
Methods¶
append_gate¶
def append_gate(self, circuit: T, gate: Any, qubits: list[int]) -> NoneAppend a gate to the circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The circuit to append to |
gate | Any | The gate to append (from circuit_to_gate) |
qubits | list[int] | Target qubit indices |
circuit_to_gate¶
def circuit_to_gate(self, circuit: T, name: str = 'U') -> AnyConvert a circuit to a reusable gate.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The circuit to convert |
name | str | Label for the gate |
Returns:
Any — Backend-specific gate object, or None if not supported
create_circuit¶
def create_circuit(self, num_qubits: int, num_clbits: int) -> TCreate a new empty circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
num_qubits | int | Number of qubits in the circuit |
num_clbits | int | Number of classical bits in the circuit |
Returns:
T — A new backend-specific circuit object
create_parameter¶
def create_parameter(self, name: str) -> AnyCreate a symbolic parameter for the backend.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Parameter name (e.g., “gammas[0]”) |
Returns:
Any — Backend-specific parameter object
emit_barrier¶
def emit_barrier(self, circuit: T, qubits: list[int]) -> NoneEmit barrier on specified qubits.
emit_ch¶
def emit_ch(self, circuit: T, control: int, target: int) -> NoneEmit controlled-Hadamard gate.
emit_cp¶
def emit_cp(self, circuit: T, control: int, target: int, angle: float | Any) -> NoneEmit controlled-Phase gate.
emit_crx¶
def emit_crx(self, circuit: T, control: int, target: int, angle: float | Any) -> NoneEmit controlled-RX gate.
emit_cry¶
def emit_cry(self, circuit: T, control: int, target: int, angle: float | Any) -> NoneEmit controlled-RY gate.
emit_crz¶
def emit_crz(self, circuit: T, control: int, target: int, angle: float | Any) -> NoneEmit controlled-RZ gate.
emit_cx¶
def emit_cx(self, circuit: T, control: int, target: int) -> NoneEmit CNOT gate.
emit_cy¶
def emit_cy(self, circuit: T, control: int, target: int) -> NoneEmit controlled-Y gate.
emit_cz¶
def emit_cz(self, circuit: T, control: int, target: int) -> NoneEmit CZ gate.
emit_else_start¶
def emit_else_start(self, circuit: T, context: Any) -> NoneStart the else branch.
emit_for_loop_end¶
def emit_for_loop_end(self, circuit: T, context: Any) -> NoneEnd a native for loop context.
emit_for_loop_start¶
def emit_for_loop_start(self, circuit: T, indexset: range) -> AnyStart a native for loop context.
Returns a context manager or loop parameter, depending on backend.
emit_h¶
def emit_h(self, circuit: T, qubit: int) -> NoneEmit Hadamard gate.
emit_if_end¶
def emit_if_end(self, circuit: T, context: Any) -> NoneEnd the if/else block.
emit_if_start¶
def emit_if_start(self, circuit: T, clbit: int, value: int = 1) -> AnyStart a native if context.
Returns context for the if/else block.
emit_measure¶
def emit_measure(self, circuit: T, qubit: int, clbit: int) -> NoneEmit measurement operation.
emit_p¶
def emit_p(self, circuit: T, qubit: int, angle: float | Any) -> NoneEmit Phase gate (P(θ) = diag(1, e^(iθ))).
emit_rx¶
def emit_rx(self, circuit: T, qubit: int, angle: float | Any) -> NoneEmit RX rotation gate.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The circuit to emit to |
qubit | int | Target qubit index |
angle | float | Any | Rotation angle (float or backend parameter) |
emit_ry¶
def emit_ry(self, circuit: T, qubit: int, angle: float | Any) -> NoneEmit RY rotation gate.
emit_rz¶
def emit_rz(self, circuit: T, qubit: int, angle: float | Any) -> NoneEmit RZ rotation gate.
emit_rzz¶
def emit_rzz(self, circuit: T, qubit1: int, qubit2: int, angle: float | Any) -> NoneEmit RZZ gate (exp(-i * θ/2 * Z⊗Z)).
emit_s¶
def emit_s(self, circuit: T, qubit: int) -> NoneEmit S gate (√Z).
emit_sdg¶
def emit_sdg(self, circuit: T, qubit: int) -> NoneEmit S-dagger gate (inverse of S).
emit_swap¶
def emit_swap(self, circuit: T, qubit1: int, qubit2: int) -> NoneEmit SWAP gate.
emit_t¶
def emit_t(self, circuit: T, qubit: int) -> NoneEmit T gate (√S).
emit_tdg¶
def emit_tdg(self, circuit: T, qubit: int) -> NoneEmit T-dagger gate (inverse of T).
emit_toffoli¶
def emit_toffoli(self, circuit: T, control1: int, control2: int, target: int) -> NoneEmit Toffoli (CCX) gate.
emit_while_end¶
def emit_while_end(self, circuit: T, context: Any) -> NoneEnd the while loop context.
emit_while_start¶
def emit_while_start(self, circuit: T, clbit: int, value: int = 1) -> AnyStart a native while loop context.
emit_x¶
def emit_x(self, circuit: T, qubit: int) -> NoneEmit Pauli-X gate.
emit_y¶
def emit_y(self, circuit: T, qubit: int) -> NoneEmit Pauli-Y gate.
emit_z¶
def emit_z(self, circuit: T, qubit: int) -> NoneEmit Pauli-Z gate.
gate_controlled¶
def gate_controlled(self, gate: Any, num_controls: int) -> AnyCreate controlled version of a gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate | Any | The gate to control |
num_controls | int | Number of control qubits |
Returns:
Any — New controlled gate
gate_power¶
def gate_power(self, gate: Any, power: int) -> AnyCreate gate raised to a power (U^n).
Parameters:
| Name | Type | Description |
|---|---|---|
gate | Any | The gate to raise to a power |
power | int | The power to raise to |
Returns:
Any — New gate representing gate^power
supports_for_loop¶
def supports_for_loop(self) -> boolCheck if backend supports native for loops.
supports_if_else¶
def supports_if_else(self) -> boolCheck if backend supports native if/else.
supports_while_loop¶
def supports_while_loop(self) -> boolCheck if backend supports native while loops.
GateKind [source]¶
class GateKind(Enum)Classification of gates for emission.
Attributes¶
CHCPCRXCRYCRZCXCYCZHMEASUREPRXRYRZRZZSSDGSWAPTTDGTOFFOLIXYZ
GateSpec [source]¶
class GateSpecSpecification for a gate type.
Constructor¶
def __init__(
self,
kind: GateKind,
num_qubits: int,
has_angle: bool = False,
num_controls: int = 0,
) -> NoneAttributes¶
has_angle: boolkind: GateKindnum_controls: intnum_qubits: int
MeasurementMode [source]¶
class MeasurementMode(Enum)How a backend handles measurement operations.
Attributes¶
NATIVERUNNABLESTATIC
qamomile.circuit.transpiler.job¶
Job classes for quantum execution results.
Overview¶
| Class | Description |
|---|---|
ExpvalJob | Job for expectation value computation. |
Job | Abstract base class for quantum execution jobs. |
JobStatus | Status of a quantum job. |
RunJob | Job for single execution. |
SampleJob | Job for sampling execution (multiple shots). |
SampleResult | Result of a sample() execution. |
Classes¶
ExpvalJob [source]¶
class ExpvalJob(Job[float])Job for expectation value computation.
Returns a single float representing <psi|H|psi>.
Constructor¶
def __init__(self, exp_val: float)Initialize expval job.
Parameters:
| Name | Type | Description |
|---|---|---|
exp_val | float | The computed expectation value |
Methods¶
result¶
def result(self) -> floatReturn the expectation value.
status¶
def status(self) -> JobStatusReturn job status.
Job [source]¶
class Job(ABC, Generic[T])Abstract base class for quantum execution jobs.
A Job represents a quantum execution that can be awaited for results.
Methods¶
result¶
def result(self) -> TWait for and return the result.
Blocks until the job completes.
Returns:
T — The execution result with the appropriate type.
Raises:
ExecutionError— If the job failed.
status¶
def status(self) -> JobStatusReturn the current job status.
JobStatus [source]¶
class JobStatus(Enum)Status of a quantum job.
Attributes¶
COMPLETEDFAILEDPENDINGRUNNING
RunJob [source]¶
class RunJob(Job[T], Generic[T])Job for single execution.
Returns a single result value matching the kernel’s return type.
Constructor¶
def __init__(self, raw_counts: dict[str, int], result_converter: Callable[[str], T])Initialize run job.
Parameters:
| Name | Type | Description |
|---|---|---|
raw_counts | dict[str, int] | Bitstring counts from executor (should have single entry) |
result_converter | Callable[[str], T] | Function to convert bitstring to typed result |
Methods¶
result¶
def result(self) -> TReturn the single result.
status¶
def status(self) -> JobStatusReturn job status.
SampleJob [source]¶
class SampleJob(Job[SampleResult[T]], Generic[T])Job for sampling execution (multiple shots).
Returns a SampleResult containing counts for each unique result.
Constructor¶
def __init__(
self,
raw_counts: dict[str, int],
result_converter: Callable[[dict[str, int]], list[tuple[T, int]]],
shots: int,
)Initialize sample job.
Parameters:
| Name | Type | Description |
|---|---|---|
raw_counts | dict[str, int] | Bitstring counts from executor (e.g., {“00”: 512, “11”: 512}) |
result_converter | Callable[[dict[str, int]], list[tuple[T, int]]] | Function to convert raw counts to typed results |
shots | int | Number of shots executed |
Methods¶
result¶
def result(self) -> SampleResult[T]Return the sample result.
status¶
def status(self) -> JobStatusReturn job status.
SampleResult [source]¶
class SampleResult(Generic[T])Result of a sample() execution.
Contains results as a list of (value, count) tuples.
Example:
result.results # [(0.25, 500), (0.75, 500)]Constructor¶
def __init__(self, results: list[tuple[T, int]], shots: int) -> NoneAttributes¶
results: list[tuple[T, int]] List of (value, count) tuples.shots: int Total number of shots executed.
Methods¶
most_common¶
def most_common(self, n: int = 1) -> list[tuple[T, int]]Return the n most common results.
Parameters:
| Name | Type | Description |
|---|---|---|
n | int | Number of results to return. |
Returns:
list[tuple[T, int]] — List of (result, count) tuples sorted by count descending.
probabilities¶
def probabilities(self) -> list[tuple[T, float]]Return probability distribution over results.
Returns:
list[tuple[T, float]] — List of (value, probability) tuples.
qamomile.circuit.transpiler.parameter_binding¶
Parameter binding structures for compiled quantum circuits.
Overview¶
| Class | Description |
|---|---|
ParameterInfo | Information about a single unbound parameter in the circuit. |
ParameterMetadata | Metadata for all parameters in a compiled segment. |
Classes¶
ParameterInfo [source]¶
class ParameterInfoInformation about a single unbound parameter in the circuit.
Constructor¶
def __init__(
self,
name: str,
array_name: str,
index: int | None,
backend_param: Any,
source_ref: str | None = None,
) -> NoneAttributes¶
array_name: strbackend_param: Anyindex: int | Nonename: strsource_ref: str | None
ParameterMetadata [source]¶
class ParameterMetadataMetadata for all parameters in a compiled segment.
Tracks parameter information for runtime binding.
Constructor¶
def __init__(self, parameters: list[ParameterInfo] = list()) -> NoneAttributes¶
parameters: list[ParameterInfo]
Methods¶
get_array_names¶
def get_array_names(self) -> set[str]Get unique array/scalar parameter names.
get_ordered_params¶
def get_ordered_params(self) -> list[Any]Get backend parameter objects in definition order.
Useful for backends that require positional parameter binding (e.g., QURI Parts).
Returns:
list[Any] — List of backend_param objects in the order they were defined.
Example:
# For QURI Parts that uses positional binding:
param_values = [bindings[p.name] for p in metadata.parameters]
bound_circuit = circuit.bind_parameters(param_values)get_param_by_name¶
def get_param_by_name(self, name: str) -> ParameterInfo | NoneGet parameter info by full name.
to_binding_dict¶
def to_binding_dict(self, bindings: dict[str, Any]) -> dict[Any, Any]Convert indexed bindings to backend parameter bindings.
Transforms user-provided bindings (with indexed names like “gammas[0]”) into a dictionary mapping backend parameter objects to values. Useful for backends that use dict-based parameter binding (e.g., Qiskit).
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | Dictionary mapping parameter names to values. e.g., {“gammas[0]”: 0.1, “gammas[1]”: 0.2, “theta”: 0.5} |
Returns:
dict[Any, Any] — Dictionary mapping backend_param objects to values.
Example:
# For Qiskit that uses dict-based binding:
qiskit_bindings = metadata.to_binding_dict(bindings)
bound_circuit = circuit.assign_parameters(qiskit_bindings)qamomile.circuit.transpiler.passes¶
Base classes for compiler passes.
Overview¶
| Class | Description |
|---|---|
AffineTypeError | Base class for affine type violations. |
AffineValidationPass | Validate affine type semantics at IR level. |
CompileTimeIfLoweringPass | Lowers compile-time resolvable IfOperations before separation. |
ConstantFoldingPass | Evaluates constant expressions at compile time. |
ControlFlowVisitor | Base class for visiting operations with control flow handling. |
DependencyError | Error when quantum operation depends on non-parameter classical value. |
OperationCollector | Collects operations matching a predicate. |
OperationTransformer | Base class for transforming operations with control flow handling. |
Pass | Base class for all compiler passes. |
QamomileCompileError | Base class for all Qamomile compilation errors. |
UUIDRemapper | Clones values and operations with fresh UUIDs and logical_ids. |
ValidateWhileContractPass | Validates that all WhileOperation conditions are measurement-backed. |
ValidationError | Error during validation (e.g., non-classical I/O). |
ValueCollector | Collects Value UUIDs from operation operands and results. |
ValueSubstitutor | Substitutes values in operations using a mapping. |
Classes¶
AffineTypeError [source]¶
class AffineTypeError(QamomileCompileError)Base class for affine type violations.
Affine types enforce that quantum resources (qubits) are used at most once. This prevents common errors such as reusing a consumed qubit or aliasing.
Constructor¶
def __init__(
self,
message: str,
handle_name: str | None = None,
operation_name: str | None = None,
first_use_location: str | None = None,
)Attributes¶
first_use_locationhandle_nameoperation_name
AffineValidationPass [source]¶
class AffineValidationPass(Pass[Block, Block])Validate affine type semantics at IR level.
This pass serves as a safety net to catch affine type violations that may have bypassed the frontend checks. It verifies:
Each quantum value is used (consumed) at most once
Quantum values are not silently discarded
Input: Block (any kind) Output: Same Block (unchanged, validation only)
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockValidate affine type semantics in the block.
Raises:
ValidationError— If the block kind is not AFFINE.AffineTypeError— If a quantum value is consumed multiple times.
CompileTimeIfLoweringPass [source]¶
class CompileTimeIfLoweringPass(Pass[Block, Block])Lowers compile-time resolvable IfOperations before separation.
After constant folding, some IfOperation conditions are statically
known but remain as control-flow nodes. SegmentationPass treats them
as segment boundaries, causing MultipleQuantumSegmentsError for
classical-only compile-time if after quantum init.
This pass:
Evaluates conditions including expression-derived ones (
CompOp,CondOp,NotOpchains).Replaces resolved
IfOperations with selected-branch operations.Substitutes phi output UUIDs with selected-branch values in all subsequent operations and block outputs.
Constructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockRun the compile-time if lowering pass.
ConstantFoldingPass [source]¶
class ConstantFoldingPass(Pass[Block, Block])Evaluates constant expressions at compile time.
This pass folds BinOp operations when all operands are constants or bound parameters, eliminating unnecessary classical operations that would otherwise split quantum segments.
Example:
Before (with bindings={"phase": 0.5}):
BinOp(phase * 2) -> classical segment split
After:
Constant 1.0 -> no segment splitConstructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockRun constant folding on the block.
ControlFlowVisitor [source]¶
class ControlFlowVisitor(ABC)Base class for visiting operations with control flow handling.
Subclasses override visit_operation to define per-operation behavior.
Control flow recursion is handled automatically by the base class.
Example:
class MeasurementCounter(ControlFlowVisitor):
def __init__(self):
self.count = 0
def visit_operation(self, op: Operation) -> None:
if isinstance(op, MeasureOperation):
self.count += 1Methods¶
visit_operation¶
def visit_operation(self, op: Operation) -> NoneProcess a single operation. Override in subclasses.
visit_operations¶
def visit_operations(self, operations: list[Operation]) -> NoneVisit all operations including nested control flow.
DependencyError [source]¶
class DependencyError(QamomileCompileError)Error when quantum operation depends on non-parameter classical value.
This error indicates that the program requires JIT compilation which is not yet supported.
Constructor¶
def __init__(
self,
message: str,
quantum_op: str | None = None,
classical_value: str | None = None,
)Attributes¶
classical_valuequantum_op
OperationCollector [source]¶
class OperationCollector(ControlFlowVisitor)Collects operations matching a predicate.
Example:
collector = OperationCollector(lambda op: isinstance(op, MeasureOperation))
collector.visit_operations(block.operations)
measurements = collector.collectedConstructor¶
def __init__(self, predicate: Callable[[Operation], bool])Attributes¶
collected: list[Operation]
Methods¶
visit_operation¶
def visit_operation(self, op: Operation) -> NoneOperationTransformer [source]¶
class OperationTransformer(ABC)Base class for transforming operations with control flow handling.
Subclasses override transform_operation to define per-operation transformation.
Control flow recursion and rebuilding is handled automatically.
Example:
class OperationRenamer(OperationTransformer):
def transform_operation(self, op: Operation) -> Operation:
# Return modified operation
return dataclasses.replace(op, ...)Methods¶
transform_operation¶
def transform_operation(self, op: Operation) -> Operation | NoneTransform a single operation. Return None to remove it.
transform_operations¶
def transform_operations(self, operations: list[Operation]) -> list[Operation]Transform all operations including nested control flow.
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
QamomileCompileError [source]¶
class QamomileCompileError(Exception)Base class for all Qamomile compilation errors.
UUIDRemapper [source]¶
class UUIDRemapperClones values and operations with fresh UUIDs and logical_ids.
Used during inlining to create unique identities for values when a block is called multiple times.
Constructor¶
def __init__(self)Attributes¶
logical_id_remap: dict[str, str] Get the mapping from old logical_ids to new logical_ids.uuid_remap: dict[str, str] Get the mapping from old UUIDs to new UUIDs.
Methods¶
clone_operation¶
def clone_operation(self, op: Operation) -> OperationClone an operation with fresh UUIDs for all values.
Cloning goes through the Operation.all_input_values() /
Operation.replace_values() protocol so every Value-typed
field — including subclass extras (ControlledUOperation.power,
ForOperation.loop_var_value, ForItemsOperation.key_var_values
etc.) — is cloned consistently with the body references that
point to it. Without this, a subclass field could keep an old
UUID while body operands referencing the same logical Value got
fresh UUIDs, breaking identity-by-UUID lookups at emit time.
clone_operations¶
def clone_operations(self, operations: list[Operation]) -> list[Operation]Clone a list of operations with fresh UUIDs.
clone_value¶
def clone_value(self, value: ValueBase) -> ValueBaseClone any value type with a fresh UUID and logical_id.
Handles Value, ArrayValue, TupleValue, and DictValue through the unified ValueBase protocol.
ValidateWhileContractPass [source]¶
class ValidateWhileContractPass(Pass[Block, Block])Validates that all WhileOperation conditions are measurement-backed.
Builds a producer map (result UUID → producing Operation instance) and checks every WhileOperation operand against it. A valid condition must be:
A
ValuewithBitTypeMeasurement-backed: produced by
MeasureOperationdirectly, or byIfOperation/PhiOpwhere every reachable leaf source is itself measurement-backed.
Both operands[0] (initial condition) and operands[1]
(loop-carried condition) are validated.
Raises ValidationError for any non-measurement while pattern.
Attributes¶
name: str
Methods¶
run¶
def run(self, block: Block) -> BlockValidate all WhileOperations and return block unchanged.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
ValueCollector [source]¶
class ValueCollector(ControlFlowVisitor)Collects Value UUIDs from operation operands and results.
Constructor¶
def __init__(self)Attributes¶
operand_uuids: set[str]result_uuids: set[str]
Methods¶
visit_operation¶
def visit_operation(self, op: Operation) -> NoneValueSubstitutor [source]¶
class ValueSubstitutorSubstitutes values in operations using a mapping.
Used during inlining to replace block parameters with caller arguments.
When transitive is True, substitute_value chases transitive chains
(A -> B -> C) to terminal values with cycle detection, which is needed
for phi substitution during compile-time if lowering.
Constructor¶
def __init__(self, value_map: dict[str, ValueBase], transitive: bool = False)Methods¶
substitute_operation¶
def substitute_operation(self, op: Operation) -> OperationSubstitute values in an operation using the value map.
Uses Operation.replace_values() to handle operands, results,
and any subclass-specific Value fields (e.g. ControlledUOperation.power).
Also handles IfOperation phi_ops recursion.
substitute_value¶
def substitute_value(self, v: ValueBase) -> ValueBaseSubstitute a single value using the value map.
Handles all value types and array elements by substituting
their parent_array if needed. When transitive is enabled,
chases transitive chains (A -> B -> C) to terminal values.
qamomile.circuit.transpiler.passes.affine_validate¶
Affine type validation pass: Verify quantum resources are used correctly.
Overview¶
| Class | Description |
|---|---|
AffineTypeError | Base class for affine type violations. |
AffineValidationPass | Validate affine type semantics at IR level. |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
Pass | Base class for all compiler passes. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Value | A typed SSA value in the IR. |
Classes¶
AffineTypeError [source]¶
class AffineTypeError(QamomileCompileError)Base class for affine type violations.
Affine types enforce that quantum resources (qubits) are used at most once. This prevents common errors such as reusing a consumed qubit or aliasing.
Constructor¶
def __init__(
self,
message: str,
handle_name: str | None = None,
operation_name: str | None = None,
first_use_location: str | None = None,
)Attributes¶
first_use_locationhandle_nameoperation_name
AffineValidationPass [source]¶
class AffineValidationPass(Pass[Block, Block])Validate affine type semantics at IR level.
This pass serves as a safety net to catch affine type violations that may have bypassed the frontend checks. It verifies:
Each quantum value is used (consumed) at most once
Quantum values are not silently discarded
Input: Block (any kind) Output: Same Block (unchanged, validation only)
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockValidate affine type semantics in the block.
Raises:
ValidationError— If the block kind is not AFFINE.AffineTypeError— If a quantum value is consumed multiple times.
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
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]]) -> OperationPass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
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.
qamomile.circuit.transpiler.passes.analyze¶
Analyze pass: Validate and analyze dependencies in an affine block.
Overview¶
| Function | Description |
|---|---|
build_dependency_graph | Build a map from each value UUID to the UUIDs it depends on. |
find_measurement_derived_values | Forward-propagate measurement taint through the dependency graph. |
find_measurement_results | Find all value UUIDs that are direct results of MeasureOperation. |
| Class | Description |
|---|---|
AnalyzePass | Analyze and validate an affine block. |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
ControlFlowVisitor | Base class for visiting operations with control flow handling. |
DependencyError | Error when quantum operation depends on non-parameter classical value. |
MeasureOperation | |
OperationKind | Classification of operations for classical/quantum separation. |
Pass | Base class for all compiler passes. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
Functions¶
build_dependency_graph [source]¶
def build_dependency_graph(operations: list[Operation]) -> dict[str, set[str]]Build a map from each value UUID to the UUIDs it depends on.
Walks operations recursively (through HasNestedOps) and records,
for each result UUID, the set of operand UUIDs that produced it.
Used downstream by measurement-taint analysis.
Parameters:
| Name | Type | Description |
|---|---|---|
operations | list[Operation] | Top-level operations of the block. |
Returns:
dict[str, set[str]] — Mapping result_uuid -> set(operand_uuid, ...).
find_measurement_derived_values [source]¶
def find_measurement_derived_values(dependency_graph: dict[str, set[str]], measurement_uuids: set[str]) -> set[str]Forward-propagate measurement taint through the dependency graph.
Parameters:
| Name | Type | Description |
|---|---|---|
dependency_graph | dict[str, set[str]] | result_uuid -> set(operand_uuid, ...). |
measurement_uuids | set[str] | Seed set (results of MeasureOperation). |
Returns:
set[str] — The set of all UUIDs transitively derived from a measurement,
set[str] — including the seeds themselves.
find_measurement_results [source]¶
def find_measurement_results(operations: list[Operation]) -> set[str]Find all value UUIDs that are direct results of MeasureOperation.
Walks operations recursively (through HasNestedOps) and collects
every measurement result’s UUID. The seed for taint propagation.
Classes¶
AnalyzePass [source]¶
class AnalyzePass(Pass[Block, Block])Analyze and validate an affine block.
This pass:
Builds a dependency graph between values (used locally for validation)
Validates that quantum ops don’t depend on non-parameter classical results
Checks that block inputs/outputs are classical
Input: Block with BlockKind.AFFINE Output: Block with BlockKind.ANALYZED
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockAnalyze the block and validate dependencies.
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
ControlFlowVisitor [source]¶
class ControlFlowVisitor(ABC)Base class for visiting operations with control flow handling.
Subclasses override visit_operation to define per-operation behavior.
Control flow recursion is handled automatically by the base class.
Example:
class MeasurementCounter(ControlFlowVisitor):
def __init__(self):
self.count = 0
def visit_operation(self, op: Operation) -> None:
if isinstance(op, MeasureOperation):
self.count += 1Methods¶
visit_operation¶
def visit_operation(self, op: Operation) -> NoneProcess a single operation. Override in subclasses.
visit_operations¶
def visit_operations(self, operations: list[Operation]) -> NoneVisit all operations including nested control flow.
DependencyError [source]¶
class DependencyError(QamomileCompileError)Error when quantum operation depends on non-parameter classical value.
This error indicates that the program requires JIT compilation which is not yet supported.
Constructor¶
def __init__(
self,
message: str,
quantum_op: str | None = None,
classical_value: str | None = None,
)Attributes¶
classical_valuequantum_op
MeasureOperation [source]¶
class MeasureOperation(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
OperationKind [source]¶
class OperationKind(enum.Enum)Classification of operations for classical/quantum separation.
This enum is used to categorize operations during compilation to determine which parts run on classical hardware vs quantum hardware.
Values:
QUANTUM: Pure quantum operations (gates, qubit allocation) CLASSICAL: Pure classical operations (arithmetic, comparisons) HYBRID: Operations that bridge classical and quantum (measurement, encode/decode) CONTROL: Control flow structures (for, while, if)
Attributes¶
CLASSICALCONTROLHYBRIDQUANTUM
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
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.
ValueBase [source]¶
class ValueBase(Protocol)Protocol for IR values with typed metadata.
Attributes are declared as read-only properties to match frozen dataclass fields in concrete implementations (Value, ArrayValue, etc.).
Attributes¶
logical_id: strmetadata: ValueMetadataname: struuid: str
Methods¶
get_const¶
def get_const(self) -> int | float | bool | Noneis_constant¶
def is_constant(self) -> boolis_parameter¶
def is_parameter(self) -> boolnext_version¶
def next_version(self) -> ValueBaseparameter_name¶
def parameter_name(self) -> str | Noneqamomile.circuit.transpiler.passes.classical_lowering¶
Classical-op lowering pass: identify runtime-evaluation classical ops.
Walks the block, identifies CompOp / CondOp / NotOp / BinOp
instances whose 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), and replaces them with the equivalent
RuntimeClassicalExpr.
Why this pass exists:
The pre-RuntimeClassicalExpr design left runtime classical ops in
their compile-time IR form (CompOp etc.) all the way to emit, where
the emit pass had to fold-or-translate via evaluate_classical_predicate
_build_runtime_predicate_expr. This put backend-specific lowering logic inside the emit pass and used thebindingsdict as a polymorphic slot holding either Python scalars (fold result) or backendExprobjects.
By identifying runtime classical ops at IR level and giving them their own node type, we:
Make “runtime evaluation required” structurally explicit in the IR.
Move backend lowering to a dedicated emit hook (
_emit_runtime_classical_expr).Preserve the existing fold path for ops that can fold at compile or emit time (loop-bound or parameter-bound) — those are not measurement- derived and stay as
CompOp/CondOp/NotOp/BinOp.
Overview¶
| Function | Description |
|---|---|
build_dependency_graph | Build a map from each value UUID to the UUIDs it depends on. |
find_measurement_derived_values | Forward-propagate measurement taint through the dependency graph. |
find_measurement_results | Find all value UUIDs that are direct results of MeasureOperation. |
runtime_kind_from_binop | Map a BinOpKind to its RuntimeOpKind counterpart. |
runtime_kind_from_compop | Map a CompOpKind to its RuntimeOpKind counterpart. |
runtime_kind_from_condop | Map a CondOpKind to its RuntimeOpKind counterpart. |
| Class | Description |
|---|---|
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
ClassicalLoweringPass | Lower measurement-derived classical ops to RuntimeClassicalExpr. |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CondOp | Conditional logical operation (AND, OR). |
HasNestedOps | Mixin for operations that contain nested operation lists. |
NotOp | |
Pass | Base class for all compiler passes. |
RuntimeClassicalExpr | A classical expression known to require runtime evaluation. |
ValueBase | Protocol for IR values with typed metadata. |
Functions¶
build_dependency_graph [source]¶
def build_dependency_graph(operations: list[Operation]) -> dict[str, set[str]]Build a map from each value UUID to the UUIDs it depends on.
Walks operations recursively (through HasNestedOps) and records,
for each result UUID, the set of operand UUIDs that produced it.
Used downstream by measurement-taint analysis.
Parameters:
| Name | Type | Description |
|---|---|---|
operations | list[Operation] | Top-level operations of the block. |
Returns:
dict[str, set[str]] — Mapping result_uuid -> set(operand_uuid, ...).
find_measurement_derived_values [source]¶
def find_measurement_derived_values(dependency_graph: dict[str, set[str]], measurement_uuids: set[str]) -> set[str]Forward-propagate measurement taint through the dependency graph.
Parameters:
| Name | Type | Description |
|---|---|---|
dependency_graph | dict[str, set[str]] | result_uuid -> set(operand_uuid, ...). |
measurement_uuids | set[str] | Seed set (results of MeasureOperation). |
Returns:
set[str] — The set of all UUIDs transitively derived from a measurement,
set[str] — including the seeds themselves.
find_measurement_results [source]¶
def find_measurement_results(operations: list[Operation]) -> set[str]Find all value UUIDs that are direct results of MeasureOperation.
Walks operations recursively (through HasNestedOps) and collects
every measurement result’s UUID. The seed for taint propagation.
runtime_kind_from_binop [source]¶
def runtime_kind_from_binop(kind: BinOpKind) -> RuntimeOpKindMap a BinOpKind to its RuntimeOpKind counterpart.
runtime_kind_from_compop [source]¶
def runtime_kind_from_compop(kind: CompOpKind) -> RuntimeOpKindMap a CompOpKind to its RuntimeOpKind counterpart.
runtime_kind_from_condop [source]¶
def runtime_kind_from_condop(kind: CondOpKind) -> RuntimeOpKindMap a CondOpKind to its RuntimeOpKind counterpart.
Classes¶
BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
ClassicalLoweringPass [source]¶
class ClassicalLoweringPass(Pass[Block, Block])Lower measurement-derived classical ops to RuntimeClassicalExpr.
Input: Block with BlockKind.ANALYZED.
Output: Block with BlockKind.ANALYZED (same kind; only op rewrites).
The pass:
Builds a measurement-taint set using the same dataflow utilities as
AnalyzePass(forward propagation fromMeasureOperationresults through the dependency graph).Walks operations recursively (through
HasNestedOps).For each
CompOp/CondOp/NotOp/BinOpwhose result UUID is in the taint set, replaces it with an equivalentRuntimeClassicalExpr(same operands and result Value, only the op type and kind enum change).Non-tainted classical ops are left unchanged so the existing fold paths (compile-time fold in
compile_time_if_lowering, emit-time fold inevaluate_classical_predicate) continue to handle them.
The dependency graph and taint set are computed once, walked once, so the pass is O(N) where N is the number of operations.
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockCompOp [source]¶
class CompOp(BinaryOperationBase)Comparison operation (EQ, NEQ, LT, LE, GT, GE).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CompOpKind | None = None,
) -> NoneAttributes¶
kind: CompOpKind | Noneoperation_kind: OperationKindsignature: Signature
CondOp [source]¶
class CondOp(BinaryOperationBase)Conditional logical operation (AND, OR).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CondOpKind | None = None,
) -> NoneAttributes¶
kind: CondOpKind | Noneoperation_kind: OperationKindsignature: Signature
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().
NotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
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/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
ValueBase [source]¶
class ValueBase(Protocol)Protocol for IR values with typed metadata.
Attributes are declared as read-only properties to match frozen dataclass fields in concrete implementations (Value, ArrayValue, etc.).
Attributes¶
logical_id: strmetadata: ValueMetadataname: struuid: str
Methods¶
get_const¶
def get_const(self) -> int | float | bool | Noneis_constant¶
def is_constant(self) -> boolis_parameter¶
def is_parameter(self) -> boolnext_version¶
def next_version(self) -> ValueBaseparameter_name¶
def parameter_name(self) -> str | Noneqamomile.circuit.transpiler.passes.compile_time_if_lowering¶
Compile-time IfOperation lowering pass.
Lowers compile-time resolvable IfOperations before the segmentation pass,
replacing them with selected-branch operations and substituting phi outputs
with selected-branch values throughout the block.
This prevents SegmentationPass from seeing classical-only compile-time
IfOperations that would otherwise split quantum segments.
Overview¶
| Function | Description |
|---|---|
fold_classical_op | Fold a classical op to a concrete value, respecting the given policy. |
| Class | Description |
|---|---|
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CompileTimeIfLoweringPass | Lowers compile-time resolvable IfOperations before separation. |
CondOp | Conditional logical operation (AND, OR). |
FoldPolicy | Policy controlling how fold_classical_op treats parameters. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
NotOp | |
Pass | Base class for all compiler passes. |
PhiOp | SSA Phi function: merge point after conditional branch. |
UnifiedValueResolver | Resolves IR Values to concrete Python values. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueSubstitutor | Substitutes values in operations using a mapping. |
Functions¶
fold_classical_op [source]¶
def fold_classical_op(
op: 'BinOp | CompOp | CondOp | NotOp',
operand_resolver: Callable[[Any], Any],
parameters: set[str],
policy: FoldPolicy,
) -> Any | NoneFold a classical op to a concrete value, respecting the given policy.
The caller supplies an operand_resolver callable that knows how
to look up a Value in the caller’s context (a concrete_values
map, an emit bindings dict + ValueResolver, or any other
source). This function handles:
The parameter guard (skips folding when an operand is a runtime parameter or parameter-array element under
EMIT_RESPECT_PARAMS).Strict scalar-only typing (rejects backend
Exprobjects and other non-numeric values that would spuriously fold toTrue).Kind dispatch via the underlying
evaluate_*_valuesprimitives.
Parameters:
| Name | Type | Description |
|---|---|---|
op | 'BinOp | CompOp | CondOp | NotOp' | The classical op to fold. Must be one of BinOp, CompOp, CondOp, NotOp. |
operand_resolver | Callable[[Any], Any] | Callable mapping each operand Value to a resolved Python scalar (or None when unresolvable). |
parameters | set[str] | Set of runtime parameter names. Used only when policy is EMIT_RESPECT_PARAMS. |
policy | FoldPolicy | Folding policy. See FoldPolicy docstring. |
Returns:
Any | None — The folded value (numeric for BinOp, bool for predicates),
Any | None — or None when any operand is symbolic, missing, or a runtime
Any | None — parameter under the policy.
Classes¶
BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
CompOp [source]¶
class CompOp(BinaryOperationBase)Comparison operation (EQ, NEQ, LT, LE, GT, GE).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CompOpKind | None = None,
) -> NoneAttributes¶
kind: CompOpKind | Noneoperation_kind: OperationKindsignature: Signature
CompileTimeIfLoweringPass [source]¶
class CompileTimeIfLoweringPass(Pass[Block, Block])Lowers compile-time resolvable IfOperations before separation.
After constant folding, some IfOperation conditions are statically
known but remain as control-flow nodes. SegmentationPass treats them
as segment boundaries, causing MultipleQuantumSegmentsError for
classical-only compile-time if after quantum init.
This pass:
Evaluates conditions including expression-derived ones (
CompOp,CondOp,NotOpchains).Replaces resolved
IfOperations with selected-branch operations.Substitutes phi output UUIDs with selected-branch values in all subsequent operations and block outputs.
Constructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockRun the compile-time if lowering pass.
CondOp [source]¶
class CondOp(BinaryOperationBase)Conditional logical operation (AND, OR).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CondOpKind | None = None,
) -> NoneAttributes¶
kind: CondOpKind | Noneoperation_kind: OperationKindsignature: Signature
FoldPolicy [source]¶
class FoldPolicy(enum.Enum)Policy controlling how fold_classical_op treats parameters.
COMPILE_TIME is for passes that have no notion of runtime
parameters (e.g. compile_time_if_lowering); every operand the
resolver returns is treated as a real value to fold.
EMIT_RESPECT_PARAMS is for emit-time passes where some Values
may correspond to runtime backend parameters whose concrete values
are placeholders or absent. Operands whose Value or
parent_array.name is in the active parameters set are
treated as symbolic and the fold returns None rather than
producing an incorrect concrete result.
Attributes¶
COMPILE_TIMEEMIT_RESPECT_PARAMS
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]]) -> OperationNotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
PhiOp [source]¶
class PhiOp(Operation)SSA Phi function: merge point after conditional branch.
This operation selects one of two values based on a condition. Used to merge values from different branches of an if-else statement.
Example:
if condition:
x = x + 1 # true_value
else:
x = x + 2 # false_value
# x is now PhiOp(condition, true_value, false_value)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
condition: Valuefalse_value: Valueoperation_kind: OperationKindoutput: Valuesignature: Signaturetrue_value: Value
ValueResolver [source]¶
class ValueResolverResolves IR Values to concrete Python values.
Parameters¶
context:
UUID-keyed map of already-resolved values. The values may be
either raw Python scalars or Value objects; if a Value is
found its get_const() is extracted automatically.
bindings:
Name-keyed parameter bindings supplied by the user at transpile
time.
Constructor¶
def __init__(
self,
context: dict[str, Any] | None = None,
bindings: dict[str, Any] | None = None,
)Methods¶
resolve¶
def resolve(self, value: Any) -> Any | NoneResolve value to a concrete Python value, or None.
If value is not a Value-like object (no uuid attribute) it
is returned as-is — the caller already has a concrete value.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
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.
ValueBase [source]¶
class ValueBase(Protocol)Protocol for IR values with typed metadata.
Attributes are declared as read-only properties to match frozen dataclass fields in concrete implementations (Value, ArrayValue, etc.).
Attributes¶
logical_id: strmetadata: ValueMetadataname: struuid: str
Methods¶
get_const¶
def get_const(self) -> int | float | bool | Noneis_constant¶
def is_constant(self) -> boolis_parameter¶
def is_parameter(self) -> boolnext_version¶
def next_version(self) -> ValueBaseparameter_name¶
def parameter_name(self) -> str | NoneValueSubstitutor [source]¶
class ValueSubstitutorSubstitutes values in operations using a mapping.
Used during inlining to replace block parameters with caller arguments.
When transitive is True, substitute_value chases transitive chains
(A -> B -> C) to terminal values with cycle detection, which is needed
for phi substitution during compile-time if lowering.
Constructor¶
def __init__(self, value_map: dict[str, ValueBase], transitive: bool = False)Methods¶
substitute_operation¶
def substitute_operation(self, op: Operation) -> OperationSubstitute values in an operation using the value map.
Uses Operation.replace_values() to handle operands, results,
and any subclass-specific Value fields (e.g. ControlledUOperation.power).
Also handles IfOperation phi_ops recursion.
substitute_value¶
def substitute_value(self, v: ValueBase) -> ValueBaseSubstitute a single value using the value map.
Handles all value types and array elements by substituting
their parent_array if needed. When transitive is enabled,
chases transitive chains (A -> B -> C) to terminal values.
qamomile.circuit.transpiler.passes.constant_fold¶
Constant folding pass for compile-time expression evaluation.
Overview¶
| Class | Description |
|---|---|
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
BinOpKind | |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
ConcreteControlledU | Controlled-U with concrete (int) number of controls. |
ConstantFoldingPass | Evaluates constant expressions at compile time. |
ControlledUOperation | Base class for controlled-U operations. |
IndexSpecControlledU | Controlled-U with explicit target/control index specification. |
OperationTransformer | Base class for transforming operations with control flow handling. |
Pass | Base class for all compiler passes. |
SymbolicControlledU | Controlled-U with symbolic (Value) number of controls. |
UnifiedValueResolver | Resolves IR Values to concrete Python values. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
Classes¶
BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
BinOpKind [source]¶
class BinOpKind(enum.Enum)Attributes¶
ADDDIVFLOORDIVMULPOWSUB
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
ConcreteControlledU [source]¶
class ConcreteControlledU(ControlledUOperation)Controlled-U with concrete (int) number of controls.
Operand layout: [ctrl_0, ..., ctrl_n, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_0', ..., ctrl_n', tgt_0', ..., tgt_m']
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: int = 1,
) -> NoneAttributes¶
control_operands: list[Value]num_controls: intparam_operands: list[Value]signature: Signaturetarget_operands: list[Value]
ConstantFoldingPass [source]¶
class ConstantFoldingPass(Pass[Block, Block])Evaluates constant expressions at compile time.
This pass folds BinOp operations when all operands are constants or bound parameters, eliminating unnecessary classical operations that would otherwise split quantum segments.
Example:
Before (with bindings={"phase": 0.5}):
BinOp(phase * 2) -> classical segment split
After:
Constant 1.0 -> no segment splitConstructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockRun constant folding on the block.
ControlledUOperation [source]¶
class ControlledUOperation(Operation)Base class for controlled-U operations.
Three concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands.IndexSpecControlledU: Single vector with explicit index lists selecting which elements are controls/targets.
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,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.has_index_spec: bool Whether target/control positions are specified via index lists.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.operation_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]) -> OperationIndexSpecControlledU [source]¶
class IndexSpecControlledU(ControlledUOperation)Controlled-U with explicit target/control index specification.
A single vector covers both controls and targets; the partition is
determined by target_indices or controlled_indices.
Operand layout: [vector, params...]
Result layout: [vector']
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,
target_indices: list[Value] | None = None,
controlled_indices: list[Value] | None = None,
) -> NoneAttributes¶
control_operands: list[Value]controlled_indices: list[Value] | Nonehas_index_spec: boolis_symbolic_num_controls: boolnum_controls: int | Valueparam_operands: list[Value]signature: Signaturetarget_indices: list[Value] | Nonetarget_operands: list[Value]
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationOperationTransformer [source]¶
class OperationTransformer(ABC)Base class for transforming operations with control flow handling.
Subclasses override transform_operation to define per-operation transformation.
Control flow recursion and rebuilding is handled automatically.
Example:
class OperationRenamer(OperationTransformer):
def transform_operation(self, op: Operation) -> Operation:
# Return modified operation
return dataclasses.replace(op, ...)Methods¶
transform_operation¶
def transform_operation(self, op: Operation) -> Operation | NoneTransform a single operation. Return None to remove it.
transform_operations¶
def transform_operations(self, operations: list[Operation]) -> list[Operation]Transform all operations including nested control flow.
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
SymbolicControlledU [source]¶
class SymbolicControlledU(ControlledUOperation)Controlled-U with symbolic (Value) number of controls.
Operand layout: [ctrl_vector, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_vector', tgt_0', ..., tgt_m']
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: Value = (lambda: Value(type=(FloatType()), name='_placeholder'))(),
) -> NoneAttributes¶
control_operands: list[Value]is_symbolic_num_controls: boolnum_controls: Valueparam_operands: list[Value]signature: Signaturetarget_operands: list[Value]
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationValueResolver [source]¶
class ValueResolverResolves IR Values to concrete Python values.
Parameters¶
context:
UUID-keyed map of already-resolved values. The values may be
either raw Python scalars or Value objects; if a Value is
found its get_const() is extracted automatically.
bindings:
Name-keyed parameter bindings supplied by the user at transpile
time.
Constructor¶
def __init__(
self,
context: dict[str, Any] | None = None,
bindings: dict[str, Any] | None = None,
)Methods¶
resolve¶
def resolve(self, value: Any) -> Any | NoneResolve value to a concrete Python value, or None.
If value is not a Value-like object (no uuid attribute) it
is returned as-is — the caller already has a concrete value.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
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.
ValueBase [source]¶
class ValueBase(Protocol)Protocol for IR values with typed metadata.
Attributes are declared as read-only properties to match frozen dataclass fields in concrete implementations (Value, ArrayValue, etc.).
Attributes¶
logical_id: strmetadata: ValueMetadataname: struuid: str
Methods¶
get_const¶
def get_const(self) -> int | float | bool | Noneis_constant¶
def is_constant(self) -> boolis_parameter¶
def is_parameter(self) -> boolnext_version¶
def next_version(self) -> ValueBaseparameter_name¶
def parameter_name(self) -> str | Noneqamomile.circuit.transpiler.passes.control_flow_visitor¶
Control flow visitor for operation traversal.
Overview¶
| Class | Description |
|---|---|
ControlFlowVisitor | Base class for visiting operations with control flow handling. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
OperationCollector | Collects operations matching a predicate. |
OperationTransformer | Base class for transforming operations with control flow handling. |
ValueCollector | Collects Value UUIDs from operation operands and results. |
Classes¶
ControlFlowVisitor [source]¶
class ControlFlowVisitor(ABC)Base class for visiting operations with control flow handling.
Subclasses override visit_operation to define per-operation behavior.
Control flow recursion is handled automatically by the base class.
Example:
class MeasurementCounter(ControlFlowVisitor):
def __init__(self):
self.count = 0
def visit_operation(self, op: Operation) -> None:
if isinstance(op, MeasureOperation):
self.count += 1Methods¶
visit_operation¶
def visit_operation(self, op: Operation) -> NoneProcess a single operation. Override in subclasses.
visit_operations¶
def visit_operations(self, operations: list[Operation]) -> NoneVisit all operations including nested control flow.
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().
OperationCollector [source]¶
class OperationCollector(ControlFlowVisitor)Collects operations matching a predicate.
Example:
collector = OperationCollector(lambda op: isinstance(op, MeasureOperation))
collector.visit_operations(block.operations)
measurements = collector.collectedConstructor¶
def __init__(self, predicate: Callable[[Operation], bool])Attributes¶
collected: list[Operation]
Methods¶
visit_operation¶
def visit_operation(self, op: Operation) -> NoneOperationTransformer [source]¶
class OperationTransformer(ABC)Base class for transforming operations with control flow handling.
Subclasses override transform_operation to define per-operation transformation.
Control flow recursion and rebuilding is handled automatically.
Example:
class OperationRenamer(OperationTransformer):
def transform_operation(self, op: Operation) -> Operation:
# Return modified operation
return dataclasses.replace(op, ...)Methods¶
transform_operation¶
def transform_operation(self, op: Operation) -> Operation | NoneTransform a single operation. Return None to remove it.
transform_operations¶
def transform_operations(self, operations: list[Operation]) -> list[Operation]Transform all operations including nested control flow.
ValueCollector [source]¶
class ValueCollector(ControlFlowVisitor)Collects Value UUIDs from operation operands and results.
Constructor¶
def __init__(self)Attributes¶
operand_uuids: set[str]result_uuids: set[str]
Methods¶
visit_operation¶
def visit_operation(self, op: Operation) -> Noneqamomile.circuit.transpiler.passes.emit¶
Emit pass: Generate backend-specific code from separated program.
Overview¶
| Class | Description |
|---|---|
ClassicalSegment | A segment of pure classical operations. |
ClassicalStep | A classical execution step. |
CompositeGateEmitter | Protocol for backend-specific CompositeGate emitters. |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CompositeGateType | Registry of known composite gate types. |
EmitPass | Base class for backend-specific emission passes. |
ExecutableProgram | A fully compiled program ready for execution. |
ExpvalSegment | A segment for expectation value computation. |
ExpvalStep | An expectation-value execution step. |
Pass | Base class for all compiler passes. |
ProgramPlan | Execution plan for a hybrid quantum/classical program. |
QuantumSegment | A segment of pure quantum operations. |
QuantumStep | A quantum execution step. |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
Value | A typed SSA value in the IR. |
ValueResolver | Resolves Value objects to concrete indices or values. |
Classes¶
ClassicalSegment [source]¶
class ClassicalSegment(Segment)A segment of pure classical operations.
Contains arithmetic, comparisons, and control flow. Will be executed directly in Python.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
kind: SegmentKind
ClassicalStep [source]¶
class ClassicalStepA classical execution step.
Constructor¶
def __init__(self, segment: ClassicalSegment, role: str = 'classical') -> NoneAttributes¶
role: strsegment: ClassicalSegment
CompositeGateEmitter [source]¶
class CompositeGateEmitter(Protocol[C])Protocol for backend-specific CompositeGate emitters.
Each backend can implement emitters for specific composite gate types (QPE, QFT, IQFT, etc.) using native backend libraries.
The emitter pattern allows:
Backends to use native implementations when available (e.g., Qiskit QFT)
Fallback to manual decomposition when native is unavailable
Easy addition of new backends without modifying core code
Example:
class QiskitQFTEmitter:
def can_emit(self, gate_type: CompositeGateType) -> bool:
return gate_type in (CompositeGateType.QFT, CompositeGateType.IQFT)
def emit(self, circuit, op, qubit_indices, bindings) -> bool:
from qiskit.circuit.library import QFTGate
qft_gate = QFTGate(len(qubit_indices))
circuit.append(qft_gate, qubit_indices)
return TrueMethods¶
can_emit¶
def can_emit(self, gate_type: CompositeGateType) -> boolCheck if this emitter can handle the given gate type.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_type | CompositeGateType | The CompositeGateType to check |
Returns:
bool — True if this emitter supports native emission for the gate type
emit¶
def emit(
self,
circuit: C,
op: CompositeGateOperation,
qubit_indices: list[int],
bindings: dict[str, Any],
) -> boolEmit the composite gate to the circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | C | The backend-specific circuit to emit to |
op | CompositeGateOperation | The CompositeGateOperation to emit |
qubit_indices | list[int] | Physical qubit indices for the operation |
bindings | dict[str, Any] | Parameter bindings for the operation |
Returns:
bool — True if emission succeeded, False to fall back to manual decomposition
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
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.
ExecutableProgram [source]¶
class ExecutableProgram(Generic[T])A fully compiled program ready for execution.
Contains compiled quantum, classical, and expectation-value segments.
Use sample() for multi-shot execution or run() for single
execution.
Example:
executable = transpiler.compile(kernel)
# Sample: multiple shots, returns counts
job = executable.sample(executor, shots=1000)
result = job.result() # SampleResult with counts
# Run: single shot, returns typed result
job = executable.run(executor)
result = job.result() # Returns kernel's return typeConstructor¶
def __init__(
self,
plan: ProgramPlan | None = None,
compiled_quantum: list[CompiledQuantumSegment[T]] = list(),
compiled_classical: list[CompiledClassicalSegment] = list(),
compiled_expval: list[CompiledExpvalSegment] = list(),
output_refs: list[str] = list(),
num_output_bits: int = 0,
) -> NoneAttributes¶
compiled_classical: list[CompiledClassicalSegment]compiled_expval: list[CompiledExpvalSegment]compiled_quantum: list[CompiledQuantumSegment[T]]has_parameters: bool Check if this program has unbound parameters.num_output_bits: intoutput_refs: list[str]parameter_names: list[str] Get list of parameter names that need binding.plan: ProgramPlan | Nonequantum_circuit: T Get the single quantum circuit.
Methods¶
get_circuits¶
def get_circuits(self) -> list[T]Get all quantum circuits in execution order.
get_first_circuit¶
def get_first_circuit(self) -> T | NoneGet the first quantum circuit, or None if no quantum segments.
run¶
def run(
self,
executor: QuantumExecutor[T],
bindings: dict[str, Any] | None = None,
) -> RunJob[Any] | ExpvalJobExecute once and return single result.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
RunJob[Any] | ExpvalJob — RunJob that resolves to the kernel’s return type, or
RunJob[Any] | ExpvalJob — ExpvalJob if the program contains expectation value computation.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.run(executor, bindings={"gamma": [0.5]})
result = job.result()
print(result) # 0.25 (for QFixed) or (0, 1) (for bits)sample¶
def sample(
self,
executor: QuantumExecutor[T],
shots: int = 1024,
bindings: dict[str, Any] | None = None,
) -> SampleJob[Any]Execute with multiple shots and return counts.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
shots | int | Number of shots to run. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
SampleJob[Any] — SampleJob that resolves to SampleResult with results.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.sample(executor, shots=1000, bindings={"gamma": [0.5]})
result = job.result()
print(result.results) # [(0.25, 500), (0.75, 500)]ExpvalSegment [source]¶
class ExpvalSegment(Segment)A segment for expectation value computation.
Represents computing <psi|H|psi> where psi is the quantum state and H is a Hamiltonian observable.
This segment bridges a quantum circuit (state preparation) to a classical expectation value.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
hamiltonian_value: Value | None = None,
qubits_value: Value | None = None,
result_ref: str = '',
) -> NoneAttributes¶
hamiltonian_value: Value | Nonekind: SegmentKindqubits_value: Value | Noneresult_ref: str
ExpvalStep [source]¶
class ExpvalStepAn expectation-value execution step.
Constructor¶
def __init__(self, segment: ExpvalSegment, quantum_step_index: int = 0) -> NoneAttributes¶
quantum_step_index: intsegment: ExpvalSegment
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
ProgramPlan [source]¶
class ProgramPlanExecution plan for a hybrid quantum/classical program.
Structure:
[Optional] Classical preprocessing (parameter computation, etc.)
Single quantum segment (REQUIRED)
[Optional] Expval segment OR classical postprocessing
This plan enforces Qamomile’s current execution model: all quantum operations must be in a single quantum circuit.
Constructor¶
def __init__(
self,
steps: list[ProgramStep] = list(),
abi: ProgramABI = ProgramABI(),
boundaries: list[HybridBoundary] = list(),
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
abi: ProgramABIboundaries: list[HybridBoundary]parameters: dict[str, Value]steps: list[ProgramStep]
QuantumSegment [source]¶
class QuantumSegment(Segment)A segment of pure quantum operations.
Contains quantum gates and qubit allocations. Will be emitted to a quantum circuit.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
qubit_values: list[Value] = list(),
num_qubits: int = 0,
) -> NoneAttributes¶
kind: SegmentKindnum_qubits: intqubit_values: list[Value]
QuantumStep [source]¶
class QuantumStepA quantum execution step.
Constructor¶
def __init__(self, segment: QuantumSegment) -> NoneAttributes¶
segment: QuantumSegment
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
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.
ValueResolver [source]¶
class ValueResolverResolves Value objects to concrete indices or values.
Constructor¶
def __init__(self, parameters: set[str] | None = None)Attributes¶
parameters
Methods¶
bind_block_params¶
def bind_block_params(
self,
block_value: Any,
param_operands: list['Value'],
bindings: dict[str, Any],
) -> dict[str, Any]Create local bindings by matching block parameter inputs to operands.
get_parameter_key¶
def get_parameter_key(self, value: 'Value', bindings: dict[str, Any]) -> str | NoneGet parameter key if this value should be a symbolic parameter.
lookup_in_bindings¶
def lookup_in_bindings(
self,
value: 'Value',
bindings: dict[str, Any],
*,
index_array: bool = False,
) -> AnyCanonical resolution chain for a Value against bindings.
All other resolver methods (resolve_bound_value,
resolve_classical_value, resolve_int_value,
resolve_operand_for_binding) wrap this single chain. Centralizing
precedence here prevents the historical drift where one resolver
checked is_parameter before UUID and another checked it after,
which manifested as obscure binding failures when name-keyed writes
were dropped from the emit pass.
Resolution order (each step returns immediately on a hit):
valueis already a concrete Python scalar (nouuid).value.is_constant()— returnvalue.get_const().value.is_parameter()and its parameter name is inbindings— return that.value.uuidis inbindings— return that. This is where emit-time-computed intermediates (evaluate_binop/evaluate_classical_predicateresults) and phi aliases live.value.nameis inbindings— return that. This is where kernel parameters and loop iteration variables live. NOT a reliable channel for auto-generated tmp names like"uint_tmp"— those are intentionally written by UUID only.(When
index_array=True)valueis an array element with a resolvable parent inbindings— index into it.
Parameters:
| Name | Type | Description |
|---|---|---|
value | 'Value' | The IR Value (or already-concrete Python scalar) to resolve. |
bindings | dict[str, Any] | The active bindings dict. |
index_array | bool | When True, also resolve array-element accesses via parent_array indexing. Off by default because not all callers want to index into bound containers. |
Returns:
Any — The resolved Python value, or None if no step matched.
resolve_bound_value¶
def resolve_bound_value(self, value: 'Value', bindings: dict[str, Any]) -> AnyResolve a Value to its raw bound Python object.
Wraps :meth:lookup_in_bindings with index_array=True so that
arr[i] accesses against a bound container resolve to the
element. Does not coerce the result — callers that need a
numeric scalar should go through :meth:resolve_classical_value.
resolve_classical_value¶
def resolve_classical_value(self, value: 'Value', bindings: dict[str, Any]) -> AnyResolve a classical Value to a concrete Python value.
Numeric bindings are normalized to native Python scalars
regardless of whether they come from a direct binding or from
array-element indexing, so downstream isinstance(x, (int, float)) checks are stable when callers bind np.pi/4 or
the like. bool is preserved (not coerced to int).
Non-numeric values (Hamiltonians, strings, dict values, …)
pass through unchanged.
resolve_int_value¶
def resolve_int_value(self, val: Any, bindings: dict[str, Any]) -> int | NoneResolve a value to an integer, or None when unresolvable.
Unresolvable symbolic Values must return None. The previous
return 0 fallback caused silent loop elision when parameter
shape dims (gamma_dim0) reached this resolver without being
folded into constants — downstream loop-bound resolution saw 0 and
quietly emitted an empty loop. Returning None propagates the
failure to emit_for_unrolled, which converts it into a hard
compile error.
resolve_operand_for_binding¶
def resolve_operand_for_binding(self, operand: 'Value', bindings: dict[str, Any]) -> AnyResolve an operand to a concrete value for block parameter binding.
Used when calling a sub-block (e.g. a controlled-U body): each param operand at the call site must resolve to a value to seed the callee’s parameter bindings.
resolve_qubit_index¶
def resolve_qubit_index(self, v: 'Value', qubit_map: QubitMap, bindings: dict[str, Any]) -> int | Noneresolve_qubit_index_detailed¶
def resolve_qubit_index_detailed(
self,
v: 'Value',
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> QubitResolutionResultResolve a Value to a physical qubit index with detailed failure info.
qamomile.circuit.transpiler.passes.emit_support¶
Shared helpers for backend emission.
Overview¶
| Function | Description |
|---|---|
map_phi_outputs | Register phi output UUIDs to the same physical resources as their sources. |
remap_static_phi_outputs | Remap phi outputs for a compile-time constant IfOperation. |
resolve_if_condition | Resolve an if-condition to a compile-time boolean. |
resolve_qubit_key | Resolve a qubit Value to its allocation key. |
| Class | Description |
|---|---|
CompositeDecomposer | Decomposes composite gates into primitive operations. |
LoopAnalyzer | Analyzes loop structures to determine emission strategy. |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
QubitResolutionResult | Result of attempting to resolve a qubit index. |
ResourceAllocator | Allocates qubit and classical bit indices from operations. |
ValueResolver | Resolves Value objects to concrete indices or values. |
Functions¶
map_phi_outputs [source]¶
def map_phi_outputs(
phi_ops: list,
qubit_map: QubitMap,
clbit_map: ClbitMap,
resolve_scalar_qubit: Any = None,
) -> NoneRegister phi output UUIDs to the same physical resources as their sources.
remap_static_phi_outputs [source]¶
def remap_static_phi_outputs(
phi_ops: list,
condition_value: bool,
qubit_map: QubitMap,
clbit_map: ClbitMap,
) -> NoneRemap phi outputs for a compile-time constant IfOperation.
resolve_if_condition [source]¶
def resolve_if_condition(condition: Any, bindings: dict[str, Any]) -> bool | NoneResolve an if-condition to a compile-time boolean.
resolve_qubit_key [source]¶
def resolve_qubit_key(qubit: 'Value') -> tuple[QubitAddress | None, bool]Resolve a qubit Value to its allocation key.
Returns a (QubitAddress | None, is_array_element) tuple.
Classes¶
CompositeDecomposer [source]¶
class CompositeDecomposerDecomposes composite gates into primitive operations.
Methods¶
iqft_structure¶
@staticmethod
def iqft_structure(n: int) -> list[tuple[str, tuple[int, ...], float | None]]qft_structure¶
@staticmethod
def qft_structure(n: int) -> list[tuple[str, tuple[int, ...], float | None]]LoopAnalyzer [source]¶
class LoopAnalyzerAnalyzes loop structures to determine emission strategy.
Methods¶
should_unroll¶
def should_unroll(self, op: ForOperation, bindings: dict[str, object]) -> boolQubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
QubitResolutionResult [source]¶
class QubitResolutionResultResult of attempting to resolve a qubit index.
Constructor¶
def __init__(
self,
success: bool,
index: int | None = None,
failure_reason: ResolutionFailureReason | None = None,
failure_details: str = '',
) -> NoneAttributes¶
failure_details: strfailure_reason: ResolutionFailureReason | Noneindex: int | Nonesuccess: bool
ResourceAllocator [source]¶
class ResourceAllocatorAllocates qubit and classical bit indices from operations.
This class handles the first pass of circuit emission: determining how many physical qubits and classical bits are needed and mapping Value UUIDs to their physical indices.
New physical indices are assigned via monotonic counters
(_next_qubit_index / _next_clbit_index) so that alias
entries — which reuse an existing physical index — never inflate
the counter. Using len(map) would cause sparse (gapped)
physical indices because alias keys increase the map size without
adding new physical resources.
Constructor¶
def __init__(self) -> NoneMethods¶
allocate¶
def allocate(
self,
operations: list[Operation],
bindings: dict[str, Any] | None = None,
) -> tuple[QubitMap, ClbitMap]Allocate qubit and clbit indices for all operations.
Parameters:
| Name | Type | Description |
|---|---|---|
operations | list[Operation] | List of operations to allocate resources for |
bindings | dict[str, Any] | None | Optional variable bindings for resolving dynamic sizes |
Returns:
QubitMap — Tuple of (qubit_map, clbit_map) where each maps
ClbitMap — QubitAddress to physical index
ValueResolver [source]¶
class ValueResolverResolves Value objects to concrete indices or values.
Constructor¶
def __init__(self, parameters: set[str] | None = None)Attributes¶
parameters
Methods¶
bind_block_params¶
def bind_block_params(
self,
block_value: Any,
param_operands: list['Value'],
bindings: dict[str, Any],
) -> dict[str, Any]Create local bindings by matching block parameter inputs to operands.
get_parameter_key¶
def get_parameter_key(self, value: 'Value', bindings: dict[str, Any]) -> str | NoneGet parameter key if this value should be a symbolic parameter.
lookup_in_bindings¶
def lookup_in_bindings(
self,
value: 'Value',
bindings: dict[str, Any],
*,
index_array: bool = False,
) -> AnyCanonical resolution chain for a Value against bindings.
All other resolver methods (resolve_bound_value,
resolve_classical_value, resolve_int_value,
resolve_operand_for_binding) wrap this single chain. Centralizing
precedence here prevents the historical drift where one resolver
checked is_parameter before UUID and another checked it after,
which manifested as obscure binding failures when name-keyed writes
were dropped from the emit pass.
Resolution order (each step returns immediately on a hit):
valueis already a concrete Python scalar (nouuid).value.is_constant()— returnvalue.get_const().value.is_parameter()and its parameter name is inbindings— return that.value.uuidis inbindings— return that. This is where emit-time-computed intermediates (evaluate_binop/evaluate_classical_predicateresults) and phi aliases live.value.nameis inbindings— return that. This is where kernel parameters and loop iteration variables live. NOT a reliable channel for auto-generated tmp names like"uint_tmp"— those are intentionally written by UUID only.(When
index_array=True)valueis an array element with a resolvable parent inbindings— index into it.
Parameters:
| Name | Type | Description |
|---|---|---|
value | 'Value' | The IR Value (or already-concrete Python scalar) to resolve. |
bindings | dict[str, Any] | The active bindings dict. |
index_array | bool | When True, also resolve array-element accesses via parent_array indexing. Off by default because not all callers want to index into bound containers. |
Returns:
Any — The resolved Python value, or None if no step matched.
resolve_bound_value¶
def resolve_bound_value(self, value: 'Value', bindings: dict[str, Any]) -> AnyResolve a Value to its raw bound Python object.
Wraps :meth:lookup_in_bindings with index_array=True so that
arr[i] accesses against a bound container resolve to the
element. Does not coerce the result — callers that need a
numeric scalar should go through :meth:resolve_classical_value.
resolve_classical_value¶
def resolve_classical_value(self, value: 'Value', bindings: dict[str, Any]) -> AnyResolve a classical Value to a concrete Python value.
Numeric bindings are normalized to native Python scalars
regardless of whether they come from a direct binding or from
array-element indexing, so downstream isinstance(x, (int, float)) checks are stable when callers bind np.pi/4 or
the like. bool is preserved (not coerced to int).
Non-numeric values (Hamiltonians, strings, dict values, …)
pass through unchanged.
resolve_int_value¶
def resolve_int_value(self, val: Any, bindings: dict[str, Any]) -> int | NoneResolve a value to an integer, or None when unresolvable.
Unresolvable symbolic Values must return None. The previous
return 0 fallback caused silent loop elision when parameter
shape dims (gamma_dim0) reached this resolver without being
folded into constants — downstream loop-bound resolution saw 0 and
quietly emitted an empty loop. Returning None propagates the
failure to emit_for_unrolled, which converts it into a hard
compile error.
resolve_operand_for_binding¶
def resolve_operand_for_binding(self, operand: 'Value', bindings: dict[str, Any]) -> AnyResolve an operand to a concrete value for block parameter binding.
Used when calling a sub-block (e.g. a controlled-U body): each param operand at the call site must resolve to a value to seed the callee’s parameter bindings.
resolve_qubit_index¶
def resolve_qubit_index(self, v: 'Value', qubit_map: QubitMap, bindings: dict[str, Any]) -> int | Noneresolve_qubit_index_detailed¶
def resolve_qubit_index_detailed(
self,
v: 'Value',
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> QubitResolutionResultResolve a Value to a physical qubit index with detailed failure info.
qamomile.circuit.transpiler.passes.emit_support.cast_binop_emission¶
Cast and binary-operation emission helpers for StandardEmitPass.
Extracted from standard_emit.py to keep the main class focused on
gate-level dispatch. Each function mirrors the original method but takes
an explicit emit_pass parameter instead of self.
Overview¶
| Function | Description |
|---|---|
default_combine_symbolic | Default combine_symbolic for backends with arithmetic-capable Parameters. |
evaluate_binop | Evaluate a BinOp and store the result in bindings. |
evaluate_classical_predicate | Evaluate a CompOp/CondOp/NotOp at emit time and bind its boolean result. |
fold_classical_op | Fold a classical op to a concrete value, respecting the given policy. |
handle_cast | Handle CastOperation - update qubit_map without emitting gates. |
| Class | Description |
|---|---|
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CondOp | Conditional logical operation (AND, OR). |
FoldPolicy | Policy controlling how fold_classical_op treats parameters. |
NotOp | |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
Functions¶
default_combine_symbolic [source]¶
def default_combine_symbolic(kind: 'BinOpKind', lhs: Any, rhs: Any) -> AnyDefault combine_symbolic for backends with arithmetic-capable Parameters.
Performs Python operator dispatch on the operands. Used by
evaluate_binop whenever the active emitter does not define its
own combine_symbolic method — the typical case for Qiskit
(ParameterExpression overloads __add__ etc.) and CUDA-Q
parameters. Backends whose Parameter type lacks Python operators
(e.g. QURI Parts) define their own combine_symbolic on the
emitter class to return a backend-native symbolic representation
instead.
Parameters:
| Name | Type | Description |
|---|---|---|
kind | 'BinOpKind' | The BinOpKind to apply. |
lhs | Any | Left operand (numeric or backend Parameter / expression). |
rhs | Any | Right operand (same shape). |
Returns:
Any — lhs OP rhs for the matching operator. 0.0 / 0 for
Any — division-by-zero in the symbolic path so the caller can finish
Any — emission without aborting on a numerically degenerate case.
Any — None for unrecognised kind values, which the caller
Any — treats as a no-op.
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.
evaluate_classical_predicate [source]¶
def evaluate_classical_predicate(
emit_pass: 'StandardEmitPass',
op: 'CompOp | CondOp | NotOp',
bindings: dict[str, Any],
) -> NoneEvaluate a CompOp/CondOp/NotOp at emit time and bind its boolean result.
Mirrors the predicate evaluation already done by
compile_time_if_lowering and classical_executor so that an
IfOperation whose condition reaches emit unfolded — typically
because its operands depend on a loop variable bound only at emit time
by emit_for_items / emit_for_unrolled — can still be resolved
via resolve_if_condition.
Delegates the actual fold (including runtime-parameter guard and
strict scalar typing) to fold_classical_op so that all three
callers of the same kind dispatch share one implementation. There
is no symbolic-Parameter fallback for predicates: a runtime classical
expression cannot be expressed as a folded scalar, so the op is left
unbound and downstream emit handles it as a runtime condition.
Parameters:
| Name | Type | Description |
|---|---|---|
emit_pass | 'StandardEmitPass' | The active emit pass (for resolver access). |
op | 'CompOp | CondOp | NotOp' | The predicate op to evaluate. |
bindings | dict[str, Any] | Current parameter/loop-variable bindings; mutated in place on successful evaluation. No-op when operands are unresolvable (e.g. measurement bits) or evaluation raises. |
Returns:
None — None.
fold_classical_op [source]¶
def fold_classical_op(
op: 'BinOp | CompOp | CondOp | NotOp',
operand_resolver: Callable[[Any], Any],
parameters: set[str],
policy: FoldPolicy,
) -> Any | NoneFold a classical op to a concrete value, respecting the given policy.
The caller supplies an operand_resolver callable that knows how
to look up a Value in the caller’s context (a concrete_values
map, an emit bindings dict + ValueResolver, or any other
source). This function handles:
The parameter guard (skips folding when an operand is a runtime parameter or parameter-array element under
EMIT_RESPECT_PARAMS).Strict scalar-only typing (rejects backend
Exprobjects and other non-numeric values that would spuriously fold toTrue).Kind dispatch via the underlying
evaluate_*_valuesprimitives.
Parameters:
| Name | Type | Description |
|---|---|---|
op | 'BinOp | CompOp | CondOp | NotOp' | The classical op to fold. Must be one of BinOp, CompOp, CondOp, NotOp. |
operand_resolver | Callable[[Any], Any] | Callable mapping each operand Value to a resolved Python scalar (or None when unresolvable). |
parameters | set[str] | Set of runtime parameter names. Used only when policy is EMIT_RESPECT_PARAMS. |
policy | FoldPolicy | Folding policy. See FoldPolicy docstring. |
Returns:
Any | None — The folded value (numeric for BinOp, bool for predicates),
Any | None — or None when any operand is symbolic, missing, or a runtime
Any | None — parameter under the policy.
handle_cast [source]¶
def handle_cast(emit_pass: 'StandardEmitPass', op: CastOperation, qubit_map: QubitMap) -> NoneHandle CastOperation - update qubit_map without emitting gates.
Classes¶
BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
CastOperation [source]¶
class CastOperation(Operation)Type cast operation for creating aliases over the same quantum resources.
This operation does NOT allocate new qubits. It creates a new Value that references the same underlying quantum resources with a different type.
Use cases:
Vector[Qubit] -> QFixed (after QPE, for phase measurement)
Vector[Qubit] -> QUInt (for quantum arithmetic)
QUInt -> QFixed (reinterpret bits with different encoding)
QFixed -> QUInt (reinterpret bits with different encoding)
operands: [source_value] - The value being cast results: [cast_result] - The new value with target type (same physical qubits)
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
source_type: ValueType | None = None,
target_type: ValueType | None = None,
qubit_mapping: list[str] = list(),
) -> NoneAttributes¶
num_qubits: int Number of qubits involved in the cast.operation_kind: OperationKind Cast stays in the same segment as its source (QUANTUM for quantum types).qubit_mapping: list[str]signature: Signature Return the type signature of this cast operation.source_type: ValueType | Nonetarget_type: ValueType | None
CompOp [source]¶
class CompOp(BinaryOperationBase)Comparison operation (EQ, NEQ, LT, LE, GT, GE).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CompOpKind | None = None,
) -> NoneAttributes¶
kind: CompOpKind | Noneoperation_kind: OperationKindsignature: Signature
CondOp [source]¶
class CondOp(BinaryOperationBase)Conditional logical operation (AND, OR).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CondOpKind | None = None,
) -> NoneAttributes¶
kind: CondOpKind | Noneoperation_kind: OperationKindsignature: Signature
FoldPolicy [source]¶
class FoldPolicy(enum.Enum)Policy controlling how fold_classical_op treats parameters.
COMPILE_TIME is for passes that have no notion of runtime
parameters (e.g. compile_time_if_lowering); every operand the
resolver returns is treated as a real value to fold.
EMIT_RESPECT_PARAMS is for emit-time passes where some Values
may correspond to runtime backend parameters whose concrete values
are placeholders or absent. Operands whose Value or
parent_array.name is in the active parameters set are
treated as symbolic and the fold returns None rather than
producing an incorrect concrete result.
Attributes¶
COMPILE_TIMEEMIT_RESPECT_PARAMS
NotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
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,
)qamomile.circuit.transpiler.passes.emit_support.composite_decomposer¶
Composite gate decomposition helpers.
Overview¶
| Class | Description |
|---|---|
CompositeDecomposer | Decomposes composite gates into primitive operations. |
Classes¶
CompositeDecomposer [source]¶
class CompositeDecomposerDecomposes composite gates into primitive operations.
Methods¶
iqft_structure¶
@staticmethod
def iqft_structure(n: int) -> list[tuple[str, tuple[int, ...], float | None]]qft_structure¶
@staticmethod
def qft_structure(n: int) -> list[tuple[str, tuple[int, ...], float | None]]qamomile.circuit.transpiler.passes.emit_support.composite_gate_emission¶
Composite gate emission helpers extracted from StandardEmitPass.
This module provides module-level functions for emitting composite gates
(QFT, IQFT, QPE) and their approximate variants. Each function takes an
emit_pass parameter (a StandardEmitPass instance) in place of
self.
Overview¶
| Function | Description |
|---|---|
emit_approximate_iqft | Emit approximate IQFT with truncated rotations matching stdlib convention. |
emit_approximate_qft | Emit approximate QFT with truncated rotations matching stdlib convention. |
emit_composite_fallback | Emit composite gate using decomposition. |
emit_composite_gate | Emit a composite gate operation. |
emit_iqft_manual | Emit inverse QFT using decomposition matching stdlib convention. |
emit_iqft_with_strategy | Emit IQFT considering strategy selection. |
emit_qft_manual | Emit QFT using decomposition matching stdlib convention. |
emit_qft_with_strategy | Emit QFT considering strategy selection. |
emit_qpe_manual | Emit QPE using manual decomposition. |
extract_phase_from_params | Extract phase parameter from QPE operation. |
update_composite_result_mapping | Update qubit_map for composite gate results. |
| Class | Description |
|---|---|
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CompositeGateType | Registry of known composite gate types. |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
Functions¶
emit_approximate_iqft [source]¶
def emit_approximate_iqft(
emit_pass: 'StandardEmitPass',
circuit: Any,
qubit_indices: list[int],
truncation_depth: int,
) -> NoneEmit approximate IQFT with truncated rotations matching stdlib convention.
IQFT = QFT†. SWAP comes first (undoing QFT’s trailing SWAP), then for each qubit j (low-to-high), applies inverse controlled-phase rotations with lower-indexed qubits first (omitting exponents > truncation_depth), then H.
Parameters:
| Name | Type | Description |
|---|---|---|
emit_pass | 'StandardEmitPass' | The StandardEmitPass instance. |
circuit | Any | Target circuit |
qubit_indices | list[int] | Qubit indices |
truncation_depth | int | Maximum exponent for controlled phase gates |
emit_approximate_qft [source]¶
def emit_approximate_qft(
emit_pass: 'StandardEmitPass',
circuit: Any,
qubit_indices: list[int],
truncation_depth: int,
) -> NoneEmit approximate QFT with truncated rotations matching stdlib convention.
Processes qubits from highest index to lowest (same as exact QFT), applying H then controlled-phase rotations with lower-indexed qubits. Rotations with exponent > truncation_depth are omitted. Finishes with bit-reversal SWAPs.
Parameters:
| Name | Type | Description |
|---|---|---|
emit_pass | 'StandardEmitPass' | The StandardEmitPass instance. |
circuit | Any | Target circuit |
qubit_indices | list[int] | Qubit indices |
truncation_depth | int | Maximum exponent for controlled phase gates |
emit_composite_fallback [source]¶
def emit_composite_fallback(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: CompositeGateOperation,
qubit_indices: list[int],
bindings: dict[str, Any],
) -> NoneEmit composite gate using decomposition.
If the operation has a strategy_name set, it attempts to use the corresponding strategy from the CompositeGate class.
emit_composite_gate [source]¶
def emit_composite_gate(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: CompositeGateOperation,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit a composite gate operation.
emit_iqft_manual [source]¶
def emit_iqft_manual(emit_pass: 'StandardEmitPass', circuit: Any, qubit_indices: list[int]) -> NoneEmit inverse QFT using decomposition matching stdlib convention.
IQFT = QFT†. SWAP comes first (undoing QFT’s trailing SWAP), then for each qubit j (low-to-high), applies inverse controlled-phase rotations with all lower-indexed qubits k (angle = -π/2^(j-k)) first, then H.
emit_iqft_with_strategy [source]¶
def emit_iqft_with_strategy(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: CompositeGateOperation,
qubit_indices: list[int],
) -> NoneEmit IQFT considering strategy selection.
If a strategy is specified and ‘approximate’, uses truncated rotations. Otherwise falls back to standard IQFT.
emit_qft_manual [source]¶
def emit_qft_manual(emit_pass: 'StandardEmitPass', circuit: Any, qubit_indices: list[int]) -> NoneEmit QFT using decomposition matching stdlib convention.
Processes qubits from highest index to lowest: for each qubit j, applies H then controlled-phase rotations with all lower-indexed qubits k (angle = π/2^(j-k)). Finishes with bit-reversal SWAPs.
emit_qft_with_strategy [source]¶
def emit_qft_with_strategy(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: CompositeGateOperation,
qubit_indices: list[int],
) -> NoneEmit QFT considering strategy selection.
If a strategy is specified and ‘approximate’, uses truncated rotations. Otherwise falls back to standard QFT.
emit_qpe_manual [source]¶
def emit_qpe_manual(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: CompositeGateOperation,
qubit_indices: list[int],
bindings: dict[str, Any],
) -> NoneEmit QPE using manual decomposition.
extract_phase_from_params [source]¶
def extract_phase_from_params(
emit_pass: 'StandardEmitPass',
op: CompositeGateOperation,
bindings: dict[str, Any],
) -> float | NoneExtract phase parameter from QPE operation.
update_composite_result_mapping [source]¶
def update_composite_result_mapping(
op: CompositeGateOperation,
qubit_indices: list[int],
qubit_map: QubitMap,
) -> NoneUpdate qubit_map for composite gate results.
Classes¶
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
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
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,
)qamomile.circuit.transpiler.passes.emit_support.condition_resolution¶
Helpers for compile-time condition resolution and phi remapping.
Overview¶
| Function | Description |
|---|---|
map_phi_outputs | Register phi output UUIDs to the same physical resources as their sources. |
remap_static_phi_outputs | Remap phi outputs for a compile-time constant IfOperation. |
resolve_if_condition | Resolve an if-condition to a compile-time boolean. |
resolve_qubit_key | Resolve a qubit Value to its allocation key. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
BitType | Type representing a classical bit. |
PhiOp | SSA Phi function: merge point after conditional branch. |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
Functions¶
map_phi_outputs [source]¶
def map_phi_outputs(
phi_ops: list,
qubit_map: QubitMap,
clbit_map: ClbitMap,
resolve_scalar_qubit: Any = None,
) -> NoneRegister phi output UUIDs to the same physical resources as their sources.
remap_static_phi_outputs [source]¶
def remap_static_phi_outputs(
phi_ops: list,
condition_value: bool,
qubit_map: QubitMap,
clbit_map: ClbitMap,
) -> NoneRemap phi outputs for a compile-time constant IfOperation.
resolve_if_condition [source]¶
def resolve_if_condition(condition: Any, bindings: dict[str, Any]) -> bool | NoneResolve an if-condition to a compile-time boolean.
resolve_qubit_key [source]¶
def resolve_qubit_key(qubit: 'Value') -> tuple[QubitAddress | None, bool]Resolve a qubit Value to its allocation key.
Returns a (QubitAddress | None, is_array_element) tuple.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
PhiOp [source]¶
class PhiOp(Operation)SSA Phi function: merge point after conditional branch.
This operation selects one of two values based on a condition. Used to merge values from different branches of an if-else statement.
Example:
if condition:
x = x + 1 # true_value
else:
x = x + 2 # false_value
# x is now PhiOp(condition, true_value, false_value)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
condition: Valuefalse_value: Valueoperation_kind: OperationKindoutput: Valuesignature: Signaturetrue_value: Value
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
qamomile.circuit.transpiler.passes.emit_support.control_flow_emission¶
Control flow emission helpers for StandardEmitPass.
Extracted from standard_emit.py to keep the main class focused on
gate-level dispatch. Each function mirrors the original method but takes
an explicit emit_pass parameter instead of self.
These are the default implementations. Backend-specific emit passes
(e.g., QiskitEmitPass) may override the corresponding methods on
StandardEmitPass; calling super()._emit_for(...) etc. will
ultimately delegate here.
Overview¶
| Function | Description |
|---|---|
emit_for | Emit a for loop. |
emit_for_items | Emit for-items loop (always unrolled). |
emit_for_unrolled | Emit for loop by unrolling. |
emit_if | Emit if/else operation. |
emit_while | Emit while loop operation. |
map_phi_outputs | Register phi output UUIDs to the same physical resources as their sources. |
register_classical_phi_aliases | Bind classical phi outputs to a concrete value when resolvable. |
register_phi_outputs | Register phi output UUIDs via the shared map_phi_outputs utility. |
remap_static_phi_outputs | Remap phi outputs for a compile-time constant IfOperation. |
resolve_dict_entries | Resolve DictValue to concrete (key, value) pairs. |
resolve_if_condition | Resolve an if-condition to a compile-time boolean. |
resolve_loop_bounds | Resolve for-loop bounds (start, stop, step) from operands. |
| Class | Description |
|---|---|
EmitError | Error during backend code emission. |
ForItemsOperation | Represents iteration over dict/iterable items. |
ForOperation | Represents a for loop operation. |
IfOperation | Represents an if-else conditional operation. |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
Value | A typed SSA value in the IR. |
WhileOperation | Represents a while loop operation. |
Functions¶
emit_for [source]¶
def emit_for(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: ForOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
force_unroll: bool = False,
) -> NoneEmit a for loop.
emit_for_items [source]¶
def emit_for_items(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: ForItemsOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit for-items loop (always unrolled).
This handles iteration over Dict items, e.g.: for (i, j), Jij in qmc.items(ising): ...
emit_for_unrolled [source]¶
def emit_for_unrolled(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: ForOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit for loop by unrolling.
emit_if [source]¶
def emit_if(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: IfOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit if/else operation.
Handles two condition types:
Compile-time constant (plain Python
int/boolfrom@qkernelAST transformer closure variables, constant-folded Values, or Values resolvable viabindings): the active branch is emitted unconditionally, the inactive branch is discarded. No backendc_if/if_testis needed.Runtime condition (measurement
Valuethat cannot be resolved at compile time): delegates to the backend’semit_if_start/emit_else_start/emit_if_endprotocol.
emit_while [source]¶
def emit_while(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: WhileOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit while loop operation.
map_phi_outputs [source]¶
def map_phi_outputs(
phi_ops: list,
qubit_map: QubitMap,
clbit_map: ClbitMap,
resolve_scalar_qubit: Any = None,
) -> NoneRegister phi output UUIDs to the same physical resources as their sources.
register_classical_phi_aliases [source]¶
def register_classical_phi_aliases(
emit_pass: 'StandardEmitPass',
phi_ops: list,
bindings: dict[str, Any],
resolved: bool | None,
) -> NoneBind classical phi outputs to a concrete value when resolvable.
The frontend creates a phi for every variable referenced in an
if-branch, including read-only ones (e.g. a for-loop index j that
is read but not assigned in the branch). These read-only phis have
true_value is false_value — both inputs reference the same IR
Value — so the phi output is deterministically equal to that input.
For classical types (UInt / Float / Bit) the phi outputs are not
captured by map_phi_outputs / remap_static_phi_outputs (which
only handle qubit / clbit phys-resource mapping). Without this
binding, downstream uses like data[j_phi_4] cannot resolve the
index and emit fails with symbolic_index_not_bound.
The alias is written to bindings by both UUID and (when present)
name, mirroring the pattern used by emit_for_unrolled for the
original loop variable.
Parameters:
| Name | Type | Description |
|---|---|---|
emit_pass | 'StandardEmitPass' | The active emit pass (for resolver access). |
phi_ops | list | IfOperation.phi_ops. |
bindings | dict[str, Any] | Current bindings; mutated in place to bind phi outputs. |
resolved | bool | None | True / False if the if was compile-time resolved (use the selected branch’s input); None if it was a runtime if (only bind when both inputs resolve to the same value). |
Returns:
None — None.
register_phi_outputs [source]¶
def register_phi_outputs(
emit_pass: 'StandardEmitPass',
op: IfOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any] | None = None,
) -> NoneRegister phi output UUIDs via the shared map_phi_outputs utility.
Uses the full ValueResolver.resolve_qubit_index_detailed for
scalar qubit resolution (handles array element operands).
remap_static_phi_outputs [source]¶
def remap_static_phi_outputs(
phi_ops: list,
condition_value: bool,
qubit_map: QubitMap,
clbit_map: ClbitMap,
) -> NoneRemap phi outputs for a compile-time constant IfOperation.
resolve_dict_entries [source]¶
def resolve_dict_entries(
emit_pass: 'StandardEmitPass',
dict_value: Any,
bindings: dict[str, Any],
) -> list[tuple[Any, Any]] | NoneResolve DictValue to concrete (key, value) pairs.
Parameters:
| Name | Type | Description |
|---|---|---|
emit_pass | 'StandardEmitPass' | The StandardEmitPass instance (for resolver access) |
dict_value | Any | The DictValue IR node being iterated |
bindings | dict[str, Any] | Current parameter bindings |
Returns:
list[tuple[Any, Any]] | None — List of (key, value) tuples, or None if cannot be resolved
resolve_if_condition [source]¶
def resolve_if_condition(condition: Any, bindings: dict[str, Any]) -> bool | NoneResolve an if-condition to a compile-time boolean.
resolve_loop_bounds [source]¶
def resolve_loop_bounds(
resolver: Any,
op: ForOperation,
bindings: dict[str, Any],
) -> tuple[int | None, int | None, int | None]Resolve for-loop bounds (start, stop, step) from operands.
Missing operands use defaults: start=0, stop=1, step=1. Returns None for bounds that cannot be resolved to concrete ints.
Classes¶
EmitError [source]¶
class EmitError(QamomileCompileError)Error during backend code emission.
Constructor¶
def __init__(self, message: str, operation: str | None = None)Attributes¶
operation
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]) -> OperationIfOperation [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]]) -> OperationQubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
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,
)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]]) -> Operationqamomile.circuit.transpiler.passes.emit_support.controlled_emission¶
Controlled operation emission helpers extracted from StandardEmitPass.
This module provides module-level functions for emitting controlled-U
operations, controlled gates, and related helpers. Each function takes an
emit_pass parameter (a StandardEmitPass instance) in place of
self.
Note: emit_controlled_fallback and blockvalue_to_gate are called
via emit_pass._emit_controlled_fallback(...) and
emit_pass._blockvalue_to_gate(...) respectively, so that subclass
overrides (e.g. CudaqEmitPass) are respected.
Overview¶
| Function | Description |
|---|---|
blockvalue_to_gate | Convert a Block to a backend gate. |
emit_controlled_block | Emit controlled version of a block. |
emit_controlled_fallback | Fallback emission for controlled-U when gate conversion fails. |
emit_controlled_gate | Emit a controlled version of a gate. |
emit_controlled_operations | Emit controlled versions of operations. |
emit_controlled_powers | Emit controlled-U^(2^k) operations. |
emit_controlled_u | Emit a ControlledUOperation. |
emit_controlled_u_with_index_spec | Emit a ControlledUOperation with target_indices/controlled_indices. |
emit_custom_composite | Emit a custom composite gate with implementation. |
resolve_power | Resolve ControlledUOperation.power to a concrete int. |
| Class | Description |
|---|---|
ConcreteControlledU | Controlled-U with concrete (int) number of controls. |
ControlledUOperation | Base class for controlled-U operations. |
EmitError | Error during backend code emission. |
ForOperation | Represents a for loop operation. |
GateOperation | Quantum gate operation. |
GateOperationType | |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IndexSpecControlledU | Controlled-U with explicit target/control index specification. |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
SymbolicControlledU | Controlled-U with symbolic (Value) number of controls. |
Value | A typed SSA value in the IR. |
Functions¶
blockvalue_to_gate [source]¶
def blockvalue_to_gate(
emit_pass: 'StandardEmitPass',
block_value: Any,
num_qubits: int,
bindings: dict[str, Any],
) -> AnyConvert a Block to a backend gate.
emit_controlled_block [source]¶
def emit_controlled_block(
emit_pass: 'StandardEmitPass',
circuit: Any,
block_value: Any,
control_idx: int,
target_indices: list[int],
bindings: dict[str, Any],
) -> NoneEmit controlled version of a block.
emit_controlled_fallback [source]¶
def emit_controlled_fallback(
emit_pass: 'StandardEmitPass',
circuit: Any,
block_value: Any,
num_controls: int,
control_indices: list[int],
target_indices: list[int],
power: int,
bindings: dict[str, Any],
) -> NoneFallback emission for controlled-U when gate conversion fails.
Decomposes the block body gate-by-gate with single-control emission. Subclasses may override to support multi-control natively.
Parameters:
| Name | Type | Description |
|---|---|---|
emit_pass | 'StandardEmitPass' | The StandardEmitPass instance. |
circuit | Any | The backend circuit being built. |
block_value | Any | The block value containing operations to control. |
num_controls | int | Number of control qubits. |
control_indices | list[int] | Physical indices of control qubits. |
target_indices | list[int] | Physical indices of target qubits. |
power | int | Number of times to repeat the controlled operation. |
bindings | dict[str, Any] | Parameter bindings. |
Raises:
EmitError— When num_controls > 1 (multi-control not supported in the default gate-by-gate decomposition).
emit_controlled_gate [source]¶
def emit_controlled_gate(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: GateOperation,
control_idx: int,
target_indices: list[int],
bindings: dict[str, Any],
) -> NoneEmit a controlled version of a gate.
emit_controlled_operations [source]¶
def emit_controlled_operations(
emit_pass: 'StandardEmitPass',
circuit: Any,
operations: list[Operation],
control_idx: int,
target_indices: list[int],
bindings: dict[str, Any],
) -> NoneEmit controlled versions of operations.
emit_controlled_powers [source]¶
def emit_controlled_powers(
emit_pass: 'StandardEmitPass',
circuit: Any,
block_value: Any,
counting_indices: list[int],
target_indices: list[int],
bindings: dict[str, Any],
) -> NoneEmit controlled-U^(2^k) operations.
emit_controlled_u [source]¶
def emit_controlled_u(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: ControlledUOperation,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit a ControlledUOperation.
emit_controlled_u_with_index_spec [source]¶
def emit_controlled_u_with_index_spec(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: ControlledUOperation,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit a ControlledUOperation with target_indices/controlled_indices.
emit_custom_composite [source]¶
def emit_custom_composite(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: Any,
impl: Any,
qubit_indices: list[int],
bindings: dict[str, Any],
) -> NoneEmit a custom composite gate with implementation.
resolve_power [source]¶
def resolve_power(
emit_pass: 'StandardEmitPass',
op: ControlledUOperation,
bindings: dict[str, Any],
) -> intResolve ControlledUOperation.power to a concrete int.
Classes¶
ConcreteControlledU [source]¶
class ConcreteControlledU(ControlledUOperation)Controlled-U with concrete (int) number of controls.
Operand layout: [ctrl_0, ..., ctrl_n, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_0', ..., ctrl_n', tgt_0', ..., tgt_m']
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: int = 1,
) -> NoneAttributes¶
control_operands: list[Value]num_controls: intparam_operands: list[Value]signature: Signaturetarget_operands: list[Value]
ControlledUOperation [source]¶
class ControlledUOperation(Operation)Base class for controlled-U operations.
Three concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands.IndexSpecControlledU: Single vector with explicit index lists selecting which elements are controls/targets.
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,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.has_index_spec: bool Whether target/control positions are specified via index lists.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.operation_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]) -> OperationEmitError [source]¶
class EmitError(QamomileCompileError)Error during backend code emission.
Constructor¶
def __init__(self, message: str, operation: str | None = None)Attributes¶
operation
ForOperation [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().
IndexSpecControlledU [source]¶
class IndexSpecControlledU(ControlledUOperation)Controlled-U with explicit target/control index specification.
A single vector covers both controls and targets; the partition is
determined by target_indices or controlled_indices.
Operand layout: [vector, params...]
Result layout: [vector']
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,
target_indices: list[Value] | None = None,
controlled_indices: list[Value] | None = None,
) -> NoneAttributes¶
control_operands: list[Value]controlled_indices: list[Value] | Nonehas_index_spec: boolis_symbolic_num_controls: boolnum_controls: int | Valueparam_operands: list[Value]signature: Signaturetarget_indices: list[Value] | Nonetarget_operands: list[Value]
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationQubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
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,
)SymbolicControlledU [source]¶
class SymbolicControlledU(ControlledUOperation)Controlled-U with symbolic (Value) number of controls.
Operand layout: [ctrl_vector, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_vector', tgt_0', ..., tgt_m']
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: Value = (lambda: Value(type=(FloatType()), name='_placeholder'))(),
) -> NoneAttributes¶
control_operands: list[Value]is_symbolic_num_controls: boolnum_controls: Valueparam_operands: list[Value]signature: Signaturetarget_operands: list[Value]
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationValue [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.
qamomile.circuit.transpiler.passes.emit_support.gate_emission¶
Gate emission helper extracted from StandardEmitPass.
Provides emit_gate and resolve_angle as module-level functions so
they can be tested and reused independently of the class.
Overview¶
| Function | Description |
|---|---|
emit_gate | Emit a single gate operation. |
resolve_angle | Resolve angle parameter for rotation gates. |
| Class | Description |
|---|---|
GateOperation | Quantum gate operation. |
GateOperationType | |
OperandResolutionInfo | Detailed information about a single operand that failed to resolve. |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
QubitIndexResolutionError | Error when qubit indices cannot be resolved during emission. |
ResolutionFailureReason | Categorizes why qubit index resolution failed. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
UnifiedValueResolver | Resolves IR Values to concrete Python values. |
Functions¶
emit_gate [source]¶
def emit_gate(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: GateOperation,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit a single gate operation.
resolve_angle [source]¶
def resolve_angle(
emit_pass: 'StandardEmitPass',
op: GateOperation,
bindings: dict[str, Any],
) -> float | AnyResolve angle parameter for rotation gates.
theta is always a Value stored as the last element of operands for rotation gates.
Classes¶
GateOperation [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
OperandResolutionInfo [source]¶
class OperandResolutionInfoDetailed information about a single operand that failed to resolve.
Constructor¶
def __init__(
self,
operand_name: str,
operand_uuid: str,
is_array_element: bool,
parent_array_name: str | None,
element_indices_names: list[str],
failure_reason: ResolutionFailureReason,
failure_details: str,
) -> NoneAttributes¶
element_indices_names: list[str]failure_details: strfailure_reason: ResolutionFailureReasonis_array_element: booloperand_name: stroperand_uuid: strparent_array_name: str | None
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
QubitIndexResolutionError [source]¶
class QubitIndexResolutionError(EmitError)Error when qubit indices cannot be resolved during emission.
This error provides detailed diagnostic information about why qubit index resolution failed and suggests remediation steps.
Constructor¶
def __init__(
self,
gate_type: str,
operand_infos: list[OperandResolutionInfo],
available_bindings_keys: list[str],
available_qubit_map_keys: list[str],
)Attributes¶
available_bindings_keysavailable_qubit_map_keysgate_typeoperand_infos
ResolutionFailureReason [source]¶
class ResolutionFailureReason(Enum)Categorizes why qubit index resolution failed.
Attributes¶
ARRAY_ELEMENT_NOT_IN_QUBIT_MAPDIRECT_UUID_NOT_FOUNDINDEX_NOT_NUMERICNESTED_ARRAY_RESOLUTION_FAILEDSYMBOLIC_INDEX_NOT_BOUNDUNKNOWN
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,
)ValueResolver [source]¶
class ValueResolverResolves IR Values to concrete Python values.
Parameters¶
context:
UUID-keyed map of already-resolved values. The values may be
either raw Python scalars or Value objects; if a Value is
found its get_const() is extracted automatically.
bindings:
Name-keyed parameter bindings supplied by the user at transpile
time.
Constructor¶
def __init__(
self,
context: dict[str, Any] | None = None,
bindings: dict[str, Any] | None = None,
)Methods¶
resolve¶
def resolve(self, value: Any) -> Any | NoneResolve value to a concrete Python value, or None.
If value is not a Value-like object (no uuid attribute) it
is returned as-is — the caller already has a concrete value.
qamomile.circuit.transpiler.passes.emit_support.loop_analyzer¶
Loop analysis helpers for emission.
Identity policy: loop variables are identified by their IR Value
UUID (ForOperation.loop_var_value.uuid), not by their display
name. Two nested or sibling loops with identical user-chosen names
(e.g. for i in range(N): for i in range(M):) are distinct here
because each ForOperation carries its own loop_var_value with
a fresh UUID, and UUIDRemapper clones that field consistently with
body references via the all_input_values / replace_values
protocol.
There is no name fallback: if loop_var_value is None (legacy
IR built before the field existed) we skip the loop-var checks entirely.
Comparing by name was the soil for nested-loop name-collision bugs.
Overview¶
| Class | Description |
|---|---|
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
ControlledUOperation | Base class for controlled-U operations. |
ForOperation | Represents a for loop operation. |
GateOperation | Quantum gate operation. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
LoopAnalyzer | Analyzes loop structures to determine emission strategy. |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
Value | A typed SSA value in the IR. |
Classes¶
BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
ControlledUOperation [source]¶
class ControlledUOperation(Operation)Base class for controlled-U operations.
Three concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands.IndexSpecControlledU: Single vector with explicit index lists selecting which elements are controls/targets.
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,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.has_index_spec: bool Whether target/control positions are specified via index lists.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.operation_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]) -> 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.
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().
LoopAnalyzer [source]¶
class LoopAnalyzerAnalyzes loop structures to determine emission strategy.
Methods¶
should_unroll¶
def should_unroll(self, op: ForOperation, bindings: dict[str, object]) -> boolPauliEvolveOp [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
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.
qamomile.circuit.transpiler.passes.emit_support.measurement_emission¶
Measurement emission helpers extracted from StandardEmitPass.
Provides emit_measure, emit_measure_vector and
emit_measure_qfixed as module-level functions.
Overview¶
| Function | Description |
|---|---|
emit_measure | Emit a single measurement. |
emit_measure_qfixed | Emit QFixed measurement. |
emit_measure_vector | Emit vector measurement. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
MeasureOperation | |
MeasureQFixedOperation | Measure a quantum fixed-point number. |
MeasureVectorOperation | Measure a vector of qubits. |
MeasurementMode | How a backend handles measurement operations. |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
Functions¶
emit_measure [source]¶
def emit_measure(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: MeasureOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any] | None = None,
) -> NoneEmit a single measurement.
Resolves the qubit operand using the full resolver (handles both scalar qubits and array element qubits with composite keys).
Raises:
warnings.warn— If the qubit or clbit cannot be resolved, a warning is emitted instead of silently dropping the measurement.
emit_measure_qfixed [source]¶
def emit_measure_qfixed(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: MeasureQFixedOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
) -> NoneEmit QFixed measurement.
emit_measure_vector [source]¶
def emit_measure_vector(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: MeasureVectorOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit vector measurement.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]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
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
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,
)qamomile.circuit.transpiler.passes.emit_support.pauli_evolve_emission¶
Pauli evolution emission helper for StandardEmitPass.
Extracted from standard_emit.py to isolate the Hamiltonian
decomposition logic from the main emit dispatch.
The emit_pauli_evolve function is the default implementation.
Backend-specific emit passes (e.g., QiskitEmitPass) may override
the corresponding _emit_pauli_evolve method; calling
super()._emit_pauli_evolve(...) will ultimately delegate here.
Overview¶
| Function | Description |
|---|---|
emit_pauli_evolve | Emit Pauli evolution: exp(-i * gamma * H). |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
EmitError | Error during backend code emission. |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
Functions¶
emit_pauli_evolve [source]¶
def emit_pauli_evolve(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: PauliEvolveOp,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit Pauli evolution: exp(-i * gamma * H).
Resolves the Hamiltonian from bindings and decomposes each term using the Pauli gadget technique:
Basis change per qubit (X->H, Y->Sdg*H, Z->identity)
CNOT ladder + RZ
Undo basis change
Subclasses can override this for backend-native implementations (e.g., Qiskit PauliEvolutionGate).
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]EmitError [source]¶
class EmitError(QamomileCompileError)Error during backend code emission.
Constructor¶
def __init__(self, message: str, operation: str | None = None)Attributes¶
operation
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
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
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,
)qamomile.circuit.transpiler.passes.emit_support.qubit_address¶
Typed key for qubit/clbit physical-index maps.
Replaces the ad-hoc f"{uuid}_{index}" string convention with an
explicit, hashable value object that makes the construction/parsing
contract type-safe.
Overview¶
| Class | Description |
|---|---|
QubitAddress | Typed key for qubit/clbit physical-index maps. |
Classes¶
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
qamomile.circuit.transpiler.passes.emit_support.resource_allocator¶
Resource allocation helpers for emission.
Overview¶
| Function | Description |
|---|---|
map_phi_outputs | Register phi output UUIDs to the same physical resources as their sources. |
remap_static_phi_outputs | Remap phi outputs for a compile-time constant IfOperation. |
resolve_if_condition | Resolve an if-condition to a compile-time boolean. |
resolve_qubit_key | Resolve a qubit Value to its allocation key. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
ConcreteControlledU | Controlled-U with concrete (int) number of controls. |
ControlledUOperation | Base class for controlled-U operations. |
GateOperation | Quantum gate operation. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
IndexSpecControlledU | Controlled-U with explicit target/control index specification. |
MeasureOperation | |
MeasureQFixedOperation | Measure a quantum fixed-point number. |
MeasureVectorOperation | Measure a vector of qubits. |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
PhiOp | SSA Phi function: merge point after conditional branch. |
QInitOperation | Initialize the qubit |
QubitAddress | Typed key for qubit/clbit physical-index maps. |
ResourceAllocator | Allocates qubit and classical bit indices from operations. |
SymbolicControlledU | Controlled-U with symbolic (Value) number of controls. |
Value | A typed SSA value in the IR. |
WhileOperation | Represents a while loop operation. |
Functions¶
map_phi_outputs [source]¶
def map_phi_outputs(
phi_ops: list,
qubit_map: QubitMap,
clbit_map: ClbitMap,
resolve_scalar_qubit: Any = None,
) -> NoneRegister phi output UUIDs to the same physical resources as their sources.
remap_static_phi_outputs [source]¶
def remap_static_phi_outputs(
phi_ops: list,
condition_value: bool,
qubit_map: QubitMap,
clbit_map: ClbitMap,
) -> NoneRemap phi outputs for a compile-time constant IfOperation.
resolve_if_condition [source]¶
def resolve_if_condition(condition: Any, bindings: dict[str, Any]) -> bool | NoneResolve an if-condition to a compile-time boolean.
resolve_qubit_key [source]¶
def resolve_qubit_key(qubit: 'Value') -> tuple[QubitAddress | None, bool]Resolve a qubit Value to its allocation key.
Returns a (QubitAddress | None, is_array_element) tuple.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]CastOperation [source]¶
class CastOperation(Operation)Type cast operation for creating aliases over the same quantum resources.
This operation does NOT allocate new qubits. It creates a new Value that references the same underlying quantum resources with a different type.
Use cases:
Vector[Qubit] -> QFixed (after QPE, for phase measurement)
Vector[Qubit] -> QUInt (for quantum arithmetic)
QUInt -> QFixed (reinterpret bits with different encoding)
QFixed -> QUInt (reinterpret bits with different encoding)
operands: [source_value] - The value being cast results: [cast_result] - The new value with target type (same physical qubits)
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
source_type: ValueType | None = None,
target_type: ValueType | None = None,
qubit_mapping: list[str] = list(),
) -> NoneAttributes¶
num_qubits: int Number of qubits involved in the cast.operation_kind: OperationKind Cast stays in the same segment as its source (QUANTUM for quantum types).qubit_mapping: list[str]signature: Signature Return the type signature of this cast operation.source_type: ValueType | Nonetarget_type: ValueType | None
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.
ConcreteControlledU [source]¶
class ConcreteControlledU(ControlledUOperation)Controlled-U with concrete (int) number of controls.
Operand layout: [ctrl_0, ..., ctrl_n, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_0', ..., ctrl_n', tgt_0', ..., tgt_m']
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: int = 1,
) -> NoneAttributes¶
control_operands: list[Value]num_controls: intparam_operands: list[Value]signature: Signaturetarget_operands: list[Value]
ControlledUOperation [source]¶
class ControlledUOperation(Operation)Base class for controlled-U operations.
Three concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands.IndexSpecControlledU: Single vector with explicit index lists selecting which elements are controls/targets.
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,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.has_index_spec: bool Whether target/control positions are specified via index lists.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.operation_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]) -> 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.
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]]) -> OperationIndexSpecControlledU [source]¶
class IndexSpecControlledU(ControlledUOperation)Controlled-U with explicit target/control index specification.
A single vector covers both controls and targets; the partition is
determined by target_indices or controlled_indices.
Operand layout: [vector, params...]
Result layout: [vector']
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,
target_indices: list[Value] | None = None,
controlled_indices: list[Value] | None = None,
) -> NoneAttributes¶
control_operands: list[Value]controlled_indices: list[Value] | Nonehas_index_spec: boolis_symbolic_num_controls: boolnum_controls: int | Valueparam_operands: list[Value]signature: Signaturetarget_indices: list[Value] | Nonetarget_operands: list[Value]
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationMeasureOperation [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
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
PhiOp [source]¶
class PhiOp(Operation)SSA Phi function: merge point after conditional branch.
This operation selects one of two values based on a condition. Used to merge values from different branches of an if-else statement.
Example:
if condition:
x = x + 1 # true_value
else:
x = x + 2 # false_value
# x is now PhiOp(condition, true_value, false_value)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
condition: Valuefalse_value: Valueoperation_kind: OperationKindoutput: Valuesignature: Signaturetrue_value: Value
QInitOperation [source]¶
class QInitOperation(Operation)Initialize the qubit
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
ResourceAllocator [source]¶
class ResourceAllocatorAllocates qubit and classical bit indices from operations.
This class handles the first pass of circuit emission: determining how many physical qubits and classical bits are needed and mapping Value UUIDs to their physical indices.
New physical indices are assigned via monotonic counters
(_next_qubit_index / _next_clbit_index) so that alias
entries — which reuse an existing physical index — never inflate
the counter. Using len(map) would cause sparse (gapped)
physical indices because alias keys increase the map size without
adding new physical resources.
Constructor¶
def __init__(self) -> NoneMethods¶
allocate¶
def allocate(
self,
operations: list[Operation],
bindings: dict[str, Any] | None = None,
) -> tuple[QubitMap, ClbitMap]Allocate qubit and clbit indices for all operations.
Parameters:
| Name | Type | Description |
|---|---|---|
operations | list[Operation] | List of operations to allocate resources for |
bindings | dict[str, Any] | None | Optional variable bindings for resolving dynamic sizes |
Returns:
QubitMap — Tuple of (qubit_map, clbit_map) where each maps
ClbitMap — QubitAddress to physical index
SymbolicControlledU [source]¶
class SymbolicControlledU(ControlledUOperation)Controlled-U with symbolic (Value) number of controls.
Operand layout: [ctrl_vector, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_vector', tgt_0', ..., tgt_m']
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: Value = (lambda: Value(type=(FloatType()), name='_placeholder'))(),
) -> NoneAttributes¶
control_operands: list[Value]is_symbolic_num_controls: boolnum_controls: Valueparam_operands: list[Value]signature: Signaturetarget_operands: list[Value]
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationValue [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]]) -> Operationqamomile.circuit.transpiler.passes.emit_support.value_resolver¶
Value resolution helpers for emission.
Overview¶
| Function | Description |
|---|---|
resolve_qubit_key | Resolve a qubit Value to its allocation key. |
| Class | Description |
|---|---|
QubitAddress | Typed key for qubit/clbit physical-index maps. |
QubitResolutionResult | Result of attempting to resolve a qubit index. |
ResolutionFailureReason | Categorizes why qubit index resolution failed. |
Value | A typed SSA value in the IR. |
ValueResolver | Resolves Value objects to concrete indices or values. |
Functions¶
resolve_qubit_key [source]¶
def resolve_qubit_key(qubit: 'Value') -> tuple[QubitAddress | None, bool]Resolve a qubit Value to its allocation key.
Returns a (QubitAddress | None, is_array_element) tuple.
Classes¶
QubitAddress [source]¶
class QubitAddressTyped key for qubit/clbit physical-index maps.
For scalar qubits: QubitAddress(uuid="abc123")
For array elements: QubitAddress(uuid="abc123", element_index=2)
This replaces the f"{uuid}_{i}" string key pattern throughout
the emit pipeline, making the key format explicit and preventing
format-string bugs.
Constructor¶
def __init__(self, uuid: str, element_index: int | None = None) -> NoneAttributes¶
element_index: int | Noneis_array_element: bool True if this address refers to an array element.uuid: str
Methods¶
from_composite_key¶
@classmethod
def from_composite_key(cls, key: str) -> QubitAddressParse a legacy composite key string into a QubitAddress.
The frontend stores qubit references as composite strings in
the format "{array_uuid}_{element_index}" (e.g., cast
operation qubit mappings, element UUIDs). This helper converts
such strings to proper QubitAddress instances.
If the key does not match the composite format (i.e., the
suffix after the last _ is not a non-negative integer),
it is treated as a plain scalar UUID.
matches_array¶
def matches_array(self, array_uuid: str) -> boolTrue if this address belongs to the given array.
with_element¶
def with_element(self, index: int) -> QubitAddressCreate an array-element address from this array’s base UUID.
QubitResolutionResult [source]¶
class QubitResolutionResultResult of attempting to resolve a qubit index.
Constructor¶
def __init__(
self,
success: bool,
index: int | None = None,
failure_reason: ResolutionFailureReason | None = None,
failure_details: str = '',
) -> NoneAttributes¶
failure_details: strfailure_reason: ResolutionFailureReason | Noneindex: int | Nonesuccess: bool
ResolutionFailureReason [source]¶
class ResolutionFailureReason(Enum)Categorizes why qubit index resolution failed.
Attributes¶
ARRAY_ELEMENT_NOT_IN_QUBIT_MAPDIRECT_UUID_NOT_FOUNDINDEX_NOT_NUMERICNESTED_ARRAY_RESOLUTION_FAILEDSYMBOLIC_INDEX_NOT_BOUNDUNKNOWN
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.
ValueResolver [source]¶
class ValueResolverResolves Value objects to concrete indices or values.
Constructor¶
def __init__(self, parameters: set[str] | None = None)Attributes¶
parameters
Methods¶
bind_block_params¶
def bind_block_params(
self,
block_value: Any,
param_operands: list['Value'],
bindings: dict[str, Any],
) -> dict[str, Any]Create local bindings by matching block parameter inputs to operands.
get_parameter_key¶
def get_parameter_key(self, value: 'Value', bindings: dict[str, Any]) -> str | NoneGet parameter key if this value should be a symbolic parameter.
lookup_in_bindings¶
def lookup_in_bindings(
self,
value: 'Value',
bindings: dict[str, Any],
*,
index_array: bool = False,
) -> AnyCanonical resolution chain for a Value against bindings.
All other resolver methods (resolve_bound_value,
resolve_classical_value, resolve_int_value,
resolve_operand_for_binding) wrap this single chain. Centralizing
precedence here prevents the historical drift where one resolver
checked is_parameter before UUID and another checked it after,
which manifested as obscure binding failures when name-keyed writes
were dropped from the emit pass.
Resolution order (each step returns immediately on a hit):
valueis already a concrete Python scalar (nouuid).value.is_constant()— returnvalue.get_const().value.is_parameter()and its parameter name is inbindings— return that.value.uuidis inbindings— return that. This is where emit-time-computed intermediates (evaluate_binop/evaluate_classical_predicateresults) and phi aliases live.value.nameis inbindings— return that. This is where kernel parameters and loop iteration variables live. NOT a reliable channel for auto-generated tmp names like"uint_tmp"— those are intentionally written by UUID only.(When
index_array=True)valueis an array element with a resolvable parent inbindings— index into it.
Parameters:
| Name | Type | Description |
|---|---|---|
value | 'Value' | The IR Value (or already-concrete Python scalar) to resolve. |
bindings | dict[str, Any] | The active bindings dict. |
index_array | bool | When True, also resolve array-element accesses via parent_array indexing. Off by default because not all callers want to index into bound containers. |
Returns:
Any — The resolved Python value, or None if no step matched.
resolve_bound_value¶
def resolve_bound_value(self, value: 'Value', bindings: dict[str, Any]) -> AnyResolve a Value to its raw bound Python object.
Wraps :meth:lookup_in_bindings with index_array=True so that
arr[i] accesses against a bound container resolve to the
element. Does not coerce the result — callers that need a
numeric scalar should go through :meth:resolve_classical_value.
resolve_classical_value¶
def resolve_classical_value(self, value: 'Value', bindings: dict[str, Any]) -> AnyResolve a classical Value to a concrete Python value.
Numeric bindings are normalized to native Python scalars
regardless of whether they come from a direct binding or from
array-element indexing, so downstream isinstance(x, (int, float)) checks are stable when callers bind np.pi/4 or
the like. bool is preserved (not coerced to int).
Non-numeric values (Hamiltonians, strings, dict values, …)
pass through unchanged.
resolve_int_value¶
def resolve_int_value(self, val: Any, bindings: dict[str, Any]) -> int | NoneResolve a value to an integer, or None when unresolvable.
Unresolvable symbolic Values must return None. The previous
return 0 fallback caused silent loop elision when parameter
shape dims (gamma_dim0) reached this resolver without being
folded into constants — downstream loop-bound resolution saw 0 and
quietly emitted an empty loop. Returning None propagates the
failure to emit_for_unrolled, which converts it into a hard
compile error.
resolve_operand_for_binding¶
def resolve_operand_for_binding(self, operand: 'Value', bindings: dict[str, Any]) -> AnyResolve an operand to a concrete value for block parameter binding.
Used when calling a sub-block (e.g. a controlled-U body): each param operand at the call site must resolve to a value to seed the callee’s parameter bindings.
resolve_qubit_index¶
def resolve_qubit_index(self, v: 'Value', qubit_map: QubitMap, bindings: dict[str, Any]) -> int | Noneresolve_qubit_index_detailed¶
def resolve_qubit_index_detailed(
self,
v: 'Value',
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> QubitResolutionResultResolve a Value to a physical qubit index with detailed failure info.
qamomile.circuit.transpiler.passes.entrypoint_validation¶
Entrypoint validation pass for top-level transpilation.
Overview¶
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
EntrypointValidationError | Error when a top-level transpilation entrypoint has unsupported I/O. |
EntrypointValidationPass | Validate top-level entrypoint constraints. |
Pass | Base class for all compiler passes. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Classes¶
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
EntrypointValidationError [source]¶
class EntrypointValidationError(ValidationError)Error when a top-level transpilation entrypoint has unsupported I/O.
EntrypointValidationPass [source]¶
class EntrypointValidationPass(Pass[Block, Block])Validate top-level entrypoint constraints.
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockPass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
qamomile.circuit.transpiler.passes.eval_utils¶
Shared evaluation utilities for transpiler passes.
This module is the single source of truth for kind-dispatched
classical-op evaluation. Three transpiler passes need to evaluate the
same family of ops (CompOp, CondOp, NotOp, BinOp):
compile_time_if_lowering— folds ops at compile time when operands resolve to constants.classical_executor— evaluates ops at runtime over a results dict.cast_binop_emission(emit pass) — folds ops at emit time for inlining loop variables and parameter bindings intoifconditions.
The low-level evaluate_*_values functions take fully resolved Python
operands and return the computed value (or None if the op cannot be
evaluated, e.g. division by zero, unknown kind, type mismatch). They
never touch bindings or resolvers — those responsibilities stay with the
caller.
The high-level fold_classical_op adds a uniform parameter-respecting
policy on top: callers supply a resolver callable and a FoldPolicy,
and the function returns either the folded scalar or None. This is
the layer that prevents the silent miscompilation class of bugs (Issue
#354 B-series): the parameter-array-element guard is now structurally
inside this function rather than re-implemented per call site.
Overview¶
| Function | Description |
|---|---|
evaluate_binop_values | Evaluate a binary arithmetic operation on two concrete values. |
evaluate_compop_values | Evaluate a comparison operation on two concrete values. |
evaluate_condop_values | Evaluate a logical and/or operation on two concrete values. |
evaluate_notop_value | Evaluate a logical-not operation on a concrete value. |
fold_classical_op | Fold a classical op to a concrete value, respecting the given policy. |
| Class | Description |
|---|---|
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
BinOpKind | |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CompOpKind | |
CondOp | Conditional logical operation (AND, OR). |
CondOpKind | |
FoldPolicy | Policy controlling how fold_classical_op treats parameters. |
NotOp |
Functions¶
evaluate_binop_values [source]¶
def evaluate_binop_values(
kind: BinOpKind | None,
left: float | int,
right: float | int,
) -> float | int | NoneEvaluate a binary arithmetic operation on two concrete values.
Parameters:
| Name | Type | Description |
|---|---|---|
kind | BinOpKind | None | The BinOpKind to apply. |
left | float | int | Left operand (numeric). |
right | float | int | Right operand (numeric). |
Returns:
float | int | None — The result, or None on division by zero, unknown kind, or
float | int | None — arithmetic error.
evaluate_compop_values [source]¶
def evaluate_compop_values(kind: CompOpKind | None, left: Any, right: Any) -> bool | NoneEvaluate a comparison operation on two concrete values.
Parameters:
| Name | Type | Description |
|---|---|---|
kind | CompOpKind | None | The CompOpKind to apply. |
left | Any | Left operand. |
right | Any | Right operand. |
Returns:
bool | None — The boolean result, or None on unknown kind or type
bool | None — incompatibility.
evaluate_condop_values [source]¶
def evaluate_condop_values(kind: CondOpKind | None, left: Any, right: Any) -> bool | NoneEvaluate a logical and/or operation on two concrete values.
Parameters:
| Name | Type | Description |
|---|---|---|
kind | CondOpKind | None | The CondOpKind to apply. |
left | Any | Left operand. |
right | Any | Right operand. |
Returns:
bool | None — The boolean result, or None on unknown kind.
evaluate_notop_value [source]¶
def evaluate_notop_value(operand: Any) -> bool | NoneEvaluate a logical-not operation on a concrete value.
Parameters:
| Name | Type | Description |
|---|---|---|
operand | Any | The operand to negate. |
Returns:
bool | None — The boolean negation, or None on type error.
fold_classical_op [source]¶
def fold_classical_op(
op: 'BinOp | CompOp | CondOp | NotOp',
operand_resolver: Callable[[Any], Any],
parameters: set[str],
policy: FoldPolicy,
) -> Any | NoneFold a classical op to a concrete value, respecting the given policy.
The caller supplies an operand_resolver callable that knows how
to look up a Value in the caller’s context (a concrete_values
map, an emit bindings dict + ValueResolver, or any other
source). This function handles:
The parameter guard (skips folding when an operand is a runtime parameter or parameter-array element under
EMIT_RESPECT_PARAMS).Strict scalar-only typing (rejects backend
Exprobjects and other non-numeric values that would spuriously fold toTrue).Kind dispatch via the underlying
evaluate_*_valuesprimitives.
Parameters:
| Name | Type | Description |
|---|---|---|
op | 'BinOp | CompOp | CondOp | NotOp' | The classical op to fold. Must be one of BinOp, CompOp, CondOp, NotOp. |
operand_resolver | Callable[[Any], Any] | Callable mapping each operand Value to a resolved Python scalar (or None when unresolvable). |
parameters | set[str] | Set of runtime parameter names. Used only when policy is EMIT_RESPECT_PARAMS. |
policy | FoldPolicy | Folding policy. See FoldPolicy docstring. |
Returns:
Any | None — The folded value (numeric for BinOp, bool for predicates),
Any | None — or None when any operand is symbolic, missing, or a runtime
Any | None — parameter under the policy.
Classes¶
BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
BinOpKind [source]¶
class BinOpKind(enum.Enum)Attributes¶
ADDDIVFLOORDIVMULPOWSUB
CompOp [source]¶
class CompOp(BinaryOperationBase)Comparison operation (EQ, NEQ, LT, LE, GT, GE).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CompOpKind | None = None,
) -> NoneAttributes¶
kind: CompOpKind | Noneoperation_kind: OperationKindsignature: Signature
CompOpKind [source]¶
class CompOpKind(enum.Enum)Attributes¶
EQGEGTLELTNEQ
CondOp [source]¶
class CondOp(BinaryOperationBase)Conditional logical operation (AND, OR).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CondOpKind | None = None,
) -> NoneAttributes¶
kind: CondOpKind | Noneoperation_kind: OperationKindsignature: Signature
CondOpKind [source]¶
class CondOpKind(enum.Enum)Attributes¶
ANDOR
FoldPolicy [source]¶
class FoldPolicy(enum.Enum)Policy controlling how fold_classical_op treats parameters.
COMPILE_TIME is for passes that have no notion of runtime
parameters (e.g. compile_time_if_lowering); every operand the
resolver returns is treated as a real value to fold.
EMIT_RESPECT_PARAMS is for emit-time passes where some Values
may correspond to runtime backend parameters whose concrete values
are placeholders or absent. Operands whose Value or
parent_array.name is in the active parameters set are
treated as symbolic and the fold returns None rather than
producing an incorrect concrete result.
Attributes¶
COMPILE_TIMEEMIT_RESPECT_PARAMS
NotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
qamomile.circuit.transpiler.passes.inline¶
Inline pass: Inline CallBlockOperations to create an affine block.
Overview¶
| Function | Description |
|---|---|
count_call_blocks | Count CallBlockOperations, including those nested inside IfOps and |
find_return_operation | Find the ReturnOperation in a list of operations (expected at the end). |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
CallBlockOperation | |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CompositeGateType | Registry of known composite gate types. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
InlinePass | Inline all CallBlockOperations to create an affine block. |
InliningError | Error during inline pass (inlining CallBlockOperations). |
Pass | Base class for all compiler passes. |
ReturnOperation | Explicit return operation marking the end of a block with return values. |
UUIDRemapper | Clones values and operations with fresh UUIDs and logical_ids. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueSubstitutor | Substitutes values in operations using a mapping. |
Functions¶
count_call_blocks [source]¶
def count_call_blocks(operations: list[Operation]) -> intCount CallBlockOperations, including those nested inside IfOps and HasNestedOps. Used by the unroll loop as the primary termination signal (count==0 means the block is fully inlined).
find_return_operation [source]¶
def find_return_operation(operations: list[Operation]) -> ReturnOperation | NoneFind the ReturnOperation in a list of operations (expected at the end).
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
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
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]]) -> OperationInlinePass [source]¶
class InlinePass(Pass[Block, Block])Inline all CallBlockOperations to create an affine block.
This pass recursively inlines function calls while preserving control flow structures (For, If, While).
Input: Block with BlockKind.HIERARCHICAL (may contain CallBlockOperations) Output: Block with BlockKind.AFFINE (no CallBlockOperations)
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockInline all CallBlockOperations.
Self-recursive CallBlockOperations (ones whose .block is the
block currently being expanded) are unrolled one level per
call: the inner self-call is substituted but left intact so
that the outer fixed-point loop (inline ↔ partial_eval in
Transpiler.transpile) can fold the base-case if between
iterations. The output kind is AFFINE when no
CallBlockOperations remain, otherwise HIERARCHICAL.
InliningError [source]¶
class InliningError(QamomileCompileError)Error during inline pass (inlining CallBlockOperations).
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
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.
UUIDRemapper [source]¶
class UUIDRemapperClones values and operations with fresh UUIDs and logical_ids.
Used during inlining to create unique identities for values when a block is called multiple times.
Constructor¶
def __init__(self)Attributes¶
logical_id_remap: dict[str, str] Get the mapping from old logical_ids to new logical_ids.uuid_remap: dict[str, str] Get the mapping from old UUIDs to new UUIDs.
Methods¶
clone_operation¶
def clone_operation(self, op: Operation) -> OperationClone an operation with fresh UUIDs for all values.
Cloning goes through the Operation.all_input_values() /
Operation.replace_values() protocol so every Value-typed
field — including subclass extras (ControlledUOperation.power,
ForOperation.loop_var_value, ForItemsOperation.key_var_values
etc.) — is cloned consistently with the body references that
point to it. Without this, a subclass field could keep an old
UUID while body operands referencing the same logical Value got
fresh UUIDs, breaking identity-by-UUID lookups at emit time.
clone_operations¶
def clone_operations(self, operations: list[Operation]) -> list[Operation]Clone a list of operations with fresh UUIDs.
clone_value¶
def clone_value(self, value: ValueBase) -> ValueBaseClone any value type with a fresh UUID and logical_id.
Handles Value, ArrayValue, TupleValue, and DictValue through the unified ValueBase protocol.
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.
ValueBase [source]¶
class ValueBase(Protocol)Protocol for IR values with typed metadata.
Attributes are declared as read-only properties to match frozen dataclass fields in concrete implementations (Value, ArrayValue, etc.).
Attributes¶
logical_id: strmetadata: ValueMetadataname: struuid: str
Methods¶
get_const¶
def get_const(self) -> int | float | bool | Noneis_constant¶
def is_constant(self) -> boolis_parameter¶
def is_parameter(self) -> boolnext_version¶
def next_version(self) -> ValueBaseparameter_name¶
def parameter_name(self) -> str | NoneValueSubstitutor [source]¶
class ValueSubstitutorSubstitutes values in operations using a mapping.
Used during inlining to replace block parameters with caller arguments.
When transitive is True, substitute_value chases transitive chains
(A -> B -> C) to terminal values with cycle detection, which is needed
for phi substitution during compile-time if lowering.
Constructor¶
def __init__(self, value_map: dict[str, ValueBase], transitive: bool = False)Methods¶
substitute_operation¶
def substitute_operation(self, op: Operation) -> OperationSubstitute values in an operation using the value map.
Uses Operation.replace_values() to handle operands, results,
and any subclass-specific Value fields (e.g. ControlledUOperation.power).
Also handles IfOperation phi_ops recursion.
substitute_value¶
def substitute_value(self, v: ValueBase) -> ValueBaseSubstitute a single value using the value map.
Handles all value types and array elements by substituting
their parent_array if needed. When transitive is enabled,
chases transitive chains (A -> B -> C) to terminal values.
qamomile.circuit.transpiler.passes.parameter_shape_resolution¶
Compile-time resolution of symbolic Vector parameter shape dimensions.
Qiskit / CUDA-Q / QuriParts circuits are fixed-structure at compile time:
loop bounds and array lengths must be concrete to emit a valid circuit.
Top-level Vector[Float] / Vector[UInt] parameters are created with
symbolic {name}_dim{i} Values (see
qamomile.circuit.frontend.func_to_block.create_dummy_input), so when a
kernel queries arr.shape[i] the IR references those symbolic Values in
loop operands, array allocations, etc.
This pass walks the HIERARCHICAL block before inlining and, for every
input array whose name is bound to a concrete array-like value in
bindings, replaces its symbolic shape dim Values with constant Values
holding the runtime length. After this pass the downstream pipeline can
unroll for i in qmc.range(arr.shape[0]) loops normally.
Parameters without a concrete binding (e.g. the library QAOA pattern where
only p is bound and gammas.shape is never queried) are left
untouched — their symbolic dims simply do not flow into any compile-time
structure decision, so they are harmless.
Overview¶
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
ParameterShapeResolutionPass | Substitute symbolic parameter array shape dims with concrete constants. |
Pass | Base class for all compiler passes. |
UIntType | Type representing an unsigned integer. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueSubstitutor | Substitutes values in operations using a mapping. |
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
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().
ParameterShapeResolutionPass [source]¶
class ParameterShapeResolutionPass(Pass[Block, Block])Substitute symbolic parameter array shape dims with concrete constants.
Input: BlockKind.HIERARCHICAL (runs before InlinePass).
Output: same block kind, with matching shape dim Values constant-folded.
Constructor¶
def __init__(self, bindings: dict[str, Any] | None = None) -> NoneAttributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockPass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
UIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
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.
ValueBase [source]¶
class ValueBase(Protocol)Protocol for IR values with typed metadata.
Attributes are declared as read-only properties to match frozen dataclass fields in concrete implementations (Value, ArrayValue, etc.).
Attributes¶
logical_id: strmetadata: ValueMetadataname: struuid: str
Methods¶
get_const¶
def get_const(self) -> int | float | bool | Noneis_constant¶
def is_constant(self) -> boolis_parameter¶
def is_parameter(self) -> boolnext_version¶
def next_version(self) -> ValueBaseparameter_name¶
def parameter_name(self) -> str | NoneValueSubstitutor [source]¶
class ValueSubstitutorSubstitutes values in operations using a mapping.
Used during inlining to replace block parameters with caller arguments.
When transitive is True, substitute_value chases transitive chains
(A -> B -> C) to terminal values with cycle detection, which is needed
for phi substitution during compile-time if lowering.
Constructor¶
def __init__(self, value_map: dict[str, ValueBase], transitive: bool = False)Methods¶
substitute_operation¶
def substitute_operation(self, op: Operation) -> OperationSubstitute values in an operation using the value map.
Uses Operation.replace_values() to handle operands, results,
and any subclass-specific Value fields (e.g. ControlledUOperation.power).
Also handles IfOperation phi_ops recursion.
substitute_value¶
def substitute_value(self, v: ValueBase) -> ValueBaseSubstitute a single value using the value map.
Handles all value types and array elements by substituting
their parent_array if needed. When transitive is enabled,
chases transitive chains (A -> B -> C) to terminal values.
qamomile.circuit.transpiler.passes.partial_eval¶
Partial evaluation pass for compile-time simplification.
Overview¶
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
CompileTimeIfLoweringPass | Lowers compile-time resolvable IfOperations before separation. |
ConstantFoldingPass | Evaluates constant expressions at compile time. |
PartialEvaluationPass | Fold constants and lower compile-time control flow. |
Pass | Base class for all compiler passes. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Classes¶
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
CompileTimeIfLoweringPass [source]¶
class CompileTimeIfLoweringPass(Pass[Block, Block])Lowers compile-time resolvable IfOperations before separation.
After constant folding, some IfOperation conditions are statically
known but remain as control-flow nodes. SegmentationPass treats them
as segment boundaries, causing MultipleQuantumSegmentsError for
classical-only compile-time if after quantum init.
This pass:
Evaluates conditions including expression-derived ones (
CompOp,CondOp,NotOpchains).Replaces resolved
IfOperations with selected-branch operations.Substitutes phi output UUIDs with selected-branch values in all subsequent operations and block outputs.
Constructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockRun the compile-time if lowering pass.
ConstantFoldingPass [source]¶
class ConstantFoldingPass(Pass[Block, Block])Evaluates constant expressions at compile time.
This pass folds BinOp operations when all operands are constants or bound parameters, eliminating unnecessary classical operations that would otherwise split quantum segments.
Example:
Before (with bindings={"phase": 0.5}):
BinOp(phase * 2) -> classical segment split
After:
Constant 1.0 -> no segment splitConstructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockRun constant folding on the block.
PartialEvaluationPass [source]¶
class PartialEvaluationPass(Pass[Block, Block])Fold constants and lower compile-time control flow.
Constructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockPass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
qamomile.circuit.transpiler.passes.separate¶
Segmentation pass: Split a block into executable program steps.
Overview¶
| Function | Description |
|---|---|
lower_measure_qfixed | Lower MeasureQFixedOperation to MeasureVectorOperation + decode. |
lower_operations | Lower high-level operations like MeasureQFixedOperation. |
materialize_return | Synchronize output_values from ReturnOperation. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
BitType | Type representing a classical bit. |
Block | Unified block representation for all pipeline stages. |
ClassicalSegment | A segment of pure classical operations. |
ClassicalStep | A classical execution step. |
ControlFlowVisitor | Base class for visiting operations with control flow handling. |
DecodeQFixedOperation | Decode measured bits to float (classical operation). |
ExpvalOp | Expectation value operation. |
ExpvalSegment | A segment for expectation value computation. |
ExpvalStep | An expectation-value execution step. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
HybridBoundary | Represents a measurement or encode operation at quantum/classical boundary. |
MeasureQFixedOperation | Measure a quantum fixed-point number. |
MeasureVectorOperation | Measure a vector of qubits. |
MultipleQuantumSegmentsError | Raised when program has multiple quantum segments. |
NisqSegmentationStrategy | Single-quantum-segment planning strategy for current Qamomile runtimes. |
OperationKind | Classification of operations for classical/quantum separation. |
Pass | Base class for all compiler passes. |
ProgramABI | Runtime-visible ABI for a segmented program. |
ProgramPlan | Execution plan for a hybrid quantum/classical program. |
QuantumSegment | A segment of pure quantum operations. |
QuantumStep | A quantum execution step. |
QubitType | Type representing a quantum bit (qubit). |
ReturnOperation | Explicit return operation marking the end of a block with return values. |
RuntimeClassicalExpr | A classical expression known to require runtime evaluation. |
Segment | Base class for separated computation segments. |
SegmentationPass | Segment a block into a strategy-specific executable program plan. |
SegmentationStrategy | Execution-model-specific strategy for building a ProgramPlan. |
UIntType | Type representing an unsigned integer. |
ValidateWhileContractPass | Validates that all WhileOperation conditions are measurement-backed. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
Functions¶
lower_measure_qfixed [source]¶
def lower_measure_qfixed(op: MeasureQFixedOperation) -> list[Operation]Lower MeasureQFixedOperation to MeasureVectorOperation + decode.
Returns:
list[Operation] — List of operations: [MeasureVectorOperation, DecodeQFixedOperation]
lower_operations [source]¶
def lower_operations(block: Block) -> BlockLower high-level operations like MeasureQFixedOperation.
MeasureQFixedOperation is lowered to:
MeasureVectorOperation for each qubit (HYBRID -> QUANTUM segment)
DecodeQFixedOperation to convert bits to float (CLASSICAL segment)
materialize_return [source]¶
def materialize_return(block: Block) -> BlockSynchronize output_values from ReturnOperation.
Uses ReturnOperation.operands as the source of truth for return values, ensuring consistency between the operation stream and block metadata.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
ClassicalSegment [source]¶
class ClassicalSegment(Segment)A segment of pure classical operations.
Contains arithmetic, comparisons, and control flow. Will be executed directly in Python.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
kind: SegmentKind
ClassicalStep [source]¶
class ClassicalStepA classical execution step.
Constructor¶
def __init__(self, segment: ClassicalSegment, role: str = 'classical') -> NoneAttributes¶
role: strsegment: ClassicalSegment
ControlFlowVisitor [source]¶
class ControlFlowVisitor(ABC)Base class for visiting operations with control flow handling.
Subclasses override visit_operation to define per-operation behavior.
Control flow recursion is handled automatically by the base class.
Example:
class MeasurementCounter(ControlFlowVisitor):
def __init__(self):
self.count = 0
def visit_operation(self, op: Operation) -> None:
if isinstance(op, MeasureOperation):
self.count += 1Methods¶
visit_operation¶
def visit_operation(self, op: Operation) -> NoneProcess a single operation. Override in subclasses.
visit_operations¶
def visit_operations(self, operations: list[Operation]) -> NoneVisit all operations including nested control flow.
DecodeQFixedOperation [source]¶
class DecodeQFixedOperation(Operation)Decode measured bits to float (classical operation).
This operation converts a sequence of classical bits from qubit measurements into a floating-point number using fixed-point encoding.
The decoding formula:
float_value = Σ bit[i] * 2^(int_bits - 1 - i)
For QPE phase (int_bits=0): float_value = 0.b0b1b2... = b00.5 + b10.25 + b2*0.125 + ...
Example:
bits = [1, 0, 1] with int_bits=0
→ 0.101 (binary) = 0.5 + 0.125 = 0.625operands: [ArrayValue of bits (vec[bit])] results: [Float value]
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
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
ExpvalSegment [source]¶
class ExpvalSegment(Segment)A segment for expectation value computation.
Represents computing <psi|H|psi> where psi is the quantum state and H is a Hamiltonian observable.
This segment bridges a quantum circuit (state preparation) to a classical expectation value.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
hamiltonian_value: Value | None = None,
qubits_value: Value | None = None,
result_ref: str = '',
) -> NoneAttributes¶
hamiltonian_value: Value | Nonekind: SegmentKindqubits_value: Value | Noneresult_ref: str
ExpvalStep [source]¶
class ExpvalStepAn expectation-value execution step.
Constructor¶
def __init__(self, segment: ExpvalSegment, quantum_step_index: int = 0) -> NoneAttributes¶
quantum_step_index: intsegment: ExpvalSegment
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().
HybridBoundary [source]¶
class HybridBoundaryRepresents a measurement or encode operation at quantum/classical boundary.
These operations bridge quantum and classical segments.
Constructor¶
def __init__(
self,
operation: Operation,
source_segment_index: int,
target_segment_index: int,
value_ref: str,
) -> NoneAttributes¶
operation: Operationsource_segment_index: inttarget_segment_index: intvalue_ref: str
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
MultipleQuantumSegmentsError [source]¶
class MultipleQuantumSegmentsError(Exception)Raised when program has multiple quantum segments.
Qamomile enforces a single quantum circuit execution pattern:
[Classical Prep] → Quantum Circuit → [Classical Post/Expval]
Your program has multiple quantum segments, suggesting quantum operations that depend on measurement results (JIT compilation not supported).
NisqSegmentationStrategy [source]¶
class NisqSegmentationStrategy(SegmentationStrategy)Single-quantum-segment planning strategy for current Qamomile runtimes.
Methods¶
create_plan¶
def create_plan(
self,
segments: list[Segment],
block: Block,
boundaries: list[HybridBoundary],
) -> ProgramPlanOperationKind [source]¶
class OperationKind(enum.Enum)Classification of operations for classical/quantum separation.
This enum is used to categorize operations during compilation to determine which parts run on classical hardware vs quantum hardware.
Values:
QUANTUM: Pure quantum operations (gates, qubit allocation) CLASSICAL: Pure classical operations (arithmetic, comparisons) HYBRID: Operations that bridge classical and quantum (measurement, encode/decode) CONTROL: Control flow structures (for, while, if)
Attributes¶
CLASSICALCONTROLHYBRIDQUANTUM
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
ProgramABI [source]¶
class ProgramABIRuntime-visible ABI for a segmented program.
Constructor¶
def __init__(
self,
public_inputs: dict[str, Value] = dict(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
output_refs: list[str]public_inputs: dict[str, Value]
ProgramPlan [source]¶
class ProgramPlanExecution plan for a hybrid quantum/classical program.
Structure:
[Optional] Classical preprocessing (parameter computation, etc.)
Single quantum segment (REQUIRED)
[Optional] Expval segment OR classical postprocessing
This plan enforces Qamomile’s current execution model: all quantum operations must be in a single quantum circuit.
Constructor¶
def __init__(
self,
steps: list[ProgramStep] = list(),
abi: ProgramABI = ProgramABI(),
boundaries: list[HybridBoundary] = list(),
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
abi: ProgramABIboundaries: list[HybridBoundary]parameters: dict[str, Value]steps: list[ProgramStep]
QuantumSegment [source]¶
class QuantumSegment(Segment)A segment of pure quantum operations.
Contains quantum gates and qubit allocations. Will be emitted to a quantum circuit.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
qubit_values: list[Value] = list(),
num_qubits: int = 0,
) -> NoneAttributes¶
kind: SegmentKindnum_qubits: intqubit_values: list[Value]
QuantumStep [source]¶
class QuantumStepA quantum execution step.
Constructor¶
def __init__(self, segment: QuantumSegment) -> NoneAttributes¶
segment: QuantumSegment
QubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
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/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
Segment [source]¶
class Segment(ABC)Base class for separated computation segments.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
input_refs: list[str]kind: SegmentKind Return the kind of this segment.operations: list[Operation]output_refs: list[str]
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.
SegmentationStrategy [source]¶
class SegmentationStrategy(ABC)Execution-model-specific strategy for building a ProgramPlan.
Methods¶
create_plan¶
def create_plan(
self,
segments: list[Segment],
block: Block,
boundaries: list[HybridBoundary],
) -> ProgramPlanBuild a ProgramPlan from segmented operations.
UIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
ValidateWhileContractPass [source]¶
class ValidateWhileContractPass(Pass[Block, Block])Validates that all WhileOperation conditions are measurement-backed.
Builds a producer map (result UUID → producing Operation instance) and checks every WhileOperation operand against it. A valid condition must be:
A
ValuewithBitTypeMeasurement-backed: produced by
MeasureOperationdirectly, or byIfOperation/PhiOpwhere every reachable leaf source is itself measurement-backed.
Both operands[0] (initial condition) and operands[1]
(loop-carried condition) are validated.
Raises ValidationError for any non-measurement while pattern.
Attributes¶
name: str
Methods¶
run¶
def run(self, block: Block) -> BlockValidate all WhileOperations and return block unchanged.
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.
ValueBase [source]¶
class ValueBase(Protocol)Protocol for IR values with typed metadata.
Attributes are declared as read-only properties to match frozen dataclass fields in concrete implementations (Value, ArrayValue, etc.).
Attributes¶
logical_id: strmetadata: ValueMetadataname: struuid: str
Methods¶
get_const¶
def get_const(self) -> int | float | bool | Noneis_constant¶
def is_constant(self) -> boolis_parameter¶
def is_parameter(self) -> boolnext_version¶
def next_version(self) -> ValueBaseparameter_name¶
def parameter_name(self) -> str | Noneqamomile.circuit.transpiler.passes.standard_emit¶
Standard emit pass using GateEmitter protocol.
This module provides StandardEmitPass, a reusable emit pass implementation that uses the GateEmitter protocol for backend-specific gate emission.
The actual emission logic is decomposed into focused modules under
emit_support/. This class serves as the orchestrator with thin
wrappers that delegate to those module functions while preserving
subclass override points (used by QiskitEmitPass, CudaqEmitPass).
Overview¶
| Function | Description |
|---|---|
blockvalue_to_gate | Convert a Block to a backend gate. |
emit_composite_gate | Emit a composite gate operation. |
emit_controlled_fallback | Fallback emission for controlled-U when gate conversion fails. |
emit_controlled_u | Emit a ControlledUOperation. |
emit_for | Emit a for loop. |
emit_for_items | Emit for-items loop (always unrolled). |
emit_gate | Emit a single gate operation. |
emit_if | Emit if/else operation. |
emit_measure | Emit a single measurement. |
emit_measure_qfixed | Emit QFixed measurement. |
emit_measure_vector | Emit vector measurement. |
emit_pauli_evolve | Emit Pauli evolution: exp(-i * gamma * H). |
emit_while | Emit while loop operation. |
evaluate_binop | Evaluate a BinOp and store the result in bindings. |
evaluate_classical_predicate | Evaluate a CompOp/CondOp/NotOp at emit time and bind its boolean result. |
handle_cast | Handle CastOperation - update qubit_map without emitting gates. |
| Class | Description |
|---|---|
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CompositeGateEmitter | Protocol for backend-specific CompositeGate emitters. |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CondOp | Conditional logical operation (AND, OR). |
ControlledUOperation | Base class for controlled-U operations. |
EmitPass | Base class for backend-specific emission passes. |
ForItemsOperation | Represents iteration over dict/iterable items. |
ForOperation | Represents a for loop operation. |
GateEmitter | Protocol for backend-specific gate emission. |
GateOperation | Quantum gate operation. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
MeasureOperation | |
MeasureQFixedOperation | Measure a quantum fixed-point number. |
MeasureVectorOperation | Measure a vector of qubits. |
NotOp | |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
QInitOperation | Initialize the qubit |
RuntimeClassicalExpr | A classical expression known to require runtime evaluation. |
StandardEmitPass | Standard emit pass implementation using GateEmitter protocol. |
WhileOperation | Represents a while loop operation. |
Functions¶
blockvalue_to_gate [source]¶
def blockvalue_to_gate(
emit_pass: 'StandardEmitPass',
block_value: Any,
num_qubits: int,
bindings: dict[str, Any],
) -> AnyConvert a Block to a backend gate.
emit_composite_gate [source]¶
def emit_composite_gate(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: CompositeGateOperation,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit a composite gate operation.
emit_controlled_fallback [source]¶
def emit_controlled_fallback(
emit_pass: 'StandardEmitPass',
circuit: Any,
block_value: Any,
num_controls: int,
control_indices: list[int],
target_indices: list[int],
power: int,
bindings: dict[str, Any],
) -> NoneFallback emission for controlled-U when gate conversion fails.
Decomposes the block body gate-by-gate with single-control emission. Subclasses may override to support multi-control natively.
Parameters:
| Name | Type | Description |
|---|---|---|
emit_pass | 'StandardEmitPass' | The StandardEmitPass instance. |
circuit | Any | The backend circuit being built. |
block_value | Any | The block value containing operations to control. |
num_controls | int | Number of control qubits. |
control_indices | list[int] | Physical indices of control qubits. |
target_indices | list[int] | Physical indices of target qubits. |
power | int | Number of times to repeat the controlled operation. |
bindings | dict[str, Any] | Parameter bindings. |
Raises:
EmitError— When num_controls > 1 (multi-control not supported in the default gate-by-gate decomposition).
emit_controlled_u [source]¶
def emit_controlled_u(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: ControlledUOperation,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit a ControlledUOperation.
emit_for [source]¶
def emit_for(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: ForOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
force_unroll: bool = False,
) -> NoneEmit a for loop.
emit_for_items [source]¶
def emit_for_items(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: ForItemsOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit for-items loop (always unrolled).
This handles iteration over Dict items, e.g.: for (i, j), Jij in qmc.items(ising): ...
emit_gate [source]¶
def emit_gate(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: GateOperation,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit a single gate operation.
emit_if [source]¶
def emit_if(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: IfOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit if/else operation.
Handles two condition types:
Compile-time constant (plain Python
int/boolfrom@qkernelAST transformer closure variables, constant-folded Values, or Values resolvable viabindings): the active branch is emitted unconditionally, the inactive branch is discarded. No backendc_if/if_testis needed.Runtime condition (measurement
Valuethat cannot be resolved at compile time): delegates to the backend’semit_if_start/emit_else_start/emit_if_endprotocol.
emit_measure [source]¶
def emit_measure(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: MeasureOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any] | None = None,
) -> NoneEmit a single measurement.
Resolves the qubit operand using the full resolver (handles both scalar qubits and array element qubits with composite keys).
Raises:
warnings.warn— If the qubit or clbit cannot be resolved, a warning is emitted instead of silently dropping the measurement.
emit_measure_qfixed [source]¶
def emit_measure_qfixed(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: MeasureQFixedOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
) -> NoneEmit QFixed measurement.
emit_measure_vector [source]¶
def emit_measure_vector(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: MeasureVectorOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit vector measurement.
emit_pauli_evolve [source]¶
def emit_pauli_evolve(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: PauliEvolveOp,
qubit_map: QubitMap,
bindings: dict[str, Any],
) -> NoneEmit Pauli evolution: exp(-i * gamma * H).
Resolves the Hamiltonian from bindings and decomposes each term using the Pauli gadget technique:
Basis change per qubit (X->H, Y->Sdg*H, Z->identity)
CNOT ladder + RZ
Undo basis change
Subclasses can override this for backend-native implementations (e.g., Qiskit PauliEvolutionGate).
emit_while [source]¶
def emit_while(
emit_pass: 'StandardEmitPass',
circuit: Any,
op: WhileOperation,
qubit_map: QubitMap,
clbit_map: ClbitMap,
bindings: dict[str, Any],
) -> NoneEmit while loop operation.
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.
evaluate_classical_predicate [source]¶
def evaluate_classical_predicate(
emit_pass: 'StandardEmitPass',
op: 'CompOp | CondOp | NotOp',
bindings: dict[str, Any],
) -> NoneEvaluate a CompOp/CondOp/NotOp at emit time and bind its boolean result.
Mirrors the predicate evaluation already done by
compile_time_if_lowering and classical_executor so that an
IfOperation whose condition reaches emit unfolded — typically
because its operands depend on a loop variable bound only at emit time
by emit_for_items / emit_for_unrolled — can still be resolved
via resolve_if_condition.
Delegates the actual fold (including runtime-parameter guard and
strict scalar typing) to fold_classical_op so that all three
callers of the same kind dispatch share one implementation. There
is no symbolic-Parameter fallback for predicates: a runtime classical
expression cannot be expressed as a folded scalar, so the op is left
unbound and downstream emit handles it as a runtime condition.
Parameters:
| Name | Type | Description |
|---|---|---|
emit_pass | 'StandardEmitPass' | The active emit pass (for resolver access). |
op | 'CompOp | CondOp | NotOp' | The predicate op to evaluate. |
bindings | dict[str, Any] | Current parameter/loop-variable bindings; mutated in place on successful evaluation. No-op when operands are unresolvable (e.g. measurement bits) or evaluation raises. |
Returns:
None — None.
handle_cast [source]¶
def handle_cast(emit_pass: 'StandardEmitPass', op: CastOperation, qubit_map: QubitMap) -> NoneHandle CastOperation - update qubit_map without emitting gates.
Classes¶
BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
CastOperation [source]¶
class CastOperation(Operation)Type cast operation for creating aliases over the same quantum resources.
This operation does NOT allocate new qubits. It creates a new Value that references the same underlying quantum resources with a different type.
Use cases:
Vector[Qubit] -> QFixed (after QPE, for phase measurement)
Vector[Qubit] -> QUInt (for quantum arithmetic)
QUInt -> QFixed (reinterpret bits with different encoding)
QFixed -> QUInt (reinterpret bits with different encoding)
operands: [source_value] - The value being cast results: [cast_result] - The new value with target type (same physical qubits)
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
source_type: ValueType | None = None,
target_type: ValueType | None = None,
qubit_mapping: list[str] = list(),
) -> NoneAttributes¶
num_qubits: int Number of qubits involved in the cast.operation_kind: OperationKind Cast stays in the same segment as its source (QUANTUM for quantum types).qubit_mapping: list[str]signature: Signature Return the type signature of this cast operation.source_type: ValueType | Nonetarget_type: ValueType | None
CompOp [source]¶
class CompOp(BinaryOperationBase)Comparison operation (EQ, NEQ, LT, LE, GT, GE).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CompOpKind | None = None,
) -> NoneAttributes¶
kind: CompOpKind | Noneoperation_kind: OperationKindsignature: Signature
CompositeGateEmitter [source]¶
class CompositeGateEmitter(Protocol[C])Protocol for backend-specific CompositeGate emitters.
Each backend can implement emitters for specific composite gate types (QPE, QFT, IQFT, etc.) using native backend libraries.
The emitter pattern allows:
Backends to use native implementations when available (e.g., Qiskit QFT)
Fallback to manual decomposition when native is unavailable
Easy addition of new backends without modifying core code
Example:
class QiskitQFTEmitter:
def can_emit(self, gate_type: CompositeGateType) -> bool:
return gate_type in (CompositeGateType.QFT, CompositeGateType.IQFT)
def emit(self, circuit, op, qubit_indices, bindings) -> bool:
from qiskit.circuit.library import QFTGate
qft_gate = QFTGate(len(qubit_indices))
circuit.append(qft_gate, qubit_indices)
return TrueMethods¶
can_emit¶
def can_emit(self, gate_type: CompositeGateType) -> boolCheck if this emitter can handle the given gate type.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_type | CompositeGateType | The CompositeGateType to check |
Returns:
bool — True if this emitter supports native emission for the gate type
emit¶
def emit(
self,
circuit: C,
op: CompositeGateOperation,
qubit_indices: list[int],
bindings: dict[str, Any],
) -> boolEmit the composite gate to the circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | C | The backend-specific circuit to emit to |
op | CompositeGateOperation | The CompositeGateOperation to emit |
qubit_indices | list[int] | Physical qubit indices for the operation |
bindings | dict[str, Any] | Parameter bindings for the operation |
Returns:
bool — True if emission succeeded, False to fall back to manual decomposition
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.
CondOp [source]¶
class CondOp(BinaryOperationBase)Conditional logical operation (AND, OR).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CondOpKind | None = None,
) -> NoneAttributes¶
kind: CondOpKind | Noneoperation_kind: OperationKindsignature: Signature
ControlledUOperation [source]¶
class ControlledUOperation(Operation)Base class for controlled-U operations.
Three concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands.IndexSpecControlledU: Single vector with explicit index lists selecting which elements are controls/targets.
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,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.has_index_spec: bool Whether target/control positions are specified via index lists.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.operation_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]) -> OperationEmitPass [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.
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]) -> OperationGateEmitter [source]¶
class GateEmitter(Protocol[T])Protocol for backend-specific gate emission.
Each backend implements this protocol to emit individual gates to their circuit representation.
Type parameter T is the backend’s circuit type (e.g., QuantumCircuit).
Attributes¶
measurement_mode: MeasurementMode Return the measurement mode for this backend.
Methods¶
append_gate¶
def append_gate(self, circuit: T, gate: Any, qubits: list[int]) -> NoneAppend a gate to the circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The circuit to append to |
gate | Any | The gate to append (from circuit_to_gate) |
qubits | list[int] | Target qubit indices |
circuit_to_gate¶
def circuit_to_gate(self, circuit: T, name: str = 'U') -> AnyConvert a circuit to a reusable gate.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The circuit to convert |
name | str | Label for the gate |
Returns:
Any — Backend-specific gate object, or None if not supported
create_circuit¶
def create_circuit(self, num_qubits: int, num_clbits: int) -> TCreate a new empty circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
num_qubits | int | Number of qubits in the circuit |
num_clbits | int | Number of classical bits in the circuit |
Returns:
T — A new backend-specific circuit object
create_parameter¶
def create_parameter(self, name: str) -> AnyCreate a symbolic parameter for the backend.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Parameter name (e.g., “gammas[0]”) |
Returns:
Any — Backend-specific parameter object
emit_barrier¶
def emit_barrier(self, circuit: T, qubits: list[int]) -> NoneEmit barrier on specified qubits.
emit_ch¶
def emit_ch(self, circuit: T, control: int, target: int) -> NoneEmit controlled-Hadamard gate.
emit_cp¶
def emit_cp(self, circuit: T, control: int, target: int, angle: float | Any) -> NoneEmit controlled-Phase gate.
emit_crx¶
def emit_crx(self, circuit: T, control: int, target: int, angle: float | Any) -> NoneEmit controlled-RX gate.
emit_cry¶
def emit_cry(self, circuit: T, control: int, target: int, angle: float | Any) -> NoneEmit controlled-RY gate.
emit_crz¶
def emit_crz(self, circuit: T, control: int, target: int, angle: float | Any) -> NoneEmit controlled-RZ gate.
emit_cx¶
def emit_cx(self, circuit: T, control: int, target: int) -> NoneEmit CNOT gate.
emit_cy¶
def emit_cy(self, circuit: T, control: int, target: int) -> NoneEmit controlled-Y gate.
emit_cz¶
def emit_cz(self, circuit: T, control: int, target: int) -> NoneEmit CZ gate.
emit_else_start¶
def emit_else_start(self, circuit: T, context: Any) -> NoneStart the else branch.
emit_for_loop_end¶
def emit_for_loop_end(self, circuit: T, context: Any) -> NoneEnd a native for loop context.
emit_for_loop_start¶
def emit_for_loop_start(self, circuit: T, indexset: range) -> AnyStart a native for loop context.
Returns a context manager or loop parameter, depending on backend.
emit_h¶
def emit_h(self, circuit: T, qubit: int) -> NoneEmit Hadamard gate.
emit_if_end¶
def emit_if_end(self, circuit: T, context: Any) -> NoneEnd the if/else block.
emit_if_start¶
def emit_if_start(self, circuit: T, clbit: int, value: int = 1) -> AnyStart a native if context.
Returns context for the if/else block.
emit_measure¶
def emit_measure(self, circuit: T, qubit: int, clbit: int) -> NoneEmit measurement operation.
emit_p¶
def emit_p(self, circuit: T, qubit: int, angle: float | Any) -> NoneEmit Phase gate (P(θ) = diag(1, e^(iθ))).
emit_rx¶
def emit_rx(self, circuit: T, qubit: int, angle: float | Any) -> NoneEmit RX rotation gate.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The circuit to emit to |
qubit | int | Target qubit index |
angle | float | Any | Rotation angle (float or backend parameter) |
emit_ry¶
def emit_ry(self, circuit: T, qubit: int, angle: float | Any) -> NoneEmit RY rotation gate.
emit_rz¶
def emit_rz(self, circuit: T, qubit: int, angle: float | Any) -> NoneEmit RZ rotation gate.
emit_rzz¶
def emit_rzz(self, circuit: T, qubit1: int, qubit2: int, angle: float | Any) -> NoneEmit RZZ gate (exp(-i * θ/2 * Z⊗Z)).
emit_s¶
def emit_s(self, circuit: T, qubit: int) -> NoneEmit S gate (√Z).
emit_sdg¶
def emit_sdg(self, circuit: T, qubit: int) -> NoneEmit S-dagger gate (inverse of S).
emit_swap¶
def emit_swap(self, circuit: T, qubit1: int, qubit2: int) -> NoneEmit SWAP gate.
emit_t¶
def emit_t(self, circuit: T, qubit: int) -> NoneEmit T gate (√S).
emit_tdg¶
def emit_tdg(self, circuit: T, qubit: int) -> NoneEmit T-dagger gate (inverse of T).
emit_toffoli¶
def emit_toffoli(self, circuit: T, control1: int, control2: int, target: int) -> NoneEmit Toffoli (CCX) gate.
emit_while_end¶
def emit_while_end(self, circuit: T, context: Any) -> NoneEnd the while loop context.
emit_while_start¶
def emit_while_start(self, circuit: T, clbit: int, value: int = 1) -> AnyStart a native while loop context.
emit_x¶
def emit_x(self, circuit: T, qubit: int) -> NoneEmit Pauli-X gate.
emit_y¶
def emit_y(self, circuit: T, qubit: int) -> NoneEmit Pauli-Y gate.
emit_z¶
def emit_z(self, circuit: T, qubit: int) -> NoneEmit Pauli-Z gate.
gate_controlled¶
def gate_controlled(self, gate: Any, num_controls: int) -> AnyCreate controlled version of a gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate | Any | The gate to control |
num_controls | int | Number of control qubits |
Returns:
Any — New controlled gate
gate_power¶
def gate_power(self, gate: Any, power: int) -> AnyCreate gate raised to a power (U^n).
Parameters:
| Name | Type | Description |
|---|---|---|
gate | Any | The gate to raise to a power |
power | int | The power to raise to |
Returns:
Any — New gate representing gate^power
supports_for_loop¶
def supports_for_loop(self) -> boolCheck if backend supports native for loops.
supports_if_else¶
def supports_if_else(self) -> boolCheck if backend supports native if/else.
supports_while_loop¶
def supports_while_loop(self) -> boolCheck if backend supports native while loops.
GateOperation [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.
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]]) -> OperationMeasureOperation [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
NotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
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
QInitOperation [source]¶
class QInitOperation(Operation)Initialize the qubit
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
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/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
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,
)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]]) -> Operationqamomile.circuit.transpiler.passes.substitution¶
Substitution pass for replacing QKernel subroutines and composite gate strategies.
This pass allows replacing:
CallBlockOperation targets (QKernel subroutines) with alternative implementations
CompositeGateOperation strategies with specified decomposition strategies
Example:
# Replace a custom oracle with an optimized version
config = SubstitutionConfig(
rules=[
SubstitutionRule(source_name="my_oracle", target=optimized_oracle),
SubstitutionRule(source_name="qft", strategy="approximate"),
]
)
pass = SubstitutionPass(config)
new_block = pass.run(block)Overview¶
| Function | Description |
|---|---|
check_signature_compatibility | Check signature compatibility between two Blocks. |
create_substitution_pass | Convenience factory for creating a SubstitutionPass. |
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
CallBlockOperation | |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
Pass | Base class for all compiler passes. |
QKernel | Decorator class for Qamomile quantum kernels. |
SignatureCompatibilityError | Error raised when signatures are incompatible during substitution. |
SubstitutionConfig | Configuration for the substitution pass. |
SubstitutionPass | Pass that substitutes CallBlockOperations and CompositeGateOperations. |
SubstitutionRule | A single substitution rule. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Functions¶
check_signature_compatibility [source]¶
def check_signature_compatibility(source: Block, target: Block, strict: bool = True) -> tuple[bool, str | None]Check signature compatibility between two Blocks.
Parameters:
| Name | Type | Description |
|---|---|---|
source | Block | The source Block being replaced |
target | Block | The target Block to replace with |
strict | bool | If True, require exact type matches |
Returns:
bool — Tuple of (is_compatible, error_message).
str | None — If compatible, error_message is None.
create_substitution_pass [source]¶
def create_substitution_pass(
block_replacements: dict[str, 'Block | QKernel'] | None = None,
*,
strategy_overrides: dict[str, str] | None = None,
validate_signatures: bool = True,
) -> SubstitutionPassConvenience factory for creating a SubstitutionPass.
Parameters:
| Name | Type | Description |
|---|---|---|
block_replacements | dict[str, 'Block | QKernel'] | None | Map of block name to replacement |
strategy_overrides | dict[str, str] | None | Map of gate name to strategy name |
validate_signatures | bool | If True, validate signature compatibility when replacing blocks. Default is True. |
Returns:
SubstitutionPass — Configured SubstitutionPass
Example:
pass = create_substitution_pass(
block_replacements={"my_oracle": optimized_oracle},
strategy_overrides={"qft": "approximate", "iqft": "approximate"},
)Classes¶
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
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.
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().
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
QKernel [source]¶
class QKernel(Generic[P, R])Decorator class for Qamomile quantum kernels.
Constructor¶
def __init__(self, func: Callable[P, R]) -> NoneAttributes¶
block: Block Compile the function to a hierarchical Block if not already compiled.funcinput_typesnameoutput_typesraw_funcsignature
Methods¶
build¶
def build(self, parameters: list[str] | None = None, **kwargs: Any = {}) -> BlockBuild a traced Block by tracing this kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
parameters | list[str] | None | List of argument names to keep as unbound parameters. - None (default): Auto-detect parameters (non-Qubit args without value/default) - []: No parameters (all non-Qubit args must have value/default) - [“name”]: Explicit parameter list Only float, int, UInt, and their arrays are allowed as parameters. |
**kwargs | Any | Concrete values for non-parameter arguments. |
Returns:
Block — The traced block ready for transpilation, estimation,
or visualization.
Raises:
TypeError— If a non-parameterizable type is specified as parameter.ValueError— If required arguments are missing.
Example:
@qm.qkernel
def circuit(q: Qubit, theta: float) -> Qubit:
q = qm.rx(q, theta)
return q
# Auto-detect theta as parameter
block = circuit.build()
# Explicit parameter list
block = circuit.build(parameters=["theta"])
# theta bound to concrete value
block = circuit.build(theta=0.5)
# Transpile with binding
transpiler = QiskitTranspiler()
result = transpiler.emit(graph, binding={"theta": 0.5})draw¶
def draw(
self,
inline: bool = False,
fold_loops: bool = True,
expand_composite: bool = False,
inline_depth: int | None = None,
**kwargs: Any = {},
) -> AnyVisualize the circuit using Matplotlib.
This method builds the computation graph and creates a static visualization. Parameters are auto-detected: non-Qubit arguments without concrete values are shown as symbolic parameters.
Parameters:
| Name | Type | Description |
|---|---|---|
inline | bool | If True, expand CallBlockOperation contents (inlining). If False (default), show CallBlockOperation as boxes. |
fold_loops | bool | If True (default), display ForOperation as blocks instead of unrolling. If False, expand loops and show all iterations. |
expand_composite | bool | If True, expand CompositeGateOperation (QFT, IQFT, etc.). If False (default), show as boxes. Independent of inline. |
inline_depth | int | None | Maximum nesting depth for inline expansion. None means unlimited (default). 0 means no inlining, 1 means top-level only, etc. Only affects CallBlock/ControlledU, not CompositeGate. |
**kwargs | Any | Concrete values for arguments. Arguments not provided here (and without defaults) will be shown as symbolic parameters. |
Returns:
Any — matplotlib.figure.Figure object.
Raises:
ImportError— If matplotlib is not installed.
Example:
import qamomile.circuit as qm
@qm.qkernel
def inner(q: qm.Qubit) -> qm.Qubit:
return qm.x(q)
@qm.qkernel
def circuit(q: qm.Qubit, theta: float) -> qm.Qubit:
q = inner(q)
q = qm.h(q)
q = qm.rx(q, theta)
return q
# Draw with auto-detected symbolic parameter (theta)
fig = circuit.draw()
# Draw with bound parameter
fig = circuit.draw(theta=0.5)
# Draw with blocks as boxes (default)
fig = circuit.draw()
# Draw with blocks expanded (inlined)
fig = circuit.draw(inline=True)
# Draw with loops folded (shown as blocks)
fig = circuit.draw(fold_loops=True)
# Draw with composite gates expanded
fig = circuit.draw(expand_composite=True)estimate_resources¶
def estimate_resources(self, *, bindings: dict[str, Any] | None = None) -> ResourceEstimateEstimate all resources for this kernel’s circuit.
Convenience method that delegates to the module-level
estimate_resources function, eliminating the need to
access .block directly.
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | None | Optional concrete parameter bindings (scalars and dicts). Dict values trigger |key| cardinality substitution. |
Returns:
ResourceEstimate — ResourceEstimate with qubits, gates, and parameters.
Example:
>>> @qm.qkernel
... def bell() -> qm.Vector[qm.Qubit]:
... q = qm.qubit_array(2)
... q[0] = qm.h(q[0])
... q[0], q[1] = qm.cx(q[0], q[1])
... return q
>>> est = bell.estimate_resources()
>>> print(est.qubits) # 2SignatureCompatibilityError [source]¶
class SignatureCompatibilityError(Exception)Error raised when signatures are incompatible during substitution.
SubstitutionConfig [source]¶
class SubstitutionConfigConfiguration for the substitution pass.
Constructor¶
def __init__(self, rules: list[SubstitutionRule] = list()) -> NoneAttributes¶
rules: list[SubstitutionRule]
Methods¶
get_rule_for_name¶
def get_rule_for_name(self, name: str) -> SubstitutionRule | NoneFind a rule matching the given name.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Name to look up |
Returns:
SubstitutionRule | None — Matching SubstitutionRule or None
SubstitutionPass [source]¶
class SubstitutionPass(Pass[Block, Block])Pass that substitutes CallBlockOperations and CompositeGateOperations.
This pass traverses the block and applies substitution rules:
For CallBlockOperation: replaces the block reference with the target
For CompositeGateOperation: sets the strategy_name field
The pass preserves the block structure and only modifies matching operations.
Input: Block (any kind) Output: Block with substitutions applied (same kind as input)
Constructor¶
def __init__(self, config: SubstitutionConfig) -> NoneInitialize the pass with configuration.
Parameters:
| Name | Type | Description |
|---|---|---|
config | SubstitutionConfig | Substitution configuration with rules |
Attributes¶
name: str Return pass name.
Methods¶
run¶
def run(self, input: Block) -> BlockApply substitutions to the block.
Parameters:
| Name | Type | Description |
|---|---|---|
input | Block | Block to transform |
Returns:
Block — Block with substitutions applied
SubstitutionRule [source]¶
class SubstitutionRuleA single substitution rule.
Constructor¶
def __init__(
self,
source_name: str,
target: 'Block | QKernel | None' = None,
strategy: str | None = None,
validate_signature: bool = True,
) -> NoneAttributes¶
source_name: strstrategy: str | Nonetarget: ‘Block | QKernel | None’validate_signature: bool
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
qamomile.circuit.transpiler.passes.symbolic_shape_validation¶
Validation pass: reject unresolved parameter shape dims in loop bounds.
Qamomile circuits are fixed-structure at compile time. Any loop whose
bound is a symbolic parameter array shape dimension (e.g.
gamma_dim0) must have that dimension resolved before emit — either
by ParameterShapeResolutionPass folding it from a concrete binding,
or by the user binding the dimension explicitly.
When an unresolved symbolic shape dim reaches a ForOperation operand,
this pass raises a CompileError with an actionable message that
points to the offending parameter and suggests concrete fixes. This is
the user-facing counterpart to the defensive hard fail in
emit_for_unrolled: it runs earlier (after analyze) and can
provide clean diagnostics instead of a cryptic emit-time error.
The library QAOA pattern (p bound to an int, for layer in qmc.range(p), gammas.shape never queried) is unaffected — the
pass only trips when an unresolved symbolic shape dim is actually used
as loop bound / allocation size.
Overview¶
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
ForOperation | Represents a for loop operation. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
Pass | Base class for all compiler passes. |
QamomileCompileError | Base class for all Qamomile compilation errors. |
SymbolicShapeValidationPass | Reject unresolved parameter shape dims in compile-time structure ops. |
Value | A typed SSA value in the IR. |
Classes¶
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
ForOperation [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]) -> OperationHasNestedOps [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().
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
QamomileCompileError [source]¶
class QamomileCompileError(Exception)Base class for all Qamomile compilation errors.
SymbolicShapeValidationPass [source]¶
class SymbolicShapeValidationPass(Pass[Block, Block])Reject unresolved parameter shape dims in compile-time structure ops.
Input: BlockKind.ANALYZED (runs after AnalyzePass).
Output: same block unchanged, or raises QamomileCompileError.
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockValue [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.
qamomile.circuit.transpiler.passes.validate_while¶
WhileOperation contract validation pass.
Validates that all WhileOperation conditions are measurement-backed
Bit values. A condition is measurement-backed if it originates from
qmc.measure() either directly or through phi-merged branches where
every leaf is itself measurement-backed (e.g. if sel: bit = measure(q1) else: bit = measure(q2)).
All other while patterns (classical variables, constants, comparison
results, non-measurement branch leaves) are rejected with a clear
ValidationError before reaching backend-specific emit passes.
This pass runs after lower_compile_time_ifs and before analyze.
Overview¶
| Class | Description |
|---|---|
BitType | Type representing a classical bit. |
Block | Unified block representation for all pipeline stages. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
MeasureOperation | |
Pass | Base class for all compiler passes. |
PhiOp | SSA Phi function: merge point after conditional branch. |
ValidateWhileContractPass | Validates that all WhileOperation conditions are measurement-backed. |
ValidationError | Error during validation (e.g., non-classical I/O). |
Value | A typed SSA value in the IR. |
WhileOperation | Represents a while loop operation. |
Classes¶
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
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]]) -> OperationMeasureOperation [source]¶
class MeasureOperation(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
Pass [source]¶
class Pass(ABC, Generic[InputT, OutputT])Base class for all compiler passes.
Attributes¶
name: str Human-readable name for this pass.
Methods¶
run¶
def run(self, input: InputT) -> OutputTExecute the pass transformation.
PhiOp [source]¶
class PhiOp(Operation)SSA Phi function: merge point after conditional branch.
This operation selects one of two values based on a condition. Used to merge values from different branches of an if-else statement.
Example:
if condition:
x = x + 1 # true_value
else:
x = x + 2 # false_value
# x is now PhiOp(condition, true_value, false_value)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
condition: Valuefalse_value: Valueoperation_kind: OperationKindoutput: Valuesignature: Signaturetrue_value: Value
ValidateWhileContractPass [source]¶
class ValidateWhileContractPass(Pass[Block, Block])Validates that all WhileOperation conditions are measurement-backed.
Builds a producer map (result UUID → producing Operation instance) and checks every WhileOperation operand against it. A valid condition must be:
A
ValuewithBitTypeMeasurement-backed: produced by
MeasureOperationdirectly, or byIfOperation/PhiOpwhere every reachable leaf source is itself measurement-backed.
Both operands[0] (initial condition) and operands[1]
(loop-carried condition) are validated.
Raises ValidationError for any non-measurement while pattern.
Attributes¶
name: str
Methods¶
run¶
def run(self, block: Block) -> BlockValidate all WhileOperations and return block unchanged.
ValidationError [source]¶
class ValidationError(QamomileCompileError)Error during validation (e.g., non-classical I/O).
Constructor¶
def __init__(self, message: str, value_name: str | None = None)Attributes¶
value_name
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]]) -> Operationqamomile.circuit.transpiler.passes.value_mapping¶
Value mapping utilities for IR transformations.
Overview¶
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
DictValue | A dictionary value stored as stable ordered entries. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
IfOperation | Represents an if-else conditional operation. |
TupleValue | A tuple of IR values for structured data. |
UUIDRemapper | Clones values and operations with fresh UUIDs and logical_ids. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueSubstitutor | Substitutes values in operations using a mapping. |
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
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(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]DictValue [source]¶
class DictValue(_MetadataValueMixin)A dictionary value stored as stable ordered entries.
Constructor¶
def __init__(
self,
name: str,
entries: tuple[tuple[TupleValue | Value, Value], ...] = tuple(),
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
) -> NoneAttributes¶
entries: tuple[tuple[TupleValue | Value, Value], ...]logical_id: strmetadata: ValueMetadataname: strtype: DictTypeuuid: str
Methods¶
is_constant¶
def is_constant(self) -> boolnext_version¶
def next_version(self) -> DictValueHasNestedOps [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]]) -> OperationTupleValue [source]¶
class TupleValue(_MetadataValueMixin)A tuple of IR values for structured data.
Constructor¶
def __init__(
self,
name: str,
elements: tuple[Value, ...] = tuple(),
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
) -> NoneAttributes¶
elements: tuple[Value, ...]logical_id: strmetadata: ValueMetadataname: strtype: ‘TupleType’uuid: str
Methods¶
is_constant¶
def is_constant(self) -> boolnext_version¶
def next_version(self) -> TupleValueUUIDRemapper [source]¶
class UUIDRemapperClones values and operations with fresh UUIDs and logical_ids.
Used during inlining to create unique identities for values when a block is called multiple times.
Constructor¶
def __init__(self)Attributes¶
logical_id_remap: dict[str, str] Get the mapping from old logical_ids to new logical_ids.uuid_remap: dict[str, str] Get the mapping from old UUIDs to new UUIDs.
Methods¶
clone_operation¶
def clone_operation(self, op: Operation) -> OperationClone an operation with fresh UUIDs for all values.
Cloning goes through the Operation.all_input_values() /
Operation.replace_values() protocol so every Value-typed
field — including subclass extras (ControlledUOperation.power,
ForOperation.loop_var_value, ForItemsOperation.key_var_values
etc.) — is cloned consistently with the body references that
point to it. Without this, a subclass field could keep an old
UUID while body operands referencing the same logical Value got
fresh UUIDs, breaking identity-by-UUID lookups at emit time.
clone_operations¶
def clone_operations(self, operations: list[Operation]) -> list[Operation]Clone a list of operations with fresh UUIDs.
clone_value¶
def clone_value(self, value: ValueBase) -> ValueBaseClone any value type with a fresh UUID and logical_id.
Handles Value, ArrayValue, TupleValue, and DictValue through the unified ValueBase protocol.
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.
ValueBase [source]¶
class ValueBase(Protocol)Protocol for IR values with typed metadata.
Attributes are declared as read-only properties to match frozen dataclass fields in concrete implementations (Value, ArrayValue, etc.).
Attributes¶
logical_id: strmetadata: ValueMetadataname: struuid: str
Methods¶
get_const¶
def get_const(self) -> int | float | bool | Noneis_constant¶
def is_constant(self) -> boolis_parameter¶
def is_parameter(self) -> boolnext_version¶
def next_version(self) -> ValueBaseparameter_name¶
def parameter_name(self) -> str | NoneValueSubstitutor [source]¶
class ValueSubstitutorSubstitutes values in operations using a mapping.
Used during inlining to replace block parameters with caller arguments.
When transitive is True, substitute_value chases transitive chains
(A -> B -> C) to terminal values with cycle detection, which is needed
for phi substitution during compile-time if lowering.
Constructor¶
def __init__(self, value_map: dict[str, ValueBase], transitive: bool = False)Methods¶
substitute_operation¶
def substitute_operation(self, op: Operation) -> OperationSubstitute values in an operation using the value map.
Uses Operation.replace_values() to handle operands, results,
and any subclass-specific Value fields (e.g. ControlledUOperation.power).
Also handles IfOperation phi_ops recursion.
substitute_value¶
def substitute_value(self, v: ValueBase) -> ValueBaseSubstitute a single value using the value map.
Handles all value types and array elements by substituting
their parent_array if needed. When transitive is enabled,
chases transitive chains (A -> B -> C) to terminal values.
qamomile.circuit.transpiler.program_orchestrator¶
Orchestration logic for compiled quantum-classical programs.
This module is internal. Users interact with ExecutableProgram.sample()/run().
Overview¶
| Class | Description |
|---|---|
ClassicalExecutor | Executes classical segments in Python. |
ClassicalStep | A classical execution step. |
CompiledClassicalSegment | A classical segment ready for Python execution. |
CompiledExpvalSegment | A compiled expectation value segment with concrete Hamiltonian. |
CompiledQuantumSegment | A quantum segment with emitted backend circuit. |
ExecutableProgram | A fully compiled program ready for execution. |
ExecutionContext | Holds global state during program execution. |
ExecutionError | Error during program execution. |
ExpvalJob | Job for expectation value computation. |
ExpvalStep | An expectation-value execution step. |
ParameterMetadata | Metadata for all parameters in a compiled segment. |
ProgramOrchestrator | Orchestrates execution of compiled quantum-classical programs. |
QuantumExecutor | Abstract base class for quantum backend execution. |
QuantumStep | A quantum execution step. |
RunJob | Job for single execution. |
SampleJob | Job for sampling execution (multiple shots). |
Classes¶
ClassicalExecutor [source]¶
class ClassicalExecutorExecutes classical segments in Python.
Methods¶
execute¶
def execute(self, segment: ClassicalSegment, context: ExecutionContext) -> dict[str, Any]Execute classical operations and return outputs.
Interprets the operations list directly using Python.
ClassicalStep [source]¶
class ClassicalStepA classical execution step.
Constructor¶
def __init__(self, segment: ClassicalSegment, role: str = 'classical') -> NoneAttributes¶
role: strsegment: ClassicalSegment
CompiledClassicalSegment [source]¶
class CompiledClassicalSegmentA classical segment ready for Python execution.
Constructor¶
def __init__(self, segment: ClassicalSegment) -> NoneAttributes¶
segment: ClassicalSegment
CompiledExpvalSegment [source]¶
class CompiledExpvalSegmentA compiled expectation value segment with concrete Hamiltonian.
This segment computes <psi|H|psi> where psi is the quantum state from a quantum circuit and H is a qamomile.observable.Hamiltonian.
Constructor¶
def __init__(
self,
segment: ExpvalSegment,
hamiltonian: 'qm_o.Hamiltonian',
quantum_segment_index: int = 0,
result_ref: str = '',
qubit_map: dict[int, int] = dict(),
) -> NoneAttributes¶
hamiltonian: ‘qm_o.Hamiltonian’quantum_segment_index: intqubit_map: dict[int, int]result_ref: strsegment: ExpvalSegment
CompiledQuantumSegment [source]¶
class CompiledQuantumSegment(Generic[T])A quantum segment with emitted backend circuit.
Constructor¶
def __init__(
self,
segment: QuantumSegment,
circuit: T,
qubit_map: QubitMap = dict(),
clbit_map: ClbitMap = dict(),
measurement_qubit_map: dict[int, int] = dict(),
parameter_metadata: ParameterMetadata = ParameterMetadata(),
) -> NoneAttributes¶
circuit: Tclbit_map: ClbitMapmeasurement_qubit_map: dict[int, int]parameter_metadata: ParameterMetadataqubit_map: QubitMapsegment: QuantumSegment
ExecutableProgram [source]¶
class ExecutableProgram(Generic[T])A fully compiled program ready for execution.
Contains compiled quantum, classical, and expectation-value segments.
Use sample() for multi-shot execution or run() for single
execution.
Example:
executable = transpiler.compile(kernel)
# Sample: multiple shots, returns counts
job = executable.sample(executor, shots=1000)
result = job.result() # SampleResult with counts
# Run: single shot, returns typed result
job = executable.run(executor)
result = job.result() # Returns kernel's return typeConstructor¶
def __init__(
self,
plan: ProgramPlan | None = None,
compiled_quantum: list[CompiledQuantumSegment[T]] = list(),
compiled_classical: list[CompiledClassicalSegment] = list(),
compiled_expval: list[CompiledExpvalSegment] = list(),
output_refs: list[str] = list(),
num_output_bits: int = 0,
) -> NoneAttributes¶
compiled_classical: list[CompiledClassicalSegment]compiled_expval: list[CompiledExpvalSegment]compiled_quantum: list[CompiledQuantumSegment[T]]has_parameters: bool Check if this program has unbound parameters.num_output_bits: intoutput_refs: list[str]parameter_names: list[str] Get list of parameter names that need binding.plan: ProgramPlan | Nonequantum_circuit: T Get the single quantum circuit.
Methods¶
get_circuits¶
def get_circuits(self) -> list[T]Get all quantum circuits in execution order.
get_first_circuit¶
def get_first_circuit(self) -> T | NoneGet the first quantum circuit, or None if no quantum segments.
run¶
def run(
self,
executor: QuantumExecutor[T],
bindings: dict[str, Any] | None = None,
) -> RunJob[Any] | ExpvalJobExecute once and return single result.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
RunJob[Any] | ExpvalJob — RunJob that resolves to the kernel’s return type, or
RunJob[Any] | ExpvalJob — ExpvalJob if the program contains expectation value computation.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.run(executor, bindings={"gamma": [0.5]})
result = job.result()
print(result) # 0.25 (for QFixed) or (0, 1) (for bits)sample¶
def sample(
self,
executor: QuantumExecutor[T],
shots: int = 1024,
bindings: dict[str, Any] | None = None,
) -> SampleJob[Any]Execute with multiple shots and return counts.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
shots | int | Number of shots to run. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
SampleJob[Any] — SampleJob that resolves to SampleResult with results.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.sample(executor, shots=1000, bindings={"gamma": [0.5]})
result = job.result()
print(result.results) # [(0.25, 500), (0.75, 500)]ExecutionContext [source]¶
class ExecutionContextHolds global state during program execution.
Constructor¶
def __init__(self, initial_bindings: dict[str, Any] | None = None)Methods¶
copy¶
def copy(self) -> 'ExecutionContext'Clone the execution context.
get¶
def get(self, key: str) -> Anyget_many¶
def get_many(self, keys: list[str]) -> dict[str, Any]has¶
def has(self, key: str) -> boolset¶
def set(self, key: str, value: Any) -> Noneupdate¶
def update(self, values: dict[str, Any]) -> NoneExecutionError [source]¶
class ExecutionError(QamomileCompileError)Error during program execution.
ExpvalJob [source]¶
class ExpvalJob(Job[float])Job for expectation value computation.
Returns a single float representing <psi|H|psi>.
Constructor¶
def __init__(self, exp_val: float)Initialize expval job.
Parameters:
| Name | Type | Description |
|---|---|---|
exp_val | float | The computed expectation value |
Methods¶
result¶
def result(self) -> floatReturn the expectation value.
status¶
def status(self) -> JobStatusReturn job status.
ExpvalStep [source]¶
class ExpvalStepAn expectation-value execution step.
Constructor¶
def __init__(self, segment: ExpvalSegment, quantum_step_index: int = 0) -> NoneAttributes¶
quantum_step_index: intsegment: ExpvalSegment
ParameterMetadata [source]¶
class ParameterMetadataMetadata for all parameters in a compiled segment.
Tracks parameter information for runtime binding.
Constructor¶
def __init__(self, parameters: list[ParameterInfo] = list()) -> NoneAttributes¶
parameters: list[ParameterInfo]
Methods¶
get_array_names¶
def get_array_names(self) -> set[str]Get unique array/scalar parameter names.
get_ordered_params¶
def get_ordered_params(self) -> list[Any]Get backend parameter objects in definition order.
Useful for backends that require positional parameter binding (e.g., QURI Parts).
Returns:
list[Any] — List of backend_param objects in the order they were defined.
Example:
# For QURI Parts that uses positional binding:
param_values = [bindings[p.name] for p in metadata.parameters]
bound_circuit = circuit.bind_parameters(param_values)get_param_by_name¶
def get_param_by_name(self, name: str) -> ParameterInfo | NoneGet parameter info by full name.
to_binding_dict¶
def to_binding_dict(self, bindings: dict[str, Any]) -> dict[Any, Any]Convert indexed bindings to backend parameter bindings.
Transforms user-provided bindings (with indexed names like “gammas[0]”) into a dictionary mapping backend parameter objects to values. Useful for backends that use dict-based parameter binding (e.g., Qiskit).
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | Dictionary mapping parameter names to values. e.g., {“gammas[0]”: 0.1, “gammas[1]”: 0.2, “theta”: 0.5} |
Returns:
dict[Any, Any] — Dictionary mapping backend_param objects to values.
Example:
# For Qiskit that uses dict-based binding:
qiskit_bindings = metadata.to_binding_dict(bindings)
bound_circuit = circuit.assign_parameters(qiskit_bindings)ProgramOrchestrator [source]¶
class ProgramOrchestrator(Generic[T])Orchestrates execution of compiled quantum-classical programs.
This is an internal class that handles the runtime execution logic.
Users should use ExecutableProgram.sample() and
ExecutableProgram.run() instead.
Constructor¶
def __init__(self, program: ExecutableProgram[T]) -> NoneMethods¶
run¶
def run(
self,
executor: QuantumExecutor[T],
bindings: dict[str, Any] | None,
) -> RunJob[Any] | ExpvalJobExecute once and return single result.
run_expval¶
def run_expval(
self,
executor: QuantumExecutor[T],
bindings: dict[str, Any] | None,
) -> ExpvalJobBackward-compatible helper for pure expval execution.
sample¶
def sample(
self,
executor: QuantumExecutor[T],
shots: int,
bindings: dict[str, Any] | None,
) -> SampleJob[Any]Execute with multiple shots and return counts.
QuantumExecutor [source]¶
class QuantumExecutor(ABC, Generic[T])Abstract base class for quantum backend execution.
To implement a custom executor:
execute() [Required] Execute circuit and return bitstring counts as dict[str, int]. Keys are bitstrings in big-endian format (e.g., “011” means q2=0, q1=1, q0=1).
bind_parameters() [Optional] Bind parameter values to parametric circuits. Override if your executor supports parametric circuits (e.g., QAOA variational circuits). Use ParameterMetadata.to_binding_dict() for easy conversion.
estimate() [Optional] Compute expectation values <psi|H|psi>. Override if your executor supports estimation primitives (e.g., Qiskit Estimator, QURI Parts).
Example (Minimal): class MyExecutor(QuantumExecutor[QuantumCircuit]): def init(self): from qiskit_aer import AerSimulator self.backend = AerSimulator()
def execute(self, circuit, shots):
from qiskit import transpile
if circuit.num_clbits == 0:
circuit = circuit.copy()
circuit.measure_all()
transpiled = transpile(circuit, self.backend)
return self.backend.run(transpiled, shots=shots).result().get_counts()Example (With Parameter Binding): def bind_parameters(self, circuit, bindings, metadata): # metadata.to_binding_dict() converts indexed names to backend params return circuit.assign_parameters(metadata.to_binding_dict(bindings))
Methods¶
bind_parameters¶
def bind_parameters(
self,
circuit: T,
bindings: dict[str, Any],
parameter_metadata: ParameterMetadata,
) -> TBind parameter values to the circuit.
Default implementation returns the circuit unchanged. Override for backends that support parametric circuits.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The parameterized circuit |
bindings | dict[str, Any] | Dict mapping parameter names (indexed format) to values. e.g., {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
parameter_metadata | ParameterMetadata | Metadata about circuit parameters |
Returns:
T — New circuit with parameters bound
estimate¶
def estimate(
self,
circuit: T,
hamiltonian: 'qm_o.Hamiltonian',
params: Sequence[float] | None = None,
) -> floatEstimate the expectation value of a Hamiltonian.
This method computes <psi|H|psi> where psi is the quantum state prepared by the circuit and H is the Hamiltonian.
Backends can override this method to provide optimized implementations using their native estimator primitives.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The quantum circuit (state preparation ansatz) |
hamiltonian | 'qm_o.Hamiltonian' | The qamomile.observable.Hamiltonian to measure |
params | Sequence[float] | None | Optional parameter values for parametric circuits |
Returns:
float — The estimated expectation value
Raises:
NotImplementedError— If the executor does not support estimation
execute¶
def execute(self, circuit: T, shots: int) -> dict[str, int]Execute the circuit and return bitstring counts.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The quantum circuit to execute |
shots | int | Number of measurement shots |
Returns:
dict[str, int] — Dictionary mapping bitstrings to counts.
dict[str, int] — {“00”: 512, “11”: 512}
QuantumStep [source]¶
class QuantumStepA quantum execution step.
Constructor¶
def __init__(self, segment: QuantumSegment) -> NoneAttributes¶
segment: QuantumSegment
RunJob [source]¶
class RunJob(Job[T], Generic[T])Job for single execution.
Returns a single result value matching the kernel’s return type.
Constructor¶
def __init__(self, raw_counts: dict[str, int], result_converter: Callable[[str], T])Initialize run job.
Parameters:
| Name | Type | Description |
|---|---|---|
raw_counts | dict[str, int] | Bitstring counts from executor (should have single entry) |
result_converter | Callable[[str], T] | Function to convert bitstring to typed result |
Methods¶
result¶
def result(self) -> TReturn the single result.
status¶
def status(self) -> JobStatusReturn job status.
SampleJob [source]¶
class SampleJob(Job[SampleResult[T]], Generic[T])Job for sampling execution (multiple shots).
Returns a SampleResult containing counts for each unique result.
Constructor¶
def __init__(
self,
raw_counts: dict[str, int],
result_converter: Callable[[dict[str, int]], list[tuple[T, int]]],
shots: int,
)Initialize sample job.
Parameters:
| Name | Type | Description |
|---|---|---|
raw_counts | dict[str, int] | Bitstring counts from executor (e.g., {“00”: 512, “11”: 512}) |
result_converter | Callable[[dict[str, int]], list[tuple[T, int]]] | Function to convert raw counts to typed results |
shots | int | Number of shots executed |
Methods¶
result¶
def result(self) -> SampleResult[T]Return the sample result.
status¶
def status(self) -> JobStatusReturn job status.
qamomile.circuit.transpiler.quantum_executor¶
Abstract base class for quantum backend execution.
This module provides a simple interface for implementing custom quantum executors. Executors bridge Qamomile’s compiled circuits to various quantum backends including local simulators and cloud quantum devices.
Basic Example (Local Simulator): from qiskit_aer import AerSimulator
class MyExecutor(QuantumExecutor[QuantumCircuit]):
def __init__(self):
self.backend = AerSimulator()
def execute(self, circuit: QuantumCircuit, shots: int) -> dict[str, int]:
from qiskit import transpile
if circuit.num_clbits == 0:
circuit = circuit.copy()
circuit.measure_all()
transpiled = transpile(circuit, self.backend)
job = self.backend.run(transpiled, shots=shots)
return job.result().get_counts()Cloud Backend Example (IBM Quantum): from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2
class IBMQuantumExecutor(QuantumExecutor[QuantumCircuit]):
def __init__(self, backend_name: str = "ibm_brisbane"):
self.service = QiskitRuntimeService()
self.backend_name = backend_name
def execute(self, circuit: QuantumCircuit, shots: int) -> dict[str, int]:
from qiskit.transpiler.preset_passmanagers import (
generate_preset_pass_manager,
)
backend = self.service.backend(self.backend_name)
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
transpiled = pm.run(circuit)
sampler = SamplerV2(backend)
job = sampler.run([transpiled], shots=shots)
return job.result()[0].data.meas.get_counts()
def bind_parameters(self, circuit, bindings, metadata):
# Use helper method for easy conversion
return circuit.assign_parameters(metadata.to_binding_dict(bindings))Bitstring Format:
The execute() method returns dict[str, int] where keys are bitstrings in big-endian format (leftmost bit = highest qubit index). Example: {“011”: 512, “100”: 488} for 3 qubits
Overview¶
| Class | Description |
|---|---|
ParameterMetadata | Metadata for all parameters in a compiled segment. |
QuantumExecutor | Abstract base class for quantum backend execution. |
Classes¶
ParameterMetadata [source]¶
class ParameterMetadataMetadata for all parameters in a compiled segment.
Tracks parameter information for runtime binding.
Constructor¶
def __init__(self, parameters: list[ParameterInfo] = list()) -> NoneAttributes¶
parameters: list[ParameterInfo]
Methods¶
get_array_names¶
def get_array_names(self) -> set[str]Get unique array/scalar parameter names.
get_ordered_params¶
def get_ordered_params(self) -> list[Any]Get backend parameter objects in definition order.
Useful for backends that require positional parameter binding (e.g., QURI Parts).
Returns:
list[Any] — List of backend_param objects in the order they were defined.
Example:
# For QURI Parts that uses positional binding:
param_values = [bindings[p.name] for p in metadata.parameters]
bound_circuit = circuit.bind_parameters(param_values)get_param_by_name¶
def get_param_by_name(self, name: str) -> ParameterInfo | NoneGet parameter info by full name.
to_binding_dict¶
def to_binding_dict(self, bindings: dict[str, Any]) -> dict[Any, Any]Convert indexed bindings to backend parameter bindings.
Transforms user-provided bindings (with indexed names like “gammas[0]”) into a dictionary mapping backend parameter objects to values. Useful for backends that use dict-based parameter binding (e.g., Qiskit).
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | Dictionary mapping parameter names to values. e.g., {“gammas[0]”: 0.1, “gammas[1]”: 0.2, “theta”: 0.5} |
Returns:
dict[Any, Any] — Dictionary mapping backend_param objects to values.
Example:
# For Qiskit that uses dict-based binding:
qiskit_bindings = metadata.to_binding_dict(bindings)
bound_circuit = circuit.assign_parameters(qiskit_bindings)QuantumExecutor [source]¶
class QuantumExecutor(ABC, Generic[T])Abstract base class for quantum backend execution.
To implement a custom executor:
execute() [Required] Execute circuit and return bitstring counts as dict[str, int]. Keys are bitstrings in big-endian format (e.g., “011” means q2=0, q1=1, q0=1).
bind_parameters() [Optional] Bind parameter values to parametric circuits. Override if your executor supports parametric circuits (e.g., QAOA variational circuits). Use ParameterMetadata.to_binding_dict() for easy conversion.
estimate() [Optional] Compute expectation values <psi|H|psi>. Override if your executor supports estimation primitives (e.g., Qiskit Estimator, QURI Parts).
Example (Minimal): class MyExecutor(QuantumExecutor[QuantumCircuit]): def init(self): from qiskit_aer import AerSimulator self.backend = AerSimulator()
def execute(self, circuit, shots):
from qiskit import transpile
if circuit.num_clbits == 0:
circuit = circuit.copy()
circuit.measure_all()
transpiled = transpile(circuit, self.backend)
return self.backend.run(transpiled, shots=shots).result().get_counts()Example (With Parameter Binding): def bind_parameters(self, circuit, bindings, metadata): # metadata.to_binding_dict() converts indexed names to backend params return circuit.assign_parameters(metadata.to_binding_dict(bindings))
Methods¶
bind_parameters¶
def bind_parameters(
self,
circuit: T,
bindings: dict[str, Any],
parameter_metadata: ParameterMetadata,
) -> TBind parameter values to the circuit.
Default implementation returns the circuit unchanged. Override for backends that support parametric circuits.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The parameterized circuit |
bindings | dict[str, Any] | Dict mapping parameter names (indexed format) to values. e.g., {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
parameter_metadata | ParameterMetadata | Metadata about circuit parameters |
Returns:
T — New circuit with parameters bound
estimate¶
def estimate(
self,
circuit: T,
hamiltonian: 'qm_o.Hamiltonian',
params: Sequence[float] | None = None,
) -> floatEstimate the expectation value of a Hamiltonian.
This method computes <psi|H|psi> where psi is the quantum state prepared by the circuit and H is the Hamiltonian.
Backends can override this method to provide optimized implementations using their native estimator primitives.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The quantum circuit (state preparation ansatz) |
hamiltonian | 'qm_o.Hamiltonian' | The qamomile.observable.Hamiltonian to measure |
params | Sequence[float] | None | Optional parameter values for parametric circuits |
Returns:
float — The estimated expectation value
Raises:
NotImplementedError— If the executor does not support estimation
execute¶
def execute(self, circuit: T, shots: int) -> dict[str, int]Execute the circuit and return bitstring counts.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | T | The quantum circuit to execute |
shots | int | Number of measurement shots |
Returns:
dict[str, int] — Dictionary mapping bitstrings to counts.
dict[str, int] — {“00”: 512, “11”: 512}
qamomile.circuit.transpiler.result¶
EmitResult data structures for transpiler output.
Overview¶
| Class | Description |
|---|---|
ClassicalMapping | Maps a logical Value to a classical value or measurement result slot. |
EmitResult | Structured result from Transpiler.emit(). |
OutputMapping | Maps Block output position to a physical resource. |
QubitMapping | Maps a logical Value to a physical qubit index. |
Classes¶
ClassicalMapping [source]¶
class ClassicalMappingMaps a logical Value to a classical value or measurement result slot.
Constructor¶
def __init__(
self,
value_uuid: str,
value_name: str,
value: Union[int, float, bool, None],
clbit_index: Union[int, None] = None,
) -> NoneAttributes¶
clbit_index: Union[int, None]value: Union[int, float, bool, None]value_name: strvalue_uuid: str
EmitResult [source]¶
class EmitResult(Generic[T])Structured result from Transpiler.emit().
Contains the backend-specific circuit along with mapping information that tracks the correspondence between logical Values and physical qubit/clbit indices.
Constructor¶
def __init__(
self,
circuit: T,
qubit_mappings: list[QubitMapping],
classical_mappings: list[ClassicalMapping],
output_mappings: list[OutputMapping],
num_qubits: int,
num_clbits: int = 0,
) -> NoneAttributes¶
circuit: Tclassical_mappings: list[ClassicalMapping]num_clbits: intnum_qubits: intoutput_mappings: list[OutputMapping]qubit_mappings: list[QubitMapping]
Methods¶
get_measurement_clbit_indices¶
def get_measurement_clbit_indices(self) -> list[int]Get clbit indices for all measurement outputs in order.
get_output_mapping_by_index¶
def get_output_mapping_by_index(self, index: int) -> Union[OutputMapping, None]Get output mapping by tuple index.
get_output_qubit_indices¶
def get_output_qubit_indices(self) -> list[int]Get qubit indices for all quantum outputs in order.
get_qubit_index_by_name¶
def get_qubit_index_by_name(self, name: str) -> Union[int, None]Look up qubit index by Value name.
OutputMapping [source]¶
class OutputMappingMaps Block output position to a physical resource.
Constructor¶
def __init__(
self,
output_index: int,
value_uuid: str,
value_name: str,
kind: str,
physical_index: Union[int, None],
classical_value: Union[int, float, bool, None] = None,
) -> NoneAttributes¶
classical_value: Union[int, float, bool, None]kind: stroutput_index: intphysical_index: Union[int, None]value_name: strvalue_uuid: str
QubitMapping [source]¶
class QubitMappingMaps a logical Value to a physical qubit index.
Constructor¶
def __init__(self, value_uuid: str, value_name: str, qubit_index: int) -> NoneAttributes¶
qubit_index: intvalue_name: strvalue_uuid: str
qamomile.circuit.transpiler.segments¶
Data structures for segmented quantum/classical execution plans.
Overview¶
| Class | Description |
|---|---|
ClassicalSegment | A segment of pure classical operations. |
ClassicalStep | A classical execution step. |
ExpvalSegment | A segment for expectation value computation. |
ExpvalStep | An expectation-value execution step. |
HybridBoundary | Represents a measurement or encode operation at quantum/classical boundary. |
MultipleQuantumSegmentsError | Raised when program has multiple quantum segments. |
ProgramABI | Runtime-visible ABI for a segmented program. |
ProgramPlan | Execution plan for a hybrid quantum/classical program. |
QuantumSegment | A segment of pure quantum operations. |
QuantumStep | A quantum execution step. |
Segment | Base class for separated computation segments. |
SegmentKind | Type of computation segment. |
Value | A typed SSA value in the IR. |
Constants¶
ProgramStep:TypeAlias=ClassicalStep | QuantumStep | ExpvalStep
Classes¶
ClassicalSegment [source]¶
class ClassicalSegment(Segment)A segment of pure classical operations.
Contains arithmetic, comparisons, and control flow. Will be executed directly in Python.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
kind: SegmentKind
ClassicalStep [source]¶
class ClassicalStepA classical execution step.
Constructor¶
def __init__(self, segment: ClassicalSegment, role: str = 'classical') -> NoneAttributes¶
role: strsegment: ClassicalSegment
ExpvalSegment [source]¶
class ExpvalSegment(Segment)A segment for expectation value computation.
Represents computing <psi|H|psi> where psi is the quantum state and H is a Hamiltonian observable.
This segment bridges a quantum circuit (state preparation) to a classical expectation value.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
hamiltonian_value: Value | None = None,
qubits_value: Value | None = None,
result_ref: str = '',
) -> NoneAttributes¶
hamiltonian_value: Value | Nonekind: SegmentKindqubits_value: Value | Noneresult_ref: str
ExpvalStep [source]¶
class ExpvalStepAn expectation-value execution step.
Constructor¶
def __init__(self, segment: ExpvalSegment, quantum_step_index: int = 0) -> NoneAttributes¶
quantum_step_index: intsegment: ExpvalSegment
HybridBoundary [source]¶
class HybridBoundaryRepresents a measurement or encode operation at quantum/classical boundary.
These operations bridge quantum and classical segments.
Constructor¶
def __init__(
self,
operation: Operation,
source_segment_index: int,
target_segment_index: int,
value_ref: str,
) -> NoneAttributes¶
operation: Operationsource_segment_index: inttarget_segment_index: intvalue_ref: str
MultipleQuantumSegmentsError [source]¶
class MultipleQuantumSegmentsError(Exception)Raised when program has multiple quantum segments.
Qamomile enforces a single quantum circuit execution pattern:
[Classical Prep] → Quantum Circuit → [Classical Post/Expval]
Your program has multiple quantum segments, suggesting quantum operations that depend on measurement results (JIT compilation not supported).
ProgramABI [source]¶
class ProgramABIRuntime-visible ABI for a segmented program.
Constructor¶
def __init__(
self,
public_inputs: dict[str, Value] = dict(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
output_refs: list[str]public_inputs: dict[str, Value]
ProgramPlan [source]¶
class ProgramPlanExecution plan for a hybrid quantum/classical program.
Structure:
[Optional] Classical preprocessing (parameter computation, etc.)
Single quantum segment (REQUIRED)
[Optional] Expval segment OR classical postprocessing
This plan enforces Qamomile’s current execution model: all quantum operations must be in a single quantum circuit.
Constructor¶
def __init__(
self,
steps: list[ProgramStep] = list(),
abi: ProgramABI = ProgramABI(),
boundaries: list[HybridBoundary] = list(),
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
abi: ProgramABIboundaries: list[HybridBoundary]parameters: dict[str, Value]steps: list[ProgramStep]
QuantumSegment [source]¶
class QuantumSegment(Segment)A segment of pure quantum operations.
Contains quantum gates and qubit allocations. Will be emitted to a quantum circuit.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
qubit_values: list[Value] = list(),
num_qubits: int = 0,
) -> NoneAttributes¶
kind: SegmentKindnum_qubits: intqubit_values: list[Value]
QuantumStep [source]¶
class QuantumStepA quantum execution step.
Constructor¶
def __init__(self, segment: QuantumSegment) -> NoneAttributes¶
segment: QuantumSegment
Segment [source]¶
class Segment(ABC)Base class for separated computation segments.
Constructor¶
def __init__(
self,
operations: list[Operation] = list(),
input_refs: list[str] = list(),
output_refs: list[str] = list(),
) -> NoneAttributes¶
input_refs: list[str]kind: SegmentKind Return the kind of this segment.operations: list[Operation]output_refs: list[str]
SegmentKind [source]¶
class SegmentKind(Enum)Type of computation segment.
Attributes¶
CLASSICALEXPVALQUANTUM
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.
qamomile.circuit.transpiler.transpiler¶
Base transpiler class for backend-specific compilation.
Overview¶
| Function | Description |
|---|---|
count_call_blocks | Count CallBlockOperations, including those nested inside IfOps and |
| Class | Description |
|---|---|
AffineValidationPass | Validate affine type semantics at IR level. |
AnalyzePass | Analyze and validate an affine block. |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
CompileTimeIfLoweringPass | Lowers compile-time resolvable IfOperations before separation. |
ConstantFoldingPass | Evaluates constant expressions at compile time. |
DecompositionConfig | Configuration for decomposition strategy selection. |
EmitPass | Base class for backend-specific emission passes. |
EntrypointValidationPass | Validate top-level entrypoint constraints. |
ExecutableProgram | A fully compiled program ready for execution. |
FrontendTransformError | Error during frontend AST-to-builder lowering. |
InlinePass | Inline all CallBlockOperations to create an affine block. |
ParameterShapeResolutionPass | Substitute symbolic parameter array shape dims with concrete constants. |
PartialEvaluationPass | Fold constants and lower compile-time control flow. |
ProgramPlan | Execution plan for a hybrid quantum/classical program. |
QKernel | Decorator class for Qamomile quantum kernels. |
QamomileCompileError | Base class for all Qamomile compilation errors. |
SegmentationPass | Segment a block into a strategy-specific executable program plan. |
SubstitutionConfig | Configuration for the substitution pass. |
SubstitutionPass | Pass that substitutes CallBlockOperations and CompositeGateOperations. |
SubstitutionRule | A single substitution rule. |
SymbolicShapeValidationPass | Reject unresolved parameter shape dims in compile-time structure ops. |
Transpiler | Base class for backend-specific transpilers. |
TranspilerConfig | Configuration for the transpiler pipeline. |
Functions¶
count_call_blocks [source]¶
def count_call_blocks(operations: list[Operation]) -> intCount CallBlockOperations, including those nested inside IfOps and HasNestedOps. Used by the unroll loop as the primary termination signal (count==0 means the block is fully inlined).
Classes¶
AffineValidationPass [source]¶
class AffineValidationPass(Pass[Block, Block])Validate affine type semantics at IR level.
This pass serves as a safety net to catch affine type violations that may have bypassed the frontend checks. It verifies:
Each quantum value is used (consumed) at most once
Quantum values are not silently discarded
Input: Block (any kind) Output: Same Block (unchanged, validation only)
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockValidate affine type semantics in the block.
Raises:
ValidationError— If the block kind is not AFFINE.AffineTypeError— If a quantum value is consumed multiple times.
AnalyzePass [source]¶
class AnalyzePass(Pass[Block, Block])Analyze and validate an affine block.
This pass:
Builds a dependency graph between values (used locally for validation)
Validates that quantum ops don’t depend on non-parameter classical results
Checks that block inputs/outputs are classical
Input: Block with BlockKind.AFFINE Output: Block with BlockKind.ANALYZED
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockAnalyze the block and validate dependencies.
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
CompileTimeIfLoweringPass [source]¶
class CompileTimeIfLoweringPass(Pass[Block, Block])Lowers compile-time resolvable IfOperations before separation.
After constant folding, some IfOperation conditions are statically
known but remain as control-flow nodes. SegmentationPass treats them
as segment boundaries, causing MultipleQuantumSegmentsError for
classical-only compile-time if after quantum init.
This pass:
Evaluates conditions including expression-derived ones (
CompOp,CondOp,NotOpchains).Replaces resolved
IfOperations with selected-branch operations.Substitutes phi output UUIDs with selected-branch values in all subsequent operations and block outputs.
Constructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockRun the compile-time if lowering pass.
ConstantFoldingPass [source]¶
class ConstantFoldingPass(Pass[Block, Block])Evaluates constant expressions at compile time.
This pass folds BinOp operations when all operands are constants or bound parameters, eliminating unnecessary classical operations that would otherwise split quantum segments.
Example:
Before (with bindings={"phase": 0.5}):
BinOp(phase * 2) -> classical segment split
After:
Constant 1.0 -> no segment splitConstructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockRun constant folding on the block.
DecompositionConfig [source]¶
class DecompositionConfigConfiguration for decomposition strategy selection.
This configuration is passed to the transpiler to control which decomposition strategies are used for composite gates.
Constructor¶
def __init__(
self,
strategy_overrides: dict[str, str] = dict(),
strategy_params: dict[str, dict[str, Any]] = dict(),
default_strategy: str = 'standard',
) -> NoneAttributes¶
default_strategy: strstrategy_overrides: dict[str, str]strategy_params: dict[str, dict[str, Any]]
Methods¶
get_strategy_for_gate¶
def get_strategy_for_gate(self, gate_name: str) -> strGet the strategy name for a specific gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_name | str | The gate name (e.g., “qft”, “iqft”) |
Returns:
str — Strategy name to use
get_strategy_params¶
def get_strategy_params(self, strategy_name: str) -> dict[str, Any]Get parameters for a specific strategy.
Parameters:
| Name | Type | Description |
|---|---|---|
strategy_name | str | The strategy name |
Returns:
dict[str, Any] — Dictionary of parameters
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.
EntrypointValidationPass [source]¶
class EntrypointValidationPass(Pass[Block, Block])Validate top-level entrypoint constraints.
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockExecutableProgram [source]¶
class ExecutableProgram(Generic[T])A fully compiled program ready for execution.
Contains compiled quantum, classical, and expectation-value segments.
Use sample() for multi-shot execution or run() for single
execution.
Example:
executable = transpiler.compile(kernel)
# Sample: multiple shots, returns counts
job = executable.sample(executor, shots=1000)
result = job.result() # SampleResult with counts
# Run: single shot, returns typed result
job = executable.run(executor)
result = job.result() # Returns kernel's return typeConstructor¶
def __init__(
self,
plan: ProgramPlan | None = None,
compiled_quantum: list[CompiledQuantumSegment[T]] = list(),
compiled_classical: list[CompiledClassicalSegment] = list(),
compiled_expval: list[CompiledExpvalSegment] = list(),
output_refs: list[str] = list(),
num_output_bits: int = 0,
) -> NoneAttributes¶
compiled_classical: list[CompiledClassicalSegment]compiled_expval: list[CompiledExpvalSegment]compiled_quantum: list[CompiledQuantumSegment[T]]has_parameters: bool Check if this program has unbound parameters.num_output_bits: intoutput_refs: list[str]parameter_names: list[str] Get list of parameter names that need binding.plan: ProgramPlan | Nonequantum_circuit: T Get the single quantum circuit.
Methods¶
get_circuits¶
def get_circuits(self) -> list[T]Get all quantum circuits in execution order.
get_first_circuit¶
def get_first_circuit(self) -> T | NoneGet the first quantum circuit, or None if no quantum segments.
run¶
def run(
self,
executor: QuantumExecutor[T],
bindings: dict[str, Any] | None = None,
) -> RunJob[Any] | ExpvalJobExecute once and return single result.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
RunJob[Any] | ExpvalJob — RunJob that resolves to the kernel’s return type, or
RunJob[Any] | ExpvalJob — ExpvalJob if the program contains expectation value computation.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.run(executor, bindings={"gamma": [0.5]})
result = job.result()
print(result) # 0.25 (for QFixed) or (0, 1) (for bits)sample¶
def sample(
self,
executor: QuantumExecutor[T],
shots: int = 1024,
bindings: dict[str, Any] | None = None,
) -> SampleJob[Any]Execute with multiple shots and return counts.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
shots | int | Number of shots to run. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
SampleJob[Any] — SampleJob that resolves to SampleResult with results.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.sample(executor, shots=1000, bindings={"gamma": [0.5]})
result = job.result()
print(result.results) # [(0.25, 500), (0.75, 500)]FrontendTransformError [source]¶
class FrontendTransformError(QamomileCompileError)Error during frontend AST-to-builder lowering.
InlinePass [source]¶
class InlinePass(Pass[Block, Block])Inline all CallBlockOperations to create an affine block.
This pass recursively inlines function calls while preserving control flow structures (For, If, While).
Input: Block with BlockKind.HIERARCHICAL (may contain CallBlockOperations) Output: Block with BlockKind.AFFINE (no CallBlockOperations)
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockInline all CallBlockOperations.
Self-recursive CallBlockOperations (ones whose .block is the
block currently being expanded) are unrolled one level per
call: the inner self-call is substituted but left intact so
that the outer fixed-point loop (inline ↔ partial_eval in
Transpiler.transpile) can fold the base-case if between
iterations. The output kind is AFFINE when no
CallBlockOperations remain, otherwise HIERARCHICAL.
ParameterShapeResolutionPass [source]¶
class ParameterShapeResolutionPass(Pass[Block, Block])Substitute symbolic parameter array shape dims with concrete constants.
Input: BlockKind.HIERARCHICAL (runs before InlinePass).
Output: same block kind, with matching shape dim Values constant-folded.
Constructor¶
def __init__(self, bindings: dict[str, Any] | None = None) -> NoneAttributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockPartialEvaluationPass [source]¶
class PartialEvaluationPass(Pass[Block, Block])Fold constants and lower compile-time control flow.
Constructor¶
def __init__(self, bindings: dict[str, Any] | None = None)Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockProgramPlan [source]¶
class ProgramPlanExecution plan for a hybrid quantum/classical program.
Structure:
[Optional] Classical preprocessing (parameter computation, etc.)
Single quantum segment (REQUIRED)
[Optional] Expval segment OR classical postprocessing
This plan enforces Qamomile’s current execution model: all quantum operations must be in a single quantum circuit.
Constructor¶
def __init__(
self,
steps: list[ProgramStep] = list(),
abi: ProgramABI = ProgramABI(),
boundaries: list[HybridBoundary] = list(),
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
abi: ProgramABIboundaries: list[HybridBoundary]parameters: dict[str, Value]steps: list[ProgramStep]
QKernel [source]¶
class QKernel(Generic[P, R])Decorator class for Qamomile quantum kernels.
Constructor¶
def __init__(self, func: Callable[P, R]) -> NoneAttributes¶
block: Block Compile the function to a hierarchical Block if not already compiled.funcinput_typesnameoutput_typesraw_funcsignature
Methods¶
build¶
def build(self, parameters: list[str] | None = None, **kwargs: Any = {}) -> BlockBuild a traced Block by tracing this kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
parameters | list[str] | None | List of argument names to keep as unbound parameters. - None (default): Auto-detect parameters (non-Qubit args without value/default) - []: No parameters (all non-Qubit args must have value/default) - [“name”]: Explicit parameter list Only float, int, UInt, and their arrays are allowed as parameters. |
**kwargs | Any | Concrete values for non-parameter arguments. |
Returns:
Block — The traced block ready for transpilation, estimation,
or visualization.
Raises:
TypeError— If a non-parameterizable type is specified as parameter.ValueError— If required arguments are missing.
Example:
@qm.qkernel
def circuit(q: Qubit, theta: float) -> Qubit:
q = qm.rx(q, theta)
return q
# Auto-detect theta as parameter
block = circuit.build()
# Explicit parameter list
block = circuit.build(parameters=["theta"])
# theta bound to concrete value
block = circuit.build(theta=0.5)
# Transpile with binding
transpiler = QiskitTranspiler()
result = transpiler.emit(graph, binding={"theta": 0.5})draw¶
def draw(
self,
inline: bool = False,
fold_loops: bool = True,
expand_composite: bool = False,
inline_depth: int | None = None,
**kwargs: Any = {},
) -> AnyVisualize the circuit using Matplotlib.
This method builds the computation graph and creates a static visualization. Parameters are auto-detected: non-Qubit arguments without concrete values are shown as symbolic parameters.
Parameters:
| Name | Type | Description |
|---|---|---|
inline | bool | If True, expand CallBlockOperation contents (inlining). If False (default), show CallBlockOperation as boxes. |
fold_loops | bool | If True (default), display ForOperation as blocks instead of unrolling. If False, expand loops and show all iterations. |
expand_composite | bool | If True, expand CompositeGateOperation (QFT, IQFT, etc.). If False (default), show as boxes. Independent of inline. |
inline_depth | int | None | Maximum nesting depth for inline expansion. None means unlimited (default). 0 means no inlining, 1 means top-level only, etc. Only affects CallBlock/ControlledU, not CompositeGate. |
**kwargs | Any | Concrete values for arguments. Arguments not provided here (and without defaults) will be shown as symbolic parameters. |
Returns:
Any — matplotlib.figure.Figure object.
Raises:
ImportError— If matplotlib is not installed.
Example:
import qamomile.circuit as qm
@qm.qkernel
def inner(q: qm.Qubit) -> qm.Qubit:
return qm.x(q)
@qm.qkernel
def circuit(q: qm.Qubit, theta: float) -> qm.Qubit:
q = inner(q)
q = qm.h(q)
q = qm.rx(q, theta)
return q
# Draw with auto-detected symbolic parameter (theta)
fig = circuit.draw()
# Draw with bound parameter
fig = circuit.draw(theta=0.5)
# Draw with blocks as boxes (default)
fig = circuit.draw()
# Draw with blocks expanded (inlined)
fig = circuit.draw(inline=True)
# Draw with loops folded (shown as blocks)
fig = circuit.draw(fold_loops=True)
# Draw with composite gates expanded
fig = circuit.draw(expand_composite=True)estimate_resources¶
def estimate_resources(self, *, bindings: dict[str, Any] | None = None) -> ResourceEstimateEstimate all resources for this kernel’s circuit.
Convenience method that delegates to the module-level
estimate_resources function, eliminating the need to
access .block directly.
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | None | Optional concrete parameter bindings (scalars and dicts). Dict values trigger |key| cardinality substitution. |
Returns:
ResourceEstimate — ResourceEstimate with qubits, gates, and parameters.
Example:
>>> @qm.qkernel
... def bell() -> qm.Vector[qm.Qubit]:
... q = qm.qubit_array(2)
... q[0] = qm.h(q[0])
... q[0], q[1] = qm.cx(q[0], q[1])
... return q
>>> est = bell.estimate_resources()
>>> print(est.qubits) # 2QamomileCompileError [source]¶
class QamomileCompileError(Exception)Base class for all Qamomile compilation errors.
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.
SubstitutionConfig [source]¶
class SubstitutionConfigConfiguration for the substitution pass.
Constructor¶
def __init__(self, rules: list[SubstitutionRule] = list()) -> NoneAttributes¶
rules: list[SubstitutionRule]
Methods¶
get_rule_for_name¶
def get_rule_for_name(self, name: str) -> SubstitutionRule | NoneFind a rule matching the given name.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Name to look up |
Returns:
SubstitutionRule | None — Matching SubstitutionRule or None
SubstitutionPass [source]¶
class SubstitutionPass(Pass[Block, Block])Pass that substitutes CallBlockOperations and CompositeGateOperations.
This pass traverses the block and applies substitution rules:
For CallBlockOperation: replaces the block reference with the target
For CompositeGateOperation: sets the strategy_name field
The pass preserves the block structure and only modifies matching operations.
Input: Block (any kind) Output: Block with substitutions applied (same kind as input)
Constructor¶
def __init__(self, config: SubstitutionConfig) -> NoneInitialize the pass with configuration.
Parameters:
| Name | Type | Description |
|---|---|---|
config | SubstitutionConfig | Substitution configuration with rules |
Attributes¶
name: str Return pass name.
Methods¶
run¶
def run(self, input: Block) -> BlockApply substitutions to the block.
Parameters:
| Name | Type | Description |
|---|---|---|
input | Block | Block to transform |
Returns:
Block — Block with substitutions applied
SubstitutionRule [source]¶
class SubstitutionRuleA single substitution rule.
Constructor¶
def __init__(
self,
source_name: str,
target: 'Block | QKernel | None' = None,
strategy: str | None = None,
validate_signature: bool = True,
) -> NoneAttributes¶
source_name: strstrategy: str | Nonetarget: ‘Block | QKernel | None’validate_signature: bool
SymbolicShapeValidationPass [source]¶
class SymbolicShapeValidationPass(Pass[Block, Block])Reject unresolved parameter shape dims in compile-time structure ops.
Input: BlockKind.ANALYZED (runs after AnalyzePass).
Output: same block unchanged, or raises QamomileCompileError.
Attributes¶
name: str
Methods¶
run¶
def run(self, input: Block) -> BlockTranspiler [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 |
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 the call count
stops decreasing (symbolic driver — self-calls are left in the
IR and handled by downstream passes), or when MAX_UNROLL_DEPTH
is reached (non-terminating recursion — raises).
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.
TranspilerConfig [source]¶
class TranspilerConfigConfiguration for the transpiler pipeline.
This configuration allows customizing the compilation behavior, including decomposition strategies and subroutine substitutions.
Example:
config = TranspilerConfig(
decomposition=DecompositionConfig(
strategy_overrides={"qft": "approximate"},
),
substitutions=SubstitutionConfig(
rules=[
SubstitutionRule("my_oracle", target=optimized_oracle),
],
),
)
transpiler = QiskitTranspiler(config=config)Constructor¶
def __init__(
self,
decomposition: DecompositionConfig = DecompositionConfig(),
substitutions: SubstitutionConfig = SubstitutionConfig(),
) -> NoneAttributes¶
decomposition: DecompositionConfigsubstitutions: SubstitutionConfig
Methods¶
with_strategies¶
@classmethod
def with_strategies(
cls,
strategy_overrides: dict[str, str] | None = None,
**kwargs: Any = {},
) -> 'TranspilerConfig'Create config with strategy overrides.
Parameters:
| Name | Type | Description |
|---|---|---|
strategy_overrides | dict[str, str] | None | Map of gate name to strategy name |
**kwargs | Any | Additional config options |
Returns:
'TranspilerConfig' — TranspilerConfig instance
Example:
config = TranspilerConfig.with_strategies(
strategy_overrides={"qft": "approximate", "iqft": "approximate"}
)qamomile.circuit.transpiler.value_resolver¶
Unified value resolution for transpiler passes.
Several transpiler passes need to resolve an IR Value to a concrete
Python value (int, float, bool). Each pass previously carried its own
copy of the resolution logic with slightly different lookup orders and
naming conventions.
ValueResolver consolidates those into a single class with a
deterministic resolution order:
Context map — caller-supplied
UUID → concrete valuedict (e.g.folded_values,concrete_values).Constant —
value.is_constant() → value.get_const().Bindings by parameter name —
value.is_parameter() → bindings[param_name].Bindings by value name —
value.name → bindings[name].Returns
Noneif none of the above match.
Overview¶
| Class | Description |
|---|---|
ValueResolver | Resolves IR Values to concrete Python values. |
Classes¶
ValueResolver [source]¶
class ValueResolverResolves IR Values to concrete Python values.
Parameters¶
context:
UUID-keyed map of already-resolved values. The values may be
either raw Python scalars or Value objects; if a Value is
found its get_const() is extracted automatically.
bindings:
Name-keyed parameter bindings supplied by the user at transpile
time.
Constructor¶
def __init__(
self,
context: dict[str, Any] | None = None,
bindings: dict[str, Any] | None = None,
)Methods¶
resolve¶
def resolve(self, value: Any) -> Any | NoneResolve value to a concrete Python value, or None.
If value is not a Value-like object (no uuid attribute) it
is returned as-is — the caller already has a concrete value.