Overview¶
| Function | Description |
|---|---|
bit | Create a Bit handle from a boolean/int literal or declare a named Bit parameter. |
cast | Cast a quantum value to a different type without allocating new qubits. |
ccx | Toffoli (CCX) gate: flips target when both controls are |1>. |
composite_gate | Decorator to create a CompositeGate from a qkernel function or as a stub. |
controlled | Create a controlled version of a quantum gate (QKernel). |
cp | Controlled-Phase gate. |
cx | CNOT (Controlled-X) gate. |
cz | CZ (Controlled-Z) gate. |
expval | Compute the expectation value of an observable on a quantum state. |
float_ | Create a Float handle from a float literal or declare a named Float parameter. |
for_items | Builder function to create a for-items loop in Qamomile frontend. |
h | Hadamard gate. |
items | Iterate over dictionary key-value pairs. |
measure | Measure a qubit or QFixed in the computational basis. |
p | Phase gate: P(theta)|1> = e^{i*theta}|1>. |
qkernel | Decorator to define a Qamomile quantum kernel. |
qubit | Create a new qubit and emit a QInitOperation. |
qubit_array | Create a new qubit array (vector/matrix/tensor) and emit QInitOperations. |
range | Symbolic range for use in qkernel for-loops. |
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). |
uint | Create a UInt handle from an integer literal or declare a named UInt parameter. |
x | Pauli-X gate (NOT gate). |
y | Pauli-Y gate. |
z | Pauli-Z gate. |
| Class | Description |
|---|---|
CompositeGate | Base class for user-facing composite gate definitions. |
QKernel | Decorator class for Qamomile quantum kernels. |
Functions¶
bit [source]¶
def bit(arg: bool | str | int) -> BitCreate a Bit handle from a boolean/int literal or declare a named Bit parameter.
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
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.
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.
controlled [source]¶
def controlled(qkernel: 'QKernel', num_controls: int | UInt = 1) -> ControlledGateCreate a controlled version of a quantum gate (QKernel).
Parameters:
| Name | Type | Description |
|---|---|---|
qkernel | 'QKernel' | A QKernel defining the gate to control. |
num_controls | int | UInt | Number of control qubits (default: 1). Can be int (concrete) or UInt (symbolic). |
Returns:
ControlledGate — ControlledGate that can be called with (*controls, *targets, **params)
Example:
@qmc.qkernel
def rx_gate(q: Qubit, theta: float) -> Qubit:
return qmc.rx(q, theta)
crx = qmc.controlled(rx_gate)
ctrl_out, tgt_out = crx(ctrl_qubit, target_qubit, theta=0.5)
# Double-controlled
ccrx = qmc.controlled(rx_gate, num_controls=2)
c0, c1, tgt = ccrx(ctrl0, ctrl1, target, theta=0.5)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.
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})float_ [source]¶
def float_(arg: float | str) -> FloatCreate a Float handle from a float literal or declare a named Float parameter.
for_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 qh [source]¶
def h(qubit: Qubit) -> QubitHadamard gate.
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
measure [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)p [source]¶
def p(qubit: Qubit, theta: float | Float) -> QubitPhase gate: P(theta)|1> = e^{i*theta}|1>.
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 [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.
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):rx [source]¶
def rx(qubit: Qubit, angle: float | Float) -> QubitRotation around X-axis: RX(angle) = exp(-i * angle/2 * X).
ry [source]¶
def ry(qubit: Qubit, angle: float | Float) -> QubitRotation around Y-axis: RY(angle) = exp(-i * angle/2 * Y).
rz [source]¶
def rz(qubit: Qubit, angle: float | Float) -> QubitRotation around Z-axis: RZ(angle) = exp(-i * angle/2 * Z).
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(qubit: Qubit) -> QubitS gate (square root of Z).
sdg [source]¶
def sdg(qubit: Qubit) -> QubitS-dagger gate (inverse of S gate).
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(qubit: Qubit) -> QubitT gate (fourth root of Z).
tdg [source]¶
def tdg(qubit: Qubit) -> QubitT-dagger gate (inverse of T gate).
uint [source]¶
def uint(arg: int | str) -> UIntCreate a UInt handle from an integer literal or declare a named UInt parameter.
x [source]¶
def x(qubit: Qubit) -> QubitPauli-X gate (NOT gate).
y [source]¶
def y(qubit: Qubit) -> QubitPauli-Y gate.
z [source]¶
def z(qubit: Qubit) -> QubitPauli-Z gate.
Classes¶
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 BlockValue 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 = {}) -> 'BlockValue | None'Build the decomposition circuit dynamically.
Override this method to provide a decomposition that depends on runtime arguments (e.g., QPE needs the unitary BlockValue).
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:
'BlockValue | None' — BlockValue 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) -> 'BlockValue | None'Get the implementation BlockValue, 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
QKernel [source]¶
class QKernel(Generic[P, R])Decorator class for Qamomile quantum kernels.
Constructor¶
def __init__(self, func: Callable[P, R]) -> NoneAttributes¶
block: BlockValue Compiles the function to a BlockValue (IR) if not already compiled.funcinput_typesnameoutput_typesraw_funcsignature
Methods¶
build¶
def build(self, parameters: list[str] | None = None, **kwargs: Any = {}) -> GraphBuild the computation graph 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:
Graph — The traced computation graph ready for transpilation.
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
graph = circuit.build()
# Explicit parameter list
graph = circuit.build(parameters=["theta"])
# theta bound to concrete value
graph = 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) # 2