Variational Methods: Parameter-Shift Gradient Rule

July 7, 2026 · View on GitHub

scpn_quantum_control.phase.param_shift

Analytic gradient computation for variational quantum eigensolvers (VQE). The parameter-shift rule computes exact gradients using only two circuit evaluations per parameter — no finite-difference error, works on real quantum expectation routes once the backend policy supports the required shifted evaluations. The implemented route is local simulator-first.


Theory

The Parameter-Shift Rule

For a cost function C(θ)=0U(θ)HU(θ)0C(\theta) = \langle 0 | U^\dagger(\theta) H U(\theta) | 0\rangle where U(θ)U(\theta) contains gates of the form eiθG/2e^{-i\theta G/2} with G2=IG^2 = I (standard Pauli rotations), the gradient is:

Cθk=12[C(θk+π/2)C(θkπ/2)]\frac{\partial C}{\partial \theta_k} = \frac{1}{2}\left[C(\theta_k + \pi/2) - C(\theta_k - \pi/2)\right]

This is exact — not an approximation. It requires $2Pcircuitevaluationsforcircuit evaluations forP parameters (compared to \2P$ for central finite differences, but without truncation error).

Gradient Descent VQE

The module provides a basic gradient-descent VQE loop:

  1. Initialise random parameters θ(0)\theta^{(0)}
  2. At each iteration: compute C\nabla C via parameter-shift
  3. Update: θ(t+1)=θ(t)ηC\theta^{(t+1)} = \theta^{(t)} - \eta \nabla C
  4. Repeat until convergence or iteration limit

This is a pedagogical implementation. For production VQE, use PhaseVQE.solve(gradient_method="parameter_shift") or another solver with registered gradient semantics for the target backend.


API Reference

from scpn_quantum_control.phase.param_shift import (
    parameter_shift_gradient,
    vqe_with_param_shift,
)

parameter_shift_gradient

grad = parameter_shift_gradient(
    cost_fn: Callable[[np.ndarray], float],  # params → energy
    params: np.ndarray,                       # shape (n_params,)
    shift: float = np.pi / 2,                # shift amount
) -> np.ndarray  # shape (n_params,)

Computes the gradient vector. Each component requires two evaluations of cost_fn.

Parameters:

ParameterTypeDescription
cost_fncallableMaps parameter vector → scalar expectation value
paramsndarrayCurrent parameter values
shiftfloatShift amount. π/2\pi/2 for standard Pauli rotation gates.

vqe_with_param_shift

result = vqe_with_param_shift(
    objective_or_k: Callable[[np.ndarray], float] | np.ndarray,
    omega: np.ndarray | None = None,
    n_params: int | None = None,
    learning_rate: float = 0.1,
    steps: int = 100,
    seed: int | None = None,
) -> ParamShiftVQEResult

Returns:

result.best_params       # best parameters found
result.best_energy       # best energy observed
result.energies          # accepted energy history
result.gradient_norms    # gradient norm history
result.to_dict()         # mapping form for legacy notebooks

Tutorial

Gradient of a Simple Function

import numpy as np
from scpn_quantum_control.phase.param_shift import parameter_shift_gradient

# Sinusoidal expectation-style cost: C(theta) = cos(theta_0) + sin(theta_1)
def cost(params):
    return np.cos(params[0]) + np.sin(params[1])

params = np.array([1.0, 1.0], dtype=float)
grad = parameter_shift_gradient(cost, params)
print(f"Gradient: {grad}")
# Analytic: [-sin(theta_0), cos(theta_1)]

VQE for the XY Hamiltonian

import numpy as np
from scpn_quantum_control.phase import PhaseVQE

n = 4
K = 0.45 * np.exp(-0.3 * np.abs(np.subtract.outer(range(n), range(n))))
np.fill_diagonal(K, 0.0)
omega = np.linspace(0.8, 1.2, n)
vqe = PhaseVQE(K, omega, ansatz_reps=1)
result = vqe.solve(maxiter=80, seed=42, gradient_method="parameter_shift")
print(f"VQE energy: {result['ground_energy']:.6f}")
print(f"Gradient norm: {result['gradient_norm']:.2e}")
print(f"Exact energy: {result['exact_energy']:.6f}")

Comparison

FeatureThis moduleQiskit VQEPennyLane qml.grad
Gradient methodParameter-shiftSPSA, COBYLA, etc.Parameter-shift, backprop
OptimiserVanilla GDSciPy, customBuilt-in (Adam, GD, etc.)
Hardware-compatiblePolicy-gatedYesYes
AnsatzUser-supplied cost_fnQiskit circuitsPennyLane circuits
Complexity$2P$ evaluationsMethod-dependent$2PororO(1)$ (backprop)

This module is a building block. Use the local route for deterministic gradient validation, then promote backends only after shot policy, uncertainty reporting, and backend capability checks are registered.


References

  1. Mitarai, K. et al. "Quantum circuit learning." PRA 98, 032309 (2018).
  2. Schuld, M. et al. "Evaluating analytic gradients on quantum hardware." PRA 99, 032331 (2019).

See Also