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. 02VQEや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 アーキテクチャー向けの qml.templates(StronglyEntanglingLayers など)を使用してください
  • 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 が必要です
  • ワイヤーのインデックスをハードコードしない - コードの再利用性と拡張性を高めるため、ワイヤーには変数を使用してください

アンチパターン(絶対に避ける)

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 統合

大規模シミュレーションでは、Just-In-Time(JIT)コンパイルにより、JAX が最速のインターフェースとなることがよくあります。

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 は量子物理学と人工知能の間の橋渡しをします。量子回路を微分可能にすることで、次世代の科学計算に向けた強力でトレーニング可能なツールへと変えます。

コメント