Sign outOpen workspaceSign in

MethodLayer 1

Analytic-gradient parameter search

Get the gradient of the objective exactly, rather than by finite differences, by running the same circuit again at shifted parameter values. The direction is then not an estimate of a slope taken from two noisy numbers; it is the slope, estimated to whatever precision the shots allow.

Takes

A parameterised circuit family; an objective function of its parameters, evaluated only through estimates bought with a finite shot budget; a starting point; and a stopping rule — a tolerance, an iteration cap, or an exhausted budget.

Returns

A preparation routine for the state at the parameters the search stopped at, and the total number of objective evaluations it consumed. The routine is returned whether or not the search found a minimum; that it stopped is not evidence that it converged.

Same contract as the slot it fills.

This one, drawn

From Parameterised circuit family to State you can prepare

A circle is an object you are holding. This method is drawn heavier, opened into its own steps; the other lines between the same two ends are the alternatives recorded for the same slot. Circles are named on hover, and each one is a link.

Nothing drawn here has a recorded way through it that this figure leaves shut. See it on the map

What it fills

  • Minimise the objective over the parameters

    Search the parameters of a fixed circuit family for the ones that minimise a chosen objective, given that every evaluation of that objective is a noisy estimate someone paid shots for. The output is a routine that prepares one particular state — the family collapsed to a member.

When it applies

Schuld et al. state both the mechanism and its limit: gradients "can be estimated using the same, or almost the same, architecture that executes the original circuit", and "in many important instances it is sufficient to run the original quantum circuit twice". *In many important instances* is the condition — the two-circuit form holds for the gate families the paper identifies, not for every parameterisation — and each of those runs is a full expectation estimate, so an analytic gradient is paid for in circuits per parameter rather than being free.

Requires

These do not move the route along. The method needs each of them alongside its own work, and the cost of getting them is part of what the method costs.

  • Estimate an observable

    Given the ability to prepare ψ|ψ⟩ and a description of an observable OO, return a classical scalar within ε\varepsilon of O⟨O⟩ at confidence 1δ1−δ. The state is never returned; only the number is.

    What the shift rule asks of this ingredient is not a measurement of a derivative but two further evaluations of the same objective: estimates of f(μ+s)f(\mu+s) and f(μs)f(\mu-s), the same expectation value the unshifted circuit already returns, of the same observable and through the same measurement. The shift lives in the circuit, not in the estimator — either G(π/4r)\mathcal{G}(\pi/4r) or G(π/4r)\mathcal{G}(-\pi/4r) is placed in the original circuit next to the gate being differentiated, giving s=π/4rs=\pi/4r — and the combination μf=r(f(μ+s)f(μs))\partial_\mu f = r\left(f(\mu+s)-f(\mu-s)\right) is formed afterwards on the classical coprocessor. A parameter carried by more than one gate asks for its own shifted pair at each occurrence, and the differences are summed by the product rule. approximation: each returned value is itself an average over finitely many runs, so the identity is exact but its evaluation is not: finite runs on noisy hardware return an estimate of the gradient

    approximation

Example

given  a parameterized circuit U(theta) = V G(mu) W, in which one component mu of
       theta enters a single gate G(mu) = exp(-i*mu*G) for Hermitian generator G;
       observable Qhat = V^dagger B_hat V and state |psi> = W|0> absorb the rest
       of the circuit, so f(mu) = <psi| G(mu)^dagger Qhat G(mu) |psi>
                                                              (Eq. 3, LHS argument)
    # "for simplicity, let us assume that the parameter mu affects only a single
    #   gate" is the paper's own simplifying assumption here; the multi-gate case
    #   is restored by the product rule at the end                    (above Eq. 3)
    # the undifferentiated f is never given its own equation number -- it appears
    #   only inside d_mu(...) on the left of Eq. 3                    (Sec. III)

requires  G has at most two distinct eigenvalues +/- r, after shifting the
    spectrum so the (unobservable) global phase drops out -- Theorem 1
    # eigenvalues may be repeated; "two distinct" is the condition, not
    #   "dimension two"                                               (before Eq. 6)
    # any single-qubit gate satisfies this; so does G = r*(n_hat . sigma) for
    #   any 3-vector n_hat, i.e. any Pauli-rotation generator, not only the
    #   three axis rotations                                          (Sec. III A)
    # Google Cirq's Xmon gates ExpW, ExpZ, Exp11 all qualify; Pauli-based
    #   MULTI-qubit gates in general do not, and the microwave-controlled
    #   transmon gate has 4 eigenvalues -- for a generator outside this class
    #   the construction does not apply and the ancilla /
    #   linear-combination-of-unitaries route of Sec. III B is needed instead
    #                                                                 (Sec. III A)

