Start/Blog/Wie Sie Ihre Shot-Anzahl in variationellen Quantenalgorithmen um 80 % senken
OptimizationVQEQAOAQPU

Wie Sie Ihre Shot-Anzahl in variationellen Quantenalgorithmen um 80 % senken

Praktische Techniken zur Reduzierung der Anzahl benötigter Schaltkreisausführungen in VQE und QAOA — shot-sparsame Optimierer, Tricks zur Gradientenschätzung und Messgruppierung.

FreeQuantumComputing
·· 8 min read

Jedes Mal, wenn Sie einen Quantenschaltkreis auf echter Hardware ausführen, kostet das QPU-Zeit und Geld. Variationelle Algorithmen wie VQE und QAOA können Hunderttausende von Schaltkreisausführungen benötigen, um zu konvergieren — bei $0,075–$0,90 pro Task auf Cloud-QPUs summiert sich das schnell.

Die gute Nachricht: Die meisten Standardimplementierungen sind extrem shot-ineffizient. Mit den richtigen Techniken können Sie den Shot-Bedarf um 50–90 % senken, ohne die Ergebnisqualität zu beeinträchtigen.

Warum die Shot-Anzahl standardmäßig so hoch ist

VQE berechnet Erwartungswerte von Pauli-Operatoren. Ein Hamiltonian wird in eine Summe von Pauli-Termen zerlegt, und jeder Term erfordert eine separate Schaltkreisausführung. Für ein Molekül wie H₂ (4 Qubits) gibt es ~15 Pauli-Terme. Für größere Moleküle explodiert die Anzahl:

MolekülQubitsPauli-TermeNaive Shots/Iteration
H₂41515.000
LiH12631631.000
BeH₂14666666.000
H₂O141.0861.086.000

Mit 200 Optimierer-Iterationen benötigt H₂O naiv 217 Millionen Shots. Die folgenden Techniken reduzieren dies um 80–95 %.

Technik 1: Messgruppierung (Der größte Gewinn)

Viele Pauli-Terme kommutieren — sie können in einer einzigen Schaltkreisausführung gleichzeitig gemessen werden, statt separat. Das Gruppieren kommutierender Observablen ist die größte einzelne verfügbare Reduktion.

from qiskit.primitives import StatevectorEstimator
from qiskit_nature.second_q.mappers import JordanWignerMapper
from qiskit_algorithms import VQE
from qiskit_algorithms.optimizers import COBYLA

# Qiskit automatically groups commuting Paulis in the Estimator primitive
# This reduces shots from O(n_terms) to O(n_groups) — often 5-10x reduction
estimator = StatevectorEstimator()

# With PennyLane, use grouping explicitly:
import pennylane as qml

H = qml.Hamiltonian(coeffs, observables)

# Group commuting terms — usually reduces term count by 5-10x
groups = qml.grouping.group_observables(observables, grouping_type='qwc')
print(f"Original terms: {len(observables)}, Groups: {len(groups)}")
# Original terms: 631, Groups: 68  (for LiH)

Erwartete Einsparung: 5–15× bei typischen chemischen Hamiltonians.

Technik 2: Shot-sparsame Optimierer

Klassische Optimierer wie L-BFGS-B oder ADAM setzen rauschfreie Funktionsauswertungen voraus — sie fordern mehr Gradientenauswertungen an als nötig, wenn die Ergebnisse verrauscht sind. Shot-sparsame Optimierer verteilen die Shots adaptiv basierend auf der Messvarianz.

from pennylane.optimize import AdaptiveOptimizer, ShotAdaptiveOptimizer

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

@qml.qnode(dev)
def circuit(params):
    # ansatz
    ...
    return qml.expval(H)

# ShotAdaptiveOptimizer: allocates more shots to high-variance directions
opt = ShotAdaptiveOptimizer(min_shots=10)

params = np.random.uniform(-np.pi, np.pi, n_params)
for i in range(100):
    params, _, shots_used = opt.step_and_cost(circuit, params)
    print(f"Step {i}: shots used = {shots_used}")

Der Optimierer beginnt mit wenigen Shots pro Auswertung und erhöht sie nur, wenn der Gradient unsicher ist. Ein typischer VQE-Lauf verwendet 5–10× weniger Shots als COBYLA mit fester Shot-Anzahl.

Technik 3: Parameter-Shift-Gradienten (Weniger Auswertungen nutzen)

Die naive Gradientenschätzung per Finite-Differenzen (f(x+ε) - f(x))/ε hat hohe Varianz bei kleinem ε und großen Bias bei großem ε. Die Parameter-Shift-Regel liefert exakte Gradienten mit nur 2 Schaltkreisauswertungen pro Parameter:

# PennyLane uses parameter-shift by default for gradients
@qml.qnode(dev, diff_method="parameter-shift")  # 2 evals per param
def circuit(params):
    ...

