qamomile.circuit.frontend.ast_transform¶
Overview¶
| Function | Description |
|---|---|
collect_quantum_rebind_violations | Analyze func for forbidden quantum rebind patterns. |
emit_if | Builder function for if-else conditional with Phi function merging. |
for_items | Builder function to create a for-items loop in Qamomile frontend. |
for_loop | Builder function to create a for loop in Qamomile frontend. |
transform_control_flow | |
while_loop | Create a while loop whose condition is a measurement result. |
| Class | Description |
|---|---|
ControlFlowTransformer | |
QuantumRebindAnalyzer | Detects forbidden quantum variable reassignment at the AST level. |
RebindViolation | A detected forbidden quantum variable rebinding. |
VariableCollector | Collect variables used and mutated within a block. |
Functions¶
collect_quantum_rebind_violations [source]¶
def collect_quantum_rebind_violations(func: Callable, quantum_param_names: set[str]) -> list[RebindViolation]Analyze func for forbidden quantum rebind patterns.
Returns a (possibly empty) list of violations. Never raises on
analysis failure – returns [] instead.
emit_if [source]¶
def emit_if(
cond_func: Callable,
true_func: Callable,
false_func: Callable,
variables: list,
) -> AnyBuilder function for if-else conditional with Phi function merging.
This function is called from AST-transformed code. The AST transformer converts: if condition: true_body else: false_body
Into:
def _cond_N(vars): return condition def _body_N(vars): true_body; return vars def _body_N+1(vars): false_body; return vars result = emit_if(_cond_N, _body_N, _body_N+1, [var_list])
Parameters:
| Name | Type | Description |
|---|---|---|
cond_func | typing.Callable | Function returning the condition (Bit or bool-like Handle) |
true_func | typing.Callable | Function executing true branch, returns updated variables |
false_func | typing.Callable | Function executing false branch, returns updated variables |
variables | list | List of variables used in the branches |
Returns:
typing.Any — Merged variable values after conditional execution (using Phi functions)
Example:
@qkernel
def my_kernel(q: Qubit) -> Qubit:
result = measure(q)
if result:
q = z(q)
return qfor_items [source]¶
def for_items(
d: Dict,
key_var_names: list[str],
value_var_name: str,
) -> Generator[tuple[Any, Any], None, None]Builder function to create a for-items loop in Qamomile frontend.
This context manager creates a ForItemsOperation that iterates over dictionary (key, value) pairs. The operation is always unrolled at transpile time since quantum backends cannot natively iterate over classical data structures.
Parameters:
| Name | Type | Description |
|---|---|---|
d | Dict | Dict handle to iterate over |
key_var_names | list[str] | Names of key unpacking variables (e.g., [“i”, “j”] for tuple keys) |
value_var_name | str | Name of value variable (e.g., “Jij”) |
Yields:
tuple[typing.Any, typing.Any] — Tuple of (key_handles, value_handle) for use in loop body
Example:
@qkernel
def ising_cost(
q: Vector[Qubit],
ising: Dict[Tuple[UInt, UInt], Float],
gamma: Float,
) -> Vector[Qubit]:
for (i, j), Jij in qmc.items(ising):
q[i], q[j] = qmc.rzz(q[i], q[j], gamma * Jij)
return qfor_loop [source]¶
def for_loop(
start,
stop,
step = 1,
var_name: str = '_loop_idx',
) -> Generator[UInt, None, None]Builder function to create a for loop in Qamomile frontend.
Parameters:
| Name | Type | Description |
|---|---|---|
start | `` | Loop start value (can be Handle or int) |
stop | `` | Loop stop value (can be Handle or int) |
step | `` | Loop step value (default=1) |
var_name | str | Name of the loop variable (default=“_loop_idx”) |
Yields:
UInt — The loop iteration variable (can be used as array index)
Example:
@QKernel
def my_kernel(qubits: Array[Qubit, Literal[3]]) -> Array[Qubit, Literal[3]]:
for i in qm.range(3):
qubits[i] = h(qubits[i])
return qubits
@QKernel
def my_kernel2(qubits: Array[Qubit, Literal[5]]) -> Array[Qubit, Literal[5]]:
for i in qm.range(1, 4): # i = 1, 2, 3
qubits[i] = h(qubits[i])
return qubitstransform_control_flow [source]¶
def transform_control_flow(func: Callable)while_loop [source]¶
def while_loop(cond: Callable) -> Generator[WhileLoop, None, None]Create a while loop whose condition is a measurement result.
The condition must be a Bit produced by qmc.measure().
Non-measurement conditions (classical variables, constants,
comparisons) are accepted at build time but will be rejected by
ValidateWhileContractPass during transpilation.
Parameters:
| Name | Type | Description |
|---|---|---|
cond | typing.Callable | A callable (lambda) that returns the loop condition. Must return a Bit handle originating from qmc.measure(). |
Yields:
WhileLoop — A marker object for the while loop context.
Example::
@qm.qkernel
def repeat_until_zero() -> qm.Bit:
q = qm.qubit("q")
q = qm.h(q)
bit = qm.measure(q)
while bit:
q = qm.qubit("q2")
q = qm.h(q)
bit = qm.measure(q)
return bitClasses¶
ControlFlowTransformer [source]¶
class ControlFlowTransformer(ast.NodeTransformer)Constructor¶
def __init__(
self,
global_names: set[str] | None = None,
param_names: set[str] | None = None,
namespace: dict[str, Any] | None = None,
) -> NoneAttributes¶
counter: intfor_func_nameif_func_nametype_registry: dict[str, ast.AST]while_func_name
Methods¶
visit_AnnAssign¶
def visit_AnnAssign(self, node: ast.AnnAssign) -> AnyDetect annotated assignments such as a: int = 0 and register
the type information.
visit_For¶
def visit_For(self, node: ast.For) -> Anyvisit_FunctionDef¶
def visit_FunctionDef(self, node: ast.FunctionDef) -> ast.FunctionDefProcess the function body with definition tracking.
Collects parameter names as the initial set of defined variables
and delegates to _visit_body_with_tracking for sequential
statement processing.
visit_If¶
def visit_If(self, node: ast.If) -> Anyvisit_While¶
def visit_While(self, node: ast.While) -> AnyQuantumRebindAnalyzer [source]¶
class QuantumRebindAnalyzer(ast.NodeVisitor)Detects forbidden quantum variable reassignment at the AST level.
Forbidden patterns (target is an existing quantum variable):
a = bwhere b is quantum with a different origina = f(b, ...)where b is quantum with a different origin
Allowed patterns:
a = f(a, ...)(self-update)new = f(b, ...)(new binding – target was not quantum before)alias = q(new alias – target was not quantum before)
Constructor¶
def __init__(self, quantum_param_names: set[str]) -> NoneAttributes¶
quantum_vars: dict[str, str]violations: list[RebindViolation]
Methods¶
visit_Assign¶
def visit_Assign(self, node: ast.Assign) -> NoneRebindViolation [source]¶
class RebindViolationA detected forbidden quantum variable rebinding.
Constructor¶
def __init__(
self,
target_name: str,
source_name: str,
func_name: str | None,
lineno: int,
) -> NoneAttributes¶
func_name: str | Nonelineno: intsource_name: strtarget_name: str
VariableCollector [source]¶
class VariableCollector(ast.NodeVisitor)Collect variables used and mutated within a block.
Excludes:
Function names in calls (func in Call)
Global base objects in attribute accesses (value in Attribute)
Global variables (modules, builtins, etc.)
Constructor¶
def __init__(self, global_names: set[str] | None = None)Attributes¶
incoming_vars: set[str] Variables that must come from an outer scope (first use is Load).load_vars: set[str] Variables referenced in Load context (actually read).locally_defined_vars: set[str] Variables first defined (Store) within this scope.store_vars: set[str] Variables assigned in Store context.vars
Methods¶
visit_Assign¶
def visit_Assign(self, node: ast.Assign)Visit the RHS first to match Python’s evaluation order.
q1 = qm.h(q1) → RHS q1 (Load) is first → first_context is “Load”
cond2 = qm.measure(q2) → RHS q2 (Load) first, LHS cond2 (Store) after
visit_Attribute¶
def visit_Attribute(self, node: ast.Attribute)Record the base name of an attribute access.
Global names such as module names (qm.h) are excluded as before,
while user variables (qs.shape) are treated as Load.
visit_AugAssign¶
def visit_AugAssign(self, node: ast.AugAssign)AugAssign (e.g. x += 1) is an implicit Read-before-Write.
Visit the RHS first and record Name targets as both Load and Store. first_context is “Load” (the existing value is read first).
visit_Call¶
def visit_Call(self, node: ast.Call)Exclude the function name of a call.
visit_FunctionDef¶
def visit_FunctionDef(self, node: ast.FunctionDef)Skip traversal of inner function definitions.
visit_Name¶
def visit_Name(self, node: ast.Name)Collect variable names (only those not in the exclude list).
qamomile.circuit.frontend.composite_gate¶
Frontend interface for composite gates.
Overview¶
| Function | Description |
|---|---|
composite_gate | Decorator to create a CompositeGate from a qkernel function or as a stub. |
get_current_tracer | |
trace | Context manager to set the current tracer. |
| Class | Description |
|---|---|
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
CompositeGate | Base class for user-facing composite gate definitions. |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CompositeGateType | Registry of known composite gate types. |
DecompositionStrategy | Protocol for defining decomposition strategies. |
Qubit | |
ResourceMetadata | Resource estimation metadata for composite gates. |
Tracer | |
Value | A typed SSA value in the IR. |
Vector | 1-dimensional array type. |
Functions¶
composite_gate [source]¶
def composite_gate(
func: Callable | None = None,
*,
stub: bool = False,
name: str = '',
num_qubits: int | None = None,
num_controls: int = 0,
resource_metadata: ResourceMetadata | None = None,
gate_type: CompositeGateType = CompositeGateType.CUSTOM,
) -> _WrappedCompositeGate | _StubCompositeGate | Callable[[Callable], _WrappedCompositeGate | _StubCompositeGate]Decorator to create a CompositeGate from a qkernel function or as a stub.
Usage with qkernel (implementation provided):
composite_gate [source](name=“my_qft”)
qkernel [source]
def my_qft(q0: Qubit, q1: Qubit) -> tuple[Qubit, Qubit]:
q0 = h(q0)
q0, q1 = cp(q0, q1, pi/2)
q1 = h(q1)
return q0, q1
# Usage:
q0, q1 = my_qft(q0, q1)Usage as stub (no implementation, for resource estimation):
composite_gate [source](
stub=True, name=“oracle”, num_qubits=5,
resource_metadata=ResourceMetadata(query_complexity=100, t_gates=10),
)
def oracle():
pass
# Usage:
results = oracle(*qubits)
metadata = oracle.get_resource_metadata()Parameters:
| Name | Type | Description |
|---|---|---|
func | Callable | None | The qkernel function (when used without arguments) |
stub | bool | If True, create a stub gate with no implementation |
name | str | Name for the composite gate |
num_qubits | int | None | Number of target qubits (required for stub) |
num_controls | int | Number of control qubits (default: 0) |
resource_metadata | ResourceMetadata | None | ResourceMetadata for resource estimation (stub mode) |
gate_type | CompositeGateType | The type of composite gate (default: CUSTOM) |
Returns:
_WrappedCompositeGate | _StubCompositeGate | Callable[[Callable], _WrappedCompositeGate | _StubCompositeGate] — A CompositeGate instance that can be called like a gate function.
get_current_tracer [source]¶
def get_current_tracer() -> Tracertrace [source]¶
def trace(tracer: Tracer | None = None) -> Generator[Tracer, None, None]Context manager to set the current tracer.
Classes¶
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
CompositeGate [source]¶
class CompositeGate(abc.ABC)Base class for user-facing composite gate definitions.
Subclasses can define composite gates in two ways:
Using _decompose() (recommended for users): Define the gate decomposition using frontend syntax (same as
qkernel[source]).class QFT(CompositeGate): def __init__(self, num_qubits: int): self._num_qubits = num_qubits @property def num_target_qubits(self) -> int: return self._num_qubits def _decompose(self, qubits: Vector[Qubit]) -> Vector[Qubit]: # Use frontend syntax: qm.h(), qm.cp(), qm.range(), etc. n = self._num_qubits for j in qmc.range(n - 1, -1, -1): qubits[j] = qmc.h(qubits[j]) for k in qmc.range(j - 1, -1, -1): angle = math.pi / (2 ** (j - k)) qubits[j], qubits[k] = qmc.cp(qubits[j], qubits[k], angle) return qubits def _resources(self) -> ResourceMetadata: return ResourceMetadata(t_gates=0)Using get_implementation() (advanced): Return a pre-built Block directly.
Example usage:
# Factory function pattern
def qft(qubits: Vector[Qubit]) -> Vector[Qubit]:
n = _get_size(qubits)
return QFT(n)(qubits)
# Direct class usage
result = QFT(3)(*qubit_list)Attributes¶
custom_name: strgate_type: CompositeGateTypenum_control_qubits: int Number of control qubits (default: 0).num_target_qubits: int Number of target qubits this gate operates on.
Methods¶
build_decomposition¶
def build_decomposition(self, *qubits: Qubit = (), **params: Any = {}) -> Block | NoneBuild the decomposition circuit dynamically.
Override this method to provide a decomposition that depends on runtime arguments (e.g., QPE needs the unitary Block).
This method is called by InlinePass when inlining composite gates that have dynamic implementations.
Parameters:
| Name | Type | Description |
|---|---|---|
*qubits | Qubit | The qubits passed to the gate |
**params | Any | Additional parameters (e.g., unitary for QPE) |
Returns:
Block | None — Block containing the decomposition, or None if not available.
Example:
class QPE(CompositeGate):
def build_decomposition(self, *qubits, **params):
unitary = params.get("unitary")
# Build QPE circuit using the unitary
return self._build_qpe_impl(qubits, unitary)get_implementation¶
def get_implementation(self) -> Block | NoneGet the implementation Block, if any.
Return None for stub gates (used in resource estimation). Override in subclasses to provide implementation.
Note: If _decompose() is defined, it takes precedence over this method.
get_resource_metadata¶
def get_resource_metadata(self) -> ResourceMetadata | NoneGet resource estimation metadata.
Returns _resources() if defined, otherwise None. Override _resources() to provide resource hints.
get_resources_for_strategy¶
def get_resources_for_strategy(self, strategy_name: str | None = None) -> ResourceMetadata | NoneGet resource metadata for a specific strategy.
Parameters:
| Name | Type | Description |
|---|---|---|
strategy_name | str | None | Strategy to query, or None for default |
Returns:
ResourceMetadata | None — ResourceMetadata for the strategy, or None if not available
get_strategy¶
@classmethod
def get_strategy(cls, name: str | None = None) -> 'DecompositionStrategy | None'Get a registered decomposition strategy.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | None | Strategy name, or None for default strategy |
Returns:
'DecompositionStrategy | None' — DecompositionStrategy instance, or None if not found
list_strategies¶
@classmethod
def list_strategies(cls) -> list[str]List all registered strategy names.
Returns:
list[str] — List of strategy names
register_strategy¶
@classmethod
def register_strategy(cls, name: str, strategy: 'DecompositionStrategy') -> NoneRegister a decomposition strategy for this gate type.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Strategy identifier (e.g., “standard”, “approximate”) |
strategy | 'DecompositionStrategy' | DecompositionStrategy instance |
Example:
QFT.register_strategy("approximate", ApproximateQFTStrategy(k=3))set_default_strategy¶
@classmethod
def set_default_strategy(cls, name: str) -> NoneSet the default decomposition strategy.
Parameters:
| Name | Type | Description |
|---|---|---|
name | str | Strategy name to use as default |
Raises:
ValueError— If strategy is not registered
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
DecompositionStrategy [source]¶
class DecompositionStrategy(Protocol)Protocol for defining decomposition strategies.
A decomposition strategy provides:
A unique name for identification
A decompose method that performs the actual decomposition
Resource estimation for the decomposition
Strategies allow the same composite gate to have multiple implementations with different trade-offs (e.g., precision vs. gate count).
Attributes¶
name: str Unique identifier for this strategy.
Methods¶
decompose¶
def decompose(self, qubits: tuple['Qubit', ...]) -> tuple['Qubit', ...]Perform the decomposition.
Parameters:
| Name | Type | Description |
|---|---|---|
qubits | tuple['Qubit', ...] | Input qubits to decompose |
Returns:
tuple['Qubit', ...] — Output qubits after decomposition
resources¶
def resources(self, num_qubits: int) -> 'ResourceMetadata'Return resource estimates for this decomposition.
Parameters:
| Name | Type | Description |
|---|---|---|
num_qubits | int | Number of qubits the gate operates on |
Returns:
'ResourceMetadata' — ResourceMetadata with gate counts, depth estimates, etc.
Qubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
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
Tracer [source]¶
class TracerConstructor¶
def __init__(self, _operations: list[Operation] = list()) -> NoneAttributes¶
operations: list[Operation]
Methods¶
add_operation¶
def add_operation(self, op) -> NoneValue [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.
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
qamomile.circuit.frontend.constructors¶
Overview¶
| Function | Description |
|---|---|
bit | Create a Bit handle from a boolean/int literal or declare a named Bit parameter. |
float_ | Create a Float handle from a float literal or declare a named Float parameter. |
get_current_tracer | |
qubit | Create a new qubit and emit a QInitOperation. |
qubit_array | Create a new qubit array (vector/matrix/tensor) and emit QInitOperations. |
uint | Create a UInt handle from an integer literal or declare a named UInt parameter. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
QInitOperation | Initialize the qubit |
Value | A typed SSA value in the IR. |
Functions¶
bit [source]¶
def bit(arg: bool | str | int) -> BitCreate a Bit handle from a boolean/int literal or declare a named Bit parameter.
float_ [source]¶
def float_(arg: float | str) -> FloatCreate a Float handle from a float literal or declare a named Float parameter.
get_current_tracer [source]¶
def get_current_tracer() -> Tracerqubit [source]¶
def qubit(name: str) -> QubitCreate a new qubit and emit a QInitOperation.
qubit_array [source]¶
def qubit_array(
shape: UInt | int | tuple[UInt | int, ...],
name: str,
) -> Vector[Qubit] | Matrix[Qubit] | Tensor[Qubit]Create a new qubit array (vector/matrix/tensor) and emit QInitOperations.
uint [source]¶
def uint(arg: int | str) -> UIntCreate a UInt handle from an integer literal or declare a named UInt parameter.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]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
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.frontend.decomposition¶
Decomposition strategy framework for composite gates.
This module provides the infrastructure for defining multiple decomposition patterns for composite gates, enabling flexible gate synthesis strategies.
Example:
class StandardQFTStrategy:
@property
def name(self) -> str:
return "standard"
def decompose(self, qubits: tuple[Qubit, ...]) -> tuple[Qubit, ...]:
# Full precision QFT implementation
...
def resources(self, num_qubits: int) -> ResourceMetadata:
return ResourceMetadata(...)
class ApproximateQFTStrategy:
def __init__(self, truncation_depth: int = 3):
self._k = truncation_depth
@property
def name(self) -> str:
return f"approximate_k{self._k}"
def decompose(self, qubits: tuple[Qubit, ...]) -> tuple[Qubit, ...]:
# Truncated rotations QFT
...
# Register strategies
QFT.register_strategy("standard", StandardQFTStrategy())
QFT.register_strategy("approximate", ApproximateQFTStrategy(truncation_depth=3))Overview¶
| Function | Description |
|---|---|
get_global_registry | Get the global strategy registry. |
get_strategy | Get a strategy from the global registry. |
register_strategy | Register a strategy in the global registry. |
| Class | Description |
|---|---|
DecompositionConfig | Configuration for decomposition strategy selection. |
DecompositionStrategy | Protocol for defining decomposition strategies. |
Qubit | |
ResourceMetadata | Resource estimation metadata for composite gates. |
StrategyRegistry | Registry for managing decomposition strategies. |
Functions¶
get_global_registry [source]¶
def get_global_registry() -> StrategyRegistryGet the global strategy registry.
Returns:
StrategyRegistry — The global StrategyRegistry instance
get_strategy [source]¶
def get_strategy(
gate_name: str,
strategy_name: str | None = None,
) -> DecompositionStrategy | NoneGet a strategy from the global registry.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_name | str | The gate name |
strategy_name | str | None | The strategy name (uses “standard” if None) |
Returns:
DecompositionStrategy | None — The strategy instance, or None if not found
register_strategy [source]¶
def register_strategy(gate_name: str, strategy_name: str, strategy: DecompositionStrategy) -> NoneRegister a strategy in the global registry.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_name | str | The gate name (e.g., “qft”, “iqft”) |
strategy_name | str | The strategy name (e.g., “standard”, “approximate”) |
strategy | DecompositionStrategy | The strategy instance |
Classes¶
DecompositionConfig [source]¶
class DecompositionConfigConfiguration for decomposition strategy selection.
This configuration is passed to the transpiler to control which decomposition strategies are used for composite gates.
Constructor¶
def __init__(
self,
strategy_overrides: dict[str, str] = dict(),
strategy_params: dict[str, dict[str, Any]] = dict(),
default_strategy: str = 'standard',
) -> NoneAttributes¶
default_strategy: strstrategy_overrides: dict[str, str]strategy_params: dict[str, dict[str, Any]]
Methods¶
get_strategy_for_gate¶
def get_strategy_for_gate(self, gate_name: str) -> strGet the strategy name for a specific gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_name | str | The gate name (e.g., “qft”, “iqft”) |
Returns:
str — Strategy name to use
get_strategy_params¶
def get_strategy_params(self, strategy_name: str) -> dict[str, Any]Get parameters for a specific strategy.
Parameters:
| Name | Type | Description |
|---|---|---|
strategy_name | str | The strategy name |
Returns:
dict[str, Any] — Dictionary of parameters
DecompositionStrategy [source]¶
class DecompositionStrategy(Protocol)Protocol for defining decomposition strategies.
A decomposition strategy provides:
A unique name for identification
A decompose method that performs the actual decomposition
Resource estimation for the decomposition
Strategies allow the same composite gate to have multiple implementations with different trade-offs (e.g., precision vs. gate count).
Attributes¶
name: str Unique identifier for this strategy.
Methods¶
decompose¶
def decompose(self, qubits: tuple['Qubit', ...]) -> tuple['Qubit', ...]Perform the decomposition.
Parameters:
| Name | Type | Description |
|---|---|---|
qubits | tuple['Qubit', ...] | Input qubits to decompose |
Returns:
tuple['Qubit', ...] — Output qubits after decomposition
resources¶
def resources(self, num_qubits: int) -> 'ResourceMetadata'Return resource estimates for this decomposition.
Parameters:
| Name | Type | Description |
|---|---|---|
num_qubits | int | Number of qubits the gate operates on |
Returns:
'ResourceMetadata' — ResourceMetadata with gate counts, depth estimates, etc.
Qubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
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
StrategyRegistry [source]¶
class StrategyRegistryRegistry for managing decomposition strategies.
This class provides a centralized registry for strategies, allowing them to be looked up by name across the transpiler pipeline.
Example:
registry = StrategyRegistry()
registry.register("qft", "standard", StandardQFTStrategy())
registry.register("qft", "approximate", ApproximateQFTStrategy())
strategy = registry.get("qft", "standard")Constructor¶
def __init__(self) -> NoneInitialize empty registry.
Methods¶
get¶
def get(
self,
gate_name: str,
strategy_name: str | None = None,
) -> DecompositionStrategy | NoneGet a strategy for a gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_name | str | The gate name |
strategy_name | str | None | The strategy name (uses “standard” if None) |
Returns:
DecompositionStrategy | None — The strategy instance, or None if not found
list_gates¶
def list_gates(self) -> list[str]List all gates with registered strategies.
Returns:
list[str] — List of gate names
list_strategies¶
def list_strategies(self, gate_name: str) -> list[str]List available strategies for a gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_name | str | The gate name |
Returns:
list[str] — List of strategy names
register¶
def register(
self,
gate_name: str,
strategy_name: str,
strategy: DecompositionStrategy,
) -> NoneRegister a strategy for a gate.
Parameters:
| Name | Type | Description |
|---|---|---|
gate_name | str | The gate name (e.g., “qft”, “iqft”) |
strategy_name | str | The strategy name (e.g., “standard”, “approximate”) |
strategy | DecompositionStrategy | The strategy instance |
qamomile.circuit.frontend.func_to_block¶
Overview¶
| Function | Description |
|---|---|
create_dummy_handle | Create a dummy Handle instance based on ValueType. |
create_dummy_input | Create a dummy input based on parameter type annotation. |
func_to_block | Convert a function to a hierarchical Block. |
get_current_tracer | |
handle_type_map | Map Handle type to ValueType. |
is_array_type | Check if type is a Vector, Matrix, or Tensor subclass. |
is_dict_type | Check if type is a Dict handle type. |
is_tuple_type | Check if type is a Tuple handle type. |
trace | Context manager to set the current tracer. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
Bit | |
BitType | Type representing a classical bit. |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
Dict | Dict handle for qkernel functions. |
DictType | Type representing a dictionary mapping keys to values. |
DictValue | A dictionary value stored as stable ordered entries. |
Float | Floating-point handle with arithmetic operations. |
FloatType | Type representing a floating-point number. |
Observable | Handle representing a Hamiltonian observable parameter. |
ObservableType | Type representing a Hamiltonian observable parameter. |
QInitOperation | Initialize the qubit |
Qubit | |
ReturnOperation | Explicit return operation marking the end of a block with return values. |
Tracer | |
Tuple | Tuple handle for qkernel functions. |
TupleType | Type representing a tuple of values. |
TupleValue | A tuple of IR values for structured data. |
UInt | Unsigned integer handle with arithmetic operations. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
ValueType | Base class for all value types in the IR. |
Constants¶
TYPE_MAPPING:dict[Any, Any]={int: UIntType, float: FloatType, bool: BitType}
Functions¶
create_dummy_handle [source]¶
def create_dummy_handle(value_type: ValueType, name: str = 'dummy', emit_init: bool = True) -> HandleCreate a dummy Handle instance based on ValueType.
Parameters:
| Name | Type | Description |
|---|---|---|
value_type | ValueType | The IR type for the value. |
name | str | Name for the value. |
emit_init | bool | If True, emit QInitOperation for qubit types (requires active tracer). |
Used for creating input parameters during tracing.
create_dummy_input [source]¶
def create_dummy_input(param_type: Any, name: str = 'param', emit_init: bool = True) -> HandleCreate a dummy input based on parameter type annotation.
Parameters:
| Name | Type | Description |
|---|---|---|
param_type | typing.Any | The type annotation for the parameter. |
name | str | Name for the value. |
emit_init | bool | If True, emit QInitOperation for qubit arrays (default: True). Set to False when creating a nested Block’s internal dummy inputs. |
This creates input Handles for function parameters.
func_to_block [source]¶
def func_to_block(func: Callable) -> BlockConvert a function to a hierarchical Block.
Example:
def my_func(a: UInt, b: UInt) -> tuple[UInt]:
c = a + b
return (c, )
block = func_to_block(my_func)get_current_tracer [source]¶
def get_current_tracer() -> Tracerhandle_type_map [source]¶
def handle_type_map(handle_type: type[Handle] | type) -> ValueTypeMap Handle type to ValueType.
is_array_type [source]¶
def is_array_type(t: Any) -> boolCheck if type is a Vector, Matrix, or Tensor subclass.
is_dict_type [source]¶
def is_dict_type(t: Any) -> boolCheck if type is a Dict handle type.
is_tuple_type [source]¶
def is_tuple_type(t: Any) -> boolCheck if type is a Tuple handle type.
trace [source]¶
def trace(tracer: Tracer | None = None) -> Generator[Tracer, None, None]Context manager to set the current tracer.
Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]Bit [source]¶
class Bit(Handle)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: bool = False,
) -> NoneAttributes¶
init_value: bool
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
Dict [source]¶
class Dict(Handle, Generic[K, V])Dict handle for qkernel functions.
Represents a dictionary mapping keys to values, commonly used for Ising coefficients like {(i, j): Jij}.
Example:
@qmc.qkernel
def ising_cost(
q: qmc.Vector[qmc.Qubit],
ising: qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float],
gamma: qmc.Float,
) -> qmc.Vector[qmc.Qubit]:
for (i, j), Jij in qmc.items(ising):
q[i], q[j] = qmc.rzz(q[i], q[j], gamma * Jij)
return qConstructor¶
def __init__(
self,
value: DictValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_entries: list[tuple[Handle, Handle]] = list(),
_size: UInt | None = None,
_key_type: type | None = None,
) -> NoneAttributes¶
size: UInt Return the number of entries as a UInt handle.value: DictValue
Methods¶
items¶
def items(self) -> DictItemsIterator[K, V]Return an iterator over (key, value) pairs.
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) -> DictValueFloat [source]¶
class Float(ArithmeticMixin, Handle)Floating-point handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: float = 0.0,
) -> NoneAttributes¶
init_value: float
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
Observable [source]¶
class Observable(Handle)Handle 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:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1) + 0.5 * qm_o.X(0)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
# Use Hamiltonian from bindings
return qm.expval(q, H)
# Pass via bindings
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneObservableType [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) -> NoneQInitOperation [source]¶
class QInitOperation(Operation)Initialize the qubit
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
Qubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
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.
Tracer [source]¶
class TracerConstructor¶
def __init__(self, _operations: list[Operation] = list()) -> NoneAttributes¶
operations: list[Operation]
Methods¶
add_operation¶
def add_operation(self, op) -> NoneTuple [source]¶
class Tuple(Handle, Generic[K, V])Tuple handle for qkernel functions.
Represents a tuple of values, commonly used for multi-index keys like (i, j) in Ising models.
Example:
@qmc.qkernel
def my_kernel(idx: qmc.Tuple[qmc.UInt, qmc.UInt]) -> qmc.UInt:
i, j = idx
return i + jConstructor¶
def __init__(
self,
value: TupleValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_elements: tuple[Handle, ...] = tuple(),
) -> NoneAttributes¶
value: TupleValue
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) -> TupleValueUInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
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.
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.frontend.handle¶
Overview¶
| Function | Description |
|---|---|
get_size | Return the size of a Vector handle as a Python integer. |
| Class | Description |
|---|---|
Bit | |
Dict | Dict handle for qkernel functions. |
Float | Floating-point handle with arithmetic operations. |
Handle | |
Matrix | 2-dimensional array type. |
Observable | Handle representing a Hamiltonian observable parameter. |
QFixed | |
Qubit | |
Tensor | N-dimensional array type (3 or more dimensions). |
Tuple | Tuple handle for qkernel functions. |
UInt | Unsigned integer handle with arithmetic operations. |
Vector | 1-dimensional array type. |
Functions¶
get_size [source]¶
def get_size(arr: Vector[_H]) -> intReturn the size of a Vector handle as a Python integer.
Resolves the leading axis of arr.shape through two forms a
Vector shape entry can take:
A plain Python
int(built-in bound shape; this is what you get fromqmc.qubit_array(N, ...)for literalN).A
UInthandle whose underlyingValuecarries a compile-time constant (set byuint(literal),_create_bound_input, or partial evaluation).
A UInt handle whose underlying Value is not a constant is
treated as an unresolved symbolic dimension and raises
ValueError even when the handle has the dataclass-default
init_value=0. Falling back to init_value for that case
would silently turn a runtime-symbolic Vector[Float] parameter
into a “size 0” array, hiding programming errors. Callers that
need to handle symbolic shapes (e.g., to gracefully no-op when the
size is unknown) must catch the ValueError themselves.
Parameters:
| Name | Type | Description |
|---|---|---|
arr | Vector[Handle] | Vector handle whose first axis size is requested. |
Returns:
int — The first-axis size as a plain Python int.
Raises:
ValueError— If the shape cannot be resolved to a concrete integer — e.g., the Vector is a runtime-parametric handle without compile-time bindings, or carries aUIntdimension whose underlyingValuehas not been promoted to a constant.
Classes¶
Bit [source]¶
class Bit(Handle)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: bool = False,
) -> NoneAttributes¶
init_value: bool
Dict [source]¶
class Dict(Handle, Generic[K, V])Dict handle for qkernel functions.
Represents a dictionary mapping keys to values, commonly used for Ising coefficients like {(i, j): Jij}.
Example:
@qmc.qkernel
def ising_cost(
q: qmc.Vector[qmc.Qubit],
ising: qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float],
gamma: qmc.Float,
) -> qmc.Vector[qmc.Qubit]:
for (i, j), Jij in qmc.items(ising):
q[i], q[j] = qmc.rzz(q[i], q[j], gamma * Jij)
return qConstructor¶
def __init__(
self,
value: DictValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_entries: list[tuple[Handle, Handle]] = list(),
_size: UInt | None = None,
_key_type: type | None = None,
) -> NoneAttributes¶
size: UInt Return the number of entries as a UInt handle.value: DictValue
Methods¶
items¶
def items(self) -> DictItemsIterator[K, V]Return an iterator over (key, value) pairs.
Float [source]¶
class Float(ArithmeticMixin, Handle)Floating-point handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: float = 0.0,
) -> NoneAttributes¶
init_value: float
Handle [source]¶
class Handle(abc.ABC)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
id: strindices: tuple[‘UInt’, ...]name: str | Noneparent: ‘ArrayBase | None’value: Value
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfMark this handle as consumed and return a fresh handle.
Parameters:
| Name | Type | Description |
|---|---|---|
operation_name | str | Name of the operation consuming this handle, used for error messages. |
Returns:
typing.Self — A new handle pointing to the same underlying value.
Raises:
QubitConsumedError— If this handle was already consumed and is a quantum type.
Matrix [source]¶
class Matrix(ArrayBase[T])2-dimensional array type.
Example:
import qamomile as qm
# Create a 3x4 matrix of qubits
matrix: qm.Matrix[qm.Qubit] = qm.Matrix(shape=(3, 4))
# Access elements (always requires 2 indices)
q = matrix[0, 1]
q = qm.h(q)
matrix[0, 1] = qConstructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt, int | UInt] = (0, 0),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
Observable [source]¶
class Observable(Handle)Handle 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:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1) + 0.5 * qm_o.X(0)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
# Use Hamiltonian from bindings
return qm.expval(q, H)
# Pass via bindings
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneQFixed [source]¶
class QFixed(Handle)Constructor¶
def __init__(
self,
value: Value[QFixedType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QFixedType]
Qubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
Tensor [source]¶
class Tensor(ArrayBase[T])N-dimensional array type (3 or more dimensions).
Example:
import qamomile as qm
# Create a 2x3x4 tensor of qubits
tensor: qm.Tensor[qm.Qubit] = qm.Tensor(shape=(2, 3, 4))
# Access elements (requires all indices)
q = tensor[0, 1, 2]
q = qm.h(q)
tensor[0, 1, 2] = qConstructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt, ...] = tuple(),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
Tuple [source]¶
class Tuple(Handle, Generic[K, V])Tuple handle for qkernel functions.
Represents a tuple of values, commonly used for multi-index keys like (i, j) in Ising models.
Example:
@qmc.qkernel
def my_kernel(idx: qmc.Tuple[qmc.UInt, qmc.UInt]) -> qmc.UInt:
i, j = idx
return i + jConstructor¶
def __init__(
self,
value: TupleValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_elements: tuple[Handle, ...] = tuple(),
) -> NoneAttributes¶
value: TupleValue
UInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
qamomile.circuit.frontend.handle.array¶
Overview¶
| Function | Description |
|---|---|
get_current_tracer |
| Class | Description |
|---|---|
AffineTypeError | Base class for affine type violations. |
ArrayBase | Base class for array types (Vector, Matrix, Tensor). |
ArrayValue | An array of typed IR values. |
Bit | |
BitType | Type representing a classical bit. |
CInitOperation | Initialize the classical values (const, arguments etc) |
Float | Floating-point handle with arithmetic operations. |
FloatType | Type representing a floating-point number. |
Handle | |
Matrix | 2-dimensional array type. |
QInitOperation | Initialize the qubit |
Qubit | |
QubitConsumedError | Qubit handle used after being consumed by a previous operation. |
QubitType | Type representing a quantum bit (qubit). |
Tensor | N-dimensional array type (3 or more dimensions). |
UInt | Unsigned integer handle with arithmetic operations. |
UIntType | Type representing an unsigned integer. |
UnreturnedBorrowError | Borrowed array element not returned before array use. |
Value | A typed SSA value in the IR. |
Vector | 1-dimensional array type. |
Functions¶
get_current_tracer [source]¶
def get_current_tracer() -> TracerClasses¶
AffineTypeError [source]¶
class AffineTypeError(QamomileCompileError)Base class for affine type violations.
Affine types enforce that quantum resources (qubits) are used at most once. This prevents common errors such as reusing a consumed qubit or aliasing.
Constructor¶
def __init__(
self,
message: str,
handle_name: str | None = None,
operation_name: str | None = None,
first_use_location: str | None = None,
)Attributes¶
first_use_locationhandle_nameoperation_name
ArrayBase [source]¶
class ArrayBase(Handle, Generic[T])Base class for array types (Vector, Matrix, Tensor).
Provides common functionality for array indexing and element access.
Constructor¶
def __init__(
self,
value: ArrayValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt, ...] = tuple(),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
element_type: Type[T]shape: tuple[int | UInt, ...] Return the shape of the array.value: ArrayValue
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfConsume the array, enforcing borrow-return contract for quantum arrays.
For quantum arrays, all borrowed elements must be returned before the array can be consumed. This ensures that no unreturned borrows are silently discarded by operations like qkernel calls or controlled gates.
create¶
@classmethod
def create(
cls,
shape: tuple[int | UInt, ...],
name: str,
el_type: Type[T],
) -> 'ArrayBase[T]'Create an ArrayValue for the given shape and name.
validate_all_returned¶
def validate_all_returned(self) -> NoneValidate all borrowed elements have been returned.
This method is useful for ensuring that all borrowed elements have been properly written back before using the array in operations that require the entire array.
Raises:
UnreturnedBorrowError— If any elements are still borrowed.
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]Bit [source]¶
class Bit(Handle)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: bool = False,
) -> NoneAttributes¶
init_value: bool
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
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
Float [source]¶
class Float(ArithmeticMixin, Handle)Floating-point handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: float = 0.0,
) -> NoneAttributes¶
init_value: float
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
Handle [source]¶
class Handle(abc.ABC)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
id: strindices: tuple[‘UInt’, ...]name: str | Noneparent: ‘ArrayBase | None’value: Value
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfMark this handle as consumed and return a fresh handle.
Parameters:
| Name | Type | Description |
|---|---|---|
operation_name | str | Name of the operation consuming this handle, used for error messages. |
Returns:
typing.Self — A new handle pointing to the same underlying value.
Raises:
QubitConsumedError— If this handle was already consumed and is a quantum type.
Matrix [source]¶
class Matrix(ArrayBase[T])2-dimensional array type.
Example:
import qamomile as qm
# Create a 3x4 matrix of qubits
matrix: qm.Matrix[qm.Qubit] = qm.Matrix(shape=(3, 4))
# Access elements (always requires 2 indices)
q = matrix[0, 1]
q = qm.h(q)
matrix[0, 1] = qConstructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt, int | UInt] = (0, 0),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
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
Qubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
QubitConsumedError [source]¶
class QubitConsumedError(AffineTypeError)Qubit handle used after being consumed by a previous operation.
Each qubit handle can only be used once. After a gate operation, you must reassign the result to use the new handle.
Example of incorrect code:
q1 = qm.h(q) q2 = qm.x(q) # ERROR: q was already consumed by h()
Correct code:
q = qm.h(q) # Reassign to capture new handle q = qm.x(q) # Use the reassigned handle
QubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
Tensor [source]¶
class Tensor(ArrayBase[T])N-dimensional array type (3 or more dimensions).
Example:
import qamomile as qm
# Create a 2x3x4 tensor of qubits
tensor: qm.Tensor[qm.Qubit] = qm.Tensor(shape=(2, 3, 4))
# Access elements (requires all indices)
q = tensor[0, 1, 2]
q = qm.h(q)
tensor[0, 1, 2] = qConstructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt, ...] = tuple(),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
UInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
UIntType [source]¶
class UIntType(ClassicalTypeMixin, ValueType)Type representing an unsigned integer.
UnreturnedBorrowError [source]¶
class UnreturnedBorrowError(AffineTypeError)Borrowed array element not returned before array use.
When you borrow an element from a qubit array, you must return it (write it back) before using other elements or the array itself.
Example of incorrect code:
q0 = qubits[0] q0 = qm.h(q0) q1 = qubits[1] # ERROR: q0 not returned yet
Correct code:
q0 = qubits[0] q0 = qm.h(q0) qubits[0] = q0 # Return the borrowed element q1 = qubits[1] # Now safe to borrow another
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.
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
qamomile.circuit.frontend.handle.containers¶
Container types for qkernel: Tuple and Dict handles.
Overview¶
| Class | Description |
|---|---|
Dict | Dict handle for qkernel functions. |
DictItemsIterator | Iterator for Dict.items() that yields (key, value) pairs. |
DictValue | A dictionary value stored as stable ordered entries. |
Handle | |
Tuple | Tuple handle for qkernel functions. |
TupleValue | A tuple of IR values for structured data. |
UInt | Unsigned integer handle with arithmetic operations. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
Classes¶
Dict [source]¶
class Dict(Handle, Generic[K, V])Dict handle for qkernel functions.
Represents a dictionary mapping keys to values, commonly used for Ising coefficients like {(i, j): Jij}.
Example:
@qmc.qkernel
def ising_cost(
q: qmc.Vector[qmc.Qubit],
ising: qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float],
gamma: qmc.Float,
) -> qmc.Vector[qmc.Qubit]:
for (i, j), Jij in qmc.items(ising):
q[i], q[j] = qmc.rzz(q[i], q[j], gamma * Jij)
return qConstructor¶
def __init__(
self,
value: DictValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_entries: list[tuple[Handle, Handle]] = list(),
_size: UInt | None = None,
_key_type: type | None = None,
) -> NoneAttributes¶
size: UInt Return the number of entries as a UInt handle.value: DictValue
Methods¶
items¶
def items(self) -> DictItemsIterator[K, V]Return an iterator over (key, value) pairs.
DictItemsIterator [source]¶
class DictItemsIterator(Generic[K, V])Iterator for Dict.items() that yields (key, value) pairs.
This is used internally for iterating over Dict entries in qkernel.
Constructor¶
def __init__(self, dict_handle: 'Dict[K, V]', _index: int = 0) -> NoneAttributes¶
dict_handle: ‘Dict[K, V]’
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) -> DictValueHandle [source]¶
class Handle(abc.ABC)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
id: strindices: tuple[‘UInt’, ...]name: str | Noneparent: ‘ArrayBase | None’value: Value
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfMark this handle as consumed and return a fresh handle.
Parameters:
| Name | Type | Description |
|---|---|---|
operation_name | str | Name of the operation consuming this handle, used for error messages. |
Returns:
typing.Self — A new handle pointing to the same underlying value.
Raises:
QubitConsumedError— If this handle was already consumed and is a quantum type.
Tuple [source]¶
class Tuple(Handle, Generic[K, V])Tuple handle for qkernel functions.
Represents a tuple of values, commonly used for multi-index keys like (i, j) in Ising models.
Example:
@qmc.qkernel
def my_kernel(idx: qmc.Tuple[qmc.UInt, qmc.UInt]) -> qmc.UInt:
i, j = idx
return i + jConstructor¶
def __init__(
self,
value: TupleValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_elements: tuple[Handle, ...] = tuple(),
) -> NoneAttributes¶
value: TupleValue
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) -> TupleValueUInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
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.
qamomile.circuit.frontend.handle.hamiltonian¶
Observable handle for Hamiltonian parameters.
This module provides the Observable handle class that represents a reference to a Hamiltonian observable provided via bindings during transpilation. Unlike HamiltonianExpr in previous versions, this is a pure parameter handle with no arithmetic operations.
Overview¶
| Class | Description |
|---|---|
Handle | |
Observable | Handle representing a Hamiltonian observable parameter. |
Classes¶
Handle [source]¶
class Handle(abc.ABC)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
id: strindices: tuple[‘UInt’, ...]name: str | Noneparent: ‘ArrayBase | None’value: Value
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfMark this handle as consumed and return a fresh handle.
Parameters:
| Name | Type | Description |
|---|---|---|
operation_name | str | Name of the operation consuming this handle, used for error messages. |
Returns:
typing.Self — A new handle pointing to the same underlying value.
Raises:
QubitConsumedError— If this handle was already consumed and is a quantum type.
Observable [source]¶
class Observable(Handle)Handle 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:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1) + 0.5 * qm_o.X(0)
@qm.qkernel
def vqe(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
# Use Hamiltonian from bindings
return qm.expval(q, H)
# Pass via bindings
executable = transpiler.transpile(vqe, bindings={"H": H})Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> Noneqamomile.circuit.frontend.handle.handle¶
Overview¶
| Function | Description |
|---|---|
get_current_tracer |
| Class | Description |
|---|---|
ArithmeticMixin | Mixin providing arithmetic operations for numeric Handle types. |
ArrayBase | Base class for array types (Vector, Matrix, Tensor). |
BinOp | Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW). |
BinOpKind | |
CompOp | Comparison operation (EQ, NEQ, LT, LE, GT, GE). |
CompOpKind | |
CondOp | Conditional logical operation (AND, OR). |
CondOpKind | |
Handle | |
NotOp | |
QubitConsumedError | Qubit handle used after being consumed by a previous operation. |
UInt | Unsigned integer handle with arithmetic operations. |
Value | A typed SSA value in the IR. |
Functions¶
get_current_tracer [source]¶
def get_current_tracer() -> TracerClasses¶
ArithmeticMixin [source]¶
class ArithmeticMixinMixin providing arithmetic operations for numeric Handle types.
Requires:
value: Value attribute
_make_result(): Method to create result Handle of same type
_coerce(): Method to convert Python literals to Handle
Attributes¶
value: Value
ArrayBase [source]¶
class ArrayBase(Handle, Generic[T])Base class for array types (Vector, Matrix, Tensor).
Provides common functionality for array indexing and element access.
Constructor¶
def __init__(
self,
value: ArrayValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt, ...] = tuple(),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
element_type: Type[T]shape: tuple[int | UInt, ...] Return the shape of the array.value: ArrayValue
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfConsume the array, enforcing borrow-return contract for quantum arrays.
For quantum arrays, all borrowed elements must be returned before the array can be consumed. This ensures that no unreturned borrows are silently discarded by operations like qkernel calls or controlled gates.
create¶
@classmethod
def create(
cls,
shape: tuple[int | UInt, ...],
name: str,
el_type: Type[T],
) -> 'ArrayBase[T]'Create an ArrayValue for the given shape and name.
validate_all_returned¶
def validate_all_returned(self) -> NoneValidate all borrowed elements have been returned.
This method is useful for ensuring that all borrowed elements have been properly written back before using the array in operations that require the entire array.
Raises:
UnreturnedBorrowError— If any elements are still borrowed.
BinOp [source]¶
class BinOp(BinaryOperationBase)Binary arithmetic operation (ADD, SUB, MUL, DIV, FLOORDIV, POW).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: BinOpKind | None = None,
) -> NoneAttributes¶
kind: BinOpKind | Noneoperation_kind: OperationKindsignature: Signature
BinOpKind [source]¶
class BinOpKind(enum.Enum)Attributes¶
ADDDIVFLOORDIVMULPOWSUB
CompOp [source]¶
class CompOp(BinaryOperationBase)Comparison operation (EQ, NEQ, LT, LE, GT, GE).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CompOpKind | None = None,
) -> NoneAttributes¶
kind: CompOpKind | Noneoperation_kind: OperationKindsignature: Signature
CompOpKind [source]¶
class CompOpKind(enum.Enum)Attributes¶
EQGEGTLELTNEQ
CondOp [source]¶
class CondOp(BinaryOperationBase)Conditional logical operation (AND, OR).
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
kind: CondOpKind | None = None,
) -> NoneAttributes¶
kind: CondOpKind | Noneoperation_kind: OperationKindsignature: Signature
CondOpKind [source]¶
class CondOpKind(enum.Enum)Attributes¶
ANDOR
Handle [source]¶
class Handle(abc.ABC)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
id: strindices: tuple[‘UInt’, ...]name: str | Noneparent: ‘ArrayBase | None’value: Value
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfMark this handle as consumed and return a fresh handle.
Parameters:
| Name | Type | Description |
|---|---|---|
operation_name | str | Name of the operation consuming this handle, used for error messages. |
Returns:
typing.Self — A new handle pointing to the same underlying value.
Raises:
QubitConsumedError— If this handle was already consumed and is a quantum type.
NotOp [source]¶
class NotOp(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
input: Valueoperation_kind: OperationKindoutput: Valuesignature: Signature
QubitConsumedError [source]¶
class QubitConsumedError(AffineTypeError)Qubit handle used after being consumed by a previous operation.
Each qubit handle can only be used once. After a gate operation, you must reassign the result to use the new handle.
Example of incorrect code:
q1 = qm.h(q) q2 = qm.x(q) # ERROR: q was already consumed by h()
Correct code:
q = qm.h(q) # Reassign to capture new handle q = qm.x(q) # Use the reassigned handle
UInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
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.frontend.handle.primitives¶
Overview¶
| Class | Description |
|---|---|
ArithmeticMixin | Mixin providing arithmetic operations for numeric Handle types. |
BinOpKind | |
Bit | |
BitType | Type representing a classical bit. |
CompOpKind | |
CondOpKind | |
Float | Floating-point handle with arithmetic operations. |
FloatType | Type representing a floating-point number. |
Handle | |
QFixed | |
Qubit | |
QubitType | Type representing a quantum bit (qubit). |
UInt | Unsigned integer handle with arithmetic operations. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
Classes¶
ArithmeticMixin [source]¶
class ArithmeticMixinMixin providing arithmetic operations for numeric Handle types.
Requires:
value: Value attribute
_make_result(): Method to create result Handle of same type
_coerce(): Method to convert Python literals to Handle
Attributes¶
value: Value
BinOpKind [source]¶
class BinOpKind(enum.Enum)Attributes¶
ADDDIVFLOORDIVMULPOWSUB
Bit [source]¶
class Bit(Handle)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: bool = False,
) -> NoneAttributes¶
init_value: bool
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
CompOpKind [source]¶
class CompOpKind(enum.Enum)Attributes¶
EQGEGTLELTNEQ
CondOpKind [source]¶
class CondOpKind(enum.Enum)Attributes¶
ANDOR
Float [source]¶
class Float(ArithmeticMixin, Handle)Floating-point handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: float = 0.0,
) -> NoneAttributes¶
init_value: float
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
Handle [source]¶
class Handle(abc.ABC)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
id: strindices: tuple[‘UInt’, ...]name: str | Noneparent: ‘ArrayBase | None’value: Value
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfMark this handle as consumed and return a fresh handle.
Parameters:
| Name | Type | Description |
|---|---|---|
operation_name | str | Name of the operation consuming this handle, used for error messages. |
Returns:
typing.Self — A new handle pointing to the same underlying value.
Raises:
QubitConsumedError— If this handle was already consumed and is a quantum type.
QFixed [source]¶
class QFixed(Handle)Constructor¶
def __init__(
self,
value: Value[QFixedType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QFixedType]
Qubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
QubitType [source]¶
class QubitType(QuantumTypeMixin, ValueType)Type representing a quantum bit (qubit).
UInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
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.
qamomile.circuit.frontend.handle.utils¶
Utility helpers for handle types.
Overview¶
| Function | Description |
|---|---|
get_size | Return the size of a Vector handle as a Python integer. |
Functions¶
get_size [source]¶
def get_size(arr: Vector[_H]) -> intReturn the size of a Vector handle as a Python integer.
Resolves the leading axis of arr.shape through two forms a
Vector shape entry can take:
A plain Python
int(built-in bound shape; this is what you get fromqmc.qubit_array(N, ...)for literalN).A
UInthandle whose underlyingValuecarries a compile-time constant (set byuint(literal),_create_bound_input, or partial evaluation).
A UInt handle whose underlying Value is not a constant is
treated as an unresolved symbolic dimension and raises
ValueError even when the handle has the dataclass-default
init_value=0. Falling back to init_value for that case
would silently turn a runtime-symbolic Vector[Float] parameter
into a “size 0” array, hiding programming errors. Callers that
need to handle symbolic shapes (e.g., to gracefully no-op when the
size is unknown) must catch the ValueError themselves.
Parameters:
| Name | Type | Description |
|---|---|---|
arr | Vector[Handle] | Vector handle whose first axis size is requested. |
Returns:
int — The first-axis size as a plain Python int.
Raises:
ValueError— If the shape cannot be resolved to a concrete integer — e.g., the Vector is a runtime-parametric handle without compile-time bindings, or carries aUIntdimension whose underlyingValuehas not been promoted to a constant.
Classes¶
Handle [source]¶
class Handle(abc.ABC)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
id: strindices: tuple[‘UInt’, ...]name: str | Noneparent: ‘ArrayBase | None’value: Value
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfMark this handle as consumed and return a fresh handle.
Parameters:
| Name | Type | Description |
|---|---|---|
operation_name | str | Name of the operation consuming this handle, used for error messages. |
Returns:
typing.Self — A new handle pointing to the same underlying value.
Raises:
QubitConsumedError— If this handle was already consumed and is a quantum type.
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
qamomile.circuit.frontend.operation¶
qamomile.circuit.frontend.operation.cast¶
Cast operation for type conversions over the same quantum resources.
Overview¶
| Function | Description |
|---|---|
cast | Cast a quantum value to a different type without allocating new qubits. |
get_current_tracer |
| Class | Description |
|---|---|
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
QFixed | |
QFixedType | Quantum fixed-point type. |
Qubit | |
Value | A typed SSA value in the IR. |
Vector | 1-dimensional array type. |
Functions¶
cast [source]¶
def cast(source: Vector[Qubit], target_type: type, *, int_bits: int = 0) -> QFixedCast a quantum value to a different type without allocating new qubits.
The cast performs a move: the source handle is consumed and cannot be reused after the cast. The returned handle references the same physical qubits.
Parameters:
| Name | Type | Description |
|---|---|---|
source | Vector[Qubit] | The value to cast (currently supports Vector[Qubit]) |
target_type | type | The target type class (currently supports QFixed) |
int_bits | int | For QFixed, number of integer bits (default: 0 = all fractional) |
Returns:
QFixed — A new handle of the target type referencing the same qubits.
Example:
@qmc.qkernel
def my_circuit():
phase_register = qmc.qubit_array(5, name="phase")
# ... apply some operations ...
# Cast the qubit array to QFixed for measurement
phase_qfixed = qmc.cast(phase_register, qmc.QFixed, int_bits=0)
phase_value = qmc.measure(phase_qfixed)
return phase_valueRaises:
TypeError— If the source type or target type is not supportedValueError— If int_bits is negative or larger than the number of qubits
get_current_tracer [source]¶
def get_current_tracer() -> TracerClasses¶
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
QFixed [source]¶
class QFixed(Handle)Constructor¶
def __init__(
self,
value: Value[QFixedType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QFixedType]
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) -> strQubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
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.
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
qamomile.circuit.frontend.operation.control_flow¶
Overview¶
| Function | Description |
|---|---|
emit_if | Builder function for if-else conditional with Phi function merging. |
for_items | Builder function to create a for-items loop in Qamomile frontend. |
for_loop | Builder function to create a for loop in Qamomile frontend. |
get_current_tracer | |
is_array_type | Check if type is a Vector, Matrix, or Tensor subclass. |
items | Iterate over dictionary key-value pairs. |
range | Symbolic range for use in qkernel for-loops. |
trace | Context manager to set the current tracer. |
while_loop | Create a while loop whose condition is a measurement result. |
| Class | Description |
|---|---|
ArrayBase | Base class for array types (Vector, Matrix, Tensor). |
ArrayValue | An array of typed IR values. |
Bit | |
BitType | Type representing a classical bit. |
Dict | Dict handle for qkernel functions. |
DictItemsIterator | Iterator for Dict.items() that yields (key, value) pairs. |
Float | Floating-point handle with arithmetic operations. |
FloatType | Type representing a floating-point number. |
ForItemsOperation | Represents iteration over dict/iterable items. |
ForOperation | Represents a for loop operation. |
IfOperation | Represents an if-else conditional operation. |
PhiOp | SSA Phi function: merge point after conditional branch. |
Qubit | |
Tracer | |
UInt | Unsigned integer handle with arithmetic operations. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
Vector | 1-dimensional array type. |
WhileLoop | |
WhileOperation | Represents a while loop operation. |
Functions¶
emit_if [source]¶
def emit_if(
cond_func: Callable,
true_func: Callable,
false_func: Callable,
variables: list,
) -> AnyBuilder function for if-else conditional with Phi function merging.
This function is called from AST-transformed code. The AST transformer converts: if condition: true_body else: false_body
Into:
def _cond_N(vars): return condition def _body_N(vars): true_body; return vars def _body_N+1(vars): false_body; return vars result = emit_if(_cond_N, _body_N, _body_N+1, [var_list])
Parameters:
| Name | Type | Description |
|---|---|---|
cond_func | typing.Callable | Function returning the condition (Bit or bool-like Handle) |
true_func | typing.Callable | Function executing true branch, returns updated variables |
false_func | typing.Callable | Function executing false branch, returns updated variables |
variables | list | List of variables used in the branches |
Returns:
typing.Any — Merged variable values after conditional execution (using Phi functions)
Example:
@qkernel
def my_kernel(q: Qubit) -> Qubit:
result = measure(q)
if result:
q = z(q)
return qfor_items [source]¶
def for_items(
d: Dict,
key_var_names: list[str],
value_var_name: str,
) -> Generator[tuple[Any, Any], None, None]Builder function to create a for-items loop in Qamomile frontend.
This context manager creates a ForItemsOperation that iterates over dictionary (key, value) pairs. The operation is always unrolled at transpile time since quantum backends cannot natively iterate over classical data structures.
Parameters:
| Name | Type | Description |
|---|---|---|
d | Dict | Dict handle to iterate over |
key_var_names | list[str] | Names of key unpacking variables (e.g., [“i”, “j”] for tuple keys) |
value_var_name | str | Name of value variable (e.g., “Jij”) |
Yields:
tuple[typing.Any, typing.Any] — Tuple of (key_handles, value_handle) for use in loop body
Example:
@qkernel
def ising_cost(
q: Vector[Qubit],
ising: Dict[Tuple[UInt, UInt], Float],
gamma: Float,
) -> Vector[Qubit]:
for (i, j), Jij in qmc.items(ising):
q[i], q[j] = qmc.rzz(q[i], q[j], gamma * Jij)
return qfor_loop [source]¶
def for_loop(
start,
stop,
step = 1,
var_name: str = '_loop_idx',
) -> Generator[UInt, None, None]Builder function to create a for loop in Qamomile frontend.
Parameters:
| Name | Type | Description |
|---|---|---|
start | `` | Loop start value (can be Handle or int) |
stop | `` | Loop stop value (can be Handle or int) |
step | `` | Loop step value (default=1) |
var_name | str | Name of the loop variable (default=“_loop_idx”) |
Yields:
UInt — The loop iteration variable (can be used as array index)
Example:
@QKernel
def my_kernel(qubits: Array[Qubit, Literal[3]]) -> Array[Qubit, Literal[3]]:
for i in qm.range(3):
qubits[i] = h(qubits[i])
return qubits
@QKernel
def my_kernel2(qubits: Array[Qubit, Literal[5]]) -> Array[Qubit, Literal[5]]:
for i in qm.range(1, 4): # i = 1, 2, 3
qubits[i] = h(qubits[i])
return qubitsget_current_tracer [source]¶
def get_current_tracer() -> Traceris_array_type [source]¶
def is_array_type(t: Any) -> boolCheck if type is a Vector, Matrix, or Tensor subclass.
items [source]¶
def items(d: Dict) -> DictItemsIteratorIterate over dictionary key-value pairs.
This function returns an iterator over (key, value) pairs from a Dict. Used for iterating over Ising coefficients and similar data structures.
Example:
for (i, j), Jij in qmc.items(ising):
q[i], q[j] = qmc.rzz(q[i], q[j], gamma * Jij)Parameters:
| Name | Type | Description |
|---|---|---|
d | Dict | A Dict handle to iterate over |
Returns:
DictItemsIterator — DictItemsIterator yielding (key, value) pairs
range [source]¶
def range(
stop_or_start: int | UInt,
stop: int | UInt | None = None,
step: int | UInt = 1,
) -> Iterator[UInt]Symbolic range for use in qkernel for-loops.
This function accepts UInt (symbolic) values and is transformed by the AST transformer into for_loop() calls.
Example:
for i in qmc.range(n): # 0 to n-1
for i in qmc.range(start, stop): # start to stop-1
for i in qmc.range(start, stop, step):trace [source]¶
def trace(tracer: Tracer | None = None) -> Generator[Tracer, None, None]Context manager to set the current tracer.
while_loop [source]¶
def while_loop(cond: Callable) -> Generator[WhileLoop, None, None]Create a while loop whose condition is a measurement result.
The condition must be a Bit produced by qmc.measure().
Non-measurement conditions (classical variables, constants,
comparisons) are accepted at build time but will be rejected by
ValidateWhileContractPass during transpilation.
Parameters:
| Name | Type | Description |
|---|---|---|
cond | typing.Callable | A callable (lambda) that returns the loop condition. Must return a Bit handle originating from qmc.measure(). |
Yields:
WhileLoop — A marker object for the while loop context.
Example::
@qm.qkernel
def repeat_until_zero() -> qm.Bit:
q = qm.qubit("q")
q = qm.h(q)
bit = qm.measure(q)
while bit:
q = qm.qubit("q2")
q = qm.h(q)
bit = qm.measure(q)
return bitClasses¶
ArrayBase [source]¶
class ArrayBase(Handle, Generic[T])Base class for array types (Vector, Matrix, Tensor).
Provides common functionality for array indexing and element access.
Constructor¶
def __init__(
self,
value: ArrayValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt, ...] = tuple(),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
element_type: Type[T]shape: tuple[int | UInt, ...] Return the shape of the array.value: ArrayValue
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfConsume the array, enforcing borrow-return contract for quantum arrays.
For quantum arrays, all borrowed elements must be returned before the array can be consumed. This ensures that no unreturned borrows are silently discarded by operations like qkernel calls or controlled gates.
create¶
@classmethod
def create(
cls,
shape: tuple[int | UInt, ...],
name: str,
el_type: Type[T],
) -> 'ArrayBase[T]'Create an ArrayValue for the given shape and name.
validate_all_returned¶
def validate_all_returned(self) -> NoneValidate all borrowed elements have been returned.
This method is useful for ensuring that all borrowed elements have been properly written back before using the array in operations that require the entire array.
Raises:
UnreturnedBorrowError— If any elements are still borrowed.
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]Bit [source]¶
class Bit(Handle)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: bool = False,
) -> NoneAttributes¶
init_value: bool
BitType [source]¶
class BitType(ClassicalTypeMixin, ValueType)Type representing a classical bit.
Dict [source]¶
class Dict(Handle, Generic[K, V])Dict handle for qkernel functions.
Represents a dictionary mapping keys to values, commonly used for Ising coefficients like {(i, j): Jij}.
Example:
@qmc.qkernel
def ising_cost(
q: qmc.Vector[qmc.Qubit],
ising: qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float],
gamma: qmc.Float,
) -> qmc.Vector[qmc.Qubit]:
for (i, j), Jij in qmc.items(ising):
q[i], q[j] = qmc.rzz(q[i], q[j], gamma * Jij)
return qConstructor¶
def __init__(
self,
value: DictValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_entries: list[tuple[Handle, Handle]] = list(),
_size: UInt | None = None,
_key_type: type | None = None,
) -> NoneAttributes¶
size: UInt Return the number of entries as a UInt handle.value: DictValue
Methods¶
items¶
def items(self) -> DictItemsIterator[K, V]Return an iterator over (key, value) pairs.
DictItemsIterator [source]¶
class DictItemsIterator(Generic[K, V])Iterator for Dict.items() that yields (key, value) pairs.
This is used internally for iterating over Dict entries in qkernel.
Constructor¶
def __init__(self, dict_handle: 'Dict[K, V]', _index: int = 0) -> NoneAttributes¶
dict_handle: ‘Dict[K, V]’
Float [source]¶
class Float(ArithmeticMixin, Handle)Floating-point handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: float = 0.0,
) -> NoneAttributes¶
init_value: float
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
ForItemsOperation [source]¶
class ForItemsOperation(HasNestedOps, Operation)Represents iteration over dict/iterable items.
Example:
for (i, j), Jij in qmc.items(ising):
bodyConstructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
key_vars: list[str] = list(),
value_var: str = '',
key_is_vector: bool = False,
key_var_values: tuple[Value, ...] | None = None,
value_var_value: Value | None = None,
operations: list[Operation] = list(),
) -> NoneAttributes¶
key_is_vector: boolkey_var_values: tuple[Value, ...] | Nonekey_vars: list[str]operation_kind: OperationKindoperations: list[Operation]signature: Signaturevalue_var: strvalue_var_value: Value | None
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Include the per-key/value Value fields for cloning/substitution.
Same rationale as ForOperation.all_input_values: keep the IR
identity fields in lockstep with body references so UUID-keyed
lookups stay valid after inline cloning.
nested_op_lists¶
def nested_op_lists(self) -> list[list[Operation]]rebuild_nested¶
def rebuild_nested(self, new_lists: list[list[Operation]]) -> Operationreplace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationForOperation [source]¶
class ForOperation(HasNestedOps, Operation)Represents a for loop operation.
Example:
for i in range(start, stop, step):
bodyConstructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
loop_var: str = '',
loop_var_value: Value | None = None,
operations: list[Operation] = list(),
) -> NoneAttributes¶
loop_var: strloop_var_value: Value | Noneoperation_kind: OperationKindoperations: list[Operation]signature: Signature
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]Include loop_var_value so cloning/substitution stays consistent.
Without this override, UUIDRemapper would clone every body
reference to the loop variable to a fresh UUID, but leave
loop_var_value pointing at the un-cloned original — emit-time
UUID-keyed lookups for the loop variable would then miss.
nested_op_lists¶
def nested_op_lists(self) -> list[list[Operation]]rebuild_nested¶
def rebuild_nested(self, new_lists: list[list[Operation]]) -> Operationreplace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationIfOperation [source]¶
class IfOperation(HasNestedOps, Operation)Represents an if-else conditional operation.
Example:
if condition:
true_body
else:
false_bodyConstructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
true_operations: list[Operation] = list(),
false_operations: list[Operation] = list(),
phi_ops: list[PhiOp] = list(),
) -> NoneAttributes¶
condition: Valuefalse_operations: list[Operation]operation_kind: OperationKindphi_ops: list[PhiOp]signature: Signaturetrue_operations: list[Operation]
Methods¶
nested_op_lists¶
def nested_op_lists(self) -> list[list[Operation]]rebuild_nested¶
def rebuild_nested(self, new_lists: list[list[Operation]]) -> OperationPhiOp [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
Qubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
Tracer [source]¶
class TracerConstructor¶
def __init__(self, _operations: list[Operation] = list()) -> NoneAttributes¶
operations: list[Operation]
Methods¶
add_operation¶
def add_operation(self, op) -> NoneUInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
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.
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
WhileLoop [source]¶
class WhileLoopWhileOperation [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.frontend.operation.controlled¶
Controlled gate operations.
Overview¶
| Function | Description |
|---|---|
controlled | Create a controlled version of a quantum gate. |
get_current_tracer |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
ConcreteControlledU | Controlled-U with concrete (int) number of controls. |
ControlledGate | Wrapper for controlled version of a QKernel. |
ControlledUOperation | Base class for controlled-U operations. |
Float | Floating-point handle with arithmetic operations. |
FloatType | Type representing a floating-point number. |
IndexSpecControlledU | Controlled-U with explicit target/control index specification. |
QKernel | Decorator class for Qamomile quantum kernels. |
Qubit | |
QubitAliasError | Same qubit used multiple times in one operation. |
SymbolicControlledU | Controlled-U with symbolic (Value) number of controls. |
UInt | Unsigned integer handle with arithmetic operations. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
Functions¶
controlled [source]¶
def controlled(
qkernel: QKernel | Callable[..., Any],
num_controls: int | UInt = 1,
) -> ControlledGateCreate a controlled version of a quantum gate.
Accepts either a @qmc.qkernel-decorated function or a plain built-in
gate callable (qmc.rx, qmc.h, qmc.cp, ...). When given a
plain callable, a thin @qkernel wrapper is synthesized automatically
by inspecting the callable’s signature, so users no longer need to
write a one-line wrapper just to control a primitive gate.
Parameters:
| Name | Type | Description |
|---|---|---|
qkernel | QKernel | Callable[..., Any] | A QKernel defining the gate to control, or a built-in gate callable whose parameters are annotated with Qubit, Float/float, or UInt/int (possibly inside a Union such as Union[Qubit, Vector[Qubit]]). |
num_controls | int | UInt | Number of control qubits (default: 1). Can be int (concrete) or UInt (symbolic). |
Returns:
ControlledGate — A ControlledGate that can be called with
ControlledGate — (*controls, *targets, **params).
Raises:
TypeError— Ifqkernelis a callable that cannot be auto-wrapped (missing annotations, unsupported types, or no qubit parameters).ValueError— Ifnum_controlsis a concreteintless than 1.
Example:
Built-in gates can be controlled directly, with no wrapper::
crx = qmc.controlled(qmc.rx)
ctrl_out, tgt_out = crx(ctrl, target, angle=0.5)
cch = qmc.controlled(qmc.h, num_controls=2)
c0, c1, tgt = cch(ctrl0, ctrl1, target)
``@qmc.qkernel`` arguments are still supported for cases that need
custom logic::
@qmc.qkernel
def rx_then_h(q: Qubit, theta: float) -> Qubit:
q = qmc.rx(q, theta)
q = qmc.h(q)
return q
ctrl_out, tgt_out = qmc.controlled(rx_then_h)(ctrl, target, theta=0.5)get_current_tracer [source]¶
def get_current_tracer() -> TracerClasses¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]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]
ControlledGate [source]¶
class ControlledGateWrapper for controlled version of a QKernel.
Created by calling controlled(qkernel). The resulting object
can be called like a gate function.
Example:
@qmc.qkernel
def phase_gate(q: Qubit, theta: float) -> Qubit:
return qmc.p(q, theta)
controlled_phase = qmc.controlled(phase_gate)
ctrl_out, tgt_out = controlled_phase(ctrl, target, theta=0.5)
# Double-controlled
cc_phase = qmc.controlled(phase_gate, num_controls=2)
c0, c1, tgt = cc_phase(ctrl0, ctrl1, target, theta=0.5)Constructor¶
def __init__(self, qkernel: 'QKernel', num_controls: int | UInt = 1) -> NoneControlledUOperation [source]¶
class ControlledUOperation(Operation)Base class for controlled-U operations.
Three concrete subclasses handle distinct operand layouts:
ConcreteControlledU: Fixednum_controls: int, individual qubit operands.SymbolicControlledU: Symbolicnum_controls: Value, vector-based control operands.IndexSpecControlledU: Single vector with explicit index lists selecting which elements are controls/targets.
All isinstance(op, ControlledUOperation) checks match every subclass.
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
) -> NoneAttributes¶
block: Block | Nonecontrol_operands: list[Value] Get the control qubit values.has_index_spec: bool Whether target/control positions are specified via index lists.is_symbolic_num_controls: bool Whether num_controls is symbolic (Value) rather than concrete.operation_kind: OperationKindparam_operands: list[Value] Get parameter operands (non-qubit, non-block).power: int | Valuesignature: Signaturetarget_operands: list[Value] Get the target qubit values (arguments to U).
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationFloat [source]¶
class Float(ArithmeticMixin, Handle)Floating-point handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: float = 0.0,
) -> NoneAttributes¶
init_value: float
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
IndexSpecControlledU [source]¶
class IndexSpecControlledU(ControlledUOperation)Controlled-U with explicit target/control index specification.
A single vector covers both controls and targets; the partition is
determined by target_indices or controlled_indices.
Operand layout: [vector, params...]
Result layout: [vector']
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: int | Value = 1,
target_indices: list[Value] | None = None,
controlled_indices: list[Value] | None = None,
) -> NoneAttributes¶
control_operands: list[Value]controlled_indices: list[Value] | Nonehas_index_spec: boolis_symbolic_num_controls: boolnum_controls: int | Valueparam_operands: list[Value]signature: Signaturetarget_indices: list[Value] | Nonetarget_operands: list[Value]
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationQKernel [source]¶
class QKernel(Generic[P, R])Decorator class for Qamomile quantum kernels.
Constructor¶
def __init__(self, func: Callable[P, R]) -> NoneAttributes¶
block: Block Compile the function to a hierarchical Block if not already compiled.funcinput_typesnameoutput_typesraw_funcsignature
Methods¶
build¶
def build(self, parameters: list[str] | None = None, **kwargs: Any = {}) -> BlockBuild a traced Block by tracing this kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
parameters | list[str] | None | List of argument names to keep as unbound parameters. - None (default): Auto-detect parameters (non-Qubit args without value/default) - []: No parameters (all non-Qubit args must have value/default) - [“name”]: Explicit parameter list Only float, int, UInt, and their arrays are allowed as parameters. |
**kwargs | Any | Concrete values for non-parameter arguments. |
Returns:
Block — The traced block ready for transpilation, estimation,
or visualization.
Raises:
TypeError— If a non-parameterizable type is specified as parameter.ValueError— If required arguments are missing.
Example:
@qm.qkernel
def circuit(q: Qubit, theta: float) -> Qubit:
q = qm.rx(q, theta)
return q
# Auto-detect theta as parameter
block = circuit.build()
# Explicit parameter list
block = circuit.build(parameters=["theta"])
# theta bound to concrete value
block = circuit.build(theta=0.5)
# Transpile with binding
transpiler = QiskitTranspiler()
result = transpiler.emit(graph, binding={"theta": 0.5})draw¶
def draw(
self,
inline: bool = False,
fold_loops: bool = True,
expand_composite: bool = False,
inline_depth: int | None = None,
**kwargs: Any = {},
) -> AnyVisualize the circuit using Matplotlib.
This method builds the computation graph and creates a static visualization. Parameters are auto-detected: non-Qubit arguments without concrete values are shown as symbolic parameters.
Parameters:
| Name | Type | Description |
|---|---|---|
inline | bool | If True, expand CallBlockOperation contents (inlining). If False (default), show CallBlockOperation as boxes. |
fold_loops | bool | If True (default), display ForOperation as blocks instead of unrolling. If False, expand loops and show all iterations. |
expand_composite | bool | If True, expand CompositeGateOperation (QFT, IQFT, etc.). If False (default), show as boxes. Independent of inline. |
inline_depth | int | None | Maximum nesting depth for inline expansion. None means unlimited (default). 0 means no inlining, 1 means top-level only, etc. Only affects CallBlock/ControlledU, not CompositeGate. |
**kwargs | Any | Concrete values for arguments. Arguments not provided here (and without defaults) will be shown as symbolic parameters. |
Returns:
Any — matplotlib.figure.Figure object.
Raises:
ImportError— If matplotlib is not installed.
Example:
import qamomile.circuit as qm
@qm.qkernel
def inner(q: qm.Qubit) -> qm.Qubit:
return qm.x(q)
@qm.qkernel
def circuit(q: qm.Qubit, theta: float) -> qm.Qubit:
q = inner(q)
q = qm.h(q)
q = qm.rx(q, theta)
return q
# Draw with auto-detected symbolic parameter (theta)
fig = circuit.draw()
# Draw with bound parameter
fig = circuit.draw(theta=0.5)
# Draw with blocks as boxes (default)
fig = circuit.draw()
# Draw with blocks expanded (inlined)
fig = circuit.draw(inline=True)
# Draw with loops folded (shown as blocks)
fig = circuit.draw(fold_loops=True)
# Draw with composite gates expanded
fig = circuit.draw(expand_composite=True)estimate_resources¶
def estimate_resources(self, *, bindings: dict[str, Any] | None = None) -> ResourceEstimateEstimate all resources for this kernel’s circuit.
Convenience method that delegates to the module-level
estimate_resources function, eliminating the need to
access .block directly.
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | None | Optional concrete parameter bindings (scalars and dicts). Dict values trigger |key| cardinality substitution. |
Returns:
ResourceEstimate — ResourceEstimate with qubits, gates, and parameters.
Example:
>>> @qm.qkernel
... def bell() -> qm.Vector[qm.Qubit]:
... q = qm.qubit_array(2)
... q[0] = qm.h(q[0])
... q[0], q[1] = qm.cx(q[0], q[1])
... return q
>>> est = bell.estimate_resources()
>>> print(est.qubits) # 2Qubit [source]¶
class Qubit(Handle)Constructor¶
def __init__(
self,
value: Value[QubitType],
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
) -> NoneAttributes¶
value: Value[QubitType]
QubitAliasError [source]¶
class QubitAliasError(AffineTypeError)Same qubit used multiple times in one operation.
Operations like cx() require distinct qubits for control and target. Using the same qubit in both positions is physically impossible and indicates a programming error.
Example of incorrect code:
q1, q2 = qm.cx(q, q) # ERROR: same qubit as control and target
Correct code:
q1, q2 = qm.cx(control, target) # Use distinct qubits
SymbolicControlledU [source]¶
class SymbolicControlledU(ControlledUOperation)Controlled-U with symbolic (Value) number of controls.
Operand layout: [ctrl_vector, tgt_0, ..., tgt_m, params...]
Result layout: [ctrl_vector', tgt_0', ..., tgt_m']
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
power: int | Value = 1,
block: Block | None = None,
num_controls: Value = (lambda: Value(type=(FloatType()), name='_placeholder'))(),
) -> NoneAttributes¶
control_operands: list[Value]is_symbolic_num_controls: boolnum_controls: Valueparam_operands: list[Value]signature: Signaturetarget_operands: list[Value]
Methods¶
all_input_values¶
def all_input_values(self) -> list[ValueBase]replace_values¶
def replace_values(self, mapping: dict[str, ValueBase]) -> OperationUInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
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.
qamomile.circuit.frontend.operation.expval¶
Expectation value operation for computing <psi|H|psi>.
This module provides the expval() function for computing the expectation
value of a Hamiltonian observable with respect to a quantum state.
Overview¶
| Function | Description |
|---|---|
expval | Compute the expectation value of an observable on a quantum state. |
get_current_tracer |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
ExpvalOp | Expectation value operation. |
FloatType | Type representing a floating-point number. |
Value | A typed SSA value in the IR. |
Functions¶
expval [source]¶
def expval(qubits: Vector[Qubit] | tuple[Qubit, ...], hamiltonian: Observable) -> FloatCompute the expectation value of an observable on a quantum state.
This function computes <psi|H|psi> where psi is the quantum state represented by the qubits and H is the Hamiltonian observable.
The quantum state (qubits) is NOT consumed by this operation - the qubits can still be used for further operations after expval.
Parameters:
| Name | Type | Description |
|---|---|---|
qubits | Vector[Qubit] | tuple[Qubit, ...] | The quantum register holding the prepared state. Can be a Vector[Qubit] or a tuple of individual Qubits. |
hamiltonian | Observable | The Observable parameter representing the Hamiltonian. The actual qamomile.observable.Hamiltonian is provided via bindings. |
Returns:
Float — Float containing the expectation value.
Example:
import qamomile.circuit as qm
import qamomile.observable as qm_o
# Build Hamiltonian in Python
H = qm_o.Z(0) * qm_o.Z(1) + 0.5 * (qm_o.X(0) + qm_o.X(1))
@qm.qkernel
def vqe_step(q: qm.Vector[qm.Qubit], H: qm.Observable) -> qm.Float:
# Ansatz
q[0] = qm.ry(q[0], theta)
q[0], q[1] = qm.cx(q[0], q[1])
# Expectation value -> Float
return qm.expval(q, H)
# Pass Hamiltonian via bindings
executable = transpiler.transpile(vqe_step, bindings={"H": H})get_current_tracer [source]¶
def get_current_tracer() -> TracerClasses¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]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.
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.frontend.operation.measurement¶
Measurement operations for quantum circuits.
Overview¶
| Function | Description |
|---|---|
get_current_tracer | |
measure | Measure a qubit or QFixed in the computational basis. |
| Class | Description |
|---|---|
ArrayValue | An array of typed IR values. |
IRMeasureOperation | |
MeasureQFixedOperation | Measure a quantum fixed-point number. |
MeasureVectorOperation | Measure a vector of qubits. |
UIntType | Type representing an unsigned integer. |
Value | A typed SSA value in the IR. |
VectorClass | 1-dimensional array type. |
Functions¶
get_current_tracer [source]¶
def get_current_tracer() -> Tracermeasure [source]¶
def measure(target: Union[Qubit, QFixed, Vector[Qubit]]) -> Union[Bit, Float, Vector[Bit]]Measure a qubit or QFixed in the computational basis.
Performs a projective measurement in the Z-basis. The quantum resource is consumed by this operation and cannot be used afterwards.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, QFixed, Vector[Qubit]] | The quantum resource to measure. - Qubit: Returns a classical Bit - QFixed: Returns a Float (decoded from measured bits) |
Returns:
Union[Bit, Float, Vector[Bit]] — Bit for Qubit input, Float for QFixed input.
Example:
@qkernel
def measure_qubit(q: Qubit) -> Bit:
q = h(q)
return measure(q)
@qkernel
def measure_qfixed(qf: QFixed) -> Float:
# After QPE, qf holds phase bits
return measure(qf)Classes¶
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]MeasureOperation [source]¶
class MeasureOperation(Operation)Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
MeasureQFixedOperation [source]¶
class MeasureQFixedOperation(Operation)Measure a quantum fixed-point number.
This operation measures all qubits in a QFixed register and produces a Float result. During transpilation, this is lowered to individual MeasureOperations plus a DecodeQFixedOperation.
operands: [QFixed value (contains qubit_values in params)] results: [Float value]
Encoding:
For QPE phase (int_bits=0): float_value = 0.b0b1b2... = b00.5 + b10.25 + b2*0.125 + ...
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
num_bits: int = 0,
int_bits: int = 0,
) -> NoneAttributes¶
int_bits: intnum_bits: intoperation_kind: OperationKindsignature: Signature
MeasureVectorOperation [source]¶
class MeasureVectorOperation(Operation)Measure a vector of qubits.
Takes a Vector[Qubit] (ArrayValue) and produces a Vector[Bit] (ArrayValue). This operation measures all qubits in the vector as a single operation.
operands: [ArrayValue of qubits] results: [ArrayValue of bits]
Constructor¶
def __init__(self, operands: list[Value] = list(), results: list[Value] = list()) -> NoneAttributes¶
operation_kind: OperationKindsignature: Signature
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.
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
qamomile.circuit.frontend.operation.pauli_evolve¶
Pauli evolution operation for applying exp(-i * gamma * H).
This module provides the pauli_evolve() function for applying the
time evolution operator of a Pauli Hamiltonian to a quantum state.
Overview¶
| Function | Description |
|---|---|
get_current_tracer | |
pauli_evolve | Apply exp(-i * gamma * H) to a qubit register. |
| Class | Description |
|---|---|
PauliEvolveOp | Pauli evolution operation: exp(-i * gamma * H). |
Functions¶
get_current_tracer [source]¶
def get_current_tracer() -> Tracerpauli_evolve [source]¶
def pauli_evolve(q: Vector[Qubit], hamiltonian: Observable, gamma: Float) -> Vector[Qubit]Apply exp(-i * gamma * H) to a qubit register.
Implements Hamiltonian time evolution using the Pauli gadget technique. The actual Hamiltonian is provided via bindings at transpile time.
Each backend can use native implementations:
Qiskit: PauliEvolutionGate
QuriParts: PauliRotation gates
Others: fallback decomposition (basis change + CNOT ladder + RZ)
Parameters:
| Name | Type | Description |
|---|---|---|
q | Vector[Qubit] | The quantum register to evolve. |
hamiltonian | Observable | Observable parameter referencing the Hamiltonian. The actual qamomile.observable.Hamiltonian is provided via bindings. |
gamma | Float | Evolution time / variational parameter. |
Returns:
Vector[Qubit] — Vector[Qubit]: The evolved qubit register.
Example:
import qamomile.circuit as qmc
import qamomile.observable as qm_o
H = 0.5 * qm_o.X(0) * qm_o.Z(1) + qm_o.Z(0)
@qmc.qkernel
def cost_layer(
q: qmc.Vector[qmc.Qubit],
H: qmc.Observable,
gamma: qmc.Float,
) -> qmc.Vector[qmc.Qubit]:
q = qmc.pauli_evolve(q, H, gamma)
return q
transpiler = QiskitTranspiler()
exe = transpiler.transpile(cost_layer, bindings={"H": H, "gamma": 0.5})Classes¶
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
qamomile.circuit.frontend.operation.qubit_gates¶
Overview¶
| Function | Description |
|---|---|
ccx | Toffoli (CCX) gate: flips target when both controls are |1>. |
cp | Controlled-Phase gate. |
cx | CNOT (Controlled-X) gate. |
cz | CZ (Controlled-Z) gate. |
get_current_tracer | |
h | Hadamard gate. |
p | Phase gate: P(theta)|1> = e^{i*theta}|1>. |
rx | Rotation around X-axis: RX(angle) = exp(-i * angle/2 * X). |
ry | Rotation around Y-axis: RY(angle) = exp(-i * angle/2 * Y). |
rz | Rotation around Z-axis: RZ(angle) = exp(-i * angle/2 * Z). |
rzz | RZZ gate: exp(-i * angle/2 * Z ⊗ Z). |
s | S gate (square root of Z). |
sdg | S-dagger gate (inverse of S gate). |
swap | SWAP gate: exchanges two qubits. |
t | T gate (fourth root of Z). |
tdg | T-dagger gate (inverse of T gate). |
x | Pauli-X gate (NOT gate). |
y | Pauli-Y gate. |
z | Pauli-Z gate. |
| Class | Description |
|---|---|
FloatType | Type representing a floating-point number. |
GateOperationType | |
IRGateOperation | Quantum gate operation. |
QubitAliasError | Same qubit used multiple times in one operation. |
Value | A typed SSA value in the IR. |
VectorClass | 1-dimensional array type. |
Functions¶
ccx [source]¶
def ccx(control1: Qubit, control2: Qubit, target: Qubit) -> tuple[Qubit, Qubit, Qubit]Toffoli (CCX) gate: flips target when both controls are |1>.
Parameters:
| Name | Type | Description |
|---|---|---|
control1 | Qubit | First control qubit. |
control2 | Qubit | Second control qubit. |
target | Qubit | Target qubit. |
Returns:
tuple[Qubit, Qubit, Qubit] — Tuple of (control1_out, control2_out, target_out) after CCX.
cp [source]¶
def cp(control: Qubit, target: Qubit, theta: float | Float) -> tuple[Qubit, Qubit]Controlled-Phase gate.
cx [source]¶
def cx(control: Qubit, target: Qubit) -> tuple[Qubit, Qubit]CNOT (Controlled-X) gate.
cz [source]¶
def cz(control: Qubit, target: Qubit) -> tuple[Qubit, Qubit]CZ (Controlled-Z) gate.
get_current_tracer [source]¶
def get_current_tracer() -> Tracerh [source]¶
def h(target: Union[Qubit, Vector[Qubit]]) -> Union[Qubit, Vector[Qubit]]Hadamard gate.
Applied to a single Qubit it returns the transformed qubit. Applied
to a Vector[Qubit] it broadcasts the gate over every element via a
transpile-time loop, equivalent to
for i in qmc.range(n): qs[i] = h(qs[i]).
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit] to apply H to. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
p [source]¶
def p(
target: Union[Qubit, Vector[Qubit]],
theta: float | Float,
) -> Union[Qubit, Vector[Qubit]]Phase gate: P(theta)|1> = e^{i*theta}|1>.
Broadcasts the same theta over every qubit when called with a
Vector[Qubit].
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit] to apply the phase to. |
theta | float | Float | Phase angle in radians. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
rx [source]¶
def rx(
target: Union[Qubit, Vector[Qubit]],
angle: float | Float,
) -> Union[Qubit, Vector[Qubit]]Rotation around X-axis: RX(angle) = exp(-i * angle/2 * X).
Broadcasts the same angle over every qubit when called with a
Vector[Qubit].
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
angle | float | Float | Rotation angle in radians. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
ry [source]¶
def ry(
target: Union[Qubit, Vector[Qubit]],
angle: float | Float,
) -> Union[Qubit, Vector[Qubit]]Rotation around Y-axis: RY(angle) = exp(-i * angle/2 * Y).
Broadcasts the same angle over every qubit when called with a
Vector[Qubit].
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
angle | float | Float | Rotation angle in radians. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
rz [source]¶
def rz(
target: Union[Qubit, Vector[Qubit]],
angle: float | Float,
) -> Union[Qubit, Vector[Qubit]]Rotation around Z-axis: RZ(angle) = exp(-i * angle/2 * Z).
Broadcasts the same angle over every qubit when called with a
Vector[Qubit].
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
angle | float | Float | Rotation angle in radians. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
rzz [source]¶
def rzz(qubit_0: Qubit, qubit_1: Qubit, angle: float | Float) -> tuple[Qubit, Qubit]RZZ gate: exp(-i * angle/2 * Z ⊗ Z).
The RZZ gate applies a rotation around the ZZ axis on two qubits.
Parameters:
| Name | Type | Description |
|---|---|---|
qubit_0 | Qubit | First qubit. |
qubit_1 | Qubit | Second qubit. |
angle | float | Float | Rotation angle in radians. |
Returns:
tuple[Qubit, Qubit] — Tuple of (qubit_0_out, qubit_1_out) after RZZ.
s [source]¶
def s(target: Union[Qubit, Vector[Qubit]]) -> Union[Qubit, Vector[Qubit]]S gate (square root of Z).
Broadcasts over a Vector[Qubit] when applied to one.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
sdg [source]¶
def sdg(target: Union[Qubit, Vector[Qubit]]) -> Union[Qubit, Vector[Qubit]]S-dagger gate (inverse of S gate).
Broadcasts over a Vector[Qubit] when applied to one.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
swap [source]¶
def swap(qubit_0: Qubit, qubit_1: Qubit) -> tuple[Qubit, Qubit]SWAP gate: exchanges two qubits.
The SWAP gate swaps the states of two qubits.
Parameters:
| Name | Type | Description |
|---|---|---|
qubit_0 | Qubit | First qubit. |
qubit_1 | Qubit | Second qubit. |
Returns:
tuple[Qubit, Qubit] — Tuple of (qubit_0_out, qubit_1_out) after SWAP.
t [source]¶
def t(target: Union[Qubit, Vector[Qubit]]) -> Union[Qubit, Vector[Qubit]]T gate (fourth root of Z).
Broadcasts over a Vector[Qubit] when applied to one.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
tdg [source]¶
def tdg(target: Union[Qubit, Vector[Qubit]]) -> Union[Qubit, Vector[Qubit]]T-dagger gate (inverse of T gate).
Broadcasts over a Vector[Qubit] when applied to one.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
x [source]¶
def x(target: Union[Qubit, Vector[Qubit]]) -> Union[Qubit, Vector[Qubit]]Pauli-X gate (NOT gate).
Broadcasts over a Vector[Qubit] when applied to one.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
y [source]¶
def y(target: Union[Qubit, Vector[Qubit]]) -> Union[Qubit, Vector[Qubit]]Pauli-Y gate.
Broadcasts over a Vector[Qubit] when applied to one.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
z [source]¶
def z(target: Union[Qubit, Vector[Qubit]]) -> Union[Qubit, Vector[Qubit]]Pauli-Z gate.
Broadcasts over a Vector[Qubit] when applied to one.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Union[Qubit, Vector[Qubit]] | A single Qubit or a Vector[Qubit]. |
Returns:
Union[Qubit, Vector[Qubit]] — A Qubit for scalar input, a Vector[Qubit] for array input.
Raises:
TypeError— Iftargetis neither aQubitnor aVector[Qubit].
Classes¶
FloatType [source]¶
class FloatType(ClassicalTypeMixin, ValueType)Type representing a floating-point number.
GateOperationType [source]¶
class GateOperationType(enum.Enum)Attributes¶
CPCXCZHPRXRYRZRZZSSDGSWAPTTDGTOFFOLIXYZ
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.
QubitAliasError [source]¶
class QubitAliasError(AffineTypeError)Same qubit used multiple times in one operation.
Operations like cx() require distinct qubits for control and target. Using the same qubit in both positions is physically impossible and indicates a programming error.
Example of incorrect code:
q1, q2 = qm.cx(q, q) # ERROR: same qubit as control and target
Correct code:
q1, q2 = qm.cx(control, target) # Use distinct qubits
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.
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
qamomile.circuit.frontend.qkernel¶
Overview¶
| Function | Description |
|---|---|
bit | Create a Bit handle from a boolean/int literal or declare a named Bit parameter. |
collect_quantum_rebind_violations | Analyze func for forbidden quantum rebind patterns. |
create_dummy_input | Create a dummy input based on parameter type annotation. |
float_ | Create a Float handle from a float literal or declare a named Float parameter. |
func_to_block | Convert a function to a hierarchical Block. |
get_current_tracer | |
handle_type_map | Map Handle type to ValueType. |
is_array_type | Check if type is a Vector, Matrix, or Tensor subclass. |
is_dict_type | Check if type is a Dict handle type. |
is_tuple_type | Check if type is a Tuple handle type. |
qkernel | Decorator to define a Qamomile quantum kernel. |
qubit_array | Create a new qubit array (vector/matrix/tensor) and emit QInitOperations. |
trace | Context manager to set the current tracer. |
transform_control_flow | |
uint | Create a UInt handle from an integer literal or declare a named UInt parameter. |
| Class | Description |
|---|---|
ArrayBase | Base class for array types (Vector, Matrix, Tensor). |
ArrayValue | An array of typed IR values. |
Bit | |
Block | Unified block representation for all pipeline stages. |
BlockKind | Classification of block structure for pipeline stages. |
CallBlockOperation | |
Dict | Dict handle for qkernel functions. |
DictValue | A dictionary value stored as stable ordered entries. |
Float | Floating-point handle with arithmetic operations. |
FrontendTransformError | Error during frontend AST-to-builder lowering. |
QKernel | Decorator class for Qamomile quantum kernels. |
ResourceEstimate | Comprehensive resource estimate for a quantum circuit. |
Tracer | |
UInt | Unsigned integer handle with arithmetic operations. |
Value | A typed SSA value in the IR. |
Vector | 1-dimensional array type. |
Functions¶
bit [source]¶
def bit(arg: bool | str | int) -> BitCreate a Bit handle from a boolean/int literal or declare a named Bit parameter.
collect_quantum_rebind_violations [source]¶
def collect_quantum_rebind_violations(func: Callable, quantum_param_names: set[str]) -> list[RebindViolation]Analyze func for forbidden quantum rebind patterns.
Returns a (possibly empty) list of violations. Never raises on
analysis failure – returns [] instead.
create_dummy_input [source]¶
def create_dummy_input(param_type: Any, name: str = 'param', emit_init: bool = True) -> HandleCreate a dummy input based on parameter type annotation.
Parameters:
| Name | Type | Description |
|---|---|---|
param_type | typing.Any | The type annotation for the parameter. |
name | str | Name for the value. |
emit_init | bool | If True, emit QInitOperation for qubit arrays (default: True). Set to False when creating a nested Block’s internal dummy inputs. |
This creates input Handles for function parameters.
float_ [source]¶
def float_(arg: float | str) -> FloatCreate a Float handle from a float literal or declare a named Float parameter.
func_to_block [source]¶
def func_to_block(func: Callable) -> BlockConvert a function to a hierarchical Block.
Example:
def my_func(a: UInt, b: UInt) -> tuple[UInt]:
c = a + b
return (c, )
block = func_to_block(my_func)get_current_tracer [source]¶
def get_current_tracer() -> Tracerhandle_type_map [source]¶
def handle_type_map(handle_type: type[Handle] | type) -> ValueTypeMap Handle type to ValueType.
is_array_type [source]¶
def is_array_type(t: Any) -> boolCheck if type is a Vector, Matrix, or Tensor subclass.
is_dict_type [source]¶
def is_dict_type(t: Any) -> boolCheck if type is a Dict handle type.
is_tuple_type [source]¶
def is_tuple_type(t: Any) -> boolCheck if type is a Tuple handle type.
qkernel [source]¶
def qkernel(func: Callable[P, R]) -> QKernel[P, R]Decorator to define a Qamomile quantum kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
func | Callable[P, R] | The function to decorate. |
Returns:
QKernel[P, R] — An instance of QKernel wrapping the function.
qubit_array [source]¶
def qubit_array(
shape: UInt | int | tuple[UInt | int, ...],
name: str,
) -> Vector[Qubit] | Matrix[Qubit] | Tensor[Qubit]Create a new qubit array (vector/matrix/tensor) and emit QInitOperations.
trace [source]¶
def trace(tracer: Tracer | None = None) -> Generator[Tracer, None, None]Context manager to set the current tracer.
transform_control_flow [source]¶
def transform_control_flow(func: Callable)uint [source]¶
def uint(arg: int | str) -> UIntCreate a UInt handle from an integer literal or declare a named UInt parameter.
Classes¶
ArrayBase [source]¶
class ArrayBase(Handle, Generic[T])Base class for array types (Vector, Matrix, Tensor).
Provides common functionality for array indexing and element access.
Constructor¶
def __init__(
self,
value: ArrayValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt, ...] = tuple(),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
element_type: Type[T]shape: tuple[int | UInt, ...] Return the shape of the array.value: ArrayValue
Methods¶
consume¶
def consume(self, operation_name: str = 'unknown') -> SelfConsume the array, enforcing borrow-return contract for quantum arrays.
For quantum arrays, all borrowed elements must be returned before the array can be consumed. This ensures that no unreturned borrows are silently discarded by operations like qkernel calls or controlled gates.
create¶
@classmethod
def create(
cls,
shape: tuple[int | UInt, ...],
name: str,
el_type: Type[T],
) -> 'ArrayBase[T]'Create an ArrayValue for the given shape and name.
validate_all_returned¶
def validate_all_returned(self) -> NoneValidate all borrowed elements have been returned.
This method is useful for ensuring that all borrowed elements have been properly written back before using the array in operations that require the entire array.
Raises:
UnreturnedBorrowError— If any elements are still borrowed.
ArrayValue [source]¶
class ArrayValue(Value[T])An array of typed IR values.
Constructor¶
def __init__(
self,
type: T,
name: str,
version: int = 0,
metadata: ValueMetadata = ValueMetadata(),
uuid: str = (lambda: str(uuid.uuid4()))(),
logical_id: str = (lambda: str(uuid.uuid4()))(),
parent_array: ArrayValue | None = None,
element_indices: tuple[Value, ...] = (),
shape: tuple[Value, ...] = tuple(),
) -> NoneAttributes¶
logical_id: strmetadata: ValueMetadataname: strshape: tuple[Value, ...]type: Tuuid: str
Methods¶
next_version¶
def next_version(self) -> ArrayValue[T]Bit [source]¶
class Bit(Handle)Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: bool = False,
) -> NoneAttributes¶
init_value: bool
Block [source]¶
class BlockUnified block representation for all pipeline stages.
Replaces the older traced and callable IR wrappers with a single structure.
The kind field indicates which pipeline stage this block is at.
Constructor¶
def __init__(
self,
name: str = '',
label_args: list[str] = list(),
input_values: list[Value] = list(),
output_values: list[Value] = list(),
output_names: list[str] = list(),
operations: list['Operation'] = list(),
kind: BlockKind = BlockKind.HIERARCHICAL,
parameters: dict[str, Value] = dict(),
) -> NoneAttributes¶
input_values: list[Value]kind: BlockKindlabel_args: list[str]name: stroperations: list[‘Operation’]output_names: list[str]output_values: list[Value]parameters: dict[str, Value]
Methods¶
call¶
def call(self, **kwargs: Value = {}) -> 'CallBlockOperation'Create a CallBlockOperation against this block.
is_affine¶
def is_affine(self) -> boolCheck if block contains no CallBlockOperations.
unbound_parameters¶
def unbound_parameters(self) -> list[str]Return list of unbound parameter names.
BlockKind [source]¶
class BlockKind(Enum)Classification of block structure for pipeline stages.
Attributes¶
AFFINEANALYZEDHIERARCHICALTRACED
CallBlockOperation [source]¶
class CallBlockOperation(Operation)Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
block: Block | None = None,
) -> NoneAttributes¶
block: Block | Noneoperation_kind: OperationKindsignature: Signature
Methods¶
is_self_reference_to¶
def is_self_reference_to(self, block: Block) -> boolReturn True if this call points to the given block (self-ref).
Dict [source]¶
class Dict(Handle, Generic[K, V])Dict handle for qkernel functions.
Represents a dictionary mapping keys to values, commonly used for Ising coefficients like {(i, j): Jij}.
Example:
@qmc.qkernel
def ising_cost(
q: qmc.Vector[qmc.Qubit],
ising: qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float],
gamma: qmc.Float,
) -> qmc.Vector[qmc.Qubit]:
for (i, j), Jij in qmc.items(ising):
q[i], q[j] = qmc.rzz(q[i], q[j], gamma * Jij)
return qConstructor¶
def __init__(
self,
value: DictValue,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_entries: list[tuple[Handle, Handle]] = list(),
_size: UInt | None = None,
_key_type: type | None = None,
) -> NoneAttributes¶
size: UInt Return the number of entries as a UInt handle.value: DictValue
Methods¶
items¶
def items(self) -> DictItemsIterator[K, V]Return an iterator over (key, value) pairs.
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) -> DictValueFloat [source]¶
class Float(ArithmeticMixin, Handle)Floating-point handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: float = 0.0,
) -> NoneAttributes¶
init_value: float
FrontendTransformError [source]¶
class FrontendTransformError(QamomileCompileError)Error during frontend AST-to-builder lowering.
QKernel [source]¶
class QKernel(Generic[P, R])Decorator class for Qamomile quantum kernels.
Constructor¶
def __init__(self, func: Callable[P, R]) -> NoneAttributes¶
block: Block Compile the function to a hierarchical Block if not already compiled.funcinput_typesnameoutput_typesraw_funcsignature
Methods¶
build¶
def build(self, parameters: list[str] | None = None, **kwargs: Any = {}) -> BlockBuild a traced Block by tracing this kernel.
Parameters:
| Name | Type | Description |
|---|---|---|
parameters | list[str] | None | List of argument names to keep as unbound parameters. - None (default): Auto-detect parameters (non-Qubit args without value/default) - []: No parameters (all non-Qubit args must have value/default) - [“name”]: Explicit parameter list Only float, int, UInt, and their arrays are allowed as parameters. |
**kwargs | Any | Concrete values for non-parameter arguments. |
Returns:
Block — The traced block ready for transpilation, estimation,
or visualization.
Raises:
TypeError— If a non-parameterizable type is specified as parameter.ValueError— If required arguments are missing.
Example:
@qm.qkernel
def circuit(q: Qubit, theta: float) -> Qubit:
q = qm.rx(q, theta)
return q
# Auto-detect theta as parameter
block = circuit.build()
# Explicit parameter list
block = circuit.build(parameters=["theta"])
# theta bound to concrete value
block = circuit.build(theta=0.5)
# Transpile with binding
transpiler = QiskitTranspiler()
result = transpiler.emit(graph, binding={"theta": 0.5})draw¶
def draw(
self,
inline: bool = False,
fold_loops: bool = True,
expand_composite: bool = False,
inline_depth: int | None = None,
**kwargs: Any = {},
) -> AnyVisualize the circuit using Matplotlib.
This method builds the computation graph and creates a static visualization. Parameters are auto-detected: non-Qubit arguments without concrete values are shown as symbolic parameters.
Parameters:
| Name | Type | Description |
|---|---|---|
inline | bool | If True, expand CallBlockOperation contents (inlining). If False (default), show CallBlockOperation as boxes. |
fold_loops | bool | If True (default), display ForOperation as blocks instead of unrolling. If False, expand loops and show all iterations. |
expand_composite | bool | If True, expand CompositeGateOperation (QFT, IQFT, etc.). If False (default), show as boxes. Independent of inline. |
inline_depth | int | None | Maximum nesting depth for inline expansion. None means unlimited (default). 0 means no inlining, 1 means top-level only, etc. Only affects CallBlock/ControlledU, not CompositeGate. |
**kwargs | Any | Concrete values for arguments. Arguments not provided here (and without defaults) will be shown as symbolic parameters. |
Returns:
Any — matplotlib.figure.Figure object.
Raises:
ImportError— If matplotlib is not installed.
Example:
import qamomile.circuit as qm
@qm.qkernel
def inner(q: qm.Qubit) -> qm.Qubit:
return qm.x(q)
@qm.qkernel
def circuit(q: qm.Qubit, theta: float) -> qm.Qubit:
q = inner(q)
q = qm.h(q)
q = qm.rx(q, theta)
return q
# Draw with auto-detected symbolic parameter (theta)
fig = circuit.draw()
# Draw with bound parameter
fig = circuit.draw(theta=0.5)
# Draw with blocks as boxes (default)
fig = circuit.draw()
# Draw with blocks expanded (inlined)
fig = circuit.draw(inline=True)
# Draw with loops folded (shown as blocks)
fig = circuit.draw(fold_loops=True)
# Draw with composite gates expanded
fig = circuit.draw(expand_composite=True)estimate_resources¶
def estimate_resources(self, *, bindings: dict[str, Any] | None = None) -> ResourceEstimateEstimate all resources for this kernel’s circuit.
Convenience method that delegates to the module-level
estimate_resources function, eliminating the need to
access .block directly.
Parameters:
| Name | Type | Description |
|---|---|---|
bindings | dict[str, Any] | None | Optional concrete parameter bindings (scalars and dicts). Dict values trigger |key| cardinality substitution. |
Returns:
ResourceEstimate — ResourceEstimate with qubits, gates, and parameters.
Example:
>>> @qm.qkernel
... def bell() -> qm.Vector[qm.Qubit]:
... q = qm.qubit_array(2)
... q[0] = qm.h(q[0])
... q[0], q[1] = qm.cx(q[0], q[1])
... return q
>>> est = bell.estimate_resources()
>>> print(est.qubits) # 2ResourceEstimate [source]¶
class ResourceEstimateComprehensive resource estimate for a quantum circuit.
All metrics are SymPy expressions that may contain symbols for parametric problem sizes.
Constructor¶
def __init__(
self,
qubits: sp.Expr,
gates: GateCount,
parameters: dict[str, sp.Symbol] = dict(),
) -> NoneAttributes¶
gates: GateCountparameters: dict[str, sp.Symbol]qubits: sp.Expr
Methods¶
simplify¶
def simplify(self) -> ResourceEstimateSimplify all SymPy expressions.
Returns:
ResourceEstimate — New ResourceEstimate with simplified expressions
substitute¶
def substitute(self, **values: int | float = {}) -> ResourceEstimateSubstitute concrete values for parameters.
Parameters:
| Name | Type | Description |
|---|---|---|
**values | int | float | Parameter name -> concrete value mappings |
Returns:
ResourceEstimate — New ResourceEstimate with substituted values
Example:
>>> est = estimate_resources(circuit)
>>> concrete = est.substitute(n=100, p=3)
>>> print(concrete.qubits) # 100 (instead of 'n')to_dict¶
def to_dict(self) -> dict[str, Any]Convert to a dictionary for serialization.
Returns:
dict[str, Any] — Dictionary with all metrics as strings (for JSON/YAML export)
Example:
>>> est = estimate_resources(circuit)
>>> data = est.to_dict()
>>> import json
>>> print(json.dumps(data, indent=2))Tracer [source]¶
class TracerConstructor¶
def __init__(self, _operations: list[Operation] = list()) -> NoneAttributes¶
operations: list[Operation]
Methods¶
add_operation¶
def add_operation(self, op) -> NoneUInt [source]¶
class UInt(ArithmeticMixin, Handle)Unsigned integer handle with arithmetic operations.
Constructor¶
def __init__(
self,
value: Value,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
init_value: int = 0,
) -> NoneAttributes¶
init_value: int
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.
Vector [source]¶
class Vector(ArrayBase[T])1-dimensional array type.
Example:
import qamomile.circuit as qmc
# Create a vector of 3 qubits
qubits: qmc.Vector[qmc.Qubit] = qmc.qubit_array(3, name="qubits")
# Access elements
q0 = qubits[0]
q0 = qmc.h(q0)
qubits[0] = q0
# Apply H gate to all qubits (CORRECT)
n = qubits.shape[0]
for i in qmc.range(n):
qubits[i] = qmc.h(qubits[i])Constructor¶
def __init__(
self,
value: ArrayValue = None,
parent: 'ArrayBase | None' = None,
indices: tuple['UInt', ...] = (),
name: str | None = None,
id: str = (lambda: str(uuid.uuid4()))(),
_consumed: bool = False,
_consumed_by: str | None = None,
_shape: tuple[int | UInt] = (0,),
_borrowed_indices: dict[tuple[str, ...], tuple[UInt, ...]] = dict(),
) -> NoneAttributes¶
value: ArrayValue
qamomile.circuit.frontend.tracer¶
Overview¶
| Function | Description |
|---|---|
get_current_tracer | |
trace | Context manager to set the current tracer. |
Functions¶
get_current_tracer [source]¶
def get_current_tracer() -> Tracertrace [source]¶
def trace(tracer: Tracer | None = None) -> Generator[Tracer, None, None]Context manager to set the current tracer.
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.
Tracer [source]¶
class TracerConstructor¶
def __init__(self, _operations: list[Operation] = list()) -> NoneAttributes¶
operations: list[Operation]
Methods¶
add_operation¶
def add_operation(self, op) -> None