mcpField
P
pennylane

pennylane

github.com/tondevrel开发2443 次安装39 周前更新
代码仓库

关于 pennylane

PennyLane 是用于构建和微分量子电路的 Python 框架,可将电路用于量子与经典混合模型。它支持量子机器学习、变分算法及量子化学工作流,并可连接模拟器和硬件。

主要功能

  1. 01可微分量子电路
  2. 02基于梯度的电路优化
  3. 03量子与经典混合模型
  4. 04量子化学工具
  5. 05模拟器与硬件设备接口

适用场景

  1. 01训练量子神经网络
  2. 02实现 VQE 或 QAOA
  3. 03执行可微分量子化学计算
  4. 04跨设备测试量子算法

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tondevrel/scientific-agent-skills --skill pennylane

安装后在 Claude Code 中输入/pennylane确认已加载。

详细介绍

PennyLane - 量子机器学习

PennyLane 将量子计算机视作神经网络层。它支持计算量子电路的梯度(使用参数位移规则或反向传播),从而能够优化经典-量子混合模型。

适用场景

  • 开发和训练量子神经网络(QNN)
  • 变分量子算法(VQE、QAOA)
  • 经典-量子混合机器学习(例如量子 CNN)
  • 在可微分框架中进行量子化学计算
  • 对比不同硬件上的量子算法(IBM、Rigetti、Xanadu、IonQ)
  • 优化量子控制脉冲
  • 研究贫瘠高原及其他 QML 特有现象

参考文档

官方文档:https://docs.pennylane.ai/
演示/教程:https://pennylane.ai/qml/demonstrations.html
搜索模式:qml.qnode、qml.device、qml.expval、qml.grad、qml.templates

核心原则

QNode(量子节点)

QNode 是与设备绑定的量子电路,可以像标准 Python 函数一样调用。它是 PennyLane 能够求导的基本单元。

硬件无关性

PennyLane 提供统一的接口。同一段代码可以运行在高性能模拟器(default.qubit)、GPU 加速后端(lightning.qubit)或真实量子硬件上。

自动微分

PennyLane 中的量子电路能够“感知”自身的梯度。你可以使用标准优化器(Adam、SGD)来调整电路中的旋转角度。

快速参考

安装
pip install pennylane
# For GPU support
pip install pennylane-lightning[gpu]
标准导入
import pennylane as qml
from pennylane import numpy as np # Use PennyLane's wrapped NumPy for gradients
基本模式 - 可微分电路
import pennylane as qml
from pennylane import numpy as np

# 1. Define Device
dev = qml.device("default.qubit", wires=2)

# 2. Define QNode (Quantum Node)
@qml.qnode(dev)
def circuit(params):
    qml.RX(params[0], wires=0)
    qml.RY(params[1], wires=1)
    qml.CNOT(wires=[0, 1])
    return qml.expval(qml.PauliZ(1))

# 3. Calculate Gradient
params = np.array([0.1, 0.2], requires_grad=True)
grad_fn = qml.grad(circuit)
print(f"Gradient: {grad_fn(params)}")

关键规则

✅ 应该做
  • 使用 qml.numpy - 对于需要求导的参数,始终使用 PennyLane 封装的 NumPy
  • 使用模板 - 不要手动构建层,而应使用 qml.templates(例如 StronglyEntanglingLayers)构建高效的 QML 架构
  • 设置 requires_grad - 显式使用 requires_grad=True 标记可训练参数
  • 优先选择 lightning.qubit - 对于超过 15 个量子比特的模拟,使用 lightning 设备可显著提升性能
  • 使用广播 - 许多门支持对输入数组进行广播,这比循环更快
  • 批量处理电路 - 使用 qml.batch_input 或 qml.map 同时处理多个输入
❌ 不要做
  • 混用 NumPy 版本 - 对可训练参数使用标准的 import numpy as np 会破坏自动微分引擎
  • 让 Ansatz 过于复杂 - 从简单电路开始,以避免贫瘠高原(梯度消失的现象)
  • 在模拟器上使用过多量子比特 - 内存用量随 2^N 增长。30 个量子比特的单个状态向量约需 16GB RAM
  • 硬编码 Wire 索引 - 使用变量表示线路,让代码可复用且易于扩展

反模式(切勿使用)

import pennylane as qml
# ❌ BAD: Standard numpy for trainable parameters
import numpy as np 

# ✅ GOOD: PennyLane's wrapped numpy
from pennylane import numpy as np

# ❌ BAD: Creating a device inside a loop
for i in range(100):
    dev = qml.device("default.qubit", wires=2) # Expensive initialization

# ✅ GOOD: Define device once
dev = qml.device("default.qubit", wires=2)

# ❌ BAD: Manual parameter shifting
# (shift = 0.5 * pi, calc f(x+s) - f(x-s)...)
# ✅ GOOD: Let PennyLane handle it automatically
grad = qml.grad(circuit)(params)

电路模板(qml.templates)

