Public surface for the Qamomile IR package.
Re-exports the contributor-facing debugging and canonical-form
helpers so callers can use the short form
from qamomile.circuit.ir import pretty_print_block or
from qamomile.circuit.ir import canonicalize.
Overview¶
| Function | Description |
|---|---|
canonicalize | Return a canonical-form clone of block. |
canonicalize_and_remap | Return canonical-form Block plus the UUID and logical_id remap tables. |
content_hash | Compute a content-addressable hash of block. |
format_value | Format an IR value reference as %name@vN. |
pretty_print_block | Return a MLIR-style textual dump of block. |
to_canonical_bytes | Serialize block to a deterministic byte representation. |
Functions¶
canonicalize [source]¶
def canonicalize(block: Block) -> BlockReturn a canonical-form clone of block.
The returned Block has the same structure as block but with
every Value UUID and logical_id re-issued from a deterministic
counter. All UUID references inside operations and value metadata
are rewritten consistently. Block.kind is preserved.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to canonicalize. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
Block — A new Block with canonical UUIDs. Block.kind matches
the input. Existing input/output ordering, operation
ordering, metadata structure, and the param_slots
manifest (carried over verbatim) are preserved.
Raises:
ValueError— Ifblock.kindis not in{AFFINE, ANALYZED}.NotImplementedError— If aCallBlockOperationis encountered (typically becauseinlinehas not been run yet).
Example:
>>> from qamomile.qiskit import QiskitTranspiler
>>> transpiler = QiskitTranspiler()
>>> affine = transpiler.inline(transpiler.to_block(my_kernel))
>>> canon = canonicalize(affine)
>>> canon.kind is affine.kind
Truecanonicalize_and_remap [source]¶
def canonicalize_and_remap(block: Block) -> tuple[Block, dict[str, str], dict[str, str]]Return canonical-form Block plus the UUID and logical_id remap tables.
Useful when the caller holds external references keyed on the original Value UUIDs or logical_ids (e.g., a host-side port map) and needs to update those references to match the canonical form.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to canonicalize. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
tuple[Block, dict[str, str], dict[str, str]] — tuple[Block, dict[str, str], dict[str, str]]: A triple
(canonical_block, uuid_remap, logical_id_remap) where
each remap maps every original identifier encountered
during the walk to its canonical counterpart. uuid and
logical_id share the same monotonic counter but are
tracked in separate maps.
Raises:
ValueError— Ifblock.kindis not in{AFFINE, ANALYZED}.NotImplementedError— If aCallBlockOperationis encountered.
content_hash [source]¶
def content_hash(block: Block) -> strCompute a content-addressable hash of block.
Two Blocks that canonicalize to the same form (structurally equal after UUID remapping) produce the same hash. Any IR-level change (gate added, parameter renamed, operand reordered) produces a different hash.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to hash. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
str — The SHA-256 hex digest of to_canonical_bytes(block).
Raises:
ValueError— Ifblock.kindis not in{AFFINE, ANALYZED}.
Example:
>>> h1 = content_hash(canonicalize(affine_a))
>>> h2 = content_hash(canonicalize(affine_b))
>>> # If the two kernels are structurally identical, h1 == h2.format_value [source]¶
def format_value(value: Any) -> strFormat an IR value reference as %name@vN.
Handles Value, ArrayValue, TupleValue, DictValue, and
array-element Values (rendered as %parent[i]@vN). Constants
and parameters are shown with their tagged metadata when available.
Falls back to repr() for unrecognised inputs so callers can use
this helper for any operand-like field without a type switch.
pretty_print_block [source]¶
def pretty_print_block(block: Block, *, depth: int = 0) -> strReturn a MLIR-style textual dump of block.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The Block to format. Works on any BlockKind. |
depth | int | How many levels of CallBlockOperation to expand inline. 0 (default) shows only the callee name and I/O. Positive values expand the called block’s body recursively, decrementing the allowance at each step. Useful for seeing what inline will produce without actually running the pass. |
Returns:
str — A newline-separated string. The format is for human debugging and
str — is not guaranteed to be stable across releases.
to_canonical_bytes [source]¶
def to_canonical_bytes(block: Block) -> bytesSerialize block to a deterministic byte representation.
The byte format is the internal representation backing
content_hash and is not stable across qamomile versions. It is
suitable for hashing and equality checks within a single
deployment but should not be relied upon as a serialization
format. (A stable, versioned serialization format is tracked
separately.)
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to serialize. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. The block is canonicalized first; passing an already-canonical block is harmless. |
Returns:
bytes — A UTF-8-encoded byte string. Two structurally-equal
Blocks produce the same bytes; changing the IR yields
different bytes.
Raises:
ValueError— Ifblock.kindis not in{AFFINE, ANALYZED}.
qamomile.circuit.ir.block¶
Unified block representation for all pipeline stages.
Overview¶
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
CallBlockOperation | |
ParamSlot | Metadata for a single classical kernel argument. |
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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).
ParamSlot [source]¶
class ParamSlotMetadata for a single classical kernel argument.
A ParamSlot describes one position in the kernel’s classical
parameter contract — its declared type, whether it is a runtime
parameter or a compile-time-bound value, the Python default (if
any), the actually-bound value (when kind is
COMPILE_TIME_BOUND), and any outer-DSL hints. Slots are
immutable; pipeline passes that need to update a slot must clone
via dataclasses.replace.
The slot is identified by name, which matches the kernel’s
Python parameter name and the corresponding entry in
Block.label_args. A slot’s name MUST never overlap between
RUNTIME_PARAMETER and COMPILE_TIME_BOUND instances within
one Block (this mirrors the project-level bindings /
parameters disjointness rule).
Constructor¶
def __init__(
self,
name: str,
type: 'ValueType',
kind: ParamKind,
ndim: int = 0,
default: Any = None,
bound_value: Any = None,
differentiable: bool = False,
) -> NoneAttributes¶
bound_value: Anydefault: Anydifferentiable: boolkind: ParamKindname: strndim: inttype: ‘ValueType’
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.ir.canonical¶
Canonical form for IR blocks: deterministic UUIDs and content hashing.
This module provides a normalization pass that re-numbers every Value
UUID (and logical_id) in a Block from a deterministic counter,
rewriting every UUID reference embedded in operations and value
metadata so the resulting Block is structurally invariant across
independent builds of the same kernel.
The canonical form is intended for IR-level equality checks, debugging
diffs, and a content-addressable identity (content_hash) suitable
for caching and (later) for serialization keyed on IR contents rather
than build-local Python state.
Supported scope:
Only BlockKind.AFFINE and BlockKind.ANALYZED are accepted.
HIERARCHICAL Blocks still contain CallBlockOperations that
reference sibling Blocks by Python identity; their canonical
treatment is deferred (see backlog [IR design] Add named/versioned module references for cross-process kernel composition).
Output guarantees:
canonicalizedoes not changeBlock.kind; it is a normalization, not a pipeline stage advance.For two builds of the same kernel that produce structurally identical IR,
canonicalizereturns Blocks that are equal underto_canonical_bytes(and therefore undercontent_hash).canonicalizeis idempotent: running it twice on the same Block yields the same canonical bytes as running it once.
Canonical-bytes scope:
Display-only fields (Block.name, Block.output_names,
Value.name) are excluded from to_canonical_bytes;
functional fields are included. Block.label_args (input port
names by position) and Block.param_slots (the kernel’s
classical parameter contract) are both functional: two Blocks
whose operations match but whose parameter manifests differ (e.g.,
a slot rebound from RUNTIME_PARAMETER to
COMPILE_TIME_BOUND) hash differently. param_slots holds no
Value/UUID references, so canonicalize carries the tuple over
verbatim with nothing to remap.
Limitations:
Value.parent_arraycycles (a Value whoseparent_arrayis itself reachable from the Value’s siblings) are not constructed by the frontend today; the canonicalizer assumes the Value-reference graph throughparent_arrayandelement_indicesis acyclic.ValueMetadata.dict_runtime.bound_data,ArrayRuntimeMetadata.const_array, andParamSlot.default/ParamSlot.bound_valuemay carry arbitrary frozen Python data.numpy.ndarraypayloads (except object-dtype arrays) are hashed from their raw buffer (dtype + shape + bytes) and are therefore exempt; hash stability for any other object type requires a stablerepr.
Overview¶
| Function | Description |
|---|---|
canonicalize | Return a canonical-form clone of block. |
canonicalize_and_remap | Return canonical-form Block plus the UUID and logical_id remap tables. |
content_hash | Compute a content-addressable hash of block. |
remap_indexed_identifier | Remap an identifier while preserving a legacy index suffix. |
remap_value_metadata_references | Rewrite UUID and logical-id references inside value metadata. |
to_canonical_bytes | Serialize block to a deterministic byte representation. |
| 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 | |
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
ControlledUOperation | Base class for controlled-U operations. |
DictValue | A dictionary value stored as stable ordered entries. |
HasNestedOps | Mixin for operations that contain nested operation lists. |
InverseBlockOperation | Represent an inverse qkernel/block as a first-class IR operation. |
TupleValue | A tuple of IR values for structured data. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueMetadata | Typed metadata owned by the compiler/runtime. |
ValueType | Base class for all value types in the IR. |
Functions¶
canonicalize [source]¶
def canonicalize(block: Block) -> BlockReturn a canonical-form clone of block.
The returned Block has the same structure as block but with
every Value UUID and logical_id re-issued from a deterministic
counter. All UUID references inside operations and value metadata
are rewritten consistently. Block.kind is preserved.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to canonicalize. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
Block — A new Block with canonical UUIDs. Block.kind matches
the input. Existing input/output ordering, operation
ordering, metadata structure, and the param_slots
manifest (carried over verbatim) are preserved.
Raises:
ValueError— Ifblock.kindis not in{AFFINE, ANALYZED}.NotImplementedError— If aCallBlockOperationis encountered (typically becauseinlinehas not been run yet).
Example:
>>> from qamomile.qiskit import QiskitTranspiler
>>> transpiler = QiskitTranspiler()
>>> affine = transpiler.inline(transpiler.to_block(my_kernel))
>>> canon = canonicalize(affine)
>>> canon.kind is affine.kind
Truecanonicalize_and_remap [source]¶
def canonicalize_and_remap(block: Block) -> tuple[Block, dict[str, str], dict[str, str]]Return canonical-form Block plus the UUID and logical_id remap tables.
Useful when the caller holds external references keyed on the original Value UUIDs or logical_ids (e.g., a host-side port map) and needs to update those references to match the canonical form.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to canonicalize. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
tuple[Block, dict[str, str], dict[str, str]] — tuple[Block, dict[str, str], dict[str, str]]: A triple
(canonical_block, uuid_remap, logical_id_remap) where
each remap maps every original identifier encountered
during the walk to its canonical counterpart. uuid and
logical_id share the same monotonic counter but are
tracked in separate maps.
Raises:
ValueError— Ifblock.kindis not in{AFFINE, ANALYZED}.NotImplementedError— If aCallBlockOperationis encountered.
content_hash [source]¶
def content_hash(block: Block) -> strCompute a content-addressable hash of block.
Two Blocks that canonicalize to the same form (structurally equal after UUID remapping) produce the same hash. Any IR-level change (gate added, parameter renamed, operand reordered) produces a different hash.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to hash. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
str — The SHA-256 hex digest of to_canonical_bytes(block).
Raises:
ValueError— Ifblock.kindis not in{AFFINE, ANALYZED}.
Example:
>>> h1 = content_hash(canonicalize(affine_a))
>>> h2 = content_hash(canonicalize(affine_b))
>>> # If the two kernels are structurally identical, h1 == h2.remap_indexed_identifier [source]¶
def remap_indexed_identifier(identifier: str, remap_identifier: Callable[[str], str]) -> strRemap an identifier while preserving a legacy index suffix.
Parameters:
| Name | Type | Description |
|---|---|---|
identifier | str | Scalar identifier or legacy "<base>_<index>" carrier key. |
remap_identifier | typing.Callable[[str], str] | Function that remaps scalar identifiers and carrier-key bases. |
Returns:
str — Remapped identifier. Numeric index suffixes are preserved after
remapping the base identifier.
remap_value_metadata_references [source]¶
def remap_value_metadata_references(
metadata: ValueMetadata,
remap_uuid: Callable[[str], str],
remap_logical_id: Callable[[str], str],
) -> ValueMetadataRewrite UUID and logical-id references inside value metadata.
Parameters:
| Name | Type | Description |
|---|---|---|
metadata | ValueMetadata | Metadata bundle whose embedded references should be rewritten. |
remap_uuid | typing.Callable[[str], str] | Function that maps scalar UUID references (and carrier-key bases) to replacement UUIDs. |
remap_logical_id | typing.Callable[[str], str] | Function that maps scalar logical-id references (and carrier-key bases) to replacement logical IDs. |
Returns:
ValueMetadata — Metadata with every embedded UUID / logical-id reference
rewritten. Legacy "<uuid>_<index>" carrier keys keep their
index suffix while remapping the base UUID. The original bundle is
returned unchanged when no reference is rewritten.
to_canonical_bytes [source]¶
def to_canonical_bytes(block: Block) -> bytesSerialize block to a deterministic byte representation.
The byte format is the internal representation backing
content_hash and is not stable across qamomile versions. It is
suitable for hashing and equality checks within a single
deployment but should not be relied upon as a serialization
format. (A stable, versioned serialization format is tracked
separately.)
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to serialize. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. The block is canonicalized first; passing an already-canonical block is harmless. |
Returns:
bytes — A UTF-8-encoded byte string. Two structurally-equal
Blocks produce the same bytes; changing the IR yields
different bytes.
Raises:
ValueError— Ifblock.kindis not in{AFFINE, ANALYZED}.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
When slice_of is set, this array is a strided view over another
array. Element accesses on a sliced ArrayValue resolve to
physical slots on the root parent via the affine map
parent_index = slice_start + slice_step * view_local_index,
applied recursively along slice_of chains. The emit-time
resolver walks this chain to produce the final qubit index; passes
that substitute or clone values must treat slice_of /
slice_start / slice_step as Value references that need to
track through the same mapping as parent_array.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
slice_of: 'ArrayValue | None' = None,
slice_start: 'Value | None' = None,
slice_step: 'Value | None' = None,
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]slice_of: ‘ArrayValue | None’slice_start: ‘Value | None’slice_step: ‘Value | None’type: Tuuid: str
Methods¶
is_slice¶
def is_slice(self) -> boolReturn True if this array is a strided view of another array.
Returns:
bool — True iff slice_of is non-None.
next_version¶
def next_version(self) -> ArrayValue[T]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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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).
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.
ControlledUOperation [source]¶
class ControlledUOperation(Operation)Base class for controlled-U operations.
Two concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands; optionalcontrol_indicesselects a subset of the control vector to act as controls (the rest pass through).
All isinstance(op, ControlledUOperation) checks match every subclass.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: int | Value = 1,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.num_controls: int | Valueoperation_kind: OperationKindparam_operands: list[Value] Get parameter operands (non-qubit, non-block).power: int | Valuesignature: Signaturetarget_operands: list[Value] Get the target qubit values (arguments to U).
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationDictValue [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().
InverseBlockOperation [source]¶
class InverseBlockOperation(Operation)Represent an inverse qkernel/block as a first-class IR operation.
The operation stores both the original forward block and a Qamomile-built
inverse implementation block. Emitters may use source_block with a
backend-native inverse/adjoint primitive, then fall back to
implementation_block when native inversion is unavailable.
Operands are ordered as control qubits, target quantum operands, then
classical/object parameters. Results mirror the quantum operand layout:
control results first, then one target result per target operand. Vector
target operands therefore count as one operand/result while contributing
their scalar width to num_target_qubits.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
num_control_qubits: int = 0,
num_target_qubits: int = 0,
custom_name: str = '',
source_block: Block | None = None,
implementation_block: Block | None = None,
) -> NoneAttributes¶
control_qubits: list[‘Value’] Return control quantum operands.custom_name: strimplementation_block: Block | Nonename: str Return a human-readable inverse operation name.num_control_qubits: intnum_target_qubits: intoperation_kind: OperationKind Return the operation kind.parameters: list[‘Value’] Return classical/object parameter operands.signature: Signature Return the operation signature.source_block: Block | Nonetarget_qubits: list[‘Value’] Return target quantum operands.
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.
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 | NoneValueMetadata [source]¶
class ValueMetadataTyped metadata owned by the compiler/runtime.
Constructor¶
def __init__(
self,
scalar: ScalarMetadata | None = None,
cast: CastMetadata | None = None,
qfixed: QFixedMetadata | None = None,
array_runtime: ArrayRuntimeMetadata | None = None,
dict_runtime: DictRuntimeMetadata | None = None,
) -> NoneAttributes¶
array_runtime: ArrayRuntimeMetadata | Nonecast: CastMetadata | Nonedict_runtime: DictRuntimeMetadata | Noneqfixed: QFixedMetadata | Nonescalar: ScalarMetadata | None
ValueType [source]¶
class ValueType(abc.ABC)Base class for all value types in the IR.
Type instances are compared by class - all instances of the same type class are considered equal. This allows using type instances as dictionary keys where all QubitType() instances match.
Methods¶
is_classical¶
def is_classical(self) -> boolis_object¶
def is_object(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strqamomile.circuit.ir.operation¶
Overview¶
| Class | Description |
|---|---|
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CompositeGateType | Registry of known composite gate types. |
ConcreteControlledU | Controlled-U with concrete (int) number of controls. |
ControlledUOperation | Base class for controlled-U operations. |
DecodeQFixedOperation | Decode measured bits to float (classical operation). |
ExpvalOp | Expectation value operation. |
ForItemsOperation | Represents iteration over dict/iterable items. |
GateOperation | Quantum gate operation. |
GateOperationType | |
HasNestedOps | Mixin for operations that contain nested operation lists. |
InverseBlockOperation | Represent an inverse qkernel/block as a first-class IR operation. |
MeasureOperation | |
MeasureQFixedOperation | Measure a quantum fixed-point number. |
MeasureVectorOperation | Measure a vector of qubits. |
Operation | |
ReleaseSliceViewOperation | Mark a slice view’s borrow as explicitly returned to its parent. |
ResourceMetadata | Resource estimation metadata for composite gates. |
ReturnOperation | Explicit return operation marking the end of a block with return values. |
SliceArrayOperation | Construct a strided view of an ArrayValue. |
SymbolicControlledU | Controlled-U with symbolic (Value) number of controls. |
Classes¶
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.
CompositeGateType [source]¶
class CompositeGateType(enum.Enum)Registry of known composite gate types.
Attributes¶
CUSTOMIQFTQFTQPE
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.
Two concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands; optionalcontrol_indicesselects a subset of the control vector to act as controls (the rest pass through).
All isinstance(op, ControlledUOperation) checks match every subclass.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: int | Value = 1,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.num_controls: int | Valueoperation_kind: OperationKindparam_operands: list[Value] Get parameter operands (non-qubit, non-block).power: int | Valuesignature: Signaturetarget_operands: list[Value] Get the target qubit values (arguments to U).
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationDecodeQFixedOperation [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
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]) -> 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().
InverseBlockOperation [source]¶
class InverseBlockOperation(Operation)Represent an inverse qkernel/block as a first-class IR operation.
The operation stores both the original forward block and a Qamomile-built
inverse implementation block. Emitters may use source_block with a
backend-native inverse/adjoint primitive, then fall back to
implementation_block when native inversion is unavailable.
Operands are ordered as control qubits, target quantum operands, then
classical/object parameters. Results mirror the quantum operand layout:
control results first, then one target result per target operand. Vector
target operands therefore count as one operand/result while contributing
their scalar width to num_target_qubits.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
num_control_qubits: int = 0,
num_target_qubits: int = 0,
custom_name: str = '',
source_block: Block | None = None,
implementation_block: Block | None = None,
) -> NoneAttributes¶
control_qubits: list[‘Value’] Return control quantum operands.custom_name: strimplementation_block: Block | Nonename: str Return a human-readable inverse operation name.num_control_qubits: intnum_target_qubits: intoperation_kind: OperationKind Return the operation kind.parameters: list[‘Value’] Return classical/object parameter operands.signature: Signature Return the operation signature.source_block: Block | Nonetarget_qubits: list[‘Value’] Return target quantum operands.
MeasureOperation [source]¶
class MeasureOperation(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
MeasureQFixedOperation [source]¶
class MeasureQFixedOperation(Operation)Measure a quantum fixed-point number.
This operation measures all qubits in a QFixed register and produces a Float result. During transpilation, this is lowered to individual MeasureOperations plus a DecodeQFixedOperation.
operands: [QFixed value (contains qubit_values in params)] results: [Float value]
Encoding:
For QPE phase (int_bits=0): float_value = 0.b0b1b2... = b00.5 + b10.25 + b2*0.125 + ...
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
num_bits: int = 0,
int_bits: int = 0,
) -> NoneAttributes¶
int_bits: intnum_bits: intoperation_kind: OperationKindsignature: Signature
MeasureVectorOperation [source]¶
class MeasureVectorOperation(Operation)Measure a vector of qubits.
Takes a Vector[Qubit] (ArrayValue) and produces a Vector[Bit] (ArrayValue). This operation measures all qubits in the vector as a single operation.
operands: [ArrayValue of qubits] results: [ArrayValue of bits]
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
ReleaseSliceViewOperation [source]¶
class ReleaseSliceViewOperation(Operation)Mark a slice view’s borrow as explicitly returned to its parent.
Emitted by :meth:Vector.__setitem__ when used with a slice index
(qs[a:b] = qmc.h(qs[a:b])). This op tells the post-fold
linearity checker
(:class:~qamomile.circuit.transpiler.passes.slice_borrow_check.SliceBorrowCheckPass)
that the view referenced in operands[0] no longer owns its
covered parent slots, mirroring the frontend’s
VectorView.consume(operation_name="slice assignment") borrow
release.
Like :class:SliceArrayOperation, this op is a declarative
classical-side marker that does not survive into the emit stream:
:class:~qamomile.circuit.transpiler.passes.strip_slice_ops.StripSliceArrayOpsPass
removes both :class:SliceArrayOperation and
:class:ReleaseSliceViewOperation after
:class:SliceBorrowCheckPass has observed them. Reaching emit
is a compiler-internal invariant violation and is rejected with a
RuntimeError from :mod:standard_emit.
Within a control-flow body (ForOperation / WhileOperation
/ IfOperation), this op only releases view borrows that were
created within the same body. Releasing a borrow that the
enclosing block has registered (an “outer-snapshot” borrow) is
rejected by SliceBorrowCheckPass with
SliceBorrowViolationError — the loop-merge semantics of the
pass cannot propagate entry deletions out of the body, so the only
way to keep the static check consistent is to forbid that pattern.
Example:
``qs[1:3] = qmc.h(qs[1:3])`` emits, after the broadcast loop::
ReleaseSliceViewOperation(
operands=[qmc_h_result_view], # slice_of=qs_value
results=[],
)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Release is classical — it updates borrow tracking metadata only.signature: Signature Return the type signature of this release operation.
ResourceMetadata [source]¶
class ResourceMetadataResource estimation metadata for composite gates.
Gate count fields mirror GateCount categories.
None semantics:
Fields left as None mean “unknown/unspecified”. During extraction, gate_counter treats None as 0, which may undercount resources if the true value is nonzero. To ensure accurate resource estimates, set all relevant fields explicitly.
When total_gates is set but some of single_qubit_gates, two_qubit_gates, or multi_qubit_gates are None, the extractor emits a UserWarning if the known sub-total is less than total_gates, indicating potentially missing gate category data.
Constructor¶
def __init__(
self,
query_complexity: int | None = None,
t_gates: int | None = None,
ancilla_qubits: int = 0,
total_gates: int | None = None,
single_qubit_gates: int | None = None,
two_qubit_gates: int | None = None,
multi_qubit_gates: int | None = None,
clifford_gates: int | None = None,
rotation_gates: int | None = None,
custom_metadata: dict[str, Any] = dict(),
) -> NoneAttributes¶
ancilla_qubits: intclifford_gates: int | Nonecustom_metadata: dict[str, Any]multi_qubit_gates: int | Nonequery_complexity: int | Nonerotation_gates: int | Nonesingle_qubit_gates: int | Nonet_gates: int | Nonetotal_gates: int | Nonetwo_qubit_gates: int | None
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.
SliceArrayOperation [source]¶
class SliceArrayOperation(Operation)Construct a strided view of an ArrayValue.
The op itself performs no quantum action — it records that the
result ArrayValue is a strided view of the operand parent
with the given start / step. The result’s
slice_of / slice_start / slice_step fields carry the
affine map used by the emit-time resolver.
SliceArrayOperation is classified as :attr:OperationKind.CLASSICAL
because slicing is pure index selection — no new quantum operation
is introduced. The pipeline keeps this op through
PartialEvaluationPass (which invokes
ConstantFoldingPass(..., strip_slice_ops=False)) so the
post-fold :class:~qamomile.circuit.transpiler.passes.slice_borrow_check.SliceBorrowCheckPass
can use it as a view-declaration marker; once that check has run,
StripSliceArrayOpsPass removes every SliceArrayOperation
/ ReleaseSliceViewOperation so segmentation
(:mod:~qamomile.circuit.transpiler.passes.separate) and the
downstream emit stage only see a pure quantum-op stream. By the
time :mod:~qamomile.circuit.transpiler.passes.separate runs the
op has therefore been stripped — reaching emit is a compiler-
internal invariant violation.
Example:
``q[1::2]`` on a ``Vector[Qubit]`` emits::
SliceArrayOperation(
operands=[q_value, uint_1, uint_2],
results=[sliced_value], # slice_of=q_value, slice_start=uint_1, slice_step=uint_2
)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Slice is classical — it selects indices without quantum action.signature: Signature Return the type signature of this slice operation.
SymbolicControlledU [source]¶
class SymbolicControlledU(ControlledUOperation)Controlled-U with symbolic (Value) number of controls.
Operand layout: [ctrl_arg_0, ..., ctrl_arg_{k-1}, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_arg_0', ..., ctrl_arg_{k-1}', tgt_0', ..., tgt_m']
The number of control arguments k is recorded in
num_control_args; the default k = 1 corresponds to the
historical single-pool form (operands[0] is a
Vector[Qubit] / VectorView whose length equals
num_controls, or whose control_indices-selected subset
does). When k > 1 the control prefix is a heterogeneous
sequence of scalar Qubit values and ArrayValues whose
total qubit count is num_controls; the emit pass walks them
in order to recover the per-physical-qubit control set.
When control_indices is None the entire control prefix
is used as active controls (one-arg form: len(ctrl_vector) == num_controls; multi-arg form: the qubit-count sum of the
prefix args equals num_controls). When non-None, the
listed indices select exactly num_controls slots from a
single-arg pool to act as controls; combining
control_indices with the multi-arg control prefix is
rejected at frontend time.
Each control_indices entry is stored as a Value of
UIntType regardless of whether the frontend passed an
int literal or a UInt handle, so all downstream
value-substitution passes see a uniform shape.
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=(UIntType()), name=''))(),
control_indices: tuple[Value, ...] | None = None,
num_control_args: int = 1,
) -> NoneAttributes¶
control_indices: tuple[Value, ...] | Nonecontrol_operands: list[Value]is_symbolic_num_controls: boolnum_control_args: intnum_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]) -> Operationqamomile.circuit.ir.operation.arithmetic_operations¶
Overview¶
| Function | Description |
|---|---|
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, MOD, POW, MIN). |
BinOpKind | |
BinaryOperationBase | Base for binary operations with lhs, rhs, and output. |
BitType | Type representing a classical bit. |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CompOpKind | |
CondOp | Conditional logical operation (AND, OR). |
CondOpKind | |
NotOp | |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
PhiOp | SSA Phi function: merge point after conditional branch. |
RuntimeClassicalExpr | A classical expression known to require runtime evaluation. |
RuntimeOpKind | Unified kind for RuntimeClassicalExpr covering all classical |
Signature | |
Value | A typed SSA value in the IR. |
Functions¶
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, MOD, POW, MIN).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
BinOpKind [source]¶
class BinOpKind(enum.Enum)Attributes¶
ADDDIVFLOORDIVMINMODMULPOWSUB
BinaryOperationBase [source]¶
class BinaryOperationBase(Operation)Base for binary operations with lhs, rhs, and output.
Provides common properties and validation for operations that take two operands and produce one result.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: enum.Enum | None = None,
) -> NoneAttributes¶
kind: enum.Enum | Nonelhs: Value Left-hand side operand.output: Value Output result.rhs: Value Right-hand side operand.
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
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
NotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
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
RuntimeClassicalExpr [source]¶
class RuntimeClassicalExpr(Operation)A classical expression known to require runtime evaluation.
Lowered from CompOp / CondOp / NotOp / BinOp by
ClassicalLoweringPass when the op’s operand dataflow traces back
to a MeasureOperation (i.e. cannot be folded at compile-time, by
emit-time loop unrolling, or by compile_time_if_lowering). Backend
emit translates this 1:1 to a backend-native runtime expression
(e.g. qiskit.circuit.classical.expr.Expr).
Operand convention:
Binary kinds (EQ/NEQ/LT/LE/GT/GE/AND/OR/ADD/SUB/MUL/DIV/FLOORDIV/MOD/POW):
operands = [lhs, rhs].Unary kind (NOT):
operands = [val].Result:
results = [output_value].
The single-node + unified-kind shape (vs four parallel subclasses)
keeps the backend dispatch a single match op.kind instead of four
parallel hooks, and makes the IR self-documenting: a single
RuntimeClassicalExpr instance signals “runtime evaluation
required” regardless of which classical family it came from.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: RuntimeOpKind | None = None,
) -> NoneAttributes¶
kind: RuntimeOpKind | Noneoperation_kind: OperationKindsignature: Signature
RuntimeOpKind [source]¶
class RuntimeOpKind(enum.Enum)Unified kind for RuntimeClassicalExpr covering all classical
op families that can appear at runtime.
The split between this enum and the per-family BinOpKind /
CompOpKind / CondOpKind is intentional: compile-time-foldable
classical ops keep their original IR types so the existing fold
pipeline (constant_fold → compile_time_if_lowering → emit-time
evaluate_classical_predicate) is undisturbed. Only ops identified
as runtime-evaluation-only by ClassicalLoweringPass get rewritten
to RuntimeClassicalExpr with a member of this enum.
Attributes¶
ADDANDDIVEQFLOORDIVGEGTLELTMODMULNEQNOTORPOWSUB
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
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.ir.operation.call_block_ops¶
Overview¶
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
BlockType | Type representing a block/function reference. |
CallBlockOperation | |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
Signature |
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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.
BlockType [source]¶
class BlockType(ObjectTypeMixin, ValueType)Type representing a block/function reference.
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).
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
qamomile.circuit.ir.operation.cast¶
Cast operation for type conversions over the same quantum resources.
Overview¶
| Class | Description |
|---|---|
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
Signature |
Classes¶
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
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
qamomile.circuit.ir.operation.classical_ops¶
Classical operations for quantum-classical hybrid programs.
Overview¶
| Class | Description |
|---|---|
BitType | Type representing a classical bit. |
DecodeQFixedOperation | Decode measured bits to float (classical operation). |
FloatType | Type representing a floating-point number. |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
Signature |
Classes¶
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
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
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
qamomile.circuit.ir.operation.composite_gate¶
CompositeGate operation for representing complex multi-gate operations.
Overview¶
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
BlockType | Type representing a block/function reference. |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CompositeGateType | Registry of known composite gate types. |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
QubitType | Type representing a quantum bit (qubit). |
ResourceMetadata | Resource estimation metadata for composite gates. |
Signature | |
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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.
BlockType [source]¶
class BlockType(ObjectTypeMixin, ValueType)Type representing a block/function reference.
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
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
QubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
ResourceMetadata [source]¶
class ResourceMetadataResource estimation metadata for composite gates.
Gate count fields mirror GateCount categories.
None semantics:
Fields left as None mean “unknown/unspecified”. During extraction, gate_counter treats None as 0, which may undercount resources if the true value is nonzero. To ensure accurate resource estimates, set all relevant fields explicitly.
When total_gates is set but some of single_qubit_gates, two_qubit_gates, or multi_qubit_gates are None, the extractor emits a UserWarning if the known sub-total is less than total_gates, indicating potentially missing gate category data.
Constructor¶
def __init__(
self,
query_complexity: int | None = None,
t_gates: int | None = None,
ancilla_qubits: int = 0,
total_gates: int | None = None,
single_qubit_gates: int | None = None,
two_qubit_gates: int | None = None,
multi_qubit_gates: int | None = None,
clifford_gates: int | None = None,
rotation_gates: int | None = None,
custom_metadata: dict[str, Any] = dict(),
) -> NoneAttributes¶
ancilla_qubits: intclifford_gates: int | Nonecustom_metadata: dict[str, Any]multi_qubit_gates: int | Nonequery_complexity: int | Nonerotation_gates: int | Nonesingle_qubit_gates: int | Nonet_gates: int | Nonetotal_gates: int | Nonetwo_qubit_gates: int | None
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
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.ir.operation.control_flow¶
Overview¶
| Class | Description |
|---|---|
BitType | Type representing a classical bit. |
BlockType | Type representing a block/function reference. |
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. |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
PhiOp | SSA Phi function: merge point after conditional branch. |
Signature | |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
WhileOperation | Represents a while loop operation. |
Classes¶
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
BlockType [source]¶
class BlockType(ObjectTypeMixin, ValueType)Type representing a block/function reference.
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]]) -> OperationOperation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
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
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
UIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
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 | NoneWhileOperation [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.ir.operation.expval¶
Expectation value operation for computing <psi|H|psi>.
This module defines the ExpvalOp IR operation that represents computing the expectation value of a Hamiltonian observable with respect to a quantum state.
Overview¶
| Class | Description |
|---|---|
ExpvalOp | Expectation value operation. |
FloatType | Type representing a floating-point number. |
ObservableType | Type representing a Hamiltonian observable parameter. |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
Signature | |
Value | A typed SSA value in the IR. |
Classes¶
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
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
ObservableType [source]¶
class ObservableType(ObjectTypeMixin, ValueType)Type representing a Hamiltonian observable parameter.
This is a reference type - the actual qamomile.observable.Hamiltonian is provided via bindings during transpilation. It cannot be constructed or manipulated within qkernels.
Example usage:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
return qm.expval(q, H)
# H is passed as binding
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(self) -> NoneOperation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
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.ir.operation.gate¶
Overview¶
| Class | Description |
|---|---|
BitType | Type representing a classical bit. |
Block | Unified block representation for all pipeline stages. |
ConcreteControlledU | Controlled-U with concrete (int) number of controls. |
ControlledUOperation | Base class for controlled-U operations. |
FloatType | Type representing a floating-point number. |
GateOperation | Quantum gate operation. |
GateOperationType | |
MeasureOperation | |
MeasureQFixedOperation | Measure a quantum fixed-point number. |
MeasureVectorOperation | Measure a vector of qubits. |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
QubitType | Type representing a quantum bit (qubit). |
Signature | |
SymbolicControlledU | Controlled-U with symbolic (Value) number of controls. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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.
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.
Two concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands; optionalcontrol_indicesselects a subset of the control vector to act as controls (the rest pass through).
All isinstance(op, ControlledUOperation) checks match every subclass.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: int | Value = 1,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.num_controls: int | Valueoperation_kind: OperationKindparam_operands: list[Value] Get parameter operands (non-qubit, non-block).power: int | Valuesignature: Signaturetarget_operands: list[Value] Get the target qubit values (arguments to U).
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationFloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
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
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
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
QubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
SymbolicControlledU [source]¶
class SymbolicControlledU(ControlledUOperation)Controlled-U with symbolic (Value) number of controls.
Operand layout: [ctrl_arg_0, ..., ctrl_arg_{k-1}, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_arg_0', ..., ctrl_arg_{k-1}', tgt_0', ..., tgt_m']
The number of control arguments k is recorded in
num_control_args; the default k = 1 corresponds to the
historical single-pool form (operands[0] is a
Vector[Qubit] / VectorView whose length equals
num_controls, or whose control_indices-selected subset
does). When k > 1 the control prefix is a heterogeneous
sequence of scalar Qubit values and ArrayValues whose
total qubit count is num_controls; the emit pass walks them
in order to recover the per-physical-qubit control set.
When control_indices is None the entire control prefix
is used as active controls (one-arg form: len(ctrl_vector) == num_controls; multi-arg form: the qubit-count sum of the
prefix args equals num_controls). When non-None, the
listed indices select exactly num_controls slots from a
single-arg pool to act as controls; combining
control_indices with the multi-arg control prefix is
rejected at frontend time.
Each control_indices entry is stored as a Value of
UIntType regardless of whether the frontend passed an
int literal or a UInt handle, so all downstream
value-substitution passes see a uniform shape.
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=(UIntType()), name=''))(),
control_indices: tuple[Value, ...] | None = None,
num_control_args: int = 1,
) -> NoneAttributes¶
control_indices: tuple[Value, ...] | Nonecontrol_operands: list[Value]is_symbolic_num_controls: boolnum_control_args: intnum_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]) -> OperationUIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
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.ir.operation.inverse_block¶
First-class inverse block operation.
InverseBlockOperation represents “apply the inverse of this block”
as a single IR operation. It shares the operand layout convention of
:class:~qamomile.circuit.ir.operation.composite_gate.CompositeGateOperation
(control qubits, then quantum targets, then classical/object
parameters) but is an independent :class:Operation subclass, not a
composite-gate variant.
Overview¶
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
Block | Unified block representation for all pipeline stages. |
BlockType | Type representing a block/function reference. |
InverseBlockOperation | Represent an inverse qkernel/block as a first-class IR operation. |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
QubitType | Type representing a quantum bit (qubit). |
Signature | |
Value | A typed SSA value in the IR. |
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
When slice_of is set, this array is a strided view over another
array. Element accesses on a sliced ArrayValue resolve to
physical slots on the root parent via the affine map
parent_index = slice_start + slice_step * view_local_index,
applied recursively along slice_of chains. The emit-time
resolver walks this chain to produce the final qubit index; passes
that substitute or clone values must treat slice_of /
slice_start / slice_step as Value references that need to
track through the same mapping as parent_array.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
slice_of: 'ArrayValue | None' = None,
slice_start: 'Value | None' = None,
slice_step: 'Value | None' = None,
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]slice_of: ‘ArrayValue | None’slice_start: ‘Value | None’slice_step: ‘Value | None’type: Tuuid: str
Methods¶
is_slice¶
def is_slice(self) -> boolReturn True if this array is a strided view of another array.
Returns:
bool — True iff slice_of is non-None.
next_version¶
def next_version(self) -> ArrayValue[T]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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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.
BlockType [source]¶
class BlockType(ObjectTypeMixin, ValueType)Type representing a block/function reference.
InverseBlockOperation [source]¶
class InverseBlockOperation(Operation)Represent an inverse qkernel/block as a first-class IR operation.
The operation stores both the original forward block and a Qamomile-built
inverse implementation block. Emitters may use source_block with a
backend-native inverse/adjoint primitive, then fall back to
implementation_block when native inversion is unavailable.
Operands are ordered as control qubits, target quantum operands, then
classical/object parameters. Results mirror the quantum operand layout:
control results first, then one target result per target operand. Vector
target operands therefore count as one operand/result while contributing
their scalar width to num_target_qubits.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
num_control_qubits: int = 0,
num_target_qubits: int = 0,
custom_name: str = '',
source_block: Block | None = None,
implementation_block: Block | None = None,
) -> NoneAttributes¶
control_qubits: list[‘Value’] Return control quantum operands.custom_name: strimplementation_block: Block | Nonename: str Return a human-readable inverse operation name.num_control_qubits: intnum_target_qubits: intoperation_kind: OperationKind Return the operation kind.parameters: list[‘Value’] Return classical/object parameter operands.signature: Signature Return the operation signature.source_block: Block | Nonetarget_qubits: list[‘Value’] Return target quantum operands.
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
QubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
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.ir.operation.operation¶
Overview¶
| Class | Description |
|---|---|
CInitOperation | Initialize the classical values (const, arguments etc) |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
QInitOperation | Initialize the qubit |
Signature | |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
Classes¶
CInitOperation [source]¶
class CInitOperation(Operation)Initialize the classical values (const, arguments etc)
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
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
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
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.ir.operation.pauli_evolve¶
Pauli evolution operation for applying exp(-i * gamma * H).
This module defines the PauliEvolveOp IR operation that represents applying Hamiltonian time evolution to a quantum state.
Overview¶
| Class | Description |
|---|---|
FloatType | Type representing a floating-point number. |
ObservableType | Type representing a Hamiltonian observable parameter. |
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
Signature | |
Value | A typed SSA value in the IR. |
Classes¶
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
ObservableType [source]¶
class ObservableType(ObjectTypeMixin, ValueType)Type representing a Hamiltonian observable parameter.
This is a reference type - the actual qamomile.observable.Hamiltonian is provided via bindings during transpilation. It cannot be constructed or manipulated within qkernels.
Example usage:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
return qm.expval(q, H)
# H is passed as binding
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(self) -> NoneOperation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
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
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
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.ir.operation.return_operation¶
Return operation for explicit block termination.
Overview¶
| Class | Description |
|---|---|
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
ReturnOperation | Explicit return operation marking the end of a block with return values. |
Signature |
Classes¶
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
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.
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
qamomile.circuit.ir.operation.slice_array¶
Slice operation that produces a strided view of an array.
Overview¶
| Class | Description |
|---|---|
Operation | |
OperationKind | Classification of operations for classical/quantum separation. |
ParamHint | |
ReleaseSliceViewOperation | Mark a slice view’s borrow as explicitly returned to its parent. |
Signature | |
SliceArrayOperation | Construct a strided view of an ArrayValue. |
Classes¶
Operation [source]¶
class Operation(abc.ABC)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operands: list[Value]operation_kind: OperationKind Return the kind of this operation for classical/quantum classification.results: list[Value]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Return all input Values including subclass-specific fields.
Generic passes should use this instead of accessing operands
directly to ensure no Value is missed. Subclasses override this
to include extra Value fields (e.g. ControlledUOperation.power).
replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationReturn a copy with all Values substituted via mapping.
Handles operands, results, and subclass-specific Value
fields. Subclasses override to handle their extra fields.
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
ParamHint [source]¶
class ParamHintConstructor¶
def __init__(self, name: str, type: ValueType) -> NoneAttributes¶
name: strtype: ValueType
ReleaseSliceViewOperation [source]¶
class ReleaseSliceViewOperation(Operation)Mark a slice view’s borrow as explicitly returned to its parent.
Emitted by :meth:Vector.__setitem__ when used with a slice index
(qs[a:b] = qmc.h(qs[a:b])). This op tells the post-fold
linearity checker
(:class:~qamomile.circuit.transpiler.passes.slice_borrow_check.SliceBorrowCheckPass)
that the view referenced in operands[0] no longer owns its
covered parent slots, mirroring the frontend’s
VectorView.consume(operation_name="slice assignment") borrow
release.
Like :class:SliceArrayOperation, this op is a declarative
classical-side marker that does not survive into the emit stream:
:class:~qamomile.circuit.transpiler.passes.strip_slice_ops.StripSliceArrayOpsPass
removes both :class:SliceArrayOperation and
:class:ReleaseSliceViewOperation after
:class:SliceBorrowCheckPass has observed them. Reaching emit
is a compiler-internal invariant violation and is rejected with a
RuntimeError from :mod:standard_emit.
Within a control-flow body (ForOperation / WhileOperation
/ IfOperation), this op only releases view borrows that were
created within the same body. Releasing a borrow that the
enclosing block has registered (an “outer-snapshot” borrow) is
rejected by SliceBorrowCheckPass with
SliceBorrowViolationError — the loop-merge semantics of the
pass cannot propagate entry deletions out of the body, so the only
way to keep the static check consistent is to forbid that pattern.
Example:
``qs[1:3] = qmc.h(qs[1:3])`` emits, after the broadcast loop::
ReleaseSliceViewOperation(
operands=[qmc_h_result_view], # slice_of=qs_value
results=[],
)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Release is classical — it updates borrow tracking metadata only.signature: Signature Return the type signature of this release operation.
Signature [source]¶
class SignatureConstructor¶
def __init__(
self,
operands: list[ParamHint | None] = list(),
results: list[ParamHint] = list(),
) -> NoneAttributes¶
operands: list[ParamHint | None]results: list[ParamHint]
SliceArrayOperation [source]¶
class SliceArrayOperation(Operation)Construct a strided view of an ArrayValue.
The op itself performs no quantum action — it records that the
result ArrayValue is a strided view of the operand parent
with the given start / step. The result’s
slice_of / slice_start / slice_step fields carry the
affine map used by the emit-time resolver.
SliceArrayOperation is classified as :attr:OperationKind.CLASSICAL
because slicing is pure index selection — no new quantum operation
is introduced. The pipeline keeps this op through
PartialEvaluationPass (which invokes
ConstantFoldingPass(..., strip_slice_ops=False)) so the
post-fold :class:~qamomile.circuit.transpiler.passes.slice_borrow_check.SliceBorrowCheckPass
can use it as a view-declaration marker; once that check has run,
StripSliceArrayOpsPass removes every SliceArrayOperation
/ ReleaseSliceViewOperation so segmentation
(:mod:~qamomile.circuit.transpiler.passes.separate) and the
downstream emit stage only see a pure quantum-op stream. By the
time :mod:~qamomile.circuit.transpiler.passes.separate runs the
op has therefore been stripped — reaching emit is a compiler-
internal invariant violation.
Example:
``q[1::2]`` on a ``Vector[Qubit]`` emits::
SliceArrayOperation(
operands=[q_value, uint_1, uint_2],
results=[sliced_value], # slice_of=q_value, slice_start=uint_1, slice_step=uint_2
)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Slice is classical — it selects indices without quantum action.signature: Signature Return the type signature of this slice operation.
qamomile.circuit.ir.parameter¶
First-class manifest of a kernel’s classical parameter interface.
This module defines ParamSlot and ParamKind, which together
describe every classical (non-quantum) argument of a @qkernel
function so the kernel’s parameter contract is recoverable from the
IR alone — without an external Python-side manifest.
Motivation:
The project rule documented in CLAUDE.md keeps bindings and
parameters strictly disjoint at the Transpiler.transpile()
API boundary, but the IR itself does not record which name was
decided which way. After partial_eval folds a binding into a
concrete constant, downstream readers cannot tell whether a
constant value originated from a compile-time binding or was a
literal in the kernel source. This is especially limiting for the
“qamomile as subgraph of an outer DSL’s computation graph” use
case, where the receiver needs to know the kernel’s full classical
interface (name, type, default, runtime-or-bound) to rebind values
in subsequent calls.
Per-kernel-argument metadata also makes it natural to attach
optional hints (currently just differentiable) for outer DSL
tooling such as parameter-shift gradient back-ends.
Scope:
ParamSlot covers only classical (non-quantum) arguments. Qubit
and Vector[Qubit] inputs are not part of the parameter slot
manifest; they appear in Block.input_values instead.
The companion Block.parameters: dict[str, Value] field is
retained for callers (passes, emitters) that need a direct Value
reference for runtime parameters; Block.param_slots is the
canonical, fully-typed contract that survives the pipeline.
Overview¶
| Class | Description |
|---|---|
ParamKind | Lifecycle classification for a classical kernel argument. |
ParamSlot | Metadata for a single classical kernel argument. |
Classes¶
ParamKind [source]¶
class ParamKind(enum.Enum)Lifecycle classification for a classical kernel argument.
Values:
RUNTIME_PARAMETER: The argument is intended to be bound at
execution time by the backend (or, more generally, by the
outer caller in a hybrid loop). It survives the
compilation pipeline as a symbolic parameter.
COMPILE_TIME_BOUND: The argument was provided as a binding
(or via a Python default) and is folded into the IR by
resolve_parameter_shapes / partial_eval. No
symbolic counterpart remains in the emitted circuit.
Attributes¶
COMPILE_TIME_BOUNDRUNTIME_PARAMETER
ParamSlot [source]¶
class ParamSlotMetadata for a single classical kernel argument.
A ParamSlot describes one position in the kernel’s classical
parameter contract — its declared type, whether it is a runtime
parameter or a compile-time-bound value, the Python default (if
any), the actually-bound value (when kind is
COMPILE_TIME_BOUND), and any outer-DSL hints. Slots are
immutable; pipeline passes that need to update a slot must clone
via dataclasses.replace.
The slot is identified by name, which matches the kernel’s
Python parameter name and the corresponding entry in
Block.label_args. A slot’s name MUST never overlap between
RUNTIME_PARAMETER and COMPILE_TIME_BOUND instances within
one Block (this mirrors the project-level bindings /
parameters disjointness rule).
Constructor¶
def __init__(
self,
name: str,
type: 'ValueType',
kind: ParamKind,
ndim: int = 0,
default: Any = None,
bound_value: Any = None,
differentiable: bool = False,
) -> NoneAttributes¶
bound_value: Anydefault: Anydifferentiable: boolkind: ParamKindname: strndim: inttype: ‘ValueType’
qamomile.circuit.ir.printer¶
Text pretty-printer for the Block IR.
This module provides a contributor-facing textual dump of the intermediate
representation, similar in spirit to MLIR’s textual IR format. Useful for
debugging the transpiler pipeline by inspecting the block at each stage
(HIERARCHICAL / AFFINE / ANALYZED).
Example:
>>> from qamomile.circuit.ir import pretty_print_block
>>> block = transpiler.to_block(my_kernel, bindings={"n": 3})
>>> print(pretty_print_block(block))
block my_kernel [HIERARCHICAL] (n: UIntType) -> Vector[BitType]
...The output is intended for human inspection, not for machine parsing; its format may change between Qamomile releases.
Overview¶
| Function | Description |
|---|---|
format_value | Format an IR value reference as %name@vN. |
pretty_print_block | Return a MLIR-style textual dump of block. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, MOD, POW, MIN). |
Block | Unified block representation for all pipeline stages. |
CallBlockOperation | |
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. |
ExpvalOp | Expectation value operation. |
ForOperation | Represents a for loop operation. |
IfOperation | Represents an if-else conditional operation. |
NotOp | |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
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. |
Functions¶
format_value [source]¶
def format_value(value: Any) -> strFormat an IR value reference as %name@vN.
Handles Value, ArrayValue, TupleValue, DictValue, and
array-element Values (rendered as %parent[i]@vN). Constants
and parameters are shown with their tagged metadata when available.
Falls back to repr() for unrecognised inputs so callers can use
this helper for any operand-like field without a type switch.
pretty_print_block [source]¶
def pretty_print_block(block: Block, *, depth: int = 0) -> strReturn a MLIR-style textual dump of block.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The Block to format. Works on any BlockKind. |
depth | int | How many levels of CallBlockOperation to expand inline. 0 (default) shows only the callee name and I/O. Positive values expand the called block’s body recursively, decrementing the allowance at each step. Useful for seeing what inline will produce without actually running the pass. |
Returns:
str — A newline-separated string. The format is for human debugging and
str — is not guaranteed to be stable across releases.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
When slice_of is set, this array is a strided view over another
array. Element accesses on a sliced ArrayValue resolve to
physical slots on the root parent via the affine map
parent_index = slice_start + slice_step * view_local_index,
applied recursively along slice_of chains. The emit-time
resolver walks this chain to produce the final qubit index; passes
that substitute or clone values must treat slice_of /
slice_start / slice_step as Value references that need to
track through the same mapping as parent_array.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
slice_of: 'ArrayValue | None' = None,
slice_start: 'Value | None' = None,
slice_step: 'Value | None' = None,
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]slice_of: ‘ArrayValue | None’slice_start: ‘Value | None’slice_step: ‘Value | None’type: Tuuid: str
Methods¶
is_slice¶
def is_slice(self) -> boolReturn True if this array is a strided view of another array.
Returns:
bool — True iff slice_of is non-None.
next_version¶
def next_version(self) -> ArrayValue[T]BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, MOD, POW, MIN).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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.
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).
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) -> DictValueExpvalOp [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
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]) -> 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]]) -> OperationNotOp [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
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.ir.serialize¶
Public surface for the Qamomile IR serialization package.
Two wire formats are supported on top of a shared intermediate dict
schema (see :mod:qamomile.circuit.ir.serialize.schema):
dump_json/load_json— UTF-8 JSON, easier to debug.dump_msgpack/load_msgpack— binary, more compact (numpy payloads pass through as nativebin).
to_dict / from_dict are exposed for tests and tooling that
want to operate on the intermediate Python dict directly.
Scope: BlockKind.AFFINE and BlockKind.ANALYZED only.
HIERARCHICAL blocks still hold CallBlockOperation references
by Python identity and are deferred.
Overview¶
| Function | Description |
|---|---|
dump_json | Encode block into a UTF-8 JSON byte string. |
dump_msgpack | Encode block into a msgpack byte string. |
from_dict | Reconstruct a Block from a dict envelope. |
load_json | Decode a JSON document back into a Block. |
load_msgpack | Decode a msgpack payload back into a Block. |
to_dict | Encode a Block into the intermediate dict envelope. |
Constants¶
SCHEMA_VERSION:int=1
Functions¶
dump_json [source]¶
def dump_json(block: Block) -> bytesEncode block into a UTF-8 JSON byte string.
The serialized form contains the schema_version envelope from
:func:qamomile.circuit.ir.serialize.encode.to_dict plus
base64-wrapped bytes payloads (numpy array data, raw bytes
bound values) so the output stays JSON-text-safe.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to encode. Must be AFFINE or ANALYZED. |
Returns:
bytes — A UTF-8 encoded JSON document.
Raises:
ValueError— Forwarded from :func:qamomile.circuit.ir.serialize.encode.to_dict(e.g., unsupported BlockKind).TypeError— Forwarded from the encoder when a payload type is not serializable.
dump_msgpack [source]¶
def dump_msgpack(block: Block) -> bytesEncode block into a msgpack byte string.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to encode. Must be AFFINE or ANALYZED. |
Returns:
bytes — A msgpack-encoded payload. Compatible with the standard
msgpack package; no extension types are used.
Raises:
ValueError— Forwarded from :func:qamomile.circuit.ir.serialize.encode.to_dict(e.g., unsupported BlockKind).TypeError— Forwarded from the encoder when a payload type is not serializable.
from_dict [source]¶
def from_dict(envelope: dict[str, Any]) -> BlockReconstruct a Block from a dict envelope.
Parameters:
| Name | Type | Description |
|---|---|---|
envelope | dict[str, Any] | The dict produced by :func:qamomile.circuit.ir.serialize.encode.to_dict (or an equivalent producer that respects the schema). |
Returns:
Block — The reconstructed Block at AFFINE or ANALYZED.
Raises:
ValueError— If the envelope is malformed, theschema_versiondoes not match, or any$typetag is unknown to the dispatch table.TypeError— If a payload has an unexpected Python type.
load_json [source]¶
def load_json(payload: bytes | str) -> BlockDecode a JSON document back into a Block.
Parameters:
| Name | Type | Description |
|---|---|---|
payload | bytes | str | JSON bytes (UTF-8) or a JSON string. |
Returns:
Block — The reconstructed Block.
Raises:
ValueError— Forwarded from the dict decoder for malformed envelopes or unknown$typetags.TypeError— For numeric overflow or other JSON-side conversion issues.
load_msgpack [source]¶
def load_msgpack(payload: bytes) -> BlockDecode a msgpack payload back into a Block.
The unpacker is configured with raw=False so strings come back
as Python str, and strict_map_key=False so non-string map
keys (numeric, etc.) are accepted (qamomile’s schema only uses
string keys today, but this keeps the loader robust to future
schema extensions).
Parameters:
| Name | Type | Description |
|---|---|---|
payload | bytes | A msgpack-encoded payload produced by :func:dump_msgpack or an equivalent encoder. |
Returns:
Block — The reconstructed Block.
Raises:
ValueError— Forwarded from the dict decoder for malformed envelopes or unknown$typetags.
to_dict [source]¶
def to_dict(block: Block) -> dict[str, Any]Encode a Block into the intermediate dict envelope.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to encode. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
dict[str, Any] — dict[str, Any]: {"schema_version": SCHEMA_VERSION, "block": <block dict>} ready to be passed to a wire-format
encoder (JSON / msgpack).
Raises:
ValueError— Ifblock.kindis notAFFINE/ANALYZED.NotImplementedError— If the block contains aCallBlockOperation(HIERARCHICAL holdover).TypeError— If a payload (e.g.,ParamSlot.bound_value) cannot be encoded with a known wire representation.
qamomile.circuit.ir.serialize.decode¶
Intermediate dict → IR decoder.
Reconstructs a Block from the dict envelope produced by
:mod:qamomile.circuit.ir.serialize.encode. The decoder NEVER
performs dynamic class resolution: every $type tag is routed
through a hard-coded factory table, and unknown tags raise
ValueError. This is the load-bearing security invariant — see
:mod:qamomile.circuit.ir.serialize.schema for the rationale.
Values are materialized lazily via depth-first recursion so any
referenced parent_array / element_indices / shape Value is
instantiated before the Value that points at it. A cycle (defensive;
not produced by the canonical encoder) raises ValueError.
Overview¶
| Function | Description |
|---|---|
dict_to_array | Decode a wrapper dict back into a numpy ndarray. |
dict_to_hamiltonian | Decode a wrapper dict back into a Hamiltonian. |
from_dict | Reconstruct a Block from a dict envelope. |
is_array_wrapper | Return True if d is a numpy-array wrapper dict. |
is_hamiltonian_wrapper | Return True if d is a Hamiltonian wrapper dict. |
is_plain_int | Return True if value is a Python int but not a bool. |
| Class | Description |
|---|---|
ArrayRuntimeMetadata | Metadata for array literals and explicit element identity tracking. |
ArrayValue | An array of typed IR values. |
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, MOD, POW, MIN). |
BinOpKind | |
BitType | Type representing a classical bit. |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
BlockType | Type representing a block/function reference. |
CInitOperation | Initialize the classical values (const, arguments etc) |
CastMetadata | Metadata describing a cast carrier and its underlying qubits. |
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CompOpKind | |
ConcreteControlledU | Controlled-U with concrete (int) number of controls. |
CondOp | Conditional logical operation (AND, OR). |
CondOpKind | |
DecodeQFixedOperation | Decode measured bits to float (classical operation). |
DictRuntimeMetadata | Metadata for transpile-time bound dict values. |
DictType | Type representing a dictionary mapping keys to values. |
DictValue | A dictionary value stored as stable ordered entries. |
FloatType | Type representing a floating-point number. |
ForOperation | Represents a for loop operation. |
IfOperation | Represents an if-else conditional operation. |
NotOp | |
ObservableType | Type representing a Hamiltonian observable parameter. |
ParamKind | Lifecycle classification for a classical kernel argument. |
ParamSlot | Metadata for a single classical kernel argument. |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
PhiOp | SSA Phi function: merge point after conditional branch. |
QFixedMetadata | Metadata for QFixed carriers. |
QFixedType | Quantum fixed-point type. |
QInitOperation | Initialize the qubit |
QUIntType | Quantum unsigned integer type. |
QubitType | Type representing a quantum bit (qubit). |
ReleaseSliceViewOperation | Mark a slice view’s borrow as explicitly returned to its parent. |
ResourceMetadata | Resource estimation metadata for composite gates. |
RuntimeClassicalExpr | A classical expression known to require runtime evaluation. |
RuntimeOpKind | Unified kind for RuntimeClassicalExpr covering all classical |
ScalarMetadata | Metadata for scalar constants and symbolic parameters. |
SliceArrayOperation | Construct a strided view of an ArrayValue. |
SymbolicControlledU | Controlled-U with symbolic (Value) number of controls. |
TupleType | Type representing a tuple of values. |
TupleValue | A tuple of IR values for structured data. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueMetadata | Typed metadata owned by the compiler/runtime. |
ValueType | Base class for all value types in the IR. |
WhileOperation | Represents a while loop operation. |
Constants¶
SCHEMA_VERSION:int=1
Functions¶
dict_to_array [source]¶
def dict_to_array(d: dict[str, Any]) -> np.ndarrayDecode a wrapper dict back into a numpy ndarray.
Parameters:
| Name | Type | Description |
|---|---|---|
d | dict[str, Any] | A wrapper dict previously produced by :func:array_to_dict (possibly after a JSON round-trip that converted the data field between bytes and base64). |
Returns:
np.ndarray — np.ndarray: The reconstructed array with the original dtype
and shape.
Raises:
ValueError— Ifdis not a valid wrapper dict, if the dtype is not in the allow-list, or if the byte length is inconsistent with shape × dtype.itemsize.
dict_to_hamiltonian [source]¶
def dict_to_hamiltonian(d: dict[str, Any]) -> HamiltonianDecode a wrapper dict back into a Hamiltonian.
Terms are re-added in wire order through the public add_term
API, which is the identity on the canonical term form the encoder
emits (operators sorted per term, no identities) and preserves the
term-dict insertion order.
Parameters:
| Name | Type | Description |
|---|---|---|
d | dict[str, Any] | A wrapper dict previously produced by :func:hamiltonian_to_dict (possibly after a JSON / msgpack round-trip). |
Returns:
Hamiltonian — The reconstructed Hamiltonian, equal to the
original (same terms in the same order, same coefficient
types, same constant, same declared register width).
Raises:
ValueError— Ifdis not a valid wrapper dict — missing or malformedterms, a term with an empty operator list (the constant is carried by the dedicatedconstantfield, so an empty list would double-encode it), a Pauli name outside the allow-map, a negative or non-int qubit index, a malformed coefficient, or anum_qubitsthat is neitherNonenor a non-negative int.
from_dict [source]¶
def from_dict(envelope: dict[str, Any]) -> BlockReconstruct a Block from a dict envelope.
Parameters:
| Name | Type | Description |
|---|---|---|
envelope | dict[str, Any] | The dict produced by :func:qamomile.circuit.ir.serialize.encode.to_dict (or an equivalent producer that respects the schema). |
Returns:
Block — The reconstructed Block at AFFINE or ANALYZED.
Raises:
ValueError— If the envelope is malformed, theschema_versiondoes not match, or any$typetag is unknown to the dispatch table.TypeError— If a payload has an unexpected Python type.
is_array_wrapper [source]¶
def is_array_wrapper(d: Any) -> boolReturn True if d is a numpy-array wrapper dict.
Parameters:
| Name | Type | Description |
|---|---|---|
d | Any | A value to check. Typically the result of a recursive dict walk from decode. |
Returns:
bool — True when d is a dict carrying the
$np_array tag with a True-ish value.
is_hamiltonian_wrapper [source]¶
def is_hamiltonian_wrapper(d: Any) -> boolReturn True if d is a Hamiltonian wrapper dict.
Parameters:
| Name | Type | Description |
|---|---|---|
d | Any | A value to check. Typically the result of a recursive dict walk from decode. |
Returns:
bool — True when d is a dict carrying the
$hamiltonian tag with a True value.
is_plain_int [source]¶
def is_plain_int(value: object) -> boolReturn True if value is a Python int but not a bool.
bool is a subclass of int in Python, so isinstance(True, int)
is True. This helper distinguishes a genuine integer from a boolean,
which matters wherever a boolean must be rejected in an integer slot — for
example, validating decoded wire data or a register width.
Parameters:
| Name | Type | Description |
|---|---|---|
value | object | The value to test. |
Returns:
bool — True when value is an int and not a bool.
Classes¶
ArrayRuntimeMetadata [source]¶
class ArrayRuntimeMetadataMetadata for array literals and explicit element identity tracking.
element_parent_uuids / element_parent_indices are parallel to
element_uuids: for each tracked element they record the root array’s
UUID and the element’s index within that root (as resolved by
:func:resolve_root_qubit_address at trace time). They let an emit pass map
a packed element back to the physical qubit registered under the root
array’s QubitAddress(root_uuid, index) key even when the element’s own
UUID was never registered. The sentinel ("", -1) marks an element with
no array parent (a standalone qubit), for which a flat UUID lookup is used.
Constructor¶
def __init__(
self,
const_array: Any = None,
element_uuids: tuple[str, ...] = (),
element_logical_ids: tuple[str, ...] = (),
element_parent_uuids: tuple[str, ...] = (),
element_parent_indices: tuple[int, ...] = (),
) -> NoneAttributes¶
const_array: Anyelement_logical_ids: tuple[str, ...]element_parent_indices: tuple[int, ...]element_parent_uuids: tuple[str, ...]element_uuids: tuple[str, ...]
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
When slice_of is set, this array is a strided view over another
array. Element accesses on a sliced ArrayValue resolve to
physical slots on the root parent via the affine map
parent_index = slice_start + slice_step * view_local_index,
applied recursively along slice_of chains. The emit-time
resolver walks this chain to produce the final qubit index; passes
that substitute or clone values must treat slice_of /
slice_start / slice_step as Value references that need to
track through the same mapping as parent_array.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
slice_of: 'ArrayValue | None' = None,
slice_start: 'Value | None' = None,
slice_step: 'Value | None' = None,
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]slice_of: ‘ArrayValue | None’slice_start: ‘Value | None’slice_step: ‘Value | None’type: Tuuid: str
Methods¶
is_slice¶
def is_slice(self) -> boolReturn True if this array is a strided view of another array.
Returns:
bool — True iff slice_of is non-None.
next_version¶
def next_version(self) -> ArrayValue[T]BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, MOD, POW, MIN).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
BinOpKind [source]¶
class BinOpKind(enum.Enum)Attributes¶
ADDDIVFLOORDIVMINMODMULPOWSUB
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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
BlockType [source]¶
class BlockType(ObjectTypeMixin, ValueType)Type representing a block/function reference.
CInitOperation [source]¶
class CInitOperation(Operation)Initialize the classical values (const, arguments etc)
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
CastMetadata [source]¶
class CastMetadataMetadata describing a cast carrier and its underlying qubits.
Constructor¶
def __init__(
self,
source_uuid: str,
qubit_uuids: tuple[str, ...],
source_logical_id: str | None = None,
qubit_logical_ids: tuple[str, ...] = (),
) -> NoneAttributes¶
qubit_logical_ids: tuple[str, ...]qubit_uuids: tuple[str, ...]source_logical_id: str | Nonesource_uuid: str
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
CompOpKind [source]¶
class CompOpKind(enum.Enum)Attributes¶
EQGEGTLELTNEQ
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]
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
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
DictRuntimeMetadata [source]¶
class DictRuntimeMetadataMetadata for transpile-time bound dict values.
Constructor¶
def __init__(self, bound_data: tuple[tuple[Any, Any], ...] = ()) -> NoneAttributes¶
bound_data: tuple[tuple[Any, Any], ...]
DictType [source]¶
class DictType(ValueType)Type representing a dictionary mapping keys to values.
Unlike simple types, DictType stores the key and value types, so equality and hashing depend on those types. When key_type and value_type are None, represents a generic Dict type.
Quantum/classical classification is derived from key/value types.
Constructor¶
def __init__(
self,
key_type: ValueType | None = None,
value_type: ValueType | None = None,
) -> NoneAttributes¶
key_type: ValueType | Nonevalue_type: ValueType | None
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strDictValue [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) -> DictValueFloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
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]) -> 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]]) -> OperationNotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
ObservableType [source]¶
class ObservableType(ObjectTypeMixin, ValueType)Type representing a Hamiltonian observable parameter.
This is a reference type - the actual qamomile.observable.Hamiltonian is provided via bindings during transpilation. It cannot be constructed or manipulated within qkernels.
Example usage:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
return qm.expval(q, H)
# H is passed as binding
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(self) -> NoneParamKind [source]¶
class ParamKind(enum.Enum)Lifecycle classification for a classical kernel argument.
Values:
RUNTIME_PARAMETER: The argument is intended to be bound at
execution time by the backend (or, more generally, by the
outer caller in a hybrid loop). It survives the
compilation pipeline as a symbolic parameter.
COMPILE_TIME_BOUND: The argument was provided as a binding
(or via a Python default) and is folded into the IR by
resolve_parameter_shapes / partial_eval. No
symbolic counterpart remains in the emitted circuit.
Attributes¶
COMPILE_TIME_BOUNDRUNTIME_PARAMETER
ParamSlot [source]¶
class ParamSlotMetadata for a single classical kernel argument.
A ParamSlot describes one position in the kernel’s classical
parameter contract — its declared type, whether it is a runtime
parameter or a compile-time-bound value, the Python default (if
any), the actually-bound value (when kind is
COMPILE_TIME_BOUND), and any outer-DSL hints. Slots are
immutable; pipeline passes that need to update a slot must clone
via dataclasses.replace.
The slot is identified by name, which matches the kernel’s
Python parameter name and the corresponding entry in
Block.label_args. A slot’s name MUST never overlap between
RUNTIME_PARAMETER and COMPILE_TIME_BOUND instances within
one Block (this mirrors the project-level bindings /
parameters disjointness rule).
Constructor¶
def __init__(
self,
name: str,
type: 'ValueType',
kind: ParamKind,
ndim: int = 0,
default: Any = None,
bound_value: Any = None,
differentiable: bool = False,
) -> NoneAttributes¶
bound_value: Anydefault: Anydifferentiable: boolkind: ParamKindname: strndim: inttype: ‘ValueType’
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
QFixedMetadata [source]¶
class QFixedMetadataMetadata for QFixed carriers.
Constructor¶
def __init__(self, qubit_uuids: tuple[str, ...], num_bits: int, int_bits: int) -> NoneAttributes¶
int_bits: intnum_bits: intqubit_uuids: tuple[str, ...]
QFixedType [source]¶
class QFixedType(QuantumTypeMixin, ValueType)Quantum fixed-point type.
Represents a quantum register encoding a fixed-point number with specified integer and fractional bits.
Constructor¶
def __init__(
self,
integer_bits: int | Value[UIntType] = 0,
fractional_bits: int | Value[UIntType] = 0,
) -> NoneAttributes¶
fractional_bits: int | Value[UIntType]integer_bits: int | Value[UIntType]
Methods¶
label¶
def label(self) -> strQInitOperation [source]¶
class QInitOperation(Operation)Initialize the qubit
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
QUIntType [source]¶
class QUIntType(QuantumTypeMixin, ValueType)Quantum unsigned integer type.
Represents a quantum register encoding an unsigned integer value using binary encoding (little-endian by default).
Constructor¶
def __init__(self, width: int | Value[UIntType]) -> NoneAttributes¶
width: int | Value[UIntType]
Methods¶
label¶
def label(self) -> strQubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
ReleaseSliceViewOperation [source]¶
class ReleaseSliceViewOperation(Operation)Mark a slice view’s borrow as explicitly returned to its parent.
Emitted by :meth:Vector.__setitem__ when used with a slice index
(qs[a:b] = qmc.h(qs[a:b])). This op tells the post-fold
linearity checker
(:class:~qamomile.circuit.transpiler.passes.slice_borrow_check.SliceBorrowCheckPass)
that the view referenced in operands[0] no longer owns its
covered parent slots, mirroring the frontend’s
VectorView.consume(operation_name="slice assignment") borrow
release.
Like :class:SliceArrayOperation, this op is a declarative
classical-side marker that does not survive into the emit stream:
:class:~qamomile.circuit.transpiler.passes.strip_slice_ops.StripSliceArrayOpsPass
removes both :class:SliceArrayOperation and
:class:ReleaseSliceViewOperation after
:class:SliceBorrowCheckPass has observed them. Reaching emit
is a compiler-internal invariant violation and is rejected with a
RuntimeError from :mod:standard_emit.
Within a control-flow body (ForOperation / WhileOperation
/ IfOperation), this op only releases view borrows that were
created within the same body. Releasing a borrow that the
enclosing block has registered (an “outer-snapshot” borrow) is
rejected by SliceBorrowCheckPass with
SliceBorrowViolationError — the loop-merge semantics of the
pass cannot propagate entry deletions out of the body, so the only
way to keep the static check consistent is to forbid that pattern.
Example:
``qs[1:3] = qmc.h(qs[1:3])`` emits, after the broadcast loop::
ReleaseSliceViewOperation(
operands=[qmc_h_result_view], # slice_of=qs_value
results=[],
)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Release is classical — it updates borrow tracking metadata only.signature: Signature Return the type signature of this release operation.
ResourceMetadata [source]¶
class ResourceMetadataResource estimation metadata for composite gates.
Gate count fields mirror GateCount categories.
None semantics:
Fields left as None mean “unknown/unspecified”. During extraction, gate_counter treats None as 0, which may undercount resources if the true value is nonzero. To ensure accurate resource estimates, set all relevant fields explicitly.
When total_gates is set but some of single_qubit_gates, two_qubit_gates, or multi_qubit_gates are None, the extractor emits a UserWarning if the known sub-total is less than total_gates, indicating potentially missing gate category data.
Constructor¶
def __init__(
self,
query_complexity: int | None = None,
t_gates: int | None = None,
ancilla_qubits: int = 0,
total_gates: int | None = None,
single_qubit_gates: int | None = None,
two_qubit_gates: int | None = None,
multi_qubit_gates: int | None = None,
clifford_gates: int | None = None,
rotation_gates: int | None = None,
custom_metadata: dict[str, Any] = dict(),
) -> NoneAttributes¶
ancilla_qubits: intclifford_gates: int | Nonecustom_metadata: dict[str, Any]multi_qubit_gates: int | Nonequery_complexity: int | Nonerotation_gates: int | Nonesingle_qubit_gates: int | Nonet_gates: int | Nonetotal_gates: int | Nonetwo_qubit_gates: int | None
RuntimeClassicalExpr [source]¶
class RuntimeClassicalExpr(Operation)A classical expression known to require runtime evaluation.
Lowered from CompOp / CondOp / NotOp / BinOp by
ClassicalLoweringPass when the op’s operand dataflow traces back
to a MeasureOperation (i.e. cannot be folded at compile-time, by
emit-time loop unrolling, or by compile_time_if_lowering). Backend
emit translates this 1:1 to a backend-native runtime expression
(e.g. qiskit.circuit.classical.expr.Expr).
Operand convention:
Binary kinds (EQ/NEQ/LT/LE/GT/GE/AND/OR/ADD/SUB/MUL/DIV/FLOORDIV/MOD/POW):
operands = [lhs, rhs].Unary kind (NOT):
operands = [val].Result:
results = [output_value].
The single-node + unified-kind shape (vs four parallel subclasses)
keeps the backend dispatch a single match op.kind instead of four
parallel hooks, and makes the IR self-documenting: a single
RuntimeClassicalExpr instance signals “runtime evaluation
required” regardless of which classical family it came from.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: RuntimeOpKind | None = None,
) -> NoneAttributes¶
kind: RuntimeOpKind | Noneoperation_kind: OperationKindsignature: Signature
RuntimeOpKind [source]¶
class RuntimeOpKind(enum.Enum)Unified kind for RuntimeClassicalExpr covering all classical
op families that can appear at runtime.
The split between this enum and the per-family BinOpKind /
CompOpKind / CondOpKind is intentional: compile-time-foldable
classical ops keep their original IR types so the existing fold
pipeline (constant_fold → compile_time_if_lowering → emit-time
evaluate_classical_predicate) is undisturbed. Only ops identified
as runtime-evaluation-only by ClassicalLoweringPass get rewritten
to RuntimeClassicalExpr with a member of this enum.
Attributes¶
ADDANDDIVEQFLOORDIVGEGTLELTMODMULNEQNOTORPOWSUB
ScalarMetadata [source]¶
class ScalarMetadataMetadata for scalar constants and symbolic parameters.
Constructor¶
def __init__(
self,
const_value: int | float | bool | None = None,
parameter_name: str | None = None,
) -> NoneAttributes¶
const_value: int | float | bool | Noneparameter_name: str | None
SliceArrayOperation [source]¶
class SliceArrayOperation(Operation)Construct a strided view of an ArrayValue.
The op itself performs no quantum action — it records that the
result ArrayValue is a strided view of the operand parent
with the given start / step. The result’s
slice_of / slice_start / slice_step fields carry the
affine map used by the emit-time resolver.
SliceArrayOperation is classified as :attr:OperationKind.CLASSICAL
because slicing is pure index selection — no new quantum operation
is introduced. The pipeline keeps this op through
PartialEvaluationPass (which invokes
ConstantFoldingPass(..., strip_slice_ops=False)) so the
post-fold :class:~qamomile.circuit.transpiler.passes.slice_borrow_check.SliceBorrowCheckPass
can use it as a view-declaration marker; once that check has run,
StripSliceArrayOpsPass removes every SliceArrayOperation
/ ReleaseSliceViewOperation so segmentation
(:mod:~qamomile.circuit.transpiler.passes.separate) and the
downstream emit stage only see a pure quantum-op stream. By the
time :mod:~qamomile.circuit.transpiler.passes.separate runs the
op has therefore been stripped — reaching emit is a compiler-
internal invariant violation.
Example:
``q[1::2]`` on a ``Vector[Qubit]`` emits::
SliceArrayOperation(
operands=[q_value, uint_1, uint_2],
results=[sliced_value], # slice_of=q_value, slice_start=uint_1, slice_step=uint_2
)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Slice is classical — it selects indices without quantum action.signature: Signature Return the type signature of this slice operation.
SymbolicControlledU [source]¶
class SymbolicControlledU(ControlledUOperation)Controlled-U with symbolic (Value) number of controls.
Operand layout: [ctrl_arg_0, ..., ctrl_arg_{k-1}, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_arg_0', ..., ctrl_arg_{k-1}', tgt_0', ..., tgt_m']
The number of control arguments k is recorded in
num_control_args; the default k = 1 corresponds to the
historical single-pool form (operands[0] is a
Vector[Qubit] / VectorView whose length equals
num_controls, or whose control_indices-selected subset
does). When k > 1 the control prefix is a heterogeneous
sequence of scalar Qubit values and ArrayValues whose
total qubit count is num_controls; the emit pass walks them
in order to recover the per-physical-qubit control set.
When control_indices is None the entire control prefix
is used as active controls (one-arg form: len(ctrl_vector) == num_controls; multi-arg form: the qubit-count sum of the
prefix args equals num_controls). When non-None, the
listed indices select exactly num_controls slots from a
single-arg pool to act as controls; combining
control_indices with the multi-arg control prefix is
rejected at frontend time.
Each control_indices entry is stored as a Value of
UIntType regardless of whether the frontend passed an
int literal or a UInt handle, so all downstream
value-substitution passes see a uniform shape.
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=(UIntType()), name=''))(),
control_indices: tuple[Value, ...] | None = None,
num_control_args: int = 1,
) -> NoneAttributes¶
control_indices: tuple[Value, ...] | Nonecontrol_operands: list[Value]is_symbolic_num_controls: boolnum_control_args: intnum_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]) -> OperationTupleType [source]¶
class TupleType(ValueType)Type representing a tuple of values.
Unlike simple types, TupleType stores the types of its elements, so equality and hashing depend on the element types.
Quantum/classical classification is derived from element types: quantum if any element is quantum, classical if all are classical.
Constructor¶
def __init__(self, element_types: tuple[ValueType, ...]) -> NoneAttributes¶
element_types: tuple[ValueType, ...]
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strTupleValue [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) -> TupleValueUIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
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 | NoneValueMetadata [source]¶
class ValueMetadataTyped metadata owned by the compiler/runtime.
Constructor¶
def __init__(
self,
scalar: ScalarMetadata | None = None,
cast: CastMetadata | None = None,
qfixed: QFixedMetadata | None = None,
array_runtime: ArrayRuntimeMetadata | None = None,
dict_runtime: DictRuntimeMetadata | None = None,
) -> NoneAttributes¶
array_runtime: ArrayRuntimeMetadata | Nonecast: CastMetadata | Nonedict_runtime: DictRuntimeMetadata | Noneqfixed: QFixedMetadata | Nonescalar: ScalarMetadata | None
ValueType [source]¶
class ValueType(abc.ABC)Base class for all value types in the IR.
Type instances are compared by class - all instances of the same type class are considered equal. This allows using type instances as dictionary keys where all QubitType() instances match.
Methods¶
is_classical¶
def is_classical(self) -> boolis_object¶
def is_object(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strWhileOperation [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.ir.serialize.encode¶
IR → intermediate dict encoder.
Walks a Block (AFFINE or ANALYZED) and produces the dict shape
documented in :mod:qamomile.circuit.ir.serialize.schema. Values are
deduplicated into value_table and referenced elsewhere by UUID.
Every encoder branch is dispatched through a hard-coded table keyed
on the runtime class; there is no dynamic resolution, no getattr
on user data, and no importlib use. The decoder mirrors this
discipline (see :mod:qamomile.circuit.ir.serialize.decode).
Overview¶
| Function | Description |
|---|---|
array_to_dict | Encode a numpy ndarray into the wrapper dict. |
hamiltonian_to_dict | Encode a Hamiltonian into the wrapper dict. |
is_plain_int | Return True if value is a Python int but not a bool. |
to_dict | Encode a Block into the intermediate dict envelope. |
| Class | Description |
|---|---|
ArrayRuntimeMetadata | Metadata for array literals and explicit element identity tracking. |
ArrayValue | An array of typed IR values. |
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, MOD, POW, MIN). |
BitType | Type representing a classical bit. |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
BlockType | Type representing a block/function reference. |
CInitOperation | Initialize the classical values (const, arguments etc) |
CallBlockOperation | |
CastMetadata | Metadata describing a cast carrier and its underlying qubits. |
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
ConcreteControlledU | Controlled-U with concrete (int) number of controls. |
CondOp | Conditional logical operation (AND, OR). |
DecodeQFixedOperation | Decode measured bits to float (classical operation). |
DictRuntimeMetadata | Metadata for transpile-time bound dict values. |
DictType | Type representing a dictionary mapping keys to values. |
DictValue | A dictionary value stored as stable ordered entries. |
FloatType | Type representing a floating-point number. |
ForOperation | Represents a for loop operation. |
Hamiltonian | Represents a quantum Hamiltonian as a sum of Pauli operator products. |
IfOperation | Represents an if-else conditional operation. |
NotOp | |
ObservableType | Type representing a Hamiltonian observable parameter. |
ParamSlot | Metadata for a single classical kernel argument. |
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
PhiOp | SSA Phi function: merge point after conditional branch. |
QFixedMetadata | Metadata for QFixed carriers. |
QFixedType | Quantum fixed-point type. |
QInitOperation | Initialize the qubit |
QUIntType | Quantum unsigned integer type. |
QubitType | Type representing a quantum bit (qubit). |
ReleaseSliceViewOperation | Mark a slice view’s borrow as explicitly returned to its parent. |
ResourceMetadata | Resource estimation metadata for composite gates. |
RuntimeClassicalExpr | A classical expression known to require runtime evaluation. |
ScalarMetadata | Metadata for scalar constants and symbolic parameters. |
SliceArrayOperation | Construct a strided view of an ArrayValue. |
SymbolicControlledU | Controlled-U with symbolic (Value) number of controls. |
TupleType | Type representing a tuple of values. |
TupleValue | A tuple of IR values for structured data. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueMetadata | Typed metadata owned by the compiler/runtime. |
ValueType | Base class for all value types in the IR. |
WhileOperation | Represents a while loop operation. |
Constants¶
SCHEMA_VERSION:int=1
Functions¶
array_to_dict [source]¶
def array_to_dict(arr: np.ndarray) -> dict[str, Any]Encode a numpy ndarray into the wrapper dict.
Parameters:
| Name | Type | Description |
|---|---|---|
arr | np.ndarray | Source array. arr.dtype.name must be in the allow-list (:data:_ALLOWED_DTYPES). |
Returns:
dict[str, Any] — dict[str, Any]: A wrapper dict with $np_array, dtype,
shape (list[int]), and data (raw bytes from
ndarray.tobytes()). The wire encoders are responsible
for any further bytes ⇄ text conversion at format
boundaries.
Raises:
TypeError— Ifarris not anumpy.ndarray.ValueError— If the array’s dtype is not in the allow-list.
hamiltonian_to_dict [source]¶
def hamiltonian_to_dict(h: Hamiltonian) -> dict[str, Any]Encode a Hamiltonian into the wrapper dict.
Terms are emitted in the Hamiltonian’s own term-dict iteration
order; each term is a [operators, coefficient] pair where
operators is a list of [pauli_name, qubit_index] entries.
Parameters:
| Name | Type | Description |
|---|---|---|
h | Hamiltonian | The Hamiltonian to encode. Term coefficients and the constant must be int, float, or complex, or a numpy scalar of one of those kinds (coerced via .item()). |
Returns:
dict[str, Any] — dict[str, Any]: A wrapper dict with $hamiltonian,
terms, constant, and num_qubits (the declared
register width passed to the constructor, or None).
Raises:
TypeError— Ifhis not aHamiltonian, if a coefficient / the constant is not int, float, or complex, or if the declarednum_qubitsis not an int — all after coercing anynumpyscalar to its Python equivalent.ValueError— If the declarednum_qubitsis negative.
is_plain_int [source]¶
def is_plain_int(value: object) -> boolReturn True if value is a Python int but not a bool.
bool is a subclass of int in Python, so isinstance(True, int)
is True. This helper distinguishes a genuine integer from a boolean,
which matters wherever a boolean must be rejected in an integer slot — for
example, validating decoded wire data or a register width.
Parameters:
| Name | Type | Description |
|---|---|---|
value | object | The value to test. |
Returns:
bool — True when value is an int and not a bool.
to_dict [source]¶
def to_dict(block: Block) -> dict[str, Any]Encode a Block into the intermediate dict envelope.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to encode. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
dict[str, Any] — dict[str, Any]: {"schema_version": SCHEMA_VERSION, "block": <block dict>} ready to be passed to a wire-format
encoder (JSON / msgpack).
Raises:
ValueError— Ifblock.kindis notAFFINE/ANALYZED.NotImplementedError— If the block contains aCallBlockOperation(HIERARCHICAL holdover).TypeError— If a payload (e.g.,ParamSlot.bound_value) cannot be encoded with a known wire representation.
Classes¶
ArrayRuntimeMetadata [source]¶
class ArrayRuntimeMetadataMetadata for array literals and explicit element identity tracking.
element_parent_uuids / element_parent_indices are parallel to
element_uuids: for each tracked element they record the root array’s
UUID and the element’s index within that root (as resolved by
:func:resolve_root_qubit_address at trace time). They let an emit pass map
a packed element back to the physical qubit registered under the root
array’s QubitAddress(root_uuid, index) key even when the element’s own
UUID was never registered. The sentinel ("", -1) marks an element with
no array parent (a standalone qubit), for which a flat UUID lookup is used.
Constructor¶
def __init__(
self,
const_array: Any = None,
element_uuids: tuple[str, ...] = (),
element_logical_ids: tuple[str, ...] = (),
element_parent_uuids: tuple[str, ...] = (),
element_parent_indices: tuple[int, ...] = (),
) -> NoneAttributes¶
const_array: Anyelement_logical_ids: tuple[str, ...]element_parent_indices: tuple[int, ...]element_parent_uuids: tuple[str, ...]element_uuids: tuple[str, ...]
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
When slice_of is set, this array is a strided view over another
array. Element accesses on a sliced ArrayValue resolve to
physical slots on the root parent via the affine map
parent_index = slice_start + slice_step * view_local_index,
applied recursively along slice_of chains. The emit-time
resolver walks this chain to produce the final qubit index; passes
that substitute or clone values must treat slice_of /
slice_start / slice_step as Value references that need to
track through the same mapping as parent_array.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
slice_of: 'ArrayValue | None' = None,
slice_start: 'Value | None' = None,
slice_step: 'Value | None' = None,
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]slice_of: ‘ArrayValue | None’slice_start: ‘Value | None’slice_step: ‘Value | None’type: Tuuid: str
Methods¶
is_slice¶
def is_slice(self) -> boolReturn True if this array is a strided view of another array.
Returns:
bool — True iff slice_of is non-None.
next_version¶
def next_version(self) -> ArrayValue[T]BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, MOD, POW, MIN).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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
BlockType [source]¶
class BlockType(ObjectTypeMixin, ValueType)Type representing a block/function reference.
CInitOperation [source]¶
class CInitOperation(Operation)Initialize the classical values (const, arguments etc)
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
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).
CastMetadata [source]¶
class CastMetadataMetadata describing a cast carrier and its underlying qubits.
Constructor¶
def __init__(
self,
source_uuid: str,
qubit_uuids: tuple[str, ...],
source_logical_id: str | None = None,
qubit_logical_ids: tuple[str, ...] = (),
) -> NoneAttributes¶
qubit_logical_ids: tuple[str, ...]qubit_uuids: tuple[str, ...]source_logical_id: str | Nonesource_uuid: str
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
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]
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
DictRuntimeMetadata [source]¶
class DictRuntimeMetadataMetadata for transpile-time bound dict values.
Constructor¶
def __init__(self, bound_data: tuple[tuple[Any, Any], ...] = ()) -> NoneAttributes¶
bound_data: tuple[tuple[Any, Any], ...]
DictType [source]¶
class DictType(ValueType)Type representing a dictionary mapping keys to values.
Unlike simple types, DictType stores the key and value types, so equality and hashing depend on those types. When key_type and value_type are None, represents a generic Dict type.
Quantum/classical classification is derived from key/value types.
Constructor¶
def __init__(
self,
key_type: ValueType | None = None,
value_type: ValueType | None = None,
) -> NoneAttributes¶
key_type: ValueType | Nonevalue_type: ValueType | None
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strDictValue [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) -> DictValueFloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
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]) -> OperationHamiltonian [source]¶
class HamiltonianRepresents a quantum Hamiltonian as a sum of Pauli operator products.
The Hamiltonian is stored as a dictionary where keys are tuples of PauliOperators and values are their corresponding coefficients.
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5)
>>> H.add_term((PauliOperator(Pauli.Z, 2),), 1.0)
>>> print(H.terms)
{(X0, Y1): 0.5, (Z2,): 1.0}Constructor¶
def __init__(self, num_qubits: int | None = None) -> NoneAttributes¶
constant: float | complexnum_qubits: int Calculates the number of qubits in the Hamiltonian.terms: dict[tuple[PauliOperator, ...], complex] Getter for the terms of the Hamiltonian.
Methods¶
add_term¶
def add_term(self, operators: tuple[PauliOperator, ...], coeff: float | complex)Adds a term to the Hamiltonian.
This method adds a product of Pauli operators with a given coefficient to the Hamiltonian. If the term already exists, the coefficients are summed.
Parameters:
| Name | Type | Description |
|---|---|---|
operators | Tuple[PauliOperator, ...] | A tuple of PauliOperators representing the term. |
coeff | Union[float, complex] | The coefficient of the term. |
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5)
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5j)
>>> print(H.terms)
{(X0, Y1): (0.5+0.5j)}copy¶
def copy(self) -> HamiltonianReturn an independent copy sharing no mutable state with self.
Produces a new Hamiltonian with the same terms, constant,
and declared _num_qubits. The underlying _terms dict
is fresh, so subsequent add_term / constant mutations
on either instance do not affect the other. PauliOperator
instances inside the term tuples are reused — they are
dataclass(frozen=True) values and safely shared.
Returns:
Hamiltonian — A shallow-cloned Hamiltonian instance.
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.Z, 0),), 1.0)
>>> H2 = H.copy()
>>> H2.add_term((PauliOperator(Pauli.X, 1),), 0.5)
>>> H.num_qubits # unchanged by H2's mutation
1identity¶
@classmethod
def identity(
cls,
coeff: float | complex = 1.0,
num_qubits: int | None = None,
) -> HamiltonianCreate a scalar times identity Hamiltonian.
remap_qubits¶
def remap_qubits(self, qubit_map: dict[int, int]) -> HamiltonianRemap qubit indices according to the given mapping.
This is used to translate Pauli indices (logical indices within an expval call) to physical qubit indices in the actual quantum circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
qubit_map | dict[int, int] | Mapping from logical index to physical index. e.g., {0: 5, 1: 3} maps logical index 0 → physical qubit 5 |
Returns:
Hamiltonian — New Hamiltonian with remapped qubit indices.
single_pauli¶
@classmethod
def single_pauli(cls, pauli: Pauli, index: int, coeff: float | complex = 1.0) -> HamiltonianCreate a single Pauli term Hamiltonian.
to_latex¶
def to_latex(self) -> strConverts the Hamiltonian to a LaTeX representation.
This function does not add constant term when we show the Hamiltonian. This function does not add $ symbols.
Returns:
str —
A LaTeX representation of the Hamiltonian.
import qamomile.core.operator as qm_o
import IPython.display as ipd
h = qm_o.Hamiltonian()
h += -qm_o.X(0) * qm_o.Y(1) - 2.0 * qm_o.Z(0) * qm_o.Z(1)
# Show the Hamiltonian in LaTeX at Jupyter Notebook
ipd.display(ipd.Latex("$" + h.to_latex() + "$"))to_numpy¶
def to_numpy(self) -> np.ndarrayConvert the Hamiltonian to a dense NumPy matrix.
Qubit 0 is mapped to the least-significant bit of computational-basis
indices, matching :meth:qamomile.linalg.HermitianMatrix.to_hamiltonian.
The returned array has shape (2**n, 2**n) where n is
:attr:num_qubits.
zero¶
@classmethod
def zero(cls, num_qubits: int | None = None) -> HamiltonianCreate a zero Hamiltonian.
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
ObservableType [source]¶
class ObservableType(ObjectTypeMixin, ValueType)Type representing a Hamiltonian observable parameter.
This is a reference type - the actual qamomile.observable.Hamiltonian is provided via bindings during transpilation. It cannot be constructed or manipulated within qkernels.
Example usage:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
return qm.expval(q, H)
# H is passed as binding
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(self) -> NoneParamSlot [source]¶
class ParamSlotMetadata for a single classical kernel argument.
A ParamSlot describes one position in the kernel’s classical
parameter contract — its declared type, whether it is a runtime
parameter or a compile-time-bound value, the Python default (if
any), the actually-bound value (when kind is
COMPILE_TIME_BOUND), and any outer-DSL hints. Slots are
immutable; pipeline passes that need to update a slot must clone
via dataclasses.replace.
The slot is identified by name, which matches the kernel’s
Python parameter name and the corresponding entry in
Block.label_args. A slot’s name MUST never overlap between
RUNTIME_PARAMETER and COMPILE_TIME_BOUND instances within
one Block (this mirrors the project-level bindings /
parameters disjointness rule).
Constructor¶
def __init__(
self,
name: str,
type: 'ValueType',
kind: ParamKind,
ndim: int = 0,
default: Any = None,
bound_value: Any = None,
differentiable: bool = False,
) -> NoneAttributes¶
bound_value: Anydefault: Anydifferentiable: boolkind: ParamKindname: strndim: inttype: ‘ValueType’
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
QFixedMetadata [source]¶
class QFixedMetadataMetadata for QFixed carriers.
Constructor¶
def __init__(self, qubit_uuids: tuple[str, ...], num_bits: int, int_bits: int) -> NoneAttributes¶
int_bits: intnum_bits: intqubit_uuids: tuple[str, ...]
QFixedType [source]¶
class QFixedType(QuantumTypeMixin, ValueType)Quantum fixed-point type.
Represents a quantum register encoding a fixed-point number with specified integer and fractional bits.
Constructor¶
def __init__(
self,
integer_bits: int | Value[UIntType] = 0,
fractional_bits: int | Value[UIntType] = 0,
) -> NoneAttributes¶
fractional_bits: int | Value[UIntType]integer_bits: int | Value[UIntType]
Methods¶
label¶
def label(self) -> strQInitOperation [source]¶
class QInitOperation(Operation)Initialize the qubit
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
QUIntType [source]¶
class QUIntType(QuantumTypeMixin, ValueType)Quantum unsigned integer type.
Represents a quantum register encoding an unsigned integer value using binary encoding (little-endian by default).
Constructor¶
def __init__(self, width: int | Value[UIntType]) -> NoneAttributes¶
width: int | Value[UIntType]
Methods¶
label¶
def label(self) -> strQubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
ReleaseSliceViewOperation [source]¶
class ReleaseSliceViewOperation(Operation)Mark a slice view’s borrow as explicitly returned to its parent.
Emitted by :meth:Vector.__setitem__ when used with a slice index
(qs[a:b] = qmc.h(qs[a:b])). This op tells the post-fold
linearity checker
(:class:~qamomile.circuit.transpiler.passes.slice_borrow_check.SliceBorrowCheckPass)
that the view referenced in operands[0] no longer owns its
covered parent slots, mirroring the frontend’s
VectorView.consume(operation_name="slice assignment") borrow
release.
Like :class:SliceArrayOperation, this op is a declarative
classical-side marker that does not survive into the emit stream:
:class:~qamomile.circuit.transpiler.passes.strip_slice_ops.StripSliceArrayOpsPass
removes both :class:SliceArrayOperation and
:class:ReleaseSliceViewOperation after
:class:SliceBorrowCheckPass has observed them. Reaching emit
is a compiler-internal invariant violation and is rejected with a
RuntimeError from :mod:standard_emit.
Within a control-flow body (ForOperation / WhileOperation
/ IfOperation), this op only releases view borrows that were
created within the same body. Releasing a borrow that the
enclosing block has registered (an “outer-snapshot” borrow) is
rejected by SliceBorrowCheckPass with
SliceBorrowViolationError — the loop-merge semantics of the
pass cannot propagate entry deletions out of the body, so the only
way to keep the static check consistent is to forbid that pattern.
Example:
``qs[1:3] = qmc.h(qs[1:3])`` emits, after the broadcast loop::
ReleaseSliceViewOperation(
operands=[qmc_h_result_view], # slice_of=qs_value
results=[],
)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Release is classical — it updates borrow tracking metadata only.signature: Signature Return the type signature of this release operation.
ResourceMetadata [source]¶
class ResourceMetadataResource estimation metadata for composite gates.
Gate count fields mirror GateCount categories.
None semantics:
Fields left as None mean “unknown/unspecified”. During extraction, gate_counter treats None as 0, which may undercount resources if the true value is nonzero. To ensure accurate resource estimates, set all relevant fields explicitly.
When total_gates is set but some of single_qubit_gates, two_qubit_gates, or multi_qubit_gates are None, the extractor emits a UserWarning if the known sub-total is less than total_gates, indicating potentially missing gate category data.
Constructor¶
def __init__(
self,
query_complexity: int | None = None,
t_gates: int | None = None,
ancilla_qubits: int = 0,
total_gates: int | None = None,
single_qubit_gates: int | None = None,
two_qubit_gates: int | None = None,
multi_qubit_gates: int | None = None,
clifford_gates: int | None = None,
rotation_gates: int | None = None,
custom_metadata: dict[str, Any] = dict(),
) -> NoneAttributes¶
ancilla_qubits: intclifford_gates: int | Nonecustom_metadata: dict[str, Any]multi_qubit_gates: int | Nonequery_complexity: int | Nonerotation_gates: int | Nonesingle_qubit_gates: int | Nonet_gates: int | Nonetotal_gates: int | Nonetwo_qubit_gates: int | None
RuntimeClassicalExpr [source]¶
class RuntimeClassicalExpr(Operation)A classical expression known to require runtime evaluation.
Lowered from CompOp / CondOp / NotOp / BinOp by
ClassicalLoweringPass when the op’s operand dataflow traces back
to a MeasureOperation (i.e. cannot be folded at compile-time, by
emit-time loop unrolling, or by compile_time_if_lowering). Backend
emit translates this 1:1 to a backend-native runtime expression
(e.g. qiskit.circuit.classical.expr.Expr).
Operand convention:
Binary kinds (EQ/NEQ/LT/LE/GT/GE/AND/OR/ADD/SUB/MUL/DIV/FLOORDIV/MOD/POW):
operands = [lhs, rhs].Unary kind (NOT):
operands = [val].Result:
results = [output_value].
The single-node + unified-kind shape (vs four parallel subclasses)
keeps the backend dispatch a single match op.kind instead of four
parallel hooks, and makes the IR self-documenting: a single
RuntimeClassicalExpr instance signals “runtime evaluation
required” regardless of which classical family it came from.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: RuntimeOpKind | None = None,
) -> NoneAttributes¶
kind: RuntimeOpKind | Noneoperation_kind: OperationKindsignature: Signature
ScalarMetadata [source]¶
class ScalarMetadataMetadata for scalar constants and symbolic parameters.
Constructor¶
def __init__(
self,
const_value: int | float | bool | None = None,
parameter_name: str | None = None,
) -> NoneAttributes¶
const_value: int | float | bool | Noneparameter_name: str | None
SliceArrayOperation [source]¶
class SliceArrayOperation(Operation)Construct a strided view of an ArrayValue.
The op itself performs no quantum action — it records that the
result ArrayValue is a strided view of the operand parent
with the given start / step. The result’s
slice_of / slice_start / slice_step fields carry the
affine map used by the emit-time resolver.
SliceArrayOperation is classified as :attr:OperationKind.CLASSICAL
because slicing is pure index selection — no new quantum operation
is introduced. The pipeline keeps this op through
PartialEvaluationPass (which invokes
ConstantFoldingPass(..., strip_slice_ops=False)) so the
post-fold :class:~qamomile.circuit.transpiler.passes.slice_borrow_check.SliceBorrowCheckPass
can use it as a view-declaration marker; once that check has run,
StripSliceArrayOpsPass removes every SliceArrayOperation
/ ReleaseSliceViewOperation so segmentation
(:mod:~qamomile.circuit.transpiler.passes.separate) and the
downstream emit stage only see a pure quantum-op stream. By the
time :mod:~qamomile.circuit.transpiler.passes.separate runs the
op has therefore been stripped — reaching emit is a compiler-
internal invariant violation.
Example:
``q[1::2]`` on a ``Vector[Qubit]`` emits::
SliceArrayOperation(
operands=[q_value, uint_1, uint_2],
results=[sliced_value], # slice_of=q_value, slice_start=uint_1, slice_step=uint_2
)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKind Slice is classical — it selects indices without quantum action.signature: Signature Return the type signature of this slice operation.
SymbolicControlledU [source]¶
class SymbolicControlledU(ControlledUOperation)Controlled-U with symbolic (Value) number of controls.
Operand layout: [ctrl_arg_0, ..., ctrl_arg_{k-1}, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_arg_0', ..., ctrl_arg_{k-1}', tgt_0', ..., tgt_m']
The number of control arguments k is recorded in
num_control_args; the default k = 1 corresponds to the
historical single-pool form (operands[0] is a
Vector[Qubit] / VectorView whose length equals
num_controls, or whose control_indices-selected subset
does). When k > 1 the control prefix is a heterogeneous
sequence of scalar Qubit values and ArrayValues whose
total qubit count is num_controls; the emit pass walks them
in order to recover the per-physical-qubit control set.
When control_indices is None the entire control prefix
is used as active controls (one-arg form: len(ctrl_vector) == num_controls; multi-arg form: the qubit-count sum of the
prefix args equals num_controls). When non-None, the
listed indices select exactly num_controls slots from a
single-arg pool to act as controls; combining
control_indices with the multi-arg control prefix is
rejected at frontend time.
Each control_indices entry is stored as a Value of
UIntType regardless of whether the frontend passed an
int literal or a UInt handle, so all downstream
value-substitution passes see a uniform shape.
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=(UIntType()), name=''))(),
control_indices: tuple[Value, ...] | None = None,
num_control_args: int = 1,
) -> NoneAttributes¶
control_indices: tuple[Value, ...] | Nonecontrol_operands: list[Value]is_symbolic_num_controls: boolnum_control_args: intnum_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]) -> OperationTupleType [source]¶
class TupleType(ValueType)Type representing a tuple of values.
Unlike simple types, TupleType stores the types of its elements, so equality and hashing depend on the element types.
Quantum/classical classification is derived from element types: quantum if any element is quantum, classical if all are classical.
Constructor¶
def __init__(self, element_types: tuple[ValueType, ...]) -> NoneAttributes¶
element_types: tuple[ValueType, ...]
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strTupleValue [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) -> TupleValueUIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
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 | NoneValueMetadata [source]¶
class ValueMetadataTyped metadata owned by the compiler/runtime.
Constructor¶
def __init__(
self,
scalar: ScalarMetadata | None = None,
cast: CastMetadata | None = None,
qfixed: QFixedMetadata | None = None,
array_runtime: ArrayRuntimeMetadata | None = None,
dict_runtime: DictRuntimeMetadata | None = None,
) -> NoneAttributes¶
array_runtime: ArrayRuntimeMetadata | Nonecast: CastMetadata | Nonedict_runtime: DictRuntimeMetadata | Noneqfixed: QFixedMetadata | Nonescalar: ScalarMetadata | None
ValueType [source]¶
class ValueType(abc.ABC)Base class for all value types in the IR.
Type instances are compared by class - all instances of the same type class are considered equal. This allows using type instances as dictionary keys where all QubitType() instances match.
Methods¶
is_classical¶
def is_classical(self) -> boolis_object¶
def is_object(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strWhileOperation [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.ir.serialize.hamiltonian_io¶
Hamiltonian wrapper used by both JSON and msgpack pipelines.
ParamSlot.bound_value and ArrayRuntimeMetadata.const_array may
carry :class:qamomile.observable.Hamiltonian objects — the bound
values of Observable kernel parameters (e.g. the documented Trotter
pattern kernel.build(Hs=[1.2 * Z(0), 0.8 * X(0)], ...)). This
module defines the tagged-dict wire representation for those payloads:
a sum of Pauli products plus a constant offset and the declared qubit
register width.
The wrapper is JSON-native (numbers, strings, lists, dicts — no raw bytes), so both wire formats carry it unchanged.
Two fidelity properties are load-bearing:
Term order is preserved.
Hamiltonian’s term dict iteration order is observable throughreprand therefore feedscontent_hash(canonical bytes stringify opaque payloads viarepr). The encoder emits terms in iteration order and the decoder re-adds them in wire order.Coefficient types are preserved.
repr(1.2)differs fromrepr((1.2+0j)), so int / float coefficients are written as plain numbers while complex ones get an explicit$complexsub-wrapper.
Security: decoding never resolves classes dynamically. Pauli names are
mapped through an explicit allow-map, and only Pauli /
PauliOperator / Hamiltonian instances are constructed.
Overview¶
| Function | Description |
|---|---|
dict_to_hamiltonian | Decode a wrapper dict back into a Hamiltonian. |
hamiltonian_to_dict | Encode a Hamiltonian into the wrapper dict. |
is_hamiltonian_wrapper | Return True if d is a Hamiltonian wrapper dict. |
is_plain_int | Return True if value is a Python int but not a bool. |
| Class | Description |
|---|---|
Hamiltonian | Represents a quantum Hamiltonian as a sum of Pauli operator products. |
Pauli | Enum class for Pauli operators. |
PauliOperator | Represents a single Pauli operator acting on a specific qubit. |
Functions¶
dict_to_hamiltonian [source]¶
def dict_to_hamiltonian(d: dict[str, Any]) -> HamiltonianDecode a wrapper dict back into a Hamiltonian.
Terms are re-added in wire order through the public add_term
API, which is the identity on the canonical term form the encoder
emits (operators sorted per term, no identities) and preserves the
term-dict insertion order.
Parameters:
| Name | Type | Description |
|---|---|---|
d | dict[str, Any] | A wrapper dict previously produced by :func:hamiltonian_to_dict (possibly after a JSON / msgpack round-trip). |
Returns:
Hamiltonian — The reconstructed Hamiltonian, equal to the
original (same terms in the same order, same coefficient
types, same constant, same declared register width).
Raises:
ValueError— Ifdis not a valid wrapper dict — missing or malformedterms, a term with an empty operator list (the constant is carried by the dedicatedconstantfield, so an empty list would double-encode it), a Pauli name outside the allow-map, a negative or non-int qubit index, a malformed coefficient, or anum_qubitsthat is neitherNonenor a non-negative int.
hamiltonian_to_dict [source]¶
def hamiltonian_to_dict(h: Hamiltonian) -> dict[str, Any]Encode a Hamiltonian into the wrapper dict.
Terms are emitted in the Hamiltonian’s own term-dict iteration
order; each term is a [operators, coefficient] pair where
operators is a list of [pauli_name, qubit_index] entries.
Parameters:
| Name | Type | Description |
|---|---|---|
h | Hamiltonian | The Hamiltonian to encode. Term coefficients and the constant must be int, float, or complex, or a numpy scalar of one of those kinds (coerced via .item()). |
Returns:
dict[str, Any] — dict[str, Any]: A wrapper dict with $hamiltonian,
terms, constant, and num_qubits (the declared
register width passed to the constructor, or None).
Raises:
TypeError— Ifhis not aHamiltonian, if a coefficient / the constant is not int, float, or complex, or if the declarednum_qubitsis not an int — all after coercing anynumpyscalar to its Python equivalent.ValueError— If the declarednum_qubitsis negative.
is_hamiltonian_wrapper [source]¶
def is_hamiltonian_wrapper(d: Any) -> boolReturn True if d is a Hamiltonian wrapper dict.
Parameters:
| Name | Type | Description |
|---|---|---|
d | Any | A value to check. Typically the result of a recursive dict walk from decode. |
Returns:
bool — True when d is a dict carrying the
$hamiltonian tag with a True value.
is_plain_int [source]¶
def is_plain_int(value: object) -> boolReturn True if value is a Python int but not a bool.
bool is a subclass of int in Python, so isinstance(True, int)
is True. This helper distinguishes a genuine integer from a boolean,
which matters wherever a boolean must be rejected in an integer slot — for
example, validating decoded wire data or a register width.
Parameters:
| Name | Type | Description |
|---|---|---|
value | object | The value to test. |
Returns:
bool — True when value is an int and not a bool.
Classes¶
Hamiltonian [source]¶
class HamiltonianRepresents a quantum Hamiltonian as a sum of Pauli operator products.
The Hamiltonian is stored as a dictionary where keys are tuples of PauliOperators and values are their corresponding coefficients.
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5)
>>> H.add_term((PauliOperator(Pauli.Z, 2),), 1.0)
>>> print(H.terms)
{(X0, Y1): 0.5, (Z2,): 1.0}Constructor¶
def __init__(self, num_qubits: int | None = None) -> NoneAttributes¶
constant: float | complexnum_qubits: int Calculates the number of qubits in the Hamiltonian.terms: dict[tuple[PauliOperator, ...], complex] Getter for the terms of the Hamiltonian.
Methods¶
add_term¶
def add_term(self, operators: tuple[PauliOperator, ...], coeff: float | complex)Adds a term to the Hamiltonian.
This method adds a product of Pauli operators with a given coefficient to the Hamiltonian. If the term already exists, the coefficients are summed.
Parameters:
| Name | Type | Description |
|---|---|---|
operators | Tuple[PauliOperator, ...] | A tuple of PauliOperators representing the term. |
coeff | Union[float, complex] | The coefficient of the term. |
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5)
>>> H.add_term((PauliOperator(Pauli.X, 0), PauliOperator(Pauli.Y, 1)), 0.5j)
>>> print(H.terms)
{(X0, Y1): (0.5+0.5j)}copy¶
def copy(self) -> HamiltonianReturn an independent copy sharing no mutable state with self.
Produces a new Hamiltonian with the same terms, constant,
and declared _num_qubits. The underlying _terms dict
is fresh, so subsequent add_term / constant mutations
on either instance do not affect the other. PauliOperator
instances inside the term tuples are reused — they are
dataclass(frozen=True) values and safely shared.
Returns:
Hamiltonian — A shallow-cloned Hamiltonian instance.
Example:
>>> H = Hamiltonian()
>>> H.add_term((PauliOperator(Pauli.Z, 0),), 1.0)
>>> H2 = H.copy()
>>> H2.add_term((PauliOperator(Pauli.X, 1),), 0.5)
>>> H.num_qubits # unchanged by H2's mutation
1identity¶
@classmethod
def identity(
cls,
coeff: float | complex = 1.0,
num_qubits: int | None = None,
) -> HamiltonianCreate a scalar times identity Hamiltonian.
remap_qubits¶
def remap_qubits(self, qubit_map: dict[int, int]) -> HamiltonianRemap qubit indices according to the given mapping.
This is used to translate Pauli indices (logical indices within an expval call) to physical qubit indices in the actual quantum circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
qubit_map | dict[int, int] | Mapping from logical index to physical index. e.g., {0: 5, 1: 3} maps logical index 0 → physical qubit 5 |
Returns:
Hamiltonian — New Hamiltonian with remapped qubit indices.
single_pauli¶
@classmethod
def single_pauli(cls, pauli: Pauli, index: int, coeff: float | complex = 1.0) -> HamiltonianCreate a single Pauli term Hamiltonian.
to_latex¶
def to_latex(self) -> strConverts the Hamiltonian to a LaTeX representation.
This function does not add constant term when we show the Hamiltonian. This function does not add $ symbols.
Returns:
str —
A LaTeX representation of the Hamiltonian.
import qamomile.core.operator as qm_o
import IPython.display as ipd
h = qm_o.Hamiltonian()
h += -qm_o.X(0) * qm_o.Y(1) - 2.0 * qm_o.Z(0) * qm_o.Z(1)
# Show the Hamiltonian in LaTeX at Jupyter Notebook
ipd.display(ipd.Latex("$" + h.to_latex() + "$"))to_numpy¶
def to_numpy(self) -> np.ndarrayConvert the Hamiltonian to a dense NumPy matrix.
Qubit 0 is mapped to the least-significant bit of computational-basis
indices, matching :meth:qamomile.linalg.HermitianMatrix.to_hamiltonian.
The returned array has shape (2**n, 2**n) where n is
:attr:num_qubits.
zero¶
@classmethod
def zero(cls, num_qubits: int | None = None) -> HamiltonianCreate a zero Hamiltonian.
Pauli [source]¶
class Pauli(enum.Enum)Enum class for Pauli operators.
Attributes¶
IXYZ
PauliOperator [source]¶
class PauliOperatorRepresents a single Pauli operator acting on a specific qubit.
Frozen so that Hamiltonian.copy() can share term operator
references across the original and the copy without risk of one
side mutating an operator the other still observes. None of the
existing callers mutate pauli or index after construction,
so freezing is a no-op behaviourally but makes the immutability
claim that Hamiltonian.copy()'s docstring relies on real.
Example:
>>> X0 = PauliOperator(Pauli.X, 0)
>>> print(X0)
X0Constructor¶
def __init__(self, pauli: Pauli, index: int) -> NoneAttributes¶
index: intpauli: Pauli
qamomile.circuit.ir.serialize.json_io¶
JSON wire format for the IR serialization pipeline.
JSON has no native bytes type, so this module is responsible for
converting raw bytes (used by numpy wrapper data fields) to / from
base64 strings at the wire boundary. Apart from that, the JSON output
is a faithful rendering of the intermediate dict produced by
:mod:qamomile.circuit.ir.serialize.encode.
A small sentinel field ($bytes_b64) distinguishes a base64-string
representation of bytes from a plain JSON string, so the decoder can
restore the original bytes value losslessly.
Overview¶
| Function | Description |
|---|---|
dump_json | Encode block into a UTF-8 JSON byte string. |
from_dict | Reconstruct a Block from a dict envelope. |
load_json | Decode a JSON document back into a Block. |
to_dict | Encode a Block into the intermediate dict envelope. |
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
Functions¶
dump_json [source]¶
def dump_json(block: Block) -> bytesEncode block into a UTF-8 JSON byte string.
The serialized form contains the schema_version envelope from
:func:qamomile.circuit.ir.serialize.encode.to_dict plus
base64-wrapped bytes payloads (numpy array data, raw bytes
bound values) so the output stays JSON-text-safe.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to encode. Must be AFFINE or ANALYZED. |
Returns:
bytes — A UTF-8 encoded JSON document.
Raises:
ValueError— Forwarded from :func:qamomile.circuit.ir.serialize.encode.to_dict(e.g., unsupported BlockKind).TypeError— Forwarded from the encoder when a payload type is not serializable.
from_dict [source]¶
def from_dict(envelope: dict[str, Any]) -> BlockReconstruct a Block from a dict envelope.
Parameters:
| Name | Type | Description |
|---|---|---|
envelope | dict[str, Any] | The dict produced by :func:qamomile.circuit.ir.serialize.encode.to_dict (or an equivalent producer that respects the schema). |
Returns:
Block — The reconstructed Block at AFFINE or ANALYZED.
Raises:
ValueError— If the envelope is malformed, theschema_versiondoes not match, or any$typetag is unknown to the dispatch table.TypeError— If a payload has an unexpected Python type.
load_json [source]¶
def load_json(payload: bytes | str) -> BlockDecode a JSON document back into a Block.
Parameters:
| Name | Type | Description |
|---|---|---|
payload | bytes | str | JSON bytes (UTF-8) or a JSON string. |
Returns:
Block — The reconstructed Block.
Raises:
ValueError— Forwarded from the dict decoder for malformed envelopes or unknown$typetags.TypeError— For numeric overflow or other JSON-side conversion issues.
to_dict [source]¶
def to_dict(block: Block) -> dict[str, Any]Encode a Block into the intermediate dict envelope.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to encode. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
dict[str, Any] — dict[str, Any]: {"schema_version": SCHEMA_VERSION, "block": <block dict>} ready to be passed to a wire-format
encoder (JSON / msgpack).
Raises:
ValueError— Ifblock.kindis notAFFINE/ANALYZED.NotImplementedError— If the block contains aCallBlockOperation(HIERARCHICAL holdover).TypeError— If a payload (e.g.,ParamSlot.bound_value) cannot be encoded with a known wire representation.
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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.ir.serialize.msgpack_io¶
msgpack wire format for the IR serialization pipeline.
msgpack carries bytes natively (bin type), so the numpy
wrapper’s data field passes through unchanged. This module is
mostly a thin wrapper around
:func:qamomile.circuit.ir.serialize.encode.to_dict /
:func:qamomile.circuit.ir.serialize.decode.from_dict, with safe
unpack defaults.
Overview¶
| Function | Description |
|---|---|
dump_msgpack | Encode block into a msgpack byte string. |
from_dict | Reconstruct a Block from a dict envelope. |
load_msgpack | Decode a msgpack payload back into a Block. |
to_dict | Encode a Block into the intermediate dict envelope. |
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
Functions¶
dump_msgpack [source]¶
def dump_msgpack(block: Block) -> bytesEncode block into a msgpack byte string.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to encode. Must be AFFINE or ANALYZED. |
Returns:
bytes — A msgpack-encoded payload. Compatible with the standard
msgpack package; no extension types are used.
Raises:
ValueError— Forwarded from :func:qamomile.circuit.ir.serialize.encode.to_dict(e.g., unsupported BlockKind).TypeError— Forwarded from the encoder when a payload type is not serializable.
from_dict [source]¶
def from_dict(envelope: dict[str, Any]) -> BlockReconstruct a Block from a dict envelope.
Parameters:
| Name | Type | Description |
|---|---|---|
envelope | dict[str, Any] | The dict produced by :func:qamomile.circuit.ir.serialize.encode.to_dict (or an equivalent producer that respects the schema). |
Returns:
Block — The reconstructed Block at AFFINE or ANALYZED.
Raises:
ValueError— If the envelope is malformed, theschema_versiondoes not match, or any$typetag is unknown to the dispatch table.TypeError— If a payload has an unexpected Python type.
load_msgpack [source]¶
def load_msgpack(payload: bytes) -> BlockDecode a msgpack payload back into a Block.
The unpacker is configured with raw=False so strings come back
as Python str, and strict_map_key=False so non-string map
keys (numeric, etc.) are accepted (qamomile’s schema only uses
string keys today, but this keeps the loader robust to future
schema extensions).
Parameters:
| Name | Type | Description |
|---|---|---|
payload | bytes | A msgpack-encoded payload produced by :func:dump_msgpack or an equivalent encoder. |
Returns:
Block — The reconstructed Block.
Raises:
ValueError— Forwarded from the dict decoder for malformed envelopes or unknown$typetags.
to_dict [source]¶
def to_dict(block: Block) -> dict[str, Any]Encode a Block into the intermediate dict envelope.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | The block to encode. Must be at BlockKind.AFFINE or BlockKind.ANALYZED. |
Returns:
dict[str, Any] — dict[str, Any]: {"schema_version": SCHEMA_VERSION, "block": <block dict>} ready to be passed to a wire-format
encoder (JSON / msgpack).
Raises:
ValueError— Ifblock.kindis notAFFINE/ANALYZED.NotImplementedError— If the block contains aCallBlockOperation(HIERARCHICAL holdover).TypeError— If a payload (e.g.,ParamSlot.bound_value) cannot be encoded with a known wire representation.
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(),
param_slots: tuple[ParamSlot, ...] = tuple(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]param_slots: tuple[ParamSlot, ...]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.ir.serialize.numpy_io¶
numpy ndarray wrapper used by both JSON and msgpack pipelines.
The wrapper is a tagged dict that both wire formats produce and
consume in identical shape; only the encoding of the "data"
field differs at the wire boundary (base64 string in JSON, native
bin in msgpack).
Allowed dtypes are restricted to an explicit allow-list. The decoder
rejects any dtype string outside the list, so a malicious payload
cannot coax numpy into instantiating an unexpected dtype object.
Overview¶
| Function | Description |
|---|---|
array_to_dict | Encode a numpy ndarray into the wrapper dict. |
dict_to_array | Decode a wrapper dict back into a numpy ndarray. |
is_array_wrapper | Return True if d is a numpy-array wrapper dict. |
is_plain_int | Return True if value is a Python int but not a bool. |
Functions¶
array_to_dict [source]¶
def array_to_dict(arr: np.ndarray) -> dict[str, Any]Encode a numpy ndarray into the wrapper dict.
Parameters:
| Name | Type | Description |
|---|---|---|
arr | np.ndarray | Source array. arr.dtype.name must be in the allow-list (:data:_ALLOWED_DTYPES). |
Returns:
dict[str, Any] — dict[str, Any]: A wrapper dict with $np_array, dtype,
shape (list[int]), and data (raw bytes from
ndarray.tobytes()). The wire encoders are responsible
for any further bytes ⇄ text conversion at format
boundaries.
Raises:
TypeError— Ifarris not anumpy.ndarray.ValueError— If the array’s dtype is not in the allow-list.
dict_to_array [source]¶
def dict_to_array(d: dict[str, Any]) -> np.ndarrayDecode a wrapper dict back into a numpy ndarray.
Parameters:
| Name | Type | Description |
|---|---|---|
d | dict[str, Any] | A wrapper dict previously produced by :func:array_to_dict (possibly after a JSON round-trip that converted the data field between bytes and base64). |
Returns:
np.ndarray — np.ndarray: The reconstructed array with the original dtype
and shape.
Raises:
ValueError— Ifdis not a valid wrapper dict, if the dtype is not in the allow-list, or if the byte length is inconsistent with shape × dtype.itemsize.
is_array_wrapper [source]¶
def is_array_wrapper(d: Any) -> boolReturn True if d is a numpy-array wrapper dict.
Parameters:
| Name | Type | Description |
|---|---|---|
d | Any | A value to check. Typically the result of a recursive dict walk from decode. |
Returns:
bool — True when d is a dict carrying the
$np_array tag with a True-ish value.
is_plain_int [source]¶
def is_plain_int(value: object) -> boolReturn True if value is a Python int but not a bool.
bool is a subclass of int in Python, so isinstance(True, int)
is True. This helper distinguishes a genuine integer from a boolean,
which matters wherever a boolean must be rejected in an integer slot — for
example, validating decoded wire data or a register width.
Parameters:
| Name | Type | Description |
|---|---|---|
value | object | The value to test. |
Returns:
bool — True when value is an int and not a bool.
qamomile.circuit.ir.serialize.schema¶
Intermediate dict schema for IR serialization.
This module defines SCHEMA_VERSION and the shape of the
intermediate Python dict that encode produces and decode
consumes. The wire encoders (json_io, msgpack_io) work on top
of this dict.
Top-level envelope¶
::
{
"schema_version": <int>,
"block": <block dict>
}SCHEMA_VERSION increments whenever the schema changes in a way
that breaks backward compatibility — i.e. the current decoder can
no longer read previously-written payloads (required fields added or
removed, field semantics changed). Purely additive changes do not
bump the version: new optional fields are read with
d.get(...)-with-default semantics (old payloads decode to the
default), and unknown extra fields in newer payloads are ignored by
older readers. New operation $type tags are likewise additive —
an older reader rejects them loudly with the closed-dispatch
ValueError rather than mis-decoding. The current value and the
per-bump history are recorded next to the constant at the bottom of
this module.
Block dict¶
::
{
"$type": "Block",
"kind": "AFFINE" | "ANALYZED",
"name": <str>,
"label_args": [<str>, ...],
"input_value_refs": [<uuid>, ...],
"output_value_refs": [<uuid>, ...],
"output_names": [<str>, ...],
"parameters": {<name>: <uuid>, ...},
"param_slots": [<param_slot dict>, ...],
"value_table": [<value dict>, ...], # every Value appears once
"operations": [<op dict>, ...]
}Only BlockKind.AFFINE and BlockKind.ANALYZED are accepted.
HIERARCHICAL and TRACED raise on encode because they may
embed CallBlockOperation references to sibling Blocks by Python
identity; cross-process module references will be addressed
separately.
Type tags¶
Every polymorphic structure carries a "$type" string used by the
decoder’s closed dispatch table. The decoder NEVER imports modules
or looks up classes from these strings; it dispatches through a
hard-coded $type -> factory map. Unknown tags raise
ValueError. This is the load-bearing security invariant.
Value references¶
Within a Block dict, every Value appears in exactly one place:
value_table. Everything else (operand lists, output lists,
parameter slots, parent_array pointers, etc.) references Values by
their canonical UUID string. The dict shape is therefore a tree
(no Python-level cycles) plus a flat Value table.
Numpy arrays¶
ParamSlot.bound_value and metadata fields like
ArrayRuntimeMetadata.const_array may carry numpy.ndarray
payloads. They are encoded with the tagged-dict wrapper defined in
:mod:qamomile.circuit.ir.serialize.numpy_io::
{
"$np_array": True,
"dtype": <str>, # one of the allow-list
"shape": [<int>, ...],
"data": <bytes> # ndarray.tobytes()
}JSON I/O converts data bytes to a base64 string at the JSON
boundary and back on read; msgpack passes the bytes through as a
bin native type.
Hamiltonian payloads¶
ParamSlot.bound_value and ArrayRuntimeMetadata.const_array
may carry qamomile.observable.Hamiltonian objects — the bound
values of Observable kernel parameters (e.g. a Trotter kernel
built with bindings={"Hs": [1.2 * Z(0), 0.8 * X(0)]}). They are
encoded with the tagged-dict wrapper defined in
:mod:qamomile.circuit.ir.serialize.hamiltonian_io::
{
"$hamiltonian": True,
"terms": [
[[["Z", 0], ["X", 1]], <coeff>], # one Pauli product per entry
...
],
"constant": <coeff>,
"num_qubits": <int | None> # declared register width
}<coeff> is a plain int / float, or — for complex coefficients —
{"$complex": True, "real": <float>, "imag": <float>}. Term order
follows the Hamiltonian’s own term-dict iteration order and the
float-vs-complex distinction is preserved, so the reconstructed
object is repr-identical to the original; both properties feed
content_hash, which stringifies opaque payloads via repr.
The wrapper contains no raw bytes, so both wire formats carry it
unchanged.
Forward compatibility¶
When the decoder encounters a Block whose schema_version
exceeds the loader’s SCHEMA_VERSION, it raises ValueError
rather than guess at unknown fields. Earlier versions are likewise
rejected today; a future PR may add a migration table.
Constants¶
SCHEMA_VERSION:int=1
qamomile.circuit.ir.types¶
qamomile.circuit.ir.types module.
qamomile.circuit.ir.types is most fundamental module defining types used in Qamomile IR.
Overview¶
| Class | Description |
|---|---|
BitType | Type representing a classical bit. |
DictType | Type representing a dictionary mapping keys to values. |
FloatType | Type representing a floating-point number. |
ObservableType | Type representing a Hamiltonian observable parameter. |
QFixedType | Quantum fixed-point type. |
QUIntType | Quantum unsigned integer type. |
QubitType | Type representing a quantum bit (qubit). |
TupleType | Type representing a tuple of values. |
UIntType | Type representing an unsigned integer. |
ValueType | Base class for all value types in the IR. |
Classes¶
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
DictType [source]¶
class DictType(ValueType)Type representing a dictionary mapping keys to values.
Unlike simple types, DictType stores the key and value types, so equality and hashing depend on those types. When key_type and value_type are None, represents a generic Dict type.
Quantum/classical classification is derived from key/value types.
Constructor¶
def __init__(
self,
key_type: ValueType | None = None,
value_type: ValueType | None = None,
) -> NoneAttributes¶
key_type: ValueType | Nonevalue_type: ValueType | None
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strFloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
ObservableType [source]¶
class ObservableType(ObjectTypeMixin, ValueType)Type representing a Hamiltonian observable parameter.
This is a reference type - the actual qamomile.observable.Hamiltonian is provided via bindings during transpilation. It cannot be constructed or manipulated within qkernels.
Example usage:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
return qm.expval(q, H)
# H is passed as binding
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(self) -> NoneQFixedType [source]¶
class QFixedType(QuantumTypeMixin, ValueType)Quantum fixed-point type.
Represents a quantum register encoding a fixed-point number with specified integer and fractional bits.
Constructor¶
def __init__(
self,
integer_bits: int | Value[UIntType] = 0,
fractional_bits: int | Value[UIntType] = 0,
) -> NoneAttributes¶
fractional_bits: int | Value[UIntType]integer_bits: int | Value[UIntType]
Methods¶
label¶
def label(self) -> strQUIntType [source]¶
class QUIntType(QuantumTypeMixin, ValueType)Quantum unsigned integer type.
Represents a quantum register encoding an unsigned integer value using binary encoding (little-endian by default).
Constructor¶
def __init__(self, width: int | Value[UIntType]) -> NoneAttributes¶
width: int | Value[UIntType]
Methods¶
label¶
def label(self) -> strQubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
TupleType [source]¶
class TupleType(ValueType)Type representing a tuple of values.
Unlike simple types, TupleType stores the types of its elements, so equality and hashing depend on the element types.
Quantum/classical classification is derived from element types: quantum if any element is quantum, classical if all are classical.
Constructor¶
def __init__(self, element_types: tuple[ValueType, ...]) -> NoneAttributes¶
element_types: tuple[ValueType, ...]
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strUIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
ValueType [source]¶
class ValueType(abc.ABC)Base class for all value types in the IR.
Type instances are compared by class - all instances of the same type class are considered equal. This allows using type instances as dictionary keys where all QubitType() instances match.
Methods¶
is_classical¶
def is_classical(self) -> boolis_object¶
def is_object(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strqamomile.circuit.ir.types.hamiltonian¶
Observable type for Hamiltonian parameter representation.
This module defines the ObservableType for the Qamomile IR, which represents a reference to a Hamiltonian observable provided via bindings during transpilation.
Unlike the previous HamiltonianExprType, this is purely a reference type - the actual qamomile.observable.Hamiltonian is provided from Python code.
Overview¶
| Class | Description |
|---|---|
ObjectTypeMixin | |
ObservableType | Type representing a Hamiltonian observable parameter. |
ValueType | Base class for all value types in the IR. |
Classes¶
ObjectTypeMixin [source]¶
class ObjectTypeMixinMethods¶
is_object¶
def is_object(self) -> boolObservableType [source]¶
class ObservableType(ObjectTypeMixin, ValueType)Type representing a Hamiltonian observable parameter.
This is a reference type - the actual qamomile.observable.Hamiltonian is provided via bindings during transpilation. It cannot be constructed or manipulated within qkernels.
Example usage:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
return qm.expval(q, H)
# H is passed as binding
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(self) -> NoneValueType [source]¶
class ValueType(abc.ABC)Base class for all value types in the IR.
Type instances are compared by class - all instances of the same type class are considered equal. This allows using type instances as dictionary keys where all QubitType() instances match.
Methods¶
is_classical¶
def is_classical(self) -> boolis_object¶
def is_object(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strqamomile.circuit.ir.types.primitives¶
Overview¶
| Class | Description |
|---|---|
BitType | Type representing a classical bit. |
BlockType | Type representing a block/function reference. |
ClassicalTypeMixin | |
DictType | Type representing a dictionary mapping keys to values. |
FloatType | Type representing a floating-point number. |
ObjectTypeMixin | |
QuantumTypeMixin | |
QubitType | Type representing a quantum bit (qubit). |
TupleType | Type representing a tuple of values. |
UIntType | Type representing an unsigned integer. |
ValueType | Base class for all value types in the IR. |
Classes¶
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
BlockType [source]¶
class BlockType(ObjectTypeMixin, ValueType)Type representing a block/function reference.
ClassicalTypeMixin [source]¶
class ClassicalTypeMixinMethods¶
is_classical¶
def is_classical(self) -> boolDictType [source]¶
class DictType(ValueType)Type representing a dictionary mapping keys to values.
Unlike simple types, DictType stores the key and value types, so equality and hashing depend on those types. When key_type and value_type are None, represents a generic Dict type.
Quantum/classical classification is derived from key/value types.
Constructor¶
def __init__(
self,
key_type: ValueType | None = None,
value_type: ValueType | None = None,
) -> NoneAttributes¶
key_type: ValueType | Nonevalue_type: ValueType | None
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strFloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
ObjectTypeMixin [source]¶
class ObjectTypeMixinMethods¶
is_object¶
def is_object(self) -> boolQuantumTypeMixin [source]¶
class QuantumTypeMixinMethods¶
is_quantum¶
def is_quantum(self) -> boolQubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
TupleType [source]¶
class TupleType(ValueType)Type representing a tuple of values.
Unlike simple types, TupleType stores the types of its elements, so equality and hashing depend on the element types.
Quantum/classical classification is derived from element types: quantum if any element is quantum, classical if all are classical.
Constructor¶
def __init__(self, element_types: tuple[ValueType, ...]) -> NoneAttributes¶
element_types: tuple[ValueType, ...]
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strUIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
ValueType [source]¶
class ValueType(abc.ABC)Base class for all value types in the IR.
Type instances are compared by class - all instances of the same type class are considered equal. This allows using type instances as dictionary keys where all QubitType() instances match.
Methods¶
is_classical¶
def is_classical(self) -> boolis_object¶
def is_object(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strqamomile.circuit.ir.types.q_register¶
Overview¶
| Class | Description |
|---|---|
QFixedType | Quantum fixed-point type. |
QUIntType | Quantum unsigned integer type. |
QuantumTypeMixin | |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
ValueType | Base class for all value types in the IR. |
Classes¶
QFixedType [source]¶
class QFixedType(QuantumTypeMixin, ValueType)Quantum fixed-point type.
Represents a quantum register encoding a fixed-point number with specified integer and fractional bits.
Constructor¶
def __init__(
self,
integer_bits: int | Value[UIntType] = 0,
fractional_bits: int | Value[UIntType] = 0,
) -> NoneAttributes¶
fractional_bits: int | Value[UIntType]integer_bits: int | Value[UIntType]
Methods¶
label¶
def label(self) -> strQUIntType [source]¶
class QUIntType(QuantumTypeMixin, ValueType)Quantum unsigned integer type.
Represents a quantum register encoding an unsigned integer value using binary encoding (little-endian by default).
Constructor¶
def __init__(self, width: int | Value[UIntType]) -> NoneAttributes¶
width: int | Value[UIntType]
Methods¶
label¶
def label(self) -> strQuantumTypeMixin [source]¶
class QuantumTypeMixinMethods¶
is_quantum¶
def is_quantum(self) -> boolUIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
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.
ValueType [source]¶
class ValueType(abc.ABC)Base class for all value types in the IR.
Type instances are compared by class - all instances of the same type class are considered equal. This allows using type instances as dictionary keys where all QubitType() instances match.
Methods¶
is_classical¶
def is_classical(self) -> boolis_object¶
def is_object(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strqamomile.circuit.ir.value¶
Value types and typed metadata for the Qamomile IR.
Overview¶
| Function | Description |
|---|---|
remap_indexed_identifier | Remap an identifier while preserving a legacy index suffix. |
remap_value_metadata_references | Rewrite UUID and logical-id references inside value metadata. |
resolve_root_array_index | Fold a view-local element index into the root array’s index space. |
resolve_root_qubit_address | Resolve an array-element value to its root (array_uuid, index). |
split_indexed_identifier | Split a legacy indexed identifier into base and index suffix. |
| Class | Description |
|---|---|
ArrayRuntimeMetadata | Metadata for array literals and explicit element identity tracking. |
ArrayValue | An array of typed IR values. |
CastMetadata | Metadata describing a cast carrier and its underlying qubits. |
DictRuntimeMetadata | Metadata for transpile-time bound dict values. |
DictValue | A dictionary value stored as stable ordered entries. |
QFixedMetadata | Metadata for QFixed carriers. |
ScalarMetadata | Metadata for scalar constants and symbolic parameters. |
TupleType | Type representing a tuple of values. |
TupleValue | A tuple of IR values for structured data. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueMetadata | Typed metadata owned by the compiler/runtime. |
Constants¶
ValueLike:TypeAlias='Value | ArrayValue | TupleValue | DictValue'
Functions¶
remap_indexed_identifier [source]¶
def remap_indexed_identifier(identifier: str, remap_identifier: Callable[[str], str]) -> strRemap an identifier while preserving a legacy index suffix.
Parameters:
| Name | Type | Description |
|---|---|---|
identifier | str | Scalar identifier or legacy "<base>_<index>" carrier key. |
remap_identifier | typing.Callable[[str], str] | Function that remaps scalar identifiers and carrier-key bases. |
Returns:
str — Remapped identifier. Numeric index suffixes are preserved after
remapping the base identifier.
remap_value_metadata_references [source]¶
def remap_value_metadata_references(
metadata: ValueMetadata,
remap_uuid: Callable[[str], str],
remap_logical_id: Callable[[str], str],
) -> ValueMetadataRewrite UUID and logical-id references inside value metadata.
Parameters:
| Name | Type | Description |
|---|---|---|
metadata | ValueMetadata | Metadata bundle whose embedded references should be rewritten. |
remap_uuid | typing.Callable[[str], str] | Function that maps scalar UUID references (and carrier-key bases) to replacement UUIDs. |
remap_logical_id | typing.Callable[[str], str] | Function that maps scalar logical-id references (and carrier-key bases) to replacement logical IDs. |
Returns:
ValueMetadata — Metadata with every embedded UUID / logical-id reference
rewritten. Legacy "<uuid>_<index>" carrier keys keep their
index suffix while remapping the base UUID. The original bundle is
returned unchanged when no reference is rewritten.
resolve_root_array_index [source]¶
def resolve_root_array_index(array: 'ArrayValue', index: int) -> tuple['ArrayValue', int] | NoneFold a view-local element index into the root array’s index space.
Walks the slice_of chain root-ward, composing each strided view’s
affine map parent_index = start + step * local_index. This is the
array-level counterpart of :func:resolve_root_qubit_address (which
starts from an array-element Value); both must stay consistent with
the composite carrier keys "<root_uuid>_<root_index>" registered by
QInitOperation at emit time.
Parameters:
| Name | Type | Description |
|---|---|---|
array | ArrayValue | Array the index is local to. May be a root array (slice_of unset) or an arbitrarily nested strided view. |
index | int | Element index in array’s own index space. |
Returns:
tuple['ArrayValue', int] | None — tuple[ArrayValue, int] | None: (root_array, composed_index) when
every slice bound on the chain is compile-time constant and
satisfies the frontend contract (non-negative slice_start,
positive slice_step). None when any slice_start /
slice_step on the chain is missing, symbolic, or violates
that contract; callers must then defer resolution rather than
guess. Out-of-contract bounds would compose index onto a
wrong root slot, so they are refused here too (the frontend
rejects them at trace time; this guard covers programmatically
constructed IR).
resolve_root_qubit_address [source]¶
def resolve_root_qubit_address(value: 'Value') -> tuple[str, int] | NoneResolve an array-element value to its root (array_uuid, index).
Walks the parent_array / slice_of chain and composes the nested
affine slice maps, so view[i] resolves to
(root_uuid, start + step * i) for the composed (start, step). The
returned pair is the build-stable identity of the physical qubit slot: the
root array’s QInitOperation always registers it as
QubitAddress(root_uuid, index), so this address resolves even when the
element’s own (per-version) UUID was never registered.
The transpiler’s resource allocator uses the same walk to resolve gate and measurement operands; this shared helper keeps both call sites consistent.
Parameters:
| Name | Type | Description |
|---|---|---|
value | Value | The value to resolve. Expected to be an array element (parent_array set with a single constant element_indices entry). |
Returns:
tuple[str, int] | None — tuple[str, int] | None: (root_array_uuid, composed_index) when
value is an array element with a constant index whose entire
slice_of chain has constant slice_start / slice_step.
None when value is not an array element, when its index is
non-constant, or when any slice bound in the chain is non-constant
(those cases are deferred to the emit-time resolver, which has
bindings available). Also None for a negative constant index
or a chain frame with negative slice_start / non-positive
slice_step — composing those would silently address a wrong
root slot, so they are refused rather than guessed (the frontend
rejects them at trace time; this guard covers programmatically
constructed IR).
split_indexed_identifier [source]¶
def split_indexed_identifier(identifier: str) -> tuple[str, str] | NoneSplit a legacy indexed identifier into base and index suffix.
Parameters:
| Name | Type | Description |
|---|---|---|
identifier | str | Identifier to inspect. Legacy carrier keys use the "<base>_<index>" spelling, where index is decimal. |
Returns:
tuple[str, str] | None — tuple[str, str] | None: (base, index) when identifier carries a
numeric suffix, otherwise None.
Classes¶
ArrayRuntimeMetadata [source]¶
class ArrayRuntimeMetadataMetadata for array literals and explicit element identity tracking.
element_parent_uuids / element_parent_indices are parallel to
element_uuids: for each tracked element they record the root array’s
UUID and the element’s index within that root (as resolved by
:func:resolve_root_qubit_address at trace time). They let an emit pass map
a packed element back to the physical qubit registered under the root
array’s QubitAddress(root_uuid, index) key even when the element’s own
UUID was never registered. The sentinel ("", -1) marks an element with
no array parent (a standalone qubit), for which a flat UUID lookup is used.
Constructor¶
def __init__(
self,
const_array: Any = None,
element_uuids: tuple[str, ...] = (),
element_logical_ids: tuple[str, ...] = (),
element_parent_uuids: tuple[str, ...] = (),
element_parent_indices: tuple[int, ...] = (),
) -> NoneAttributes¶
const_array: Anyelement_logical_ids: tuple[str, ...]element_parent_indices: tuple[int, ...]element_parent_uuids: tuple[str, ...]element_uuids: tuple[str, ...]
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
When slice_of is set, this array is a strided view over another
array. Element accesses on a sliced ArrayValue resolve to
physical slots on the root parent via the affine map
parent_index = slice_start + slice_step * view_local_index,
applied recursively along slice_of chains. The emit-time
resolver walks this chain to produce the final qubit index; passes
that substitute or clone values must treat slice_of /
slice_start / slice_step as Value references that need to
track through the same mapping as parent_array.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
slice_of: 'ArrayValue | None' = None,
slice_start: 'Value | None' = None,
slice_step: 'Value | None' = None,
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]slice_of: ‘ArrayValue | None’slice_start: ‘Value | None’slice_step: ‘Value | None’type: Tuuid: str
Methods¶
is_slice¶
def is_slice(self) -> boolReturn True if this array is a strided view of another array.
Returns:
bool — True iff slice_of is non-None.
next_version¶
def next_version(self) -> ArrayValue[T]CastMetadata [source]¶
class CastMetadataMetadata describing a cast carrier and its underlying qubits.
Constructor¶
def __init__(
self,
source_uuid: str,
qubit_uuids: tuple[str, ...],
source_logical_id: str | None = None,
qubit_logical_ids: tuple[str, ...] = (),
) -> NoneAttributes¶
qubit_logical_ids: tuple[str, ...]qubit_uuids: tuple[str, ...]source_logical_id: str | Nonesource_uuid: str
DictRuntimeMetadata [source]¶
class DictRuntimeMetadataMetadata for transpile-time bound dict values.
Constructor¶
def __init__(self, bound_data: tuple[tuple[Any, Any], ...] = ()) -> NoneAttributes¶
bound_data: tuple[tuple[Any, Any], ...]
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) -> DictValueQFixedMetadata [source]¶
class QFixedMetadataMetadata for QFixed carriers.
Constructor¶
def __init__(self, qubit_uuids: tuple[str, ...], num_bits: int, int_bits: int) -> NoneAttributes¶
int_bits: intnum_bits: intqubit_uuids: tuple[str, ...]
ScalarMetadata [source]¶
class ScalarMetadataMetadata for scalar constants and symbolic parameters.
Constructor¶
def __init__(
self,
const_value: int | float | bool | None = None,
parameter_name: str | None = None,
) -> NoneAttributes¶
const_value: int | float | bool | Noneparameter_name: str | None
TupleType [source]¶
class TupleType(ValueType)Type representing a tuple of values.
Unlike simple types, TupleType stores the types of its elements, so equality and hashing depend on the element types.
Quantum/classical classification is derived from element types: quantum if any element is quantum, classical if all are classical.
Constructor¶
def __init__(self, element_types: tuple[ValueType, ...]) -> NoneAttributes¶
element_types: tuple[ValueType, ...]
Methods¶
is_classical¶
def is_classical(self) -> boolis_quantum¶
def is_quantum(self) -> boollabel¶
def label(self) -> strTupleValue [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.
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 | NoneValueMetadata [source]¶
class ValueMetadataTyped metadata owned by the compiler/runtime.
Constructor¶
def __init__(
self,
scalar: ScalarMetadata | None = None,
cast: CastMetadata | None = None,
qfixed: QFixedMetadata | None = None,
array_runtime: ArrayRuntimeMetadata | None = None,
dict_runtime: DictRuntimeMetadata | None = None,
) -> NoneAttributes¶
array_runtime: ArrayRuntimeMetadata | Nonecast: CastMetadata | Nonedict_runtime: DictRuntimeMetadata | Noneqfixed: QFixedMetadata | Nonescalar: ScalarMetadata | None
qamomile.circuit.ir.value_mapping¶
Provide shared IR value substitution utilities.
Overview¶
| Function | Description |
|---|---|
resolve_root_array_index | Fold a view-local element index into the root array’s index space. |
resolve_root_qubit_address | Resolve an array-element value to its root (array_uuid, index). |
split_indexed_identifier | Split a legacy indexed identifier into base and index suffix. |
| Class | Description |
|---|---|
ArrayRuntimeMetadata | Metadata for array literals and explicit element identity tracking. |
ArrayValue | An array of typed IR values. |
CastMetadata | Metadata describing a cast carrier and its underlying qubits. |
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
DictValue | A dictionary value stored as stable ordered entries. |
IfOperation | Represents an if-else conditional operation. |
QFixedMetadata | Metadata for QFixed carriers. |
TupleValue | A tuple of IR values for structured data. |
Value | A typed SSA value in the IR. |
ValueBase | Protocol for IR values with typed metadata. |
ValueMetadata | Typed metadata owned by the compiler/runtime. |
ValueSubstitutor | Substitute IR values in operations using a UUID-keyed mapping. |
Functions¶
resolve_root_array_index [source]¶
def resolve_root_array_index(array: 'ArrayValue', index: int) -> tuple['ArrayValue', int] | NoneFold a view-local element index into the root array’s index space.
Walks the slice_of chain root-ward, composing each strided view’s
affine map parent_index = start + step * local_index. This is the
array-level counterpart of :func:resolve_root_qubit_address (which
starts from an array-element Value); both must stay consistent with
the composite carrier keys "<root_uuid>_<root_index>" registered by
QInitOperation at emit time.
Parameters:
| Name | Type | Description |
|---|---|---|
array | ArrayValue | Array the index is local to. May be a root array (slice_of unset) or an arbitrarily nested strided view. |
index | int | Element index in array’s own index space. |
Returns:
tuple['ArrayValue', int] | None — tuple[ArrayValue, int] | None: (root_array, composed_index) when
every slice bound on the chain is compile-time constant and
satisfies the frontend contract (non-negative slice_start,
positive slice_step). None when any slice_start /
slice_step on the chain is missing, symbolic, or violates
that contract; callers must then defer resolution rather than
guess. Out-of-contract bounds would compose index onto a
wrong root slot, so they are refused here too (the frontend
rejects them at trace time; this guard covers programmatically
constructed IR).
resolve_root_qubit_address [source]¶
def resolve_root_qubit_address(value: 'Value') -> tuple[str, int] | NoneResolve an array-element value to its root (array_uuid, index).
Walks the parent_array / slice_of chain and composes the nested
affine slice maps, so view[i] resolves to
(root_uuid, start + step * i) for the composed (start, step). The
returned pair is the build-stable identity of the physical qubit slot: the
root array’s QInitOperation always registers it as
QubitAddress(root_uuid, index), so this address resolves even when the
element’s own (per-version) UUID was never registered.
The transpiler’s resource allocator uses the same walk to resolve gate and measurement operands; this shared helper keeps both call sites consistent.
Parameters:
| Name | Type | Description |
|---|---|---|
value | Value | The value to resolve. Expected to be an array element (parent_array set with a single constant element_indices entry). |
Returns:
tuple[str, int] | None — tuple[str, int] | None: (root_array_uuid, composed_index) when
value is an array element with a constant index whose entire
slice_of chain has constant slice_start / slice_step.
None when value is not an array element, when its index is
non-constant, or when any slice bound in the chain is non-constant
(those cases are deferred to the emit-time resolver, which has
bindings available). Also None for a negative constant index
or a chain frame with negative slice_start / non-positive
slice_step — composing those would silently address a wrong
root slot, so they are refused rather than guessed (the frontend
rejects them at trace time; this guard covers programmatically
constructed IR).
split_indexed_identifier [source]¶
def split_indexed_identifier(identifier: str) -> tuple[str, str] | NoneSplit a legacy indexed identifier into base and index suffix.
Parameters:
| Name | Type | Description |
|---|---|---|
identifier | str | Identifier to inspect. Legacy carrier keys use the "<base>_<index>" spelling, where index is decimal. |
Returns:
tuple[str, str] | None — tuple[str, str] | None: (base, index) when identifier carries a
numeric suffix, otherwise None.
Classes¶
ArrayRuntimeMetadata [source]¶
class ArrayRuntimeMetadataMetadata for array literals and explicit element identity tracking.
element_parent_uuids / element_parent_indices are parallel to
element_uuids: for each tracked element they record the root array’s
UUID and the element’s index within that root (as resolved by
:func:resolve_root_qubit_address at trace time). They let an emit pass map
a packed element back to the physical qubit registered under the root
array’s QubitAddress(root_uuid, index) key even when the element’s own
UUID was never registered. The sentinel ("", -1) marks an element with
no array parent (a standalone qubit), for which a flat UUID lookup is used.
Constructor¶
def __init__(
self,
const_array: Any = None,
element_uuids: tuple[str, ...] = (),
element_logical_ids: tuple[str, ...] = (),
element_parent_uuids: tuple[str, ...] = (),
element_parent_indices: tuple[int, ...] = (),
) -> NoneAttributes¶
const_array: Anyelement_logical_ids: tuple[str, ...]element_parent_indices: tuple[int, ...]element_parent_uuids: tuple[str, ...]element_uuids: tuple[str, ...]
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
When slice_of is set, this array is a strided view over another
array. Element accesses on a sliced ArrayValue resolve to
physical slots on the root parent via the affine map
parent_index = slice_start + slice_step * view_local_index,
applied recursively along slice_of chains. The emit-time
resolver walks this chain to produce the final qubit index; passes
that substitute or clone values must treat slice_of /
slice_start / slice_step as Value references that need to
track through the same mapping as parent_array.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
slice_of: 'ArrayValue | None' = None,
slice_start: 'Value | None' = None,
slice_step: 'Value | None' = None,
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]slice_of: ‘ArrayValue | None’slice_start: ‘Value | None’slice_step: ‘Value | None’type: Tuuid: str
Methods¶
is_slice¶
def is_slice(self) -> boolReturn True if this array is a strided view of another array.
Returns:
bool — True iff slice_of is non-None.
next_version¶
def next_version(self) -> ArrayValue[T]CastMetadata [source]¶
class CastMetadataMetadata describing a cast carrier and its underlying qubits.
Constructor¶
def __init__(
self,
source_uuid: str,
qubit_uuids: tuple[str, ...],
source_logical_id: str | None = None,
qubit_logical_ids: tuple[str, ...] = (),
) -> NoneAttributes¶
qubit_logical_ids: tuple[str, ...]qubit_uuids: tuple[str, ...]source_logical_id: str | Nonesource_uuid: str
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
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) -> DictValueIfOperation [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]]) -> OperationQFixedMetadata [source]¶
class QFixedMetadataMetadata for QFixed carriers.
Constructor¶
def __init__(self, qubit_uuids: tuple[str, ...], num_bits: int, int_bits: int) -> NoneAttributes¶
int_bits: intnum_bits: intqubit_uuids: tuple[str, ...]
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.
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 | NoneValueMetadata [source]¶
class ValueMetadataTyped metadata owned by the compiler/runtime.
Constructor¶
def __init__(
self,
scalar: ScalarMetadata | None = None,
cast: CastMetadata | None = None,
qfixed: QFixedMetadata | None = None,
array_runtime: ArrayRuntimeMetadata | None = None,
dict_runtime: DictRuntimeMetadata | None = None,
) -> NoneAttributes¶
array_runtime: ArrayRuntimeMetadata | Nonecast: CastMetadata | Nonedict_runtime: DictRuntimeMetadata | Noneqfixed: QFixedMetadata | Nonescalar: ScalarMetadata | None
ValueSubstitutor [source]¶
class ValueSubstitutorSubstitute IR values in operations using a UUID-keyed mapping.
Parameters:
| Name | Type | Description |
|---|---|---|
value_map | Mapping[str, ValueBase] | Mapping from original value UUIDs to replacement values. |
transitive | bool | Whether substitutions should chase chains such as A -> B -> C to the terminal value. Defaults to False. |
Constructor¶
def __init__(self, value_map: Mapping[str, ValueBase], transitive: bool = False)Initialize the substitutor.
Parameters:
| Name | Type | Description |
|---|---|---|
value_map | Mapping[str, ValueBase] | Mapping from original value UUIDs to replacement values. |
transitive | bool | Whether substitutions should chase chains to their terminal value. Defaults to False. |
Methods¶
substitute_operation¶
def substitute_operation(self, op: Operation) -> OperationSubstitute values in an operation.
Parameters:
| Name | Type | Description |
|---|---|---|
op | Operation | Operation whose operands, results, and subclass-specific value fields should be substituted. |
Returns:
Operation — Operation with all mapped value references replaced.
substitute_value¶
def substitute_value(self, value: ValueBase) -> ValueBaseSubstitute a single value.
Parameters:
| Name | Type | Description |
|---|---|---|
value | ValueBase | Value to replace or rebuild. |
Returns:
ValueBase — Replacement value, rebuilt value with substituted
ValueBase — metadata, or the original value when nothing maps.