# --- fix the shift from the generator's own spectrum -----------------------
r = the positive number with spectrum(G) = {+r, -r} after the shift
    # "half the eigenvalue spacing" is a paraphrase; the paper names r only by
    #   writing the shifted eigenvalues as +/- r, and never states r > 0, which
    #   the next line silently needs                        (Thm. 1, before Eq. 6)
s = pi / (4*r)                                                        (Eq. 8, Thm. 1)
    # for a Pauli rotation generator (1/2)*sigma_{x,y,z}: r = 1/2, s = pi/2 --
    #   the familiar rule is this special case, not the general statement
    #                                                                 (Sec. III A)

# --- evaluate the SAME circuit twice, gate parameter shifted by +/- s ------
f_plus  = run the circuit with G(mu) replaced by G(mu + s), measure Qhat
f_minus = run the circuit with G(mu) replaced by G(mu - s), measure Qhat
    # the paper's primitive move is to place the extra gate G(+/- pi/(4r)) in
    #   the original circuit next to the gate being differentiated; because
    #   G(a)G(b) = G(a+b) for a unitarily-generated one-parameter gate, that
    #   is equivalent to shifting the gate's own parameter in place
    #                                            (Sec. III A, between Eq. 12, 13)
    # each of f_plus, f_minus is itself a full expectation-value estimate, i.e.
    #   an average over finitely many runs on hardware: the identity below is
    #   exact, its hardware evaluation is not -- the paper makes this point
    #   about its differentiation rules generally, not about Eq. 14 by name
    #                                                                 (Sec. II)

d_mu_f_here = r * (f_plus - f_minus)                                  (Eq. 14)
# unlike the finite-difference formula of Eq. 2, s here is a fixed "macroscopic"
#   shift rather than a small step taken to zero, and Eq. 14 is exact, not an
#   approximation refined by shrinking it                             (Sec. III A)
# exact AT s = pi/(4r): that is the only shift this derivation fixes, since it
#   comes from Theorem 1's closed form for G(pi/(4r)). The paper states no
#   family of other admissible shifts, so do not read "exact" as "exact for any
#   shift size"                                                       (Eqs. 8, 13, 14)

# --- if mu enters more than one gate, repeat and sum (product rule) --------
if mu appears in several gates in the circuit:
    d_mu_f = sum over each occurrence of (its own d_mu_f_here, by the steps above)
    # shift and difference separately at each occurrence, then sum -- the
    #   ordinary product rule applied gate by gate           (Sec. III A, below Eq. 14)
else:
    d_mu_f = d_mu_f_here

return  d_mu_f, the exact partial derivative of f with respect to mu, bought at
        exactly two expectation-value evaluations per occurrence of mu
                                          (Sec. II, enumerated property 3)
# each of those evaluations can often run on a circuit architecture very similar
#   or identical to the one that evaluates f itself       (Sec. II, property 2)
# repeating this once per component of theta gives the full gradient; the paper
#   stops at supplying components of the gradient -- what an outer classical
#   optimizer does with them (a step, a line search, ...) is not part of this
#   construction
# a generator with more than two distinct eigenvalues is out of scope for this
#   recipe entirely, not merely more expensive under it -- see requires

Cost, as the source states it

Schuld, Bergholm, Gogolin, Izaac and Killoran: two expectation values per differentiated gate occurrence, exact rather than a finite difference. For a gate G(μ)=eiμG\mathcal{G}(\mu)=e^{-i\mu G} whose Hermitian generator has at most two unique eigenvalues ±r\pm r (Theorem 1) — which covers any single-qubit gate — μf=r(f(μ+s)f(μs))\partial_\mu f = r\left(f(\mu+s)-f(\mu-s)\right) at the macroscopic shift s=π/(4r)s=\pi/(4r), Eq. (14); r=1/2r=1/2, s=π/2s=\pi/2 for rotations generated by 12{σx,σy,σz}\frac{1}{2}\{\sigma_x,\sigma_y,\sigma_z\}. A parameter appearing in several gates is shifted in each separately and the results summed, so one component costs two per occurrence, and each evaluation is itself a full expectation estimate. Generators outside that class — their transmon example has four eigenvalues — take the ancilla route of Sec. III B: 2K2K expectation values and 2K2K probabilities for a KK-term unitary decomposition of μG\partial_\mu\mathcal{G}, always achievable at K=2K=2, on one added ancilla qubit with no post-selection penalty, since either ancilla outcome contributes. Nothing bounds shots or iterations: the paper derives differentiation rules and reports no numerics.