内置 QML 层
import pennylane as qml

@qml.qnode(dev)
def qnn_layer(inputs, weights):
    # Encoding classical data into quantum state
    qml.AngleEmbedding(inputs, wires=range(n_qubits))
    
    # Trainable entangling layer
    qml.StronglyEntanglingLayers(weights, wires=range(n_qubits))
    
    return qml.expval(qml.PauliZ(0))

混合优化(PyTorch/TF)

与经典框架集成
import torch
import pennylane as qml

dev = qml.device("default.qubit", wires=2)

@qml.qnode(dev, interface="torch")
def quantum_layer(phi, theta):
    qml.RX(phi, wires=0)
    qml.RZ(theta, wires=1)
    return qml.expval(qml.PauliZ(0))

# Now this QNode can be used in a Torch Module
phi = torch.tensor(0.1, requires_grad=True)
theta = torch.tensor(0.2, requires_grad=True)
result = quantum_layer(phi, theta)
result.backward()
print(phi.grad)

量子化学(qml.qchem)

VQE 工作流
from pennylane import qchem

# 1. Define molecule
symbols = ["H", "H"]
coordinates = np.array([0.0, 0.0, -0.6614, 0.0, 0.0, 0.6614])

# 2. Build Hamiltonian
H, qubits = qchem.molecular_hamiltonian(symbols, coordinates)

# 3. Define VQE circuit
dev = qml.device("default.qubit", wires=qubits)
@qml.qnode(dev)
def vqe_circuit(params):
    # Simple Hartree-Fock state + rotations
    qml.BasisState(np.array([1, 1, 0, 0]), wires=range(qubits))
    qml.DoubleExcitation(params[0], wires=[0, 1, 2, 3])
    return qml.expval(H)

测量与可观测量

期望值之外
@qml.qnode(dev)
def multi_measure(params):
    qml.RX(params[0], wires=0)
    return (
        qml.expval(qml.PauliZ(0)), # Expectation value
        qml.var(qml.PauliZ(0)),    # Variance
        qml.probs(wires=[0, 1]),   # Probabilities
        qml.sample(qml.PauliX(1))  # Raw samples (shots)
    )

实用工作流

1. 量子变分分类器
def variational_classifier(weights, bias, x):
    """A simple QNN classifier."""
    return circuit(weights, x) + bias

def cost(weights, bias, X, Y):
    predictions = [variational_classifier(weights, bias, x) for x in X]
    return square_loss(Y, predictions)

# Optimizer
opt = qml.AdamOptimizer(stepsize=0.1)
# ... loop with opt.step(cost, ...)
2. 在硬件上计算梯度(参数位移)
# When running on real hardware, PennyLane automatically uses
# the parameter-shift rule to calculate gradients via multiple executions.
dev_remote = qml.device("braket.aws.qubit", device_arn="...", wires=2)

@qml.qnode(dev_remote, diff_method="parameter-shift")
def hardware_circuit(params):
    qml.RY(params[0], wires=0)
    return qml.expval(qml.PauliZ(0))
3. 噪声模拟
dev_noisy = qml.device("default.mixed", wires=2)

@qml.qnode(dev_noisy)
def noisy_circuit(p):
    qml.Hadamard(wires=0)
    # Apply depolarizing noise to wire 0
    qml.DepolarizingChannel(p, wires=0)
    return qml.state()

性能优化

集成 JAX 以提升速度

对于大规模模拟,JAX 通常是速度最快的接口,这得益于其即时(JIT)编译。

import jax

@qml.qnode(dev, interface="jax")
def fast_circuit(x):
    qml.RX(x, wires=0)
    return qml.expval(qml.PauliZ(0))

jit_circuit = jax.jit(fast_circuit)
伴随微分

对于大型电路,diff_method="adjoint" 比反向传播更加节省内存。

dev = qml.device("lightning.qubit", wires=20)
@qml.qnode(dev, diff_method="adjoint")
def large_circuit(params):
    ...

常见问题与解决方案

“梯度消失”(贫瘠高原)

随着量子比特数和层数增加,梯度通常会变得极小。

# ✅ Solution: 
# 1. Use better initialization for weights.
# 2. Use local observables (PauliZ(i)) instead of global ones.
# 3. Use identity-block initialization.
不可训练的输入

有时你希望传入不应参与优化的数据(例如图像)。

# ✅ Solution: Use the 'argnum' in qml.grad or use non-array types
# Or explicitly:
params = np.array(0.1, requires_grad=True)
data = np.array(0.5, requires_grad=False)
输出形状不匹配

qml.probs 返回一个大小为 2^N 的数组。

# ❌ Problem: Using probs(wires=[0,1,2]) in a loss function expecting a scalar.
# ✅ Solution: Use expval() for a single scalar or handle the distribution.

PennyLane 架起了量子物理学与人工智能之间的桥梁。通过使量子电路可微,它将量子电路转变为强大的可训练工具,助力新一代科学计算。

评论

支持 Markdown