diff --git a/docs/eyerahnik_QAOA_doc.md b/docs/eyerahnik_QAOA_doc.md new file mode 100644 index 0000000..70598a4 --- /dev/null +++ b/docs/eyerahnik_QAOA_doc.md @@ -0,0 +1,393 @@ +【**pyqpanda_alg.QAOA文档注释补充**】 + +注意:官方算法文档请参考:https://qcloud.originqc.com.cn/document/pyqpanda-algorithm/index.html + +本文档补充 pyqpanda_alg.QAOA 模块中的详细注释与使用示例,帮助开发者更好地理解量子近似优化算法 (QAOA) 的原理与应用。 + +--- + +## 一、QAOA 算法简介 + +**量子近似优化算法 (Quantum Approximate Optimization Algorithm, QAOA)** 是一种用于解决组合优化问题的变分量子算法。由 Farhi 等人于 2014 年提出,QAOA 通过交替应用问题哈密顿量和混合哈密顿量来寻找优化问题的近似解。 + +**核心思想:** +1. 将优化问题编码为哈密顿量 H_P(问题哈密顿量) +2. 构造混合哈密顿量 H_M(通常为横向场) +3. 通过参数化的量子电路寻找基态近似 +4. 使用经典优化器调整参数 + +**应用场景:** +- 最大割问题 (MaxCut) +- 组合优化问题 +- 二次无约束二元优化 (QUBO) +- 调度问题 +- 投资组合优化 + +--- + +## 二、核心函数注释补充 + +### 2.1 p_1 函数 - 二进制变量转泡利算符(变量值为1) + +```python +def p_1(n): + """ + 将二进制变量 x_n 转换为泡利算符 (I - Z_n) / 2 + + 数学表示: + x_n → (I - Z_n) / 2 + + 当 x_n = 1 时,(I - Z_n) / 2 = 1 + 当 x_n = 0 时,(I - Z_n) / 2 = 0 + + Parameters + n : int + 变量的索引,从 0 开始计数 + 例如:n=0 表示变量 x_0,n=1 表示变量 x_1 + + Returns + operator : PauliOperator + 泡利算符 (I - Z_n) / 2 + + Examples + 将 x_0 转换为泡利算符 + """ + from pyqpanda_alg.QAOA import qaoa + operator_0 = qaoa.p_1(0) + print(operator_0) + # 输出: { qbit_total = 1, pauli_with_coef_s = { '':0.5 + 0j, 'Z0 ':-0.5 + 0j, } } +``` + +**注释说明:** +- 该函数用于将经典优化问题中的二进制变量映射到量子算符 +- `qbit_total = 1` 表示算符作用在 1 个量子比特上 +- 输出中 `'':0.5` 表示单位矩阵系数,`'Z0 ':-0.5` 表示 Z_0 算符的系数 + +--- + +### 2.2 p_0 函数 - 二进制变量转泡利算符(变量值为0) + +```python +def p_0(n): + """ + 将二进制变量 x_n 转换为泡利算符 (I + Z_n) / 2 + + 数学表示: + x_n → (I + Z_n) / 2 + + 注意:此函数表示"反变量",即: + 当 x_n = 0 时,(I + Z_n) / 2 = 1 + 当 x_n = 1 时,(I + Z_n) / 2 = 0 + + Parameters + n : int + 变量的索引,从 0 开始计数 + + Returns + operator : PauliOperator + 泡利算符 (I + Z_n) / 2 + + 使用场景 + 在构造目标函数时,有时需要表示"变量取反"的情况 + """ + from pyqpanda_alg.QAOA import qaoa + operator_0 = qaoa.p_0(0) + print(operator_0) + # 输出: { qbit_total = 1, pauli_with_coef_s = { '':0.5 + 0j, 'Z0 ':0.5 + 0j, } } +``` + +--- + +### 2.3 problem_to_z_operator - 多项式函数转泡利算符 + +```python +def problem_to_z_operator(problem, norm=False): + """ + 将包含二进制变量的多项式函数转换为泡利算符形式 + + 数学原理: + 对于任意多项式 f(x_0, ..., x_n),使用替换规则: + x_i → (I - Z_i) / 2 + + 例如: + f(x_0, x_1) = x_0 * x_1 + → (I - Z_0)/2 * (I - Z_1)/2 + → (I - Z_0 - Z_1 + Z_0*Z_1) / 4 + + Parameters + problem : sympy.expression + 包含二进制变量的 sympy 表达式 + 例如:2*x0*x1 + 3*x2 - 1 + + norm : bool, optional + 是否对结果进行归一化处理,默认为 False + + Returns + hamiltonian : PauliOperator + 转换后的泡利算符,可直接用于 QAOA 电路构造 + + Examples + 将目标函数 2*x0*x1 + 3*x2 - 1 转换为泡利算符 + """ + import sympy as sp + from pyqpanda_alg.QAOA import qaoa + + # 定义变量符号 + vars = sp.symbols('x0:3') # 创建 x0, x1, x2 + f = 2*vars[0]*vars[1] + 3*vars[2] - 1 + print(f"目标函数: {f}") + + # 转换为泡利算符 + hamiltonian = qaoa.problem_to_z_operator(f) + print(f"泡利算符: {hamiltonian}") + + # 输出示例: + # 目标函数: 2*x0*x1 + 3*x2 - 1 + # 泡利算符: { qbit_total = 3, pauli_with_coef_s = { '':1 + 0j, 'Z2 ':-1.5 + 0j, 'Z1 ':-0.5 + 0j, 'Z0 ':-0.5 + 0j, 'Z0 Z1 ':0.5 + 0j, } } +``` + +**注释说明:** +- `qbit_total = 3` 表示需要 3 个量子比特 +- `'Z0 Z1 ':0.5` 表示 Z_0 ⊗ Z_1 算符的系数为 0.5 +- 转换后的哈密顿量可直接用于 QAOA 电路 + +--- + +## 三、QAOA 类完整使用示例 + +### 3.1 解决 MaxCut 问题 + +MaxCut(最大割)问题:给定一个图,找到一种顶点划分方式,使得跨越两个集合的边数最多。 + +```python +""" +QAOA 解决 MaxCut 问题完整示例 +================================ + +问题描述: + 给定图 G = (V, E),将顶点分为两组 S 和 V-S, + 使得连接两组的边数最大化。 + +编码方式: + 使用二进制变量 x_i 表示顶点 i 的分组 + x_i = 0 表示顶点 i 属于组 S + x_i = 1 表示顶点 i 属于组 V-S + +目标函数: + 对于边 (i, j),贡献为: + x_i * (1 - x_j) + x_j * (1 - x_i) + = x_i + x_j - 2*x_i*x_j + + 总目标:最大化所有边的贡献之和 +""" + +import numpy as np +from pyqpanda_alg.QAOA import qaoa +from pyqpanda3.core import CPUQVM, QProg +import sympy as sp + +# ====== 步骤 1:定义问题 ====== +# 三角形图的 MaxCut 问题 +# 顶点: 0, 1, 2 +# 边: (0,1), (1,2), (0,2) + +x0, x1, x2 = sp.symbols('x0 x1 x2') + +# 目标函数(最大化):x_i + x_j - 2*x_i*x_j 对每条边求和 +objective = (x0 + x1 - 2*x0*x1) + (x1 + x2 - 2*x1*x2) + (x0 + x2 - 2*x0*x2) +print(f"目标函数: {objective}") + +# ====== 步骤 2:转换为哈密顿量 ====== +hamiltonian = qaoa.problem_to_z_operator(objective) +print(f"哈密顿量: {hamiltonian}") + +# ====== 步骤 3:运行 QAOA ====== +qaoa_solver = qaoa.QAOA(problem=hamiltonian) + +# 使用 3 层 QAOA 电路 +result, params = qaoa_solver.run( + layer=3, # QAOA 层数 + loss_type='default', # 损失函数类型 + optimize_type='default', # 优化类型 + optimizer='COBYLA', # 经典优化器 + optimizer_option={'options': {'maxiter': 100}} +) + +print(f"\n结果概率分布:") +for state, prob in sorted(result.items(), key=lambda x: -x[1])[:4]: + print(f" 状态 {state}: 概率 {prob:.4f}") + +# ====== 步骤 4:解释结果 ====== +# 概率最高的状态即为近似最优解 +best_state = max(result.items(), key=lambda x: x[1]) +print(f"\n最优解: {best_state[0]} (概率: {best_state[1]:.4f})") +print(f"分组: 顶点 {best_state[0].count('0')} 个在组 A,{best_state[0].count('1')} 个在组 B") +``` + +--- + +### 3.2 QAOA 参数优化过程可视化 + +```python +""" +QAOA 参数优化追踪示例 +==================== + +本示例展示如何追踪 QAOA 优化过程中的参数变化, +帮助理解变分量子算法的工作原理。 +""" + +import numpy as np +from pyqpanda_alg.QAOA import qaoa +import sympy as sp +import matplotlib.pyplot as plt + +# 定义简单的优化问题 +x0, x1 = sp.symbols('x0 x1') +problem = -x0*x1 + x0 + x1 # 目标函数 + +# 转换为哈密顿量 +H = qaoa.problem_to_z_operator(problem) + +# 创建 QAOA 求解器 +solver = qaoa.QAOA(problem=H) + +# 运行 QAOA 并获取优化历史 +layer_num = 4 +result, optimal_params = solver.run( + layer=layer_num, + optimizer='SLSQP', + optimizer_option={'options': {'maxiter': 50}} +) + +print(f"优化后的参数: {optimal_params}") +print(f"\n结果分布:") +for state, prob in sorted(result.items(), key=lambda x: -x[1])[:2]: + print(f" |{state}⟩: {prob*100:.2f}%") + +# 参数说明: +# - optimal_params 包含 2*layer 个参数 +# - 前 layer 个是 γ 参数(问题哈密顿量) +# - 后 layer 个是 β 参数(混合哈密顿量) +gamma_params = optimal_params[:layer_num] +beta_params = optimal_params[layer_num:] + +print(f"\nγ 参数(问题层): {gamma_params}") +print(f"β 参数(混合层): {beta_params}") +``` + +--- + +## 四、常见问题与异常处理 + +### 4.1 变量数量与量子比特 + +```python +""" +注意事项:变量数量与量子比特的关系 +==================================== + +QAOA 中需要的量子比特数 = 问题中二进制变量的数量 + +例如: + - 问题有 3 个变量 x0, x1, x2 → 需要 3 个量子比特 + - 问题有 10 个变量 → 需要 10 个量子比特 + +重要限制: + - 当前量子计算机的量子比特数有限 + - 模拟器可处理的量子比特数取决于内存 + - 建议在小规模问题上测试(< 20 比特) +""" + +from pyqpanda_alg.QAOA import qaoa +import sympy as sp + +# 正确示例:明确变量数量 +vars = sp.symbols('x0:5') # 5 个变量 → 5 个量子比特 +f = sum(vars) # 简单求和 +H = qaoa.problem_to_z_operator(f) +print(f"量子比特数: {H.max_index() + 1}") # 输出量子比特数 +``` + +### 4.2 优化器选择建议 + +```python +""" +优化器选择指南 +============== + +不同优化器的特点和适用场景: + +1. SLSQP (推荐默认) + - 序列二次规划 + - 收敛快,适合中小规模问题 + - 参数:maxiter, ftol, eps + +2. COBYLA + - 无需梯度信息 + - 适合噪声较大的情况 + - 参数:maxiter, rhobeg + +3. SPSA (量子场景推荐) + - 同时扰动随机逼近 + - 对噪声鲁棒 + - 适合真实量子硬件 + - 参数:见 spsa.spsa_minimize 文档 + +4. Nelder-Mead + - 单纯形法 + - 无需梯度 + - 可能陷入局部最优 + +选择建议: + - 模拟器 + 小问题 → SLSQP + - 真实硬件/噪声环境 → SPSA + - 不确定时 → COBYLA +""" + +from pyqpanda_alg.QAOA import qaoa +import sympy as sp + +x0, x1 = sp.symbols('x0 x1') +problem = x0*x1 - x0 - x1 +H = qaoa.problem_to_z_operator(problem) +solver = qaoa.QAOA(problem=H) + +# 使用不同优化器的示例 +# 方式1:SLSQP(快速收敛) +result_slsqp = solver.run(layer=2, optimizer='SLSQP') + +# 方式2:COBYLA(无梯度) +result_cobyla = solver.run(layer=2, optimizer='COBYLA') + +# 方式3:SPSA(适合噪声环境) +result_spsa = solver.run(layer=2, optimizer='SPSA') +``` + +--- + +## 五、API 快速参考 + +| 函数名 | 功能 | 输入 | 输出 | +|--------|------|------|------| +| `p_1(n)` | 变量→泡利算符(值为1) | 索引 n | PauliOperator | +| `p_0(n)` | 变量→泡利算符(值为0) | 索引 n | PauliOperator | +| `problem_to_z_operator(f)` | 多项式→哈密顿量 | sympy表达式 | PauliOperator | +| `QAOA(problem)` | 创建求解器 | PauliOperator | QAOA实例 | +| `run(layer, optimizer)` | 运行优化 | 层数、优化器 | (结果字典, 参数) | + +--- + +## 六、参考文献 + +[1] E. Farhi, J. Goldstone, S. Gutmann, "A Quantum Approximate Optimization Algorithm", arXiv:1411.4028 (2014) + +[2] S. Hadfield et al., "From the Quantum Approximate Optimization Algorithm to a Quantum Alternating Operator Ansatz", Algorithms 12.2 (2019) + +[3] 本源量子云平台文档:https://qcloud.originqc.com.cn/document/pyqpanda-algorithm/ + +--- + +**贡献者:** eyerahnik +**日期:** 2026-03-07 +**关联Issue:** [#1 内容纠错与注释补充](https://github.com/OriginQ/pyqpanda-algorithm/issues/1)