Implementations

  • The param_shift gradient transform in PennyLane

    The paper names its own implementation in the introduction: "The results of this paper are implemented in the software framework PennyLane [8], which facilitates hybrid quantum-classical optimization across various quantum hardwares and simulator platforms [8]." Reference [8] is given in its own bibliography as Ville Bergholm, Josh Izaac, Maria Schuld, Christian Gogolin and Nathan Killoran, "PennyLane: Automatic differentiation of hybrid quantum-classical computations" (2018), arxiv:1811.04968 — the same five names as on this paper. One caption points a reader onward for rules the paper does not tabulate, "More derivative rules can be found in the PennyLane [8] documentation (https://pennylane.readthedocs.io)", but it is the caption of Table II, which opens "Parameter shift rules for the partial derivatives of important Gaussian gates": what it defers on is the continuous-variable material of Sec. IV, not the discrete-variable rules of Sec. III that this module implements. The library's gradients module says what such a thing is — "Quantum gradient transforms are strategies for computing the gradient of a quantum circuit that work by transforming the quantum circuit into one or more gradient circuits. These gradient circuits, once executed and post-processed, return the gradient of the original circuit." — and places it where this method sits rather than offering it as the general answer: "When using a simulator device with exact measurement statistics, backpropagation is preferred due to performance and memory improvements", against "When using a hardware device, or a simulator with a finite number of shots, a quantum gradient transform---such as the parameter-shift rule---is preferred."

    The entry point is a transform, not a routine that runs anything: `qp.gradients.param_shift(tape, argnum=None, shifts=None, gradient_recipes=None, fallback_fn=finite_diff, f0=None, broadcast=False)` returns the batch of shifted circuits together with the classical post-processing that combines them, and its internal `transform_name` is the string "parameter-shift rule". The two-term rule is the documented default of the `gradient_recipes` argument — "If `None`, the default gradient recipe containing the two terms [c0,a0,s0]=[1/2,1,π/2][c_0, a_0, s_0]=[1/2, 1, \pi/2] and [c1,a1,s1]=[1/2,1,π/2][c_1, a_1, s_1]=[-1/2, 1, -\pi/2] is assumed for every parameter" — under the general recipe form ϕkf=icif(aiϕk+si)\frac{\partial}{\partial\phi_k}f = \sum_{i} c_i f(a_i \phi_k + s_i), and `RX`'s own docstring writes the same rule out as a derivative: "Gradient recipe: ddϕf(Rx(ϕ))=12[f(Rx(ϕ+π/2))f(Rx(ϕπ/2))]\frac{d}{d\phi}f(R_x(\phi)) = \frac{1}{2}\left[f(R_x(\phi+\pi/2)) - f(R_x(\phi-\pi/2))\right] where ff is an expectation value depending on Rx(ϕ)R_x(\phi)." That is Eq. (14) at r=1/2r=1/2, s=π/2s=\pi/2. What supplies the recipe is the gate rather than the transform: `_get_operation_recipe` tries a stored `grad_recipe`, then `parameter_frequencies`, then the generator, and `RX` carries `grad_method = "A"`, `parameter_frequencies = [(1,)]` and a `generator` returning `qp.Hamiltonian([-0.5], [PauliX(wires=self.wires)])` rather than a stored recipe. The general rule the docstring carries is credited to nobody. It states fp=μ=12Rf(p+2μ12Rπ)(1)μ14Rsin2(2μ14Rπ)\frac{\partial f}{\partial \mathbf{p}} = \sum_{\mu=1}^{2R} f\left(\mathbf{p}+\frac{2\mu-1}{2R}\pi\right)\frac{(-1)^{\mu-1}}{4R\sin^2\left(\frac{2\mu-1}{4R}\pi\right)} under nothing but "The gradient of this expectation value can be calculated via the parameter-shift rule:", and only afterwards adds that RR is the number of frequencies with which the parameter p\mathbf{p} enters the function ff via the operation UU, "and we assumed that these frequencies are equidistant. For more general shift rules, both regarding the shifts and the frequencies, and for more technical details, see Vidal and Theis (2018) and Wierichs et al. (2022)." Those two names are attached to what lies beyond the equidistant case, not to the displayed formula, and at the version read Schuld et al. is named nowhere in this file. The paper's "in many important instances" survives in two places all the same. Any trainable parameter whose gradient method comes back as `"F"` is handed to `fallback_fn`, whose default is `finite_diff` — the thing the rule exists to replace, kept as the escape hatch, and the transform asks for `"analytic"` rather than `"best"` only when the caller passes `fallback_fn=None`. And where it is asked to shift a parameter with none of the three sources, `_get_operation_recipe` raises `OperatorPropertyUndefined`: "The operation {op.name} does not have a grad_recipe, parameter_frequencies or a generator defined. No parameter shift rule can be applied."

    None of its own: the transform differentiates whatever circuit and observable the caller hands it. Every worked example in the file runs on the `default.qubit` simulator — `dev = qp.device("default.qubit")` — and on one-wire, three-parameter circuits, almost always `RX(params[0], wires=0)`, `RY(params[1], wires=0)`, `RX(params[2], wires=0)` at `params = np.array([0.1, 0.2, 0.3], requires_grad=True)`. That circuit is measured two ways across the eight examples in the file: `expval(qp.Z(0))` alone in four of them, and `expval(qp.Z(0))` together with `var(qp.Z(0))` in the other four. One variant sets a shot vector, `shots = (10, 100, 1000)`; the rest are exact. No molecule and no problem instance appears anywhere in the file, and `default.qubit` is the only device it names.

    `pennylane/gradients/parameter_shift.py` in https://github.com/PennyLaneAI/pennylane — Python, Apache License 2.0, header "Copyright 2018-2021 Xanadu Quantum Technologies Inc.", module docstring "This module contains functions for computing the parameter-shift gradient of a qubit-based quantum tape." The README states the licence in the same words: "PennyLane is free and open source, released under the Apache License, Version 2.0." Read at tag `v0.45.1`, the release published 2026-06-26 and the version distributed on PyPI as `PennyLane`; the documented name on the API page at that version is `qp.gradients.param_shift`. What a caller usually types instead is recorded in the package docstring: "passing `diff_method="parameter-shift"` is equivalent to passing `diff_method=qp.gradients.param_shift`." The construction the transform defers to for anything but a stored recipe sits beside it as `generate_shift_rule(frequencies, shifts=None, order=1)` in `pennylane/gradients/general_shift_rules.py`.

    Documented output rather than a study. The autograd example — the one-wire, three-parameter circuit under `diff_method="parameter-shift"`, measuring `expval(qp.Z(0))` — prints `array([-0.3875172 , -0.18884787, -0.38355704])`, and the JAX example returns the same three numbers beside the variance gradient `Array([0.69916862, 0.34072424, 0.69202359], dtype=float64)`. The circuit count is what the low-level examples make visible, because they return the gradient circuits instead of executing them. With `broadcast=True` on a three-parameter tape measuring `expval(qp.Z(0))`, `len(gradient_tapes)` is `3` and `[t.batch_size for t in gradient_tapes]` is `[2, 2, 2]` — two shifted evaluations per parameter, batched one tape per operation. With the default `broadcast=False` on the same three parameters measuring both `expval(qp.Z(0))` and `var(qp.Z(0))`, seven `QuantumScript` objects come back, and the docstring does not say how those seven divide. The one timing in the file is classical and is offered as a speedup of batching rather than of the rule: over `number = 100` calls on `default.qubit`, `0.020183045039993887` seconds per call at `broadcast=False` against `0.01244492811998498` at `broadcast=True`. No shot count is attached to any of the exact examples; the one example that sets shots sets the vector `shots = (10, 100, 1000)` on the same simulator, and no run on hardware is reported.

  • Parameter-shift gradients in Qiskit Algorithms (ParamShiftEstimatorGradient and ParamShiftSamplerGradient)

    A released library that names this paper for the rule, rather than a study. The whole class docstring of `ParamShiftEstimatorGradient` is its subject and its source: "Compute the gradients of the expectation values by the parameter shift rule [1]." and "[1] Schuld, M., Bergholm, V., Gogolin, C., Izaac, J., and Killoran, N. Evaluating analytic gradients on quantum hardware", followed by a link to doi.org/10.1103/PhysRevA.99.032331 — the journal version of the paper cited here, Phys. Rev. A 99, 032331 (2019). Its sampler counterpart `ParamShiftSamplerGradient` carries the same reference for "the gradients of the sampling probability". The same subpackage also ships this paper's other route: `LinCombEstimatorGradient` says "This method employs a linear combination of unitaries [1]", citing the same paper under a different string — "[1] Schuld et al., Evaluating analytic gradients on quantum hardware, 2018" with a link to arXiv:1811.11184 rather than to the DOI. It pays for that route with an added register, though not in its own file: `LinCombEstimatorGradient` imports `_make_lin_comb_gradient_circuit` from `qiskit_algorithms/gradients/utils.py`, and it is there that `qr_aux = QuantumRegister(1, "qr_aux")` is added and a Hadamard and an `sdg` are put on it. That is Sec. III B rather than the shift rule. Both files are headed "(C) Copyright IBM 2022, 2025." The package README opens with a warning about the package rather than the code: "Qiskit Algorithms is no longer officially supported by IBM", and "Like any other Apache 2 licensed code, you are free to use it or/and extend it, but please be aware that it is under your own risk."

    The gate set is a list on the class — `SUPPORTED_GATES = ["x", "y", "z", "h", "rx", "ry", "rz", "p", "cx", "cy", "cz", "ryy", "rxx", "rzz", "rzx"]` — and a circuit outside it is rewritten rather than refused: `_preprocess` runs `TranslateParameterizedGates(supported_gates)` and then `_assign_unique_parameters`, which replaces every parameterised gate angle with a fresh parameter named `__gθ<n>` and records `parameter_map[parameter].append((new_parameter, angle.gradient(parameter)))`. Shifting is then arithmetic on bound values rather than a change to the circuit: `_make_param_shift_parameter_values` builds an identity matrix restricted to the requested parameters and forms `plus_offsets = parameter_values + offset * np.pi / 2` and `minus_offsets = parameter_values - offset * np.pi / 2`, submits both halves as a single estimator job "to reduce overhead", and combines the returned expectation values as `gradient_ = (evs[: n // 2] - evs[n // 2 :]) / 2`. That is s=π/2s=\pi/2 and r=1/2r=1/2 in μf=r(f(μ+s)f(μs))\partial_\mu f = r\left(f(\mu+s)-f(\mu-s)\right). `_postprocess` then folds the fresh parameters back onto the caller's, "by using the chain rule", multiplying each unique-parameter gradient by the recorded coefficient and summing. Where a gate angle is the bare parameter that coefficient is 1 and the fold reduces to summing the parameter's separate occurrences, which is the step the paper reaches for above Eq. (3), where the circuit "can be decomposed into a sequence of single-parameter gates, which can be differentiated using the product rule" before it narrows to "the parameter μθ\mu \in \theta only affects a single gate G(μ)G(\mu) in the sequence". Where the angle is an expression the coefficient is `angle.gradient(parameter)` and the fold is the chain rule the file names, which is more than the paper's step. Neither the file nor the paper draws the correspondence; it is a reading of the two against each other.

    None of its own: the circuits, observables and parameter values are the caller's. What the repository supplies is the test module, and its circuits are sketches rather than problems. The recurring one is `qc.h(0)`, `qc.p(a, 0)`, `qc.h(0)` measured against `SparsePauliOp.from_list([("Z", 1)])`; the same shape with `qc.u(a, b, c, 0)` in place of the phase gate exercises the translation step, `u` being outside `SUPPORTED_GATES`. The largest is three qubits: `real_amplitudes(num_qubits=3, reps=1)` with seventeen further gates appended, several of whose angles are nonlinear expressions in that circuit's own parameters, a parameterised `global_phase = params[0] * params[1] + params[2].cos().exp()`, and a random ten-term observable `SparsePauliOp(random_pauli_list(num_qubits=qc.num_qubits, size=size, seed=rng))` whose coefficients are drawn `rng.normal(0, 10, size)`. No molecule and no benchmark instance appears anywhere.

    `ParamShiftEstimatorGradient` in `qiskit_algorithms/gradients/param_shift/param_shift_estimator_gradient.py`, with `ParamShiftSamplerGradient` beside it in `param_shift_sampler_gradient.py`, at https://github.com/qiskit-community/qiskit-algorithms — Python, "This code is licensed under the Apache License, Version 2.0". The shared machinery is one directory up: `_make_param_shift_parameter_values` in `qiskit_algorithms/gradients/utils.py`, and `_preprocess` and `_postprocess` in `qiskit_algorithms/gradients/base/base_estimator_gradient.py`. It is distributed on PyPI as `qiskit-algorithms` ("Qiskit Algorithms: A library of quantum computing algorithms"), version 0.4.0 at the time of reading, with the tests in `test/gradients/test_estimator_gradient.py` in the same repository.

    What shows that it runs is the repository's own test suite, and the machine is `StatevectorEstimator`. `ParamShiftEstimatorGradient` is one of the six entries in the module's `gradient_factories` list, so it is held to the same expected numbers as the three finite-difference variants beside it — `method="central"`, `"forward"` and `"backward"` — the linear-combination gradient and the reverse gradient. `test_gradient_p` differentiates `expval(Z)` through `h · p(a) · h` at `param_list = [[np.pi / 4], [0], [np.pi / 2]]` and requires `correct_results = [[-1 / np.sqrt(2)], [0], [-1]]` to three decimal places. `test_gradient_u` does the same through `h · u(a, b, c) · h` and requires `[[-0.70710678, 0.0, 0.0], [-0.35355339, -0.85355339, -0.85355339]]`. `test_gradient_parameter_coefficient` is the one that exercises the fold: it takes `real_amplitudes(num_qubits=2, reps=1)`, appends five more gates whose angles are expressions in that circuit's own parameters — among them `qc.rz(qc.parameters[0].exp() + 2 * qc.parameters[1], 0)`, `qc.rx(3.0 * qc.parameters[0] + qc.parameters[1].sin(), 1)` and `qc.rxx(qc.parameters[0] + 2, 0, 1)` — and requires `[-0.7266653, -0.4905135, -0.0068606, -0.9228880]` with every parameter at π/4\pi/4, to `atol=1e-3`. `test_gradient_random_parameters`, which runs for the parameter-shift and linear-combination gradients only, is the one that checks the rule against what it replaces: on the three-qubit `real_amplitudes(num_qubits=3, reps=1)` circuit, over `num_tries = 10` parameter draws from `rng.normal(0, 2, ...)`, the parameter-shift gradients must match those of `FiniteDiffEstimatorGradient(estimator, 1e-6)` to `rtol=1e-4`. Each of these four builds a bare `StatevectorEstimator()`, whose `default_precision` is `0.0`, so each is exact. That is not true of the whole file: `test_precision` and `test_transpiler` both build `StatevectorEstimator(default_precision=0.2)`, and in the V2 primitives a non-zero precision is what took the place of a shot count — `qiskit/primitives/statevector_estimator.py` does `if precision != 0: ... expectation_value = rng.normal(expectation_value, precision)`. Neither of those two checks a gradient value: the first asserts the precision that comes back, the second that a pass manager was called. No timing is reported anywhere in the file, and the only backend it names, `GenericBackendV2(num_qubits=3, coupling_map=[[0, 1], [1, 2]], seed=54)`, is there to build that pass manager rather than to run anything.

