Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
393 changes: 393 additions & 0 deletions docs/eyerahnik_QAOA_doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,393 @@
【**pyqpanda_alg.QAOA文档注释补充**】

<u>注意:官方算法文档请参考:https://qcloud.originqc.com.cn/document/pyqpanda-algorithm/index.html</u>

本文档补充 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)