跳转至

从目标求值到最终采样,读懂一次 QAOA

对图问题中的三节点路径运行一层 QAOA。先阅读 QUBO 映射,使用安装好的环境。本例的求值预算很小,用于观察流程,不用于展示收敛表现。

按 (a,b,c) 读取比特,最小化的代价为 f(x) = −(xa + xb + xc) + 2(xa xb + xb xc)。独立集 101 的值为 −2。三个节点全选得到 −3 + 2×2 = 1,同时违反约束。过低的罚系数可能使无效集合更有利,因此图接口会要求合适的罚系数。

层数、求值次数和采样次数各指什么

QAOA 从等幅叠加态开始,交替施加由 γ 控制的代价演化和由 β 控制的 X 混合操作。一层有两个参数,initial_parameters=(0.2, -0.3) 依次提供 γ 和 β。一层不等于求值一次:优化器会尝试多组参数。

"""针对小型 MIS 问题运行完整的本地 QAOA 流程。

程序完成问题投影、ansatz 构造、Backend objective evaluation、SciPy 优化、最终
采样和候选解码,并给出有界的经典比较。该比较只适用于当前小问题,不证明全局最优。
"""

from __future__ import annotations

import json

from cascaqit import QAOA, GraphProblemIR, LocalBackend, OptimizerConfig


def main() -> None:
    """使用固定输入优化并采样一个三节点路径图。"""
    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_zh.py

配置最多允许五次目标求值,之后在选定参数处单独执行 64 次最终采样。max_iterations=8 不会覆盖 max_evaluations=5。查看停止原因,才能知道实际由哪个条件结束优化。

{
  "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"
}

求值方式为 exact_state,且 objective_total_shots 为零,表示优化器直接读取模拟状态的期望值。final_shots=64 影响单独的最终采样,不影响这些期望值的精度。每次状态演化仍然消耗 CPU。

best_energy 是对所有可能比特串的期望值。candidate_bitstring 是最终计数中实际出现过、代价最低的比特串,不一定是出现次数最多的那个。candidate_feasible 检查图约束。经典基准穷举这个小问题,找到值为 −2 的 101。

即使最佳期望值还高于 −2、停止原因为 max_evaluations,最终采样仍可能碰到最优候选。得到一次好样本,并不说明分布已经集中到最优解,也不说明优化器收敛。SDK 在候选的最优性字段上保留 not_claimed。

改变预算并解释影响

  1. 保持优化配置不变,只把 final_shots 提高到 1024,哪些输出可能变化?
  2. 改为两层,却仍提供两个初始参数。解释输入错误,再尝试四元素向量。
  3. 从计数计算 101 的频率,以及所有可行集合的总频率。它们与期望能量有什么区别?

增加最终采样会改变采样成本和计数,本例精确求值的优化计算不变。两层需要四个参数,同时要调整 COBYLA 预算:最低求值次数为 参数数目 + 2,四个参数不能继续只给五次。可行串为 000、001、010、100、101,只有 101 最优。可行率、最优解频率和平均代价回答的是不同问题。

接口详情见变分算法指南。下一课通过 VQE改变线路的构造方式。

English version

SDK 1.0.8a · `8b227bff`