ワンクリックで
spsa
Concise guide to the SPSA estimator and sampler gradient examples for parameterized quantum circuits.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Concise guide to the SPSA estimator and sampler gradient examples for parameterized quantum circuits.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Root entrypoint for the quantum-skills package. Use this skill to route requests to the correct simulator or algorithm sub-skill, enforce full skill-chain reading before coding, and avoid duplicating implementation details that are already defined in leaf skills.
A set of quantum algorithms for solving linear systems of equations and related Fourier/signal-processing subroutines. This skill includes UnitaryLab implementations and educational resources for AQC, HHL, LCU, QFT, the basic single-qubit QSP demo, QSVT-QLSA, and VQLS.
Solve user-provided linear systems Ax = b with the UnitaryLab Variational Quantum Linear Solver, using a hardware-efficient ansatz and selectable local Hadamard-test, local classical, or global cost functions.
A top-level index of quantum algorithms centered on the UnitaryLab implementation, covering quantum primitives, linear systems, state preparation, cryptography, Hamiltonian simulation, Schrodingerization, quantum machine learning, eigensolvers, gradients, and quantum error correction, with selected Qiskit, PennyLane, and Classiq examples included as reference extensions.
Use when users ask about solving the discrete logarithm problem g^x ≡ y (mod P) with Shor-style two-register Fourier sampling, building/explaining DLP circuits, running simulator demos, or debugging post-processing (continued fractions plus two-dimensional Fourier-sample congruence solving). Relevant trigger terms include discrete log, DLP, Shor discrete logarithm, g^x mod P, modular exponentiation, two-dimensional Fourier sampling, continued fractions, congruence solving, and quantum cryptography demos.
Use this skill when the user asks for Shor integer factorization, quantum order-finding, period estimation, or implementing/running/debugging ShorAlgorithm in this repository (especially matrix/operator methods, IQFT-based phase post-processing, and continued-fraction period recovery). Relevant keywords include shor, factor N, order finding, period finding, modular exponentiation, continued fraction, quantum factoring, and ShorAlgorithm.
| name | spsa |
| description | Concise guide to the SPSA estimator and sampler gradient examples for parameterized quantum circuits. |
Use this skill for the SPSA gradient examples in this folder:
scripts/algorithm.pyThey estimate gradients of:
SPSAEstimatorGradientSPSASamplerGradientSPSA is useful when circuits have many parameters, because each batch needs only 2 * batch_size circuit evaluations, independent of parameter count.
For each random perturbation vector delta in {+1, -1}^d, the implementation evaluates:
f(theta + epsilon * delta)f(theta - epsilon * delta)It then forms a central-difference estimate and averages across batch_size perturbations.
The real entry classes are:
SPSAEstimatorGradientSPSASamplerGradientPublic usage goes through inherited run(...); the algorithm itself is implemented in _run(...).
Minimal estimator example:
from qiskit.circuit import QuantumCircuit, ParameterVector
from qiskit.primitives import StatevectorEstimator
from qiskit.quantum_info import SparsePauliOp
from qiskit_algorithms.gradients import SPSAEstimatorGradient
theta = ParameterVector("theta", 2)
qc = QuantumCircuit(2)
qc.ry(theta[0], 0)
qc.ry(theta[1], 1)
qc.cx(0, 1)
estimator = StatevectorEstimator()
obs = SparsePauliOp("ZZ")
grad = SPSAEstimatorGradient(estimator=estimator, epsilon=0.01, batch_size=4, seed=123)
result = grad.run(
circuits=[qc],
observables=[obs],
parameter_values=[[0.3, -0.2]],
parameters=[[theta[0], theta[1]]],
precision=None,
).result()
print(result.gradients)
Minimal sampler example:
from qiskit.circuit import QuantumCircuit, ParameterVector
from qiskit.primitives import StatevectorSampler
from qiskit_algorithms.gradients import SPSASamplerGradient
theta = ParameterVector("theta", 2)
qc = QuantumCircuit(2)
qc.ry(theta[0], 0)
qc.ry(theta[1], 1)
qc.cx(0, 1)
qc.measure_all()
sampler = StatevectorSampler()
grad = SPSASamplerGradient(sampler=sampler, epsilon=0.01, batch_size=4, seed=123)
result = grad.run(
circuits=[qc],
parameter_values=[[0.3, -0.2]],
parameters=[[theta[0], theta[1]]],
shots=None,
).result()
print(result.gradients)
SPSAEstimatorGradientestimator: expectation-value primitiveepsilon: perturbation size, must be positivebatch_size=1: number of SPSA samples to averageseed=None: RNG seedprecision=None: estimator precision overridetranspiler=None, transpiler_options=None: optional transpilationRun inputs:
circuitsobservablesparameter_valuesparametersprecisionReturn fields:
gradientsmetadataprecisionSPSASamplerGradientsampler: sampling primitiveepsilon: perturbation size, must be positivebatch_size=1: number of SPSA samples to averageseed=None: RNG seedshots=None: sampler shot overridetranspiler=None, transpiler_options=None: optional transpilationRun inputs:
circuitsparameter_valuesparametersshotsReturn fields:
gradientsmetadatashotsSPSAEstimatorGradient._run(...) does the following:
precision.batch_size random sign vectors.theta + epsilon * delta and theta - epsilon * delta parameter sets.Simplified reconstruction:
for each circuit:
deltas = random_pm_one_vectors(batch_size)
plus = [theta + epsilon * d for d in deltas]
minus = [theta - epsilon * d for d in deltas]
pubs.append((circuit, observable, plus + minus, precision))
results = estimator.run(pubs).result()
gradient = mean(((f_plus - f_minus) / (2 * epsilon)) / delta over batch)
SPSASamplerGradient._run(...) is similar, but works on probability distributions:
shots.Simplified reconstruction:
for each circuit:
deltas = random_pm_one_vectors(batch_size)
plus = [theta + epsilon * d for d in deltas]
minus = [theta - epsilon * d for d in deltas]
pubs.append((circuit, plus + minus, shots))
results = sampler.run(pubs).result()
for each target parameter j:
gradient_j = average_k(diff_distribution_k * deltas[k][j])
U(theta)f(theta)p_theta(z)delta in {+1, -1}^dtheta +/- epsilon * deltatheta: parameter_valuesdelta: random +1/-1 vectors built with NumPy RNGepsilon: constructor argument epsilonf(theta + epsilon * delta), f(theta - epsilon * delta): plus and minus evaluationsparametersFor scalar objective f(theta):
$$ \hat g_i(\theta) = \frac{f(\theta + \epsilon \delta) - f(\theta - \epsilon \delta)}{2\epsilon,\delta_i} $$
For batch_size = B:
$$ \hat g(\theta) = \frac{1}{B}\sum_{k=1}^B \frac{f(\theta + \epsilon \delta^{(k)}) - f(\theta - \epsilon \delta^{(k)})}{2\epsilon} \odot \delta^{(k)} $$
Since delta_i in {+1, -1}, dividing by delta_i is equivalent to multiplying by delta_i.
For sampler gradients, the same idea is applied per output bitstring probability.
If you request only a parameter subset, the output keeps that order:
result = grad.run(
circuits=[qc],
observables=[obs],
parameter_values=[[0.1, -0.4, 0.7]],
parameters=[[theta[0], theta[2]]],
precision=None,
).result()
print(result.gradients[0])
print(result.metadata[0]["parameters"])
Expected behavior:
parameters=[[...]]import numpy as np
def spsa_gradient(eval_fn, theta, epsilon, batch_size, rng):
grads = []
for _ in range(batch_size):
delta = (-1) ** rng.integers(0, 2, len(theta))
f_plus = eval_fn(theta + epsilon * delta)
f_minus = eval_fn(theta - epsilon * delta)
grads.append(((f_plus - f_minus) / (2 * epsilon)) / delta)
return np.mean(np.asarray(grads), axis=0)
This matches the core logic of the estimator implementation; the sampler version replaces scalar outputs with sparse probability dictionaries.
epsilon <= 0 raises ValueError.epsilon can make noise dominate.batch_size reduces variance but increases runtime.epsilon and batch_size are not exposed as public attributes on gradient objects; prefer tracking configured values in local variables rather than reading grad.epsilon or grad.batch_size.