# Compare to finite-difference (requires 1 eval per param but biased):
@qml.qnode(dev, diff_method="finite-diff")  # 1 eval but approximate

# For large circuits, use "best" — PennyLane chooses adjoint on simulator,
# parameter-shift on hardware
@qml.qnode(dev, diff_method="best")
def circuit(params):
    ...

Bei n Parametern kostet Parameter-Shift 2n Auswertungen pro Gradientenschritt. Verwenden Sie gradientenfreie Optimierer (COBYLA, SPSA, Nelder-Mead), wenn n groß ist.

Technik 4: SPSA — Stochastische Gradientenschätzung

Simultaneous Perturbation Stochastic Approximation (SPSA) schätzt den vollständigen Gradienten mit nur 2 Schaltkreisauswertungen unabhängig von der Anzahl der Parameter, indem alle Parameter gleichzeitig gestört werden:

from qiskit_algorithms.optimizers import SPSA

# SPSA: 2 evaluations per step regardless of parameter count
# vs parameter-shift: 2n evaluations per step
optimizer = SPSA(maxiter=300, learning_rate=0.1, perturbation=0.05)

# For 10 parameters:
# - Parameter shift: 2×10 = 20 evals/step × 300 steps = 6,000 total
# - SPSA: 2 evals/step × 300 steps = 600 total  ← 10x reduction

Am besten geeignet, wenn: der Schaltkreis viele Parameter hat (> 10). Der Kompromiss ist eine langsamere Konvergenz pro Schritt, aber insgesamt weniger Shots.

Technik 5: Vorzeitiger Abbruch + Varianzschwellenwert

Führen Sie Schaltkreise nicht bis zum Ende aus, wenn das Ergebnis bereits gut genug ist:

from pennylane.optimize import AdamOptimizer
import numpy as np

opt = AdamOptimizer(stepsize=0.02)
params = init_params.copy()
prev_energy = float('inf')

for step in range(max_steps):
    params, energy = opt.step_and_cost(circuit, params)

    # Stop when change is below shot-noise floor
    variance = 1.0 / np.sqrt(shots_per_eval)  # shot noise floor
    if abs(energy - prev_energy) < variance:
        print(f"Converged at step {step}")
        break

    prev_energy = energy

Viele VQE-Läufe erreichen früh ein Plateau — eine Fortsetzung verschwendet nur Shots auf Rauschfluktuationen.

Technik 6: Warmstart

Initialisieren Sie QAOA- oder VQE-Parameter aus einer verwandten klassischen Lösung statt zufällig:

# For QAOA on Max-Cut: warm start from a greedy classical solution
import networkx as nx

G = nx.from_edgelist(edges)
classical_cut = nx.algorithms.approximation.one_exchange(G)

# Map classical solution to initial QAOA angles
# γ₀ ≈ π/4 for a good cut, β₀ ≈ π/8
init_gamma = [np.pi / 4]
init_beta = [np.pi / 8]

# Warm-started QAOA typically converges in 30-50% fewer iterations

Alles kombinieren: Eine praktische VQE-Vorlage

import pennylane as qml
import numpy as np
from pennylane.optimize import ShotAdaptiveOptimizer

dev = qml.device("default.qubit", wires=n_qubits, shots=512)

# 1. Group commuting terms (5-10x reduction in circuit count)
grouped_H = qml.Hamiltonian(*qml.grouping.group_observables(H))

@qml.qnode(dev, diff_method="parameter-shift")
def ansatz(params):
    # Hardware-efficient ansatz
    for i in range(n_qubits):
        qml.RY(params[i], wires=i)
    for i in range(n_qubits - 1):
        qml.CNOT(wires=[i, i + 1])
    return qml.expval(grouped_H)

# 2. Use shot-adaptive optimizer
opt = ShotAdaptiveOptimizer(min_shots=50)

# 3. Warm start
params = warm_start_params(H)

# 4. Run with early stopping
for step in range(300):
    params, energy, shots = opt.step_and_cost(ansatz, params)
    if check_convergence(energy, shots):
        break

print(f"Ground state energy: {energy:.4f} Ha")

Kurzreferenz: Shot-Budget nach Methode

MethodeShots/SchrittAm besten für
COBYLA + feste Shotsn_terms × shotsKleine Parameteranzahl
Parameter-Shift + Adam2n_params × shotsDifferenzierbare Schaltkreise
SPSA2 × shotsGroße Parameteranzahl
ShotAdaptiveOptimizerAdaptivAllgemeines VQE
Gruppierte Paulis÷5–15×Immer zuerst anwenden

Wenden Sie zuerst die Messgruppierung an — sie ist der größte einzelne Gewinn und erfordert keine Änderungen an Ihrem Optimierer oder Schaltkreis.

Verwandt: VQE with PennyLane · QPU access guide · HLQuantum