What it needs

Every step this method names is listed under Requires above. It walks its own span in one hop and calls out to the rest — that is a fact about the recorded route, not a claim that the span is simple.

Other ways to fill the same slot

Different approaches

  • Conditional-value-at-risk objective

    Change what the classical loop is minimising rather than how it minimises. Instead of averaging every measurement outcome into an expectation value, keep only the best tail of them and average that — which is defensible precisely when the answer is a single good bitstring rather than a physical average.

  • Minimise the energy variance

    Minimise how much the energy fluctuates rather than the energy itself. Any eigenstate has zero variance, so the objective's own value tells you whether you have arrived — which the energy never does, since a low number is only low relative to a minimum nobody knows.

  • Follow the steepest descent in the state's own geometry

    Take the step that moves the state fastest, not the one that moves the parameters fastest. The two differ because equal changes in parameters do not make equal changes in the state, and the metric measuring that difference has to be estimated before every step.

  • Grow the circuit a layer at a time while training it

    Do not settle the circuit before optimising it. Start shallow, train what is there, then hold most of it fixed and add the next layer on top — so every step of the search runs on a shallow circuit with few free parameters, which is where a gradient is still large enough to follow.

  • Simultaneous-perturbation optimization

    Perturb every parameter at once, in one random direction, and take the difference of two objective evaluations as the gradient estimate. The estimate is bad in any single round and unbiased across rounds, so the cost of a step stops growing with the number of parameters.

In the Atlas

  • Analytic-gradient VQE

    Parameter-shift or analytic derivative measurements supply gradients to a classical optimizer.

Sources