Skip to content

Compile an optimization problem and run the generated program

Import ProblemCompiler from cascaqit.problems. It turns Graph, MIS, MWIS, QUBO or Ising problems into native programs while retaining logical order and decoding rules. Start with a small problem and a classical reference before increasing the parameter budget or circuit depth.

Mode and algorithm Generated program Check before choosing
digital + qaoa Digital circuit Depth and parameter budget
digital + vqe Variational digital circuit Ansatz, constraints and measurement method
hybrid + qaoa Alternating Digital–Analog program A nonempty Analog contribution is required; remaining terms are explicit Digital operations
analog + qaa AHS program Whether target geometry and controls can express the full Hamiltonian

analyze(problem, target=...) examines mappings and route feasibility without running an experiment. compile(...) requires explicit mode, algorithm and target arguments. Its result still needs parameter values and an execution call.

Run a three-node example first

This example executes one set of Digital QAOA parameters on a three-node path. Enumerating the eight classical candidates gives a maximum independent-set size of 2, selecting a and c.

"""Run a small graph problem through the digital compilation route."""

from __future__ import annotations

import json

from cascaqit import MockNeutralAtomTarget
from cascaqit.problems import GraphProblemIR, ProblemCompiler, decode_graph_bitstring


def main() -> None:
    """Compare sampled candidates with a three-node classical reference."""
    graph = GraphProblemIR.from_edges(
        problem_id="guide.problem.path",
        positions={"a": (0.0, 0.0), "b": (6.0, 0.0), "c": (12.0, 0.0)},
        edges=(("a", "b"), ("b", "c")),
    )
    compiled = ProblemCompiler().compile(
        graph,
        mode="digital",
        algorithm="qaoa",
        target=MockNeutralAtomTarget.local_ahs_v0_1(),
        layers=1,
    )
    execution = compiled.run(
        params={"gamma_0": 0.16, "beta_0": 0.24}, shots=128, seed=508
    )
    candidates = [decode_graph_bitstring(graph, f"{i:03b}") for i in range(8)]
    optimum = max(
        item["selection_size"] for item in candidates if item["is_independent"]
    )
    counts = execution.result.counts
    feasible_counts = sum(
        count
        for bits, count in counts.items()
        if decode_graph_bitstring(graph, bits)["is_independent"]
    )
    if sum(counts.values()) != 128 or optimum != 2:
        raise RuntimeError("The sample total or classical reference is incorrect.")
    print(
        json.dumps(
            {
                "mode": "digital",
                "algorithm": "qaoa",
                "logical_order": list(execution.logical_order),
                "counts": counts,
                "counts_total": sum(counts.values()),
                "classical_maximum_size": optimum,
                "feasible_frequency": feasible_counts / 128,
                "best_observed_bitstring": execution.best_observed_candidate.bitstring,
                "best_observed_feasible": execution.best_observed_candidate.feasible,
                "objective_value": execution.objective_value,
            },
            sort_keys=True,
        )
    )


if __name__ == "__main__":
    main()

Download the full script

python examples/learning/guides/problem_compile_en.py
{
  "algorithm": "qaoa",
  "best_observed_bitstring": "101",
  "best_observed_feasible": true,
  "classical_maximum_size": 2,
  "counts": {
    "000": 19,
    "001": 13,
    "010": 14,
    "011": 19,
    "100": 14,
    "101": 10,
    "110": 15,
    "111": 24
  },
  "counts_total": 128,
  "feasible_frequency": 0.546875,
  "logical_order": [
    "a",
    "b",
    "c"
  ],
  "mode": "digital",
  "objective_value": -0.33529298728005646
}

The logical_order is a, b, c, so 101 selects a and c. Counts should total 128. feasible_frequency is the fraction of samples satisfying the independent-set constraints; it depends on the sampling budget and seed.

There is no parameter search in this example, so it makes no claim about QAOA convergence. objective_value is the expected objective for these parameters. best_observed_bitstring identifies the best sampled candidate, which is a different quantity.

Compare parameters or compilation routes

Use compiled.evaluate(params=...) for one objective evaluation, or compiled.optimize(parameter_sets=...) to compare a specified list of candidates. For continuous search, pass optimizer=OptimizerConfig(...) instead. Choose either discrete candidates or an optimizer configuration. Record actual evaluation and sampling costs before comparing outcomes.

The three-route MIS project runs Digital, Hybrid and Analog experiments for the same problem and creates reports. Check problem_hash and logical order before comparing results; retain each route’s target, algorithm, parameters, budgets and simulation settings. Resource estimates in different units do not give a performance ranking.

Analog compilation rejects couplings it cannot represent; it does not insert hidden Digital blocks. In Hybrid QAOA, each gamma_i also sets an Analog duration and must be strictly positive. The unified Analog and Hybrid compilation results currently reject noisy requests and gradient execution, even where the general backend supports those features.

See OptimizerConfig for optimizer fields and the full compiler guide in the repository for ansatz choices, depth experiments and result details.

中文版

SDK 1.0.8a · `8b227bff`