Overview¶
| Function | Description |
|---|---|
hubo_qaoa_state | Generate HUBO QAOA state. |
is_close_zero | Check if a given floating-point value is close to zero within a small tolerance. |
qaoa_state | Generate QAOA State for Ising model. |
| Class | Description |
|---|---|
ExecutableProgram | A fully compiled program ready for execution. |
MathematicalProblemConverter | |
QAOAConverter | Converter for Quantum Approximate Optimization Algorithm (QAOA). |
Transpiler | Base class for backend-specific transpilers. |
Functions¶
hubo_qaoa_state [source]¶
def hubo_qaoa_state(
p_val: qmc.UInt,
quad: qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float],
linear: qmc.Dict[qmc.UInt, qmc.Float],
higher: qmc.Dict[qmc.Vector[qmc.UInt], qmc.Float],
n: qmc.UInt,
gammas: qmc.Vector[qmc.Float],
betas: qmc.Vector[qmc.Float],
) -> qmc.Vector[qmc.Qubit]Generate HUBO QAOA state.
Creates a uniform superposition and applies p layers of the HUBO QAOA circuit.
Parameters:
| Name | Type | Description |
|---|---|---|
p_val | qmc.UInt | Number of QAOA layers. |
quad | qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float] | Quadratic coefficients of the Ising model. |
linear | qmc.Dict[qmc.UInt, qmc.Float] | Linear coefficients of the Ising model. |
higher | qmc.Dict[qmc.Vector[qmc.UInt], qmc.Float] | Higher-order coefficients keyed by index vectors. |
n | qmc.UInt | Number of qubits. |
gammas | qmc.Vector[qmc.Float] | Cost-layer parameters, one per layer. |
betas | qmc.Vector[qmc.Float] | Mixer-layer parameters, one per layer. |
Returns:
qmc.Vector[qmc.Qubit] — qmc.Vector[qmc.Qubit]: HUBO QAOA state vector.
is_close_zero [source]¶
def is_close_zero(value: float, abs_tol: float = 1e-15) -> boolCheck if a given floating-point value is close to zero within a small tolerance.
Parameters:
| Name | Type | Description |
|---|---|---|
value | float | The floating-point value to check. |
abs_tol | float | Absolute tolerance passed to :func:math.isclose. Defaults to 1e-15. |
Returns:
bool — True if the value is close to zero, False otherwise.
qaoa_state [source]¶
def qaoa_state(
p: qmc.UInt,
quad: qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float],
linear: qmc.Dict[qmc.UInt, qmc.Float],
n: qmc.UInt,
gammas: qmc.Vector[qmc.Float],
betas: qmc.Vector[qmc.Float],
) -> qmc.Vector[qmc.Qubit]Generate QAOA State for Ising model.
Parameters:
| Name | Type | Description |
|---|---|---|
p | qmc.UInt | Number of QAOA layers. |
quad | qmc.Dict[qmc.Tuple[qmc.UInt, qmc.UInt], qmc.Float] | Quadratic coefficients of the Ising model. |
linear | qmc.Dict[qmc.UInt, qmc.Float] | Linear coefficients of the Ising model. |
n | qmc.UInt | Number of qubits. |
gammas | qmc.Vector[qmc.Float] | Cost-layer parameters, one per layer. |
betas | qmc.Vector[qmc.Float] | Mixer-layer parameters, one per layer. |
Returns:
qmc.Vector[qmc.Qubit] — qmc.Vector[qmc.Qubit]: QAOA state vector.
Classes¶
ExecutableProgram [source]¶
class ExecutableProgram(Generic[T])A fully compiled program ready for execution.
Contains compiled quantum, classical, and expectation-value segments.
Use sample() for multi-shot execution or run() for single
execution.
Example:
executable = transpiler.compile(kernel)
# Sample: multiple shots, returns counts
job = executable.sample(executor, shots=1000)
result = job.result() # SampleResult with counts
# Run: single shot, returns typed result
job = executable.run(executor)
result = job.result() # Returns kernel's return typeConstructor¶
def __init__(
self,
plan: ProgramPlan | None = None,
compiled_quantum: list[CompiledQuantumSegment[T]] = list(),
compiled_classical: list[CompiledClassicalSegment] = list(),
compiled_expval: list[CompiledExpvalSegment] = list(),
output_refs: list[str] = list(),
num_output_bits: int = 0,
) -> NoneAttributes¶
compiled_classical: list[CompiledClassicalSegment]compiled_expval: list[CompiledExpvalSegment]compiled_quantum: list[CompiledQuantumSegment[T]]has_parameters: bool Check if this program has unbound parameters.num_output_bits: intoutput_refs: list[str]parameter_names: list[str] Get list of parameter names that need binding.plan: ProgramPlan | Nonequantum_circuit: T Get the single quantum circuit.
Methods¶
get_circuits¶
def get_circuits(self) -> list[T]Get all quantum circuits in execution order.
get_first_circuit¶
def get_first_circuit(self) -> T | NoneGet the first quantum circuit, or None if no quantum segments.
run¶
def run(
self,
executor: QuantumExecutor[T],
bindings: dict[str, Any] | None = None,
) -> RunJob[Any] | ExpvalJobExecute once and return single result.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
RunJob[Any] | ExpvalJob — RunJob that resolves to the kernel’s return type, or
RunJob[Any] | ExpvalJob — ExpvalJob if the program contains expectation value computation.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.run(executor, bindings={"gamma": [0.5]})
result = job.result()
print(result) # 0.25 (for QFixed) or (0, 1) (for bits)sample¶
def sample(
self,
executor: QuantumExecutor[T],
shots: int = 1024,
bindings: dict[str, Any] | None = None,
) -> SampleJob[Any]Execute with multiple shots and return counts.
Parameters:
| Name | Type | Description |
|---|---|---|
executor | QuantumExecutor[T] | Backend-specific quantum executor. |
shots | int | Number of shots to run. |
bindings | dict[str, Any] | None | Parameter bindings. Supports two formats: - Vector: {“gammas”: [0.1, 0.2], “betas”: [0.3, 0.4]} - Indexed: {“gammas[0]”: 0.1, “gammas[1]”: 0.2} |
Returns:
SampleJob[Any] — SampleJob that resolves to SampleResult with results.
Raises:
ExecutionError— If no quantum circuit to executeValueError— If required parameters are missing
Example:
job = executable.sample(executor, shots=1000, bindings={"gamma": [0.5]})
result = job.result()
print(result.results) # [(0.25, 500), (0.75, 500)]MathematicalProblemConverter [source]¶
class MathematicalProblemConverter(abc.ABC)Constructor¶
def __init__(self, instance: ommx.v1.Instance | BinaryModel) -> NoneAttributes¶
instanceoriginal_vartypespin_model
Methods¶
decode¶
def decode(self, samples: SampleResult[list[int]]) -> BinarySampleSet | ommx.v1.SampleSetDecode quantum measurement results.
The return type tracks the input that built this converter:
Built from an :class:
ommx.v1.Instance— returns an :class:ommx.v1.SampleSetevaluated against the original (un-penalized) instance, so feasibility, objective, and per-constraint violations are available through OMMX’s own API (.summary,.summary_with_constraints,.best_feasible,.feasible,.objectives).Built from a :class:
BinaryModel— returns a :class:BinarySampleSetwith samples in the model’s original vartype (BINARY 0/1 or SPIN ±1), energies, and shot counts.
Parameters:
| Name | Type | Description |
|---|---|---|
samples | SampleResult[list[int]] | Raw quantum measurement results from ExecutableProgram.sample(...).result(). |
Returns:
BinarySampleSet | ommx.v1.SampleSet — BinarySampleSet | ommx.v1.SampleSet: see method description.
See Also:
:meth:decode_to_binary_sampleset: always returns a
:class:BinarySampleSet. Use it when you need the
QUBO-domain (penalty-included) energy — e.g. to drive a
classical optimizer that must penalize infeasibility.
Example:
>>> # OMMX in → OMMX out
>>> converter = QAOAConverter(ommx_instance)
>>> exe = converter.transpile(QiskitTranspiler(), p=2)
>>> result = exe.sample(QiskitTranspiler().executor(),
... shots=1024,
... bindings={"gammas": gs, "betas": bs}).result()
>>> sample_set = converter.decode(result)
>>> sample_set.best_feasible.objectivedecode_to_binary_sampleset¶
def decode_to_binary_sampleset(self, samples: SampleResult[list[int]]) -> BinarySampleSetDecode samples into a :class:BinarySampleSet.
Always returns a :class:BinarySampleSet, regardless of whether
this converter was constructed with an :class:ommx.v1.Instance
or a :class:BinaryModel. Use this when you need:
The QUBO-domain
energy(penalty-included), e.g. as the cost driving a classical optimizer like COBYLA — :meth:decodeon OMMX-backed converters returns the un-penalized OMMX objective which won’t penalize infeasibility.The per-state
samples/num_occurrences/vartypeviews from :class:BinarySampleSet.
For most usage — feasibility, original-objective evaluation,
per-constraint diagnostics — prefer the polymorphic
:meth:decode, which returns an :class:ommx.v1.SampleSet for
OMMX-backed converters.
Parameters:
| Name | Type | Description |
|---|---|---|
samples | SampleResult[list[int]] | Raw quantum measurement results from ExecutableProgram.sample(...).result(). |
Returns:
BinarySampleSet — keyed by the SPIN model’s original variable
BinarySampleSet — indices (the QUBO variable IDs for OMMX-backed converters)
BinarySampleSet — in the converter’s original_vartype — BINARY for
BinarySampleSet — OMMX-backed converters, the :class:BinaryModel’s declared
BinarySampleSet — vartype otherwise.
get_cost_hamiltonian¶
def get_cost_hamiltonian(self) -> qm_o.HamiltonianConstruct the cost Hamiltonian.
Subclasses must implement this method to build the appropriate Hamiltonian for their specific algorithm (e.g., Pauli-Z for QAOA, QRAC-encoded for QRAO).
Returns:
qm_o.Hamiltonian — qm_o.Hamiltonian: The cost Hamiltonian.
QAOAConverter [source]¶
class QAOAConverter(MathematicalProblemConverter)Converter for Quantum Approximate Optimization Algorithm (QAOA).
Supports both standard quadratic (QUBO/Ising) models and higher-order binary optimization (HUBO) models. When higher-order terms are present, automatically uses phase-gadget decomposition for k-body Z-rotations.
Example:
>>> model = BinaryModel.from_hubo({(0, 1, 2): 1.0, (0,): -2.0})
>>> converter = QAOAConverter(model)
>>> executable = converter.transpile(QiskitTranspiler(), p=2)Methods¶
get_cost_hamiltonian¶
def get_cost_hamiltonian(self) -> qm_o.HamiltonianConstruct the Ising cost Hamiltonian from the spin model.
Builds a Pauli-Z Hamiltonian from the spin model’s linear, quadratic, and higher-order terms.
Returns:
qm_o.Hamiltonian — qm_o.Hamiltonian: The cost Hamiltonian.
transpile¶
def transpile(self, transpiler: Transpiler, *, p: int) -> ExecutableProgramTranspile the model into an executable QAOA circuit.
Dispatches to the quadratic-only fast path when no higher-order terms are present, otherwise uses the HUBO path with phase-gadget decomposition.
Parameters:
| Name | Type | Description |
|---|---|---|
transpiler | Transpiler | Backend transpiler to use. |
p | int | Number of QAOA layers. |
Returns:
ExecutableProgram — The compiled circuit program.
Transpiler [source]¶
class Transpiler(ABC, Generic[T])Base class for backend-specific transpilers.
Provides the full compilation pipeline from QKernel to executable program.
Usage:
transpiler = QiskitTranspiler()
Option 1: Full pipeline¶
executable = transpiler.compile(kernel, bindings={“theta”: 0.5}) results = executable.run(transpiler.executor())
Option 2: Step-by-step¶
block = transpiler.to_block(kernel) substituted = transpiler.substitute(block) affine = transpiler.inline(substituted) validated = transpiler.affine_validate(affine) folded = transpiler.constant_fold(validated, bindings={“theta”: 0.5}) analyzed = transpiler.analyze(folded) plan = transpiler.plan(analyzed) executable = transpiler.emit(plan, bindings={“theta”: 0.5})
Option 3: Just get the circuit (no execution)¶
circuit = transpiler.to_circuit(kernel, bindings={“theta”: 0.5})
With configuration (strategy overrides)¶
config = TranspilerConfig.with_strategies({“qft”: “approximate”}) transpiler = QiskitTranspiler(config=config)
Attributes¶
MAX_UNROLL_DEPTH: intconfig: TranspilerConfig Get the transpiler configuration.
Methods¶
affine_validate¶
def affine_validate(self, block: Block) -> BlockPass 1.5: Validate affine type semantics.
This is a safety net to catch affine type violations that may have bypassed frontend checks. Validates that quantum values are used at most once.
analyze¶
def analyze(self, block: Block) -> BlockPass 2: Validate and analyze dependencies.
classical_lowering¶
def classical_lowering(self, block: Block) -> BlockPass 2.25: Lower measurement-derived classical ops.
Identifies CompOp / CondOp / NotOp / BinOp
instances whose operand dataflow traces back to a measurement and
rewrites them to RuntimeClassicalExpr. Compile-time-foldable
and emit-time-foldable (loop-bound, parameter-bound) classical
ops are left unchanged.
Runs after analyze so the measurement-taint analysis has the
full dependency graph available, and before
validate_symbolic_shapes / plan / emit so downstream
passes can rely on the cleaner IR (in particular: future
segmentation work can dispatch on RuntimeClassicalExpr type
instead of the BitType-only heuristic).
constant_fold¶
def constant_fold(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockPass 1.5: Fold constant expressions.
Evaluates BinOp operations when all operands are constants
or bound parameters. This prevents quantum segment splitting
from parametric expressions like phase * 2.
emit¶
def emit(
self,
separated: ProgramPlan,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
) -> ExecutableProgram[T]Pass 4: Generate backend-specific code.
Parameters:
| Name | Type | Description |
|---|---|---|
separated | ProgramPlan | The separated program to emit |
bindings | dict[str, Any] | None | Parameter values to bind at compile time |
parameters | list[str] | None | Parameter names to preserve as backend parameters |
executor¶
def executor(self, **kwargs: Any = {}) -> QuantumExecutor[T]Create a quantum executor for this backend.
inline¶
def inline(self, block: Block) -> BlockPass 1: Inline all CallBlockOperations.
lower_compile_time_ifs¶
def lower_compile_time_ifs(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockPass 1.75: Lower compile-time resolvable IfOperations.
Evaluates IfOperation conditions (including expression-derived conditions via CompOp/CondOp/NotOp) and replaces resolved ones with selected-branch operations. Phi outputs are substituted with selected-branch values throughout the block.
This prevents SegmentationPass from seeing classical-only compile-time IfOperations that would otherwise split quantum segments.
partial_eval¶
def partial_eval(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockPass 1.75: Fold constants and lower compile-time control flow.
plan¶
def plan(self, block: Block) -> ProgramPlanPass 3: Lower and split into a program plan.
Validates C→Q→C pattern with single quantum segment.
resolve_parameter_shapes¶
def resolve_parameter_shapes(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockPass 0.75: Resolve symbolic Vector parameter shape dims.
Qamomile circuits are compile-time fixed-structure. Parameter
Vector[Float] / Vector[UInt] inputs carry symbolic
{name}_dim{i} shape Values so frontend code like
arr.shape[0] returns a usable handle. This pass looks at
bindings and, for every parameter array that has a concrete
binding, substitutes those symbolic dims with constants so that
downstream loop-bound resolution sees fixed lengths.
Parameters without a concrete binding are left as-is; their symbolic dims are harmless as long as no compile-time structure decision depends on them (the library QAOA pattern).
set_config¶
def set_config(self, config: TranspilerConfig) -> NoneSet the transpiler configuration.
Parameters:
| Name | Type | Description |
|---|---|---|
config | TranspilerConfig | Transpiler configuration to use |
substitute¶
def substitute(self, block: Block) -> BlockPass 0.5: Apply substitutions (optional).
This pass replaces CallBlockOperation targets and sets strategy names on CompositeGateOperations based on config.
Parameters:
| Name | Type | Description |
|---|---|---|
block | Block | Block to transform |
Returns:
Block — Block with substitutions applied
to_block¶
def to_block(
self,
kernel: QKernel,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
) -> BlockConvert a QKernel to a Block.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel | QKernel | The QKernel to convert |
bindings | dict[str, Any] | None | Concrete values to bind at trace time (resolves array shapes) |
parameters | list[str] | None | Names to keep as unbound parameters |
When bindings or parameters are provided, uses kernel.build() to properly resolve array shapes from the bound data. Otherwise uses the cached hierarchical block for efficiency.
to_circuit¶
def to_circuit(self, kernel: QKernel, bindings: dict[str, Any] | None = None) -> TCompile and extract just the quantum circuit.
This is a convenience method for when you just want the backend circuit without the full executable.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel | QKernel | The QKernel to compile |
bindings | dict[str, Any] | None | Parameter values to bind |
Returns:
T — Backend-specific quantum circuit
transpile¶
def transpile(
self,
kernel: QKernel,
bindings: dict[str, Any] | None = None,
parameters: list[str] | None = None,
) -> ExecutableProgram[T]Full compilation pipeline from QKernel to executable.
Parameters:
| Name | Type | Description |
|---|---|---|
kernel | QKernel | The QKernel to compile |
bindings | dict[str, Any] | None | Parameter values to bind (also resolves array shapes). Names in bindings and parameters must be disjoint — a name is either compile-time bound or runtime symbolic, never both. |
parameters | list[str] | None | Parameter names to preserve as backend parameters |
Returns:
ExecutableProgram[T] — ExecutableProgram ready for execution
Raises:
ValueError— If a name appears in bothbindingsandparameters. A name being in both is ambiguous (placeholder value vs runtime symbol) and used to silently miscompile control-flow predicates that depended on parameter-array elements; rejecting the overlap up front keeps the contract unambiguous.QamomileCompileError— If compilation fails (validation, dependency errors)
Pipeline:
to_block: Convert QKernel to Block
substitute: Apply substitutions (if configured)
resolve_parameter_shapes: Constant-fold symbolic Vector param dims
inline: Inline CallBlockOperations
affine_validate: Validate affine type semantics
partial_eval: Fold constants and lower compile-time control flow
analyze: Validate and analyze dependencies
validate_symbolic_shapes: Reject unresolved parameter shape dims
plan: Build ProgramPlan (segment into C->Q->C steps)
emit: Generate backend-specific code
unroll_recursion¶
def unroll_recursion(self, block: Block, bindings: dict[str, Any] | None = None) -> BlockFixed-point loop of inline ↔ partial_eval for self-recursive kernels.
Each iteration unrolls one layer of self-referential
CallBlockOperation and then folds the base-case
IfOperation via partial_eval. Terminates when no
CallBlockOperation remains (success), when the call count
stops decreasing (symbolic driver — self-calls are left in the
IR and handled by downstream passes), or when MAX_UNROLL_DEPTH
is reached (non-terminating recursion — raises).
validate_symbolic_shapes¶
def validate_symbolic_shapes(self, block: Block) -> BlockPass 2.5: Reject unresolved parameter shape dims in loop bounds.
Runs after analyze so dependency info is complete. Raises
QamomileCompileError with an actionable message when a
gamma_dim0-style symbolic Value reaches a ForOperation
bound without being folded to a constant by
ParameterShapeResolutionPass.