SPDX-License-Identifier: AGPL-3.0-or-later¶
Commercial license available¶
© Concepts 1996–2026 Miroslav Šotek. All rights reserved.¶
© Code 2020–2026 Miroslav Šotek. All rights reserved.¶
ORCID: 0009-0009-3560-0851¶
Contact: www.anulum.li | protoscience@anulum.li¶
scpn-quantum-control — Variational Methods Documentation¶
Variational Methods: Parameter-Shift Gradient Rule¶
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 hardware.
Theory¶
The Parameter-Shift Rule¶
For a cost function \(C(\theta) = \langle 0 | U^\dagger(\theta) H U(\theta) | 0\rangle\) where \(U(\theta)\) contains gates of the form \(e^{-i\theta G/2}\) with \(G^2 = I\) (standard Pauli rotations), the gradient is:
This is exact — not an approximation. It requires \(2P\) circuit evaluations for \(P\) parameters (compared to \(2P\) for central finite differences, but without truncation error).
Gradient Descent VQE¶
The module provides a basic gradient-descent VQE loop:
- Initialise random parameters \(\theta^{(0)}\)
- At each iteration: compute \(\nabla C\) via parameter-shift
- Update: \(\theta^{(t+1)} = \theta^{(t)} - \eta \nabla C\)
- Repeat until convergence or iteration limit
This is a pedagogical implementation. For production VQE, use
SciPy optimisers (L-BFGS-B, COBYLA) or Qiskit's VQE class.
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:
| Parameter | Type | Description |
|---|---|---|
cost_fn |
callable |
Maps parameter vector → scalar expectation value |
params |
ndarray |
Current parameter values |
shift |
float |
Shift amount. \(\pi/2\) for standard Pauli rotation gates. |
vqe_with_param_shift¶
result = vqe_with_param_shift(
cost_fn: Callable[[np.ndarray], float],
n_params: int,
learning_rate: float = 0.1,
n_iterations: int = 100,
seed: int | None = None,
) -> dict
Returns:
{
"optimal_params": np.ndarray, # best parameters found
"energy": float, # final energy
"energy_history": list[float], # energy at each iteration
"grad_norms": list[float], # gradient norm at each iteration
}
Tutorial¶
Gradient of a Simple Function¶
import numpy as np
from scpn_quantum_control.phase.param_shift import parameter_shift_gradient
# Quadratic cost: C(θ) = θ₀² + 2θ₁²
def cost(params):
return params[0]**2 + 2 * params[1]**2
params = np.array([1.0, 1.0])
grad = parameter_shift_gradient(cost, params)
print(f"Gradient: {grad}")
# Analytic: [2.0, 4.0] — parameter-shift gives exact result for sinusoidal
# functions, approximate for polynomials
VQE for the XY Hamiltonian¶
import numpy as np
from scpn_quantum_control.phase.param_shift import vqe_with_param_shift
from scpn_quantum_control.bridge.knm_hamiltonian import knm_to_dense_matrix
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)
H = knm_to_dense_matrix(K, omega)
dim = 2**n
def vqe_cost(params):
"""Simple Ry-layer ansatz."""
psi = np.zeros(dim, dtype=complex)
psi[0] = 1.0
# Apply Ry rotations
for i in range(n):
c, s = np.cos(params[i]/2), np.sin(params[i]/2)
# Single-qubit Ry on qubit i
new_psi = np.zeros_like(psi)
for k in range(dim):
bit = (k >> i) & 1
k_flip = k ^ (1 << i)
if bit == 0:
new_psi[k] += c * psi[k]
new_psi[k_flip] += s * psi[k]
else:
new_psi[k] += c * psi[k]
new_psi[k_flip] -= s * psi[k]
psi = new_psi
return np.real(psi.conj() @ H @ psi)
result = vqe_with_param_shift(vqe_cost, n_params=n,
learning_rate=0.1, n_iterations=200, seed=42)
print(f"VQE energy: {result['energy']:.6f}")
print(f"Final gradient norm: {result['grad_norms'][-1]:.2e}")
E_exact = np.linalg.eigvalsh(H)[0]
print(f"Exact energy: {E_exact:.6f}")
Comparison¶
| Feature | This module | Qiskit VQE |
PennyLane qml.grad |
|---|---|---|---|
| Gradient method | Parameter-shift | SPSA, COBYLA, etc. | Parameter-shift, backprop |
| Optimiser | Vanilla GD | SciPy, custom | Built-in (Adam, GD, etc.) |
| Hardware-compatible | Yes (2 evals/param) | Yes | Yes |
| Ansatz | User-supplied cost_fn |
Qiskit circuits | PennyLane circuits |
| Complexity | \(2P\) evaluations | Method-dependent | \(2P\) or \(O(1)\) (backprop) |
This module is a building block. For production VQE with adaptive ansätze and advanced optimisers, use Qiskit or PennyLane.
References¶
- Mitarai, K. et al. "Quantum circuit learning." PRA 98, 032309 (2018).
- Schuld, M. et al. "Evaluating analytic gradients on quantum hardware." PRA 99, 032331 (2019).
See Also¶
- Neural Quantum States — RBM variational ansatz
- GPU Batch VQE — parallel parameter scanning
- XY Compiler — depth-optimised circuits for VQE