Processing math: 50%

qml.QNSPSAOptimizer

class QNSPSAOptimizer(stepsize=0.001, regularization=0.001, finite_diff_step=0.01, resamplings=1, blocking=True, history_length=5, seed=None)[source]

Bases: object

Quantum natural SPSA (QNSPSA) optimizer. QNSPSA is a second-order SPSA algorithm, which updates the ansatz parameters with the following equation:

x(t+1)=x(t)ηˆg1(x(t))^f(x(t)),

where f(x) is the objective function with input parameters x, while f is the gradient, g is the second-order Fubini-Study metric tensor. With QNSPSA algorithm, both the gradient and the metric tensor are estimated stochastically, with ^f and ˆg. This stochastic approach requires only a fixed number of circuit executions per optimization step, independent of the problem size. This preferred scaling makes it a promising candidate for the optimization tasks for high-dimensional ansatzes. On the other hand, the introduction of the Fubini-Study metric into the optimization helps to find better minima and allows for faster convergence.

The gradient is estimated similarly as the SPSA optimizer, with a pair of perturbations:

^f(x)=^f(x,h)12ϵ(f(x+ϵh)f(xϵh)),

where ϵ is the finite-difference step size specified by the user, and h is a randomly sampled direction vector to perform the perturbation.

The Fubini-Study metric tensor is estimated with another two pairs of perturbations along randomly sampled directions h1 and h2:

ˆg(x)=ˆg(x,h1,h2)δF8ϵ2(h1h2

where F(\mathbf{x}', \mathbf{x}) = \bigr\rvert\langle \phi(\mathbf{x}') | \phi(\mathbf{x}) \rangle \bigr\rvert ^ 2 measures the state overlap between \phi(\mathbf{x}') and \phi(\mathbf{x}), where \phi is the parametrized ansatz. The finite difference \delta F is computed from the two perturbations:

\delta F = F(\mathbf{x, \mathbf{x} + \epsilon \mathbf{h}_1} + \epsilon \mathbf{h}_2) - F (\mathbf{x, \mathbf{x} + \epsilon \mathbf{h}_1}) - F(\mathbf{x, \mathbf{x} - \epsilon \mathbf{h}_1} + \epsilon \mathbf{h}_2) + F(\mathbf{x, \mathbf{x} - \epsilon \mathbf{h}_1}).

For more details, see:

Julien Gacon, Christa Zoufal, Giuseppe Carleo, and Stefan Woerner. “Simultaneous Perturbation Stochastic Approximation of the Quantum Fisher Information.” Quantum, 5, 567, 2021.

You can also find a walkthrough of the implementation in this tutorial.

Examples:

For VQE/VQE-like problems, the objective function can be defined within a qnode:

>>> num_qubits = 2
>>> dev = qml.device("default.qubit", wires=num_qubits)
>>> @qml.qnode(dev)
... def cost(params):
...     qml.RX(params[0], wires=0)
...     qml.CRY(params[1], wires=[0, 1])
...     return qml.expval(qml.Z(0) @ qml.Z(1))

Once constructed, the qnode can be passed directly to the step or step_and_cost function of the optimizer.

>>> from pennylane import numpy as np
>>> params = np.random.rand(2)
>>> opt = QNSPSAOptimizer(stepsize=5e-2)
>>> for i in range(51):
>>>     params, loss = opt.step_and_cost(cost, params)
>>>     if i % 10 == 0:
...         print(f"Step {i}: cost = {loss:.4f}")
Step 0: cost = 0.9987
Step 10: cost = 0.9841
Step 20: cost = 0.8921
Step 30: cost = 0.0910
Step 40: cost = -0.9369
Step 50: cost = -0.9984
Keyword Arguments
  • stepsize (float) – the user-defined hyperparameter \eta for learning rate (default: 1e-3)

  • regularization (float) – regularization term \beta to the Fubini-Study metric tensor for numerical stability (default: 1e-3)

  • finite_diff_step (float) – step size \epsilon to compute the finite difference gradient and the Fubini-Study metric tensor (default: 1e-2)

  • resamplings (int) – the number of samples to average for each parameter update (default: 1)

  • blocking (boolean) – when set to be True, the optimizer only accepts updates that lead to a loss value no larger than the loss value before update, plus a tolerance. The tolerance is set with the hyperparameter history_length. The blocking option is observed to help the optimizer to converge significantly faster (default: True)

  • history_length (int) – when blocking is True, the tolerance is set to be the average of the cost values in the last history_length steps (default: 5)

  • seed (int) – seed for the random sampling (default: None)

step(cost, *args, **kwargs)

Update trainable arguments with one step of the optimizer.

step_and_cost(cost, *args, **kwargs)

Update trainable parameters with one step of the optimizer and return the corresponding objective function value after the step.

step(cost, *args, **kwargs)[source]

Update trainable arguments with one step of the optimizer.

Note

When blocking is set to be True, step calls step_and_cost on the backend, as loss measurements are required by the algorithm in this scenario.

Parameters
  • cost (QNode) – the QNode wrapper for the objective function for optimization

  • args – variable length argument list for qnode

  • kwargs – variable length of keyword arguments for the qnode

Returns

the new variable values after step-wise update x^{(t+1)}

Return type

pnp.ndarray

step_and_cost(cost, *args, **kwargs)[source]

Update trainable parameters with one step of the optimizer and return the corresponding objective function value after the step.

Parameters
  • cost (QNode) – the QNode wrapper for the objective function for optimization

  • args – variable length argument list for qnode

  • kwargs – variable length of keyword arguments for the qnode

Returns

the new variable values x^{(t+1)} and the objective function output prior to the step

Return type

(np.array, float)

Contents

Using PennyLane

Release news

Development

API

Internals