Quantum Phase Estimation implementation.
Example:
@qmc.qkernel
def p_gate(q: qmc.Qubit, theta: float) -> qmc.Qubit:
return qmc.p(q, theta)
@qmc.qkernel
def circuit(theta: float) -> qmc.Float:
counting = qmc.qubit_array(3, name="counting")
target = qmc.qubit(name="target")
target = qmc.x(target)
phase = qmc.qpe(target, counting, p_gate, theta=theta)
return qmc.measure(phase)Overview¶
| Function | Description |
|---|---|
for_loop | Builder function to create a for loop in Qamomile frontend. |
get_current_tracer | |
qpe | Quantum Phase Estimation. |
| Class | Description |
|---|---|
CastOperation | Type cast operation for creating aliases over the same quantum resources. |
CompositeGateOperation | Represents a composite gate (QPE, QFT, etc.) as a single operation. |
CompositeGateType | Registry of known composite gate types. |
QKernel | Decorator class for Qamomile quantum kernels. |
ResourceMetadata | Resource estimation metadata for composite gates. |
Value | A typed SSA value in the IR. |
Functions¶
for_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() -> Tracerqpe [source]¶
def qpe(
target: Qubit,
counting: Vector[Qubit],
unitary: QKernel,
**params: Any = {},
) -> QFixedQuantum Phase Estimation.
Estimates the phase φ where U|ψ> = e^{2πiφ}|ψ>.
Parameters:
| Name | Type | Description |
|---|---|---|
target | Qubit | The eigenstate |ψ> of the unitary U |
counting | Vector[Qubit] | Vector of qubits for phase estimation result |
unitary | QKernel | The unitary operation U as a QKernel |
**params | Any | Parameters to pass to the unitary |
Returns:
QFixed — Phase register as quantum fixed-point number
Classes¶
CastOperation [source]¶
class CastOperation(Operation)Type cast operation for creating aliases over the same quantum resources.
This operation does NOT allocate new qubits. It creates a new Value that references the same underlying quantum resources with a different type.
Use cases:
Vector[Qubit] -> QFixed (after QPE, for phase measurement)
Vector[Qubit] -> QUInt (for quantum arithmetic)
QUInt -> QFixed (reinterpret bits with different encoding)
QFixed -> QUInt (reinterpret bits with different encoding)
operands: [source_value] - The value being cast results: [cast_result] - The new value with target type (same physical qubits)
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
source_type: ValueType | None = None,
target_type: ValueType | None = None,
qubit_mapping: list[str] = list(),
) -> NoneAttributes¶
num_qubits: int Number of qubits involved in the cast.operation_kind: OperationKind Cast stays in the same segment as its source (QUANTUM for quantum types).qubit_mapping: list[str]signature: Signature Return the type signature of this cast operation.source_type: ValueType | Nonetarget_type: ValueType | None
CompositeGateOperation [source]¶
class CompositeGateOperation(Operation)Represents a composite gate (QPE, QFT, etc.) as a single operation.
CompositeGate allows representing complex multi-gate operations as a single atomic operation in the IR. This enables:
Resource estimation without full implementation
Backend-native conversion (e.g., Qiskit’s QPE)
User-defined complex gates
The operands structure is:
operands[0:num_control_qubits]: Control qubits (if any)
operands[num_control_qubits:num_control_qubits+num_target_qubits]: Target qubits
operands[num_control_qubits+num_target_qubits:]: Parameters
The results structure:
results[0:num_control_qubits]: Control qubits (returned)
results[num_control_qubits:]: Target qubits (returned)
Constructor¶
def __init__(
self,
operands: list[Value] = list(),
results: list[Value] = list(),
gate_type: CompositeGateType = CompositeGateType.CUSTOM,
num_control_qubits: int = 0,
num_target_qubits: int = 0,
custom_name: str = '',
resource_metadata: ResourceMetadata | None = None,
has_implementation: bool = True,
implementation_block: Block | None = None,
composite_gate_instance: Any = None,
strategy_name: str | None = None,
) -> NoneAttributes¶
composite_gate_instance: Anycontrol_qubits: list[‘Value’] Get the control qubit operands.custom_name: strgate_type: CompositeGateTypehas_implementation: boolimplementation: Block | None Get the implementation block, if any.implementation_block: Block | Nonename: str Human-readable name of this composite gate.num_control_qubits: intnum_target_qubits: intoperation_kind: OperationKind Return the operation kind (always QUANTUM).parameters: list[‘Value’] Get the parameter operands (angles, etc.).resource_metadata: ResourceMetadata | Nonesignature: Signature Return the operation signature.strategy_name: str | Nonetarget_qubits: list[‘Value’] Get the target qubit operands.
CompositeGateType [source]¶
class CompositeGateType(enum.Enum)Registry of known composite gate types.
Attributes¶
CUSTOMIQFTQFTQPE
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) # 2ResourceMetadata [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
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.