QURI Parts backend for Qamomile.
Design intent: this package concretizes circuit’s abstract IR for QURI
Parts through QuriPartsMaterializer. QuriPartsTranspiler plugs the
materializer into the shared compiler pipeline, while observable.py
converts Hamiltonians to QURI Parts Operators.
Backend-specific quirks stay confined here: parametric circuits use
LinearMappedUnboundParametricQuantumCircuit, so symbolic angles are
normalized to linear-combination form ({param: coeff, CONST: offset})
at emit time, and controlled gates without a native equivalent fall back
to circuit’s shared decomposition recipes. Failures surface as
QamomileQuriPartsTranspileError (exceptions.py) rather than raw
SDK errors.
Constraints: depend only on qamomile.circuit public APIs plus the
quri-parts SDK — never on qamomile.optimization or other
backends. Lowering decisions belong at emit time, not in the IR.
Overview¶
| Function | Description |
|---|---|
hamiltonian_to_quri_operator | Convert qamomile.observable.Hamiltonian to QURI Parts Operator. |
to_quri_operator | Convert Hamiltonian to QURI Parts Operator. |
| Class | Description |
|---|---|
QamomileQuriPartsTranspileError | Exception raised for errors in the Qamomile to QURI Parts conversion process. |
QuriPartsExecutor | Execute QURI Parts circuits with sampling and expectation estimation. |
QuriPartsGateEmitter | GateEmitter implementation for QURI Parts. |
QuriPartsTranspiler | Transpile Qamomile programs to QURI Parts circuits. |
Functions¶
hamiltonian_to_quri_operator [source]¶
def hamiltonian_to_quri_operator(hamiltonian: qm_o.Hamiltonian) -> 'Operator'Convert qamomile.observable.Hamiltonian to QURI Parts Operator.
Parameters:
| Name | Type | Description |
|---|---|---|
hamiltonian | qm_o.Hamiltonian | The qamomile Hamiltonian to convert. |
Returns:
'Operator' — QURI Parts Operator representation.
Example:
import qamomile.observable as qm_o
from qamomile.quri_parts.observable import hamiltonian_to_quri_operator
H = qm_o.Z(0) * qm_o.Z(1) + 0.5 * (qm_o.X(0) + qm_o.X(1))
operator = hamiltonian_to_quri_operator(H)to_quri_operator [source]¶
def to_quri_operator(hamiltonian: qm_o.Hamiltonian) -> 'Operator'Convert Hamiltonian to QURI Parts Operator.
Convenience alias for :func:hamiltonian_to_quri_operator.
Parameters:
| Name | Type | Description |
|---|---|---|
hamiltonian | qm_o.Hamiltonian | The qamomile Hamiltonian to convert. |
Returns:
'Operator' — QURI Parts Operator representation.
Classes¶
QamomileQuriPartsTranspileError [source]¶
class QamomileQuriPartsTranspileError(QamomileCompileError)Exception raised for errors in the Qamomile to QURI Parts conversion process.
QuriPartsExecutor [source]¶
class QuriPartsExecutor(QuantumExecutor['qp_c.LinearMappedUnboundParametricQuantumCircuit'])Execute QURI Parts circuits with sampling and expectation estimation.
Constructor¶
def __init__(
self,
sampler: Any = None,
estimator: Any = None,
seed: int | None = None,
*,
bound_estimator: Any = None,
)Initialize the executor.
Parameters:
| Name | Type | Description |
|---|---|---|
sampler | Any | Optional QURI Parts sampler. |
estimator | Any | Optional QURI Parts parametric estimator, used only with unbound parametric circuit states. |
seed | int | None | Optional seed for the default Qulacs sampler. |
bound_estimator | Any | Optional non-parametric estimator for circuits that have already been bound by ExecutableProgram. |
Attributes¶
non_parametric_estimator: Any Return the non-parametric estimator, creating it lazily.parametric_estimator: Any Return the parametric estimator, creating the default lazily.sampler: Any Return the configured sampler, creating the default lazily.
Methods¶
bind_parameters¶
def bind_parameters(
self,
circuit: 'qp_c.LinearMappedUnboundParametricQuantumCircuit',
bindings: dict[str, Any],
parameter_metadata: ParameterMetadata,
) -> 'ImmutableBoundParametricQuantumCircuit'Bind named parameters in backend order.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | 'qp_c.LinearMappedUnboundParametricQuantumCircuit' | Unbound parametric circuit. |
bindings | dict[str, Any] | Parameter values by Qamomile name. |
parameter_metadata | ParameterMetadata | Ordered backend parameter metadata. |
Returns:
'ImmutableBoundParametricQuantumCircuit' — Bound QURI Parts circuit.
Raises:
QamomileQuriPartsTranspileError— If a required value is absent.
estimate¶
def estimate(
self,
circuit: 'qp_c.LinearMappedUnboundParametricQuantumCircuit',
hamiltonian: 'qm_o.Hamiltonian',
params: Sequence[float] | None = None,
) -> floatEstimate a Hamiltonian expectation value.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | 'qp_c.LinearMappedUnboundParametricQuantumCircuit' | State-preparation circuit. |
hamiltonian | 'qm_o.Hamiltonian' | Qamomile Hamiltonian or native QURI Parts operator. |
params | Sequence[float] | None | Optional circuit parameter values. |
Returns:
float — Real expectation value.
estimate_expectation¶
def estimate_expectation(
self,
circuit: 'qp_c.LinearMappedUnboundParametricQuantumCircuit',
hamiltonian: 'qp_o.Operator',
param_values: Sequence[float],
) -> floatEstimate a native QURI Parts operator expectation value.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | 'qp_c.LinearMappedUnboundParametricQuantumCircuit' | Parametric or concrete QURI Parts circuit. |
hamiltonian | 'qp_o.Operator' | Native QURI Parts operator. |
param_values | Sequence[float] | Values for an unbound parametric circuit. |
Returns:
float — Real expectation value.
execute¶
def execute(self, circuit: Any, shots: int) -> dict[str, int]Sample a circuit and return bitstring counts.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | Any | Bound or unbound QURI Parts circuit. |
shots | int | Number of measurement shots. |
Returns:
dict[str, int] — Counts keyed by zero-padded bitstrings. A zero-qubit circuit
dict[str, int] — returns {"": shots} without invoking the sampler.
QuriPartsGateEmitter [source]¶
class QuriPartsGateEmitterGateEmitter implementation for QURI Parts.
Emits individual quantum gates to QURI Parts circuits.
QURI Parts parametric circuits accept angles in dictionary form: {parameter: coefficient, CONST: constant_offset}
Constructor¶
def __init__(self, phase_carrier: int | None = None) -> NoneInitialize the emitter.
Parameters:
| Name | Type | Description |
|---|---|---|
phase_carrier | int | None | Dedicated clean |0> qubit used only where exact scalar-phase synthesis cannot reuse an existing qubit. None still permits a concrete phase when the caller supplies an existing carrier, but rejects symbolic or zero-qubit phase emission. |
Attributes¶
measurement_mode: MeasurementMode QURI Parts always uses STATIC measurement (sampler handles it).
Methods¶
append_gate¶
def append_gate(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
gate: Any,
qubits: list[int],
) -> NoneAppend a gate to the circuit.
Since circuit_to_gate returns None, this is only called with QURI Parts native gates which can be extended into the circuit.
circuit_to_gate¶
def circuit_to_gate(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
name: str = 'U',
) -> AnyQURI Parts doesn’t support converting circuits to gates.
Returns None to signal that manual decomposition should be used.
combine_symbolic¶
def combine_symbolic(self, kind: BinOpKind, lhs: Any, rhs: Any) -> 'dict[Parameter, float]'Combine two angle operands as a QURI Parts linear-combination dict.
QURI Parts’ Parameter is Rust-backed and exposes no Python
arithmetic operators (param * float raises TypeError).
The only supported representation for parametric angles is the
linear-combination dict consumed by
LinearMappedUnboundParametricQuantumCircuit.add_Parametric*,
which fundamentally cannot express non-linear combinations
(parameter × parameter, parameter ** n, etc.). This override
produces such a dict for every linear case and raises a clear
QamomileQuriPartsTranspileError for non-linear cases instead
of letting the underlying TypeError bubble up.
Parameters:
| Name | Type | Description |
|---|---|---|
kind | BinOpKind | The BinOpKind from the IR. |
lhs | Any | Left operand (numeric, QURI Parts Parameter, or an existing linear-combination dict). |
rhs | Any | Right operand (same shapes). |
Returns:
'dict[Parameter, float]' — A fresh dict[Parameter, float] representing the linear
'dict[Parameter, float]' — combination of the operands.
Raises:
QamomileQuriPartsTranspileError— When the operation cannot be expressed as a linear combination (e.g.param * param,param / param,param ** n,param // n, division by zero in the symbolic path).
create_circuit¶
def create_circuit(
self,
num_qubits: int,
num_clbits: int,
) -> 'LinearMappedUnboundParametricQuantumCircuit'Create a new QURI Parts parametric circuit.
Note: QURI Parts does not support classical bits in circuits. The num_clbits parameter is accepted for interface compatibility but is not used.
create_parameter¶
def create_parameter(self, name: str) -> 'Parameter'Create a QURI Parts parameter and register it with the circuit.
emit_barrier¶
def emit_barrier(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubits: list[int],
) -> NoneNo-op: QURI Parts doesn’t support barrier instructions.
emit_ch¶
def emit_ch(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control: int,
target: int,
) -> NoneEmit controlled-Hadamard gate using decomposition.
Follows the shared CH_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions.
emit_cp¶
def emit_cp(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-Phase gate using decomposition.
Follows the shared CP decomposition. The concrete case replaces its
final exp(iθ/4) RZ(θ/2) pair with the exact native U1(θ/2).
The parametric case has no native ParametricU1, so it emits RZ plus
the missing scalar factor on the dedicated phase carrier.
emit_crx¶
def emit_crx(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RX gate using decomposition.
CRX(ctrl, tgt, θ) = RZ(tgt, π/2) CNOT(ctrl, tgt) RY(tgt, -θ/2) CNOT(ctrl, tgt) RY(tgt, θ/2) RZ(tgt, -π/2)
emit_cry¶
def emit_cry(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RY gate using decomposition.
Follows the shared CRY_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions.
Inlined here because QURI Parts parametric angles use dict representation.
emit_crz¶
def emit_crz(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control: int,
target: int,
angle: float | Any,
) -> NoneEmit controlled-RZ gate using decomposition.
Follows the shared CRZ_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions.
Inlined here because QURI Parts parametric angles use dict representation.
emit_cx¶
def emit_cx(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control: int,
target: int,
) -> NoneEmit CNOT (controlled-X) gate.
emit_cy¶
def emit_cy(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control: int,
target: int,
) -> NoneEmit controlled-Y gate using decomposition.
Follows the shared CY_DECOMPOSITION recipe from
qamomile.circuit.transpiler.decompositions.
emit_cz¶
def emit_cz(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control: int,
target: int,
) -> NoneEmit controlled-Z gate.
emit_global_phase¶
def emit_global_phase(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
angle: float | Any,
carrier: int | None = None,
) -> NoneSynthesize exp(i * angle) I exactly.
A concrete phase reuses an arbitrary existing qubit through
U1(2a) RZ(-2a) = exp(ia) I. Symbolic and zero-qubit phases use the
configured clean carrier because QURI Parts has no ParametricU1 or
circuit-level phase operation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | LinearMappedUnboundParametricQuantumCircuit | Destination QURI circuit. |
angle | float | Any | Concrete or linear phase in radians. |
carrier | int | None | Existing arbitrary-state qubit available for concrete two-gate synthesis. Defaults to None. |
Raises:
EmitError— If an explicit carrier is invalid, or if symbolic or zero-qubit emission has no valid dedicated clean carrier.
emit_h¶
def emit_h(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneEmit Hadamard gate.
emit_measure¶
def emit_measure(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
clbit: int,
) -> NoneNo-op: QURI Parts circuits don’t support measurement gates.
Measurement is handled separately by samplers/estimators.
emit_p¶
def emit_p(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
angle: float | Any,
) -> NoneEmit Phase gate using U1.
P(θ) = U1(θ) = diag(1, e^{iθ}).
For non-parametric angles we use the native U1 gate which is
mathematically identical to the Phase gate.
For parametric angles we use ParametricRZ plus a scalar phase on the
dedicated clean carrier that restores
P(θ) = exp(iθ/2) RZ(θ) exactly.
emit_pauli_rotation¶
def emit_pauli_rotation(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubits: list[int],
pauli_ids: list[int],
angle: float | Any,
) -> NoneEmit one native QURI Parts Pauli-string rotation.
Parameters:
| Name | Type | Description |
|---|---|---|
circuit | LinearMappedUnboundParametricQuantumCircuit | Destination QURI Parts circuit. |
qubits | list[int] | Target qubit indices in Pauli-word order. |
pauli_ids | list[int] | QURI Pauli identifiers aligned with qubits. |
angle | float | Any | Rotation angle for exp(-i * angle / 2 * P). |
emit_reset¶
def emit_reset(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneRaise because QURI Parts circuits do not support reset.
emit_rx¶
def emit_rx(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
angle: float | Any,
) -> NoneEmit RX rotation gate.
emit_ry¶
def emit_ry(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
angle: float | Any,
) -> NoneEmit RY rotation gate.
emit_rz¶
def emit_rz(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
angle: float | Any,
) -> NoneEmit RZ rotation gate.
emit_rzz¶
def emit_rzz(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit1: int,
qubit2: int,
angle: float | Any,
) -> NoneEmit RZZ gate using ParametricPauliRotation.
emit_s¶
def emit_s(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneEmit S (phase) gate.
emit_sdg¶
def emit_sdg(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneEmit S-dagger (inverse S) gate.
emit_swap¶
def emit_swap(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit1: int,
qubit2: int,
) -> NoneEmit SWAP gate.
emit_t¶
def emit_t(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneEmit T gate.
emit_tdg¶
def emit_tdg(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneEmit T-dagger (inverse T) gate.
emit_toffoli¶
def emit_toffoli(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
control1: int,
control2: int,
target: int,
) -> NoneEmit Toffoli (CCX) gate.
emit_x¶
def emit_x(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneEmit Pauli-X gate.
emit_y¶
def emit_y(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneEmit Pauli-Y gate.
emit_z¶
def emit_z(
self,
circuit: 'LinearMappedUnboundParametricQuantumCircuit',
qubit: int,
) -> NoneEmit Pauli-Z gate.
gate_controlled¶
def gate_controlled(self, gate: Any, num_controls: int) -> AnyCreate controlled version of a gate.
Returns None since QURI Parts doesn’t support this natively.
gate_inverse¶
def gate_inverse(self, gate: Any) -> AnyReturn the inverse of a concrete QURI Parts circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
gate | Any | Candidate QURI Parts circuit to invert. Runtime parametric circuits are expected to fall back to Qamomile’s gate-by-gate inverse implementation. |
Returns:
Any — Inverted QURI Parts circuit when inverse_circuit can
handle gate; otherwise None so callers can fall back to
Qamomile-level decomposition.
gate_power¶
def gate_power(self, gate: Any, power: int) -> AnyCreate gate raised to a power.
Returns None since QURI Parts doesn’t support this natively.
supports_for_loop¶
def supports_for_loop(self) -> boolQURI Parts does not support native for loops.
supports_gate_inverse¶
def supports_gate_inverse(self) -> boolReport QURI Parts circuit inverse support.
Returns:
bool — True because gate_inverse can invert concrete
bool — QURI Parts circuits. The backend still reports no reusable
bool — gate support, so inverse blocks normally use the
bool — transpiler-level native path rather than the shared
bool — blockvalue_to_gate path.
supports_if_else¶
def supports_if_else(self) -> boolQURI Parts does not support native if/else.
supports_while_loop¶
def supports_while_loop(self) -> boolQURI Parts does not support native while loops.
QuriPartsTranspiler [source]¶
class QuriPartsTranspiler(Transpiler['qp_c.LinearMappedUnboundParametricQuantumCircuit'])Transpile Qamomile programs to QURI Parts circuits.
Methods¶
executor¶
def executor(
self,
sampler: Any = None,
estimator: Any = None,
seed: int | None = None,
*,
bound_estimator: Any = None,
) -> QuriPartsExecutorCreate a QURI Parts executor.
Parameters:
| Name | Type | Description |
|---|---|---|
sampler | Any | Optional custom sampler. |
estimator | Any | Optional custom parametric estimator for unbound states. |
seed | int | None | Optional seed for the default sampler. |
bound_estimator | Any | Optional custom non-parametric estimator for circuits already bound by ExecutableProgram. |
Returns:
QuriPartsExecutor — Configured QURI Parts executor.