Follow a QAOA run from objective to samples¶
Run one-layer QAOA on the three-node path from graph problems. Read QUBO projection first, then use the installed environment. The small evaluation budget exposes the workflow; it is not a convergence demonstration.
For bits in (a,b,c) order, the minimized cost is f(x) = −(xa + xb + xc) + 2(xa xb + xb xc). The independent set 101 has value −2. Selecting all three nodes gives −3 + 2×2 = 1 and is infeasible. A low penalty could favor an invalid set, so the graph interface requires an appropriate penalty.
Distinguish layers, evaluations and shots¶
QAOA starts from equal superposition and alternates a cost evolution controlled by γ and an X mixer controlled by β. One layer has two parameters; initial_parameters=(0.2, -0.3) supplies γ then β. One layer is not one objective evaluation: the optimizer evaluates several parameter choices.
"""Run a complete local QAOA workflow for a small MIS problem.
One workflow covers problem projection, ansatz construction, real Backend
objective evaluations, SciPy optimization, final sampling, candidate decoding,
and a bounded classical baseline. No global-optimality claim is inferred.
"""
from __future__ import annotations
import json
from cascaqit import QAOA, GraphProblemIR, LocalBackend, OptimizerConfig
def main() -> None:
"""Optimize and sample a three-node path graph with fixed inputs."""
graph = GraphProblemIR.from_edges(
problem_id="lesson.optimization.qaoa",
positions={"a": (0.0, 0.0), "b": (5.0, 0.0), "c": (10.0, 0.0)},
edges=(("a", "b"), ("b", "c")),
)
result = QAOA(graph, layers=1, mis_penalty=2.0).run(
backend=LocalBackend(seed=501),
optimizer=OptimizerConfig(
method="COBYLA", max_iterations=8, max_evaluations=5, seed=501
),
initial_parameters=(0.2, -0.3),
final_shots=64,
)
candidate = result.best_observed_candidate
baseline = result.baseline
assert candidate is not None and baseline is not None
assert result.final_result is not None
payload = {
"track": "optimization_researcher",
"level": "applied",
"lesson": "qaoa_workflow",
"facts": {
"objective_estimator": result.metadata["objective_estimator"],
"objective_total_shots": result.metadata["objective_total_shots"],
"workflow_total_shots": result.metadata["workflow_total_shots"],
"backend_executions": result.metadata["workflow_backend_execution_count"],
"final_counts": result.final_result.counts,
"final_probabilities": result.final_result.probabilities,
"candidate_count": candidate.count,
"best_energy": round(result.best_evaluation.energy, 10),
"candidate_value": candidate.objective_value,
"termination_reason": result.termination.reason,
"evaluations": len(result.evaluations),
"counts_total": sum(result.final_result.counts.values()),
"candidate_bitstring": candidate.bitstring,
"candidate_feasible": candidate.feasible,
"baseline_value": baseline.objective_value,
"optimality_claim": candidate.optimality_claim,
},
"boundaries": {
"hardware_execution": False,
"cloud_execution": False,
"network_accessed": False,
"credentials_loaded": False,
},
}
print(json.dumps(payload, sort_keys=True))
if __name__ == "__main__":
main()
python3 examples/user/tracks/optimization_researcher/03_applied_qaoa_workflow_en.py
The configuration permits at most five objective evaluations, then performs a separate 64-shot sampling run at the selected parameters. max_iterations=8 does not override max_evaluations=5. Read the termination reason to see which condition stopped optimization.
{
"boundaries": {
"cloud_execution": false,
"credentials_loaded": false,
"hardware_execution": false,
"network_accessed": false
},
"facts": {
"backend_executions": 6,
"baseline_value": -2.0,
"best_energy": -1.0259301196,
"candidate_bitstring": "101",
"candidate_count": 14,
"candidate_feasible": true,
"candidate_value": -2.0,
"counts_total": 64,
"evaluations": 5,
"final_counts": {
"001": 9,
"010": 21,
"011": 4,
"100": 3,
"101": 14,
"110": 2,
"111": 11
},
"final_probabilities": {
"000": 0.006485865446572203,
"001": 0.13794438752156066,
"010": 0.31275386143691747,
"011": 0.04281588559494963,
"100": 0.13794438752156063,
"101": 0.2521757366567452,
"110": 0.042815885594949664,
"111": 0.06706399022674457
},
"objective_estimator": "exact_state",
"objective_total_shots": 0,
"optimality_claim": "not_claimed",
"termination_reason": "max_evaluations",
"workflow_total_shots": 64
},
"lesson": "qaoa_workflow",
"level": "applied",
"track": "optimization_researcher"
}
The exact_state estimator and zero objective_total_shots mean the optimizer reads expectations from the simulated state. final_shots=64 affects the separate sample, not the accuracy of those expectations. Each evolution still consumes CPU.
best_energy is an expectation across all possible bitstrings. candidate_bitstring is the lowest-cost bitstring actually observed in the final counts, not necessarily the most frequent one. candidate_feasible checks the graph constraint. The classical baseline enumerates this small problem and finds 101 with value −2.
You can observe that optimal candidate while the best expectation remains above −2 and termination reports max_evaluations. One good sample does not show that the distribution concentrates on the optimum or that the optimizer converged. The SDK retains not_claimed on the candidate's optimality field.
Test a budget change¶
- Increase
final_shotsto 1024 with all optimizer settings fixed. Which results can change? - Increase layers to two but retain the two-element initial vector. Explain the input error, then try four initial parameters.
- Compute the frequency of
101and the total frequency of feasible sets from the recorded counts. How do these differ from expectation energy?
More final shots change sampling cost and counts; this exact optimization follows the same objective calculation. Two layers need four parameters. Also revisit COBYLA's minimum evaluation budget of parameter_count + 2: five is insufficient for four parameters. The feasible strings are 000, 001, 010, 100, 101; only 101 is optimal. Feasible frequency, optimal frequency and mean cost answer different questions.
See variational algorithms for interface details. Continue with VQE to change how the circuit is constructed.