PennyLaneAI / pennylane

PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
https://pennylane.ai
Apache License 2.0
2.29k stars 591 forks source link

QNGoptimizer with reused parameters #1759

Closed ghost closed 2 years ago

ghost commented 2 years ago

I would like to use the QNGoptimizer to train an ansatz that uses the same parameter as an input to multiple rotation gates. Here is an example.

import numpy as np
import pennylane as qml

dev = qml.device("default.qubit", wires=2)
@qml.qnode(dev)
def circuit(params):

    qml.RY(params[0], wires=0)
    #qml.RY(params[0], wires=1)

    return qml.expval(qml.PauliZ(0))

steps = 200
qng_cost = []
opt = qml.QNGOptimizer(0.01)

theta = np.array([1.0])
for _ in range(steps):
    theta = opt.step(circuit, theta)
    qng_cost.append(circuit(theta))

The code above runs fine, however, if the second line in circuit() is uncommented, I get the error:

Traceback (most recent call last):
  File "example.py", line 160, in <module>
    theta = opt.step(circuit, theta)
  File "/opt/anaconda3/envs/qml-env/lib/python3.7/site-packages/pennylane/optimize/qng.py", line 242, in step
    **kwargs,
  File "/opt/anaconda3/envs/qml-env/lib/python3.7/site-packages/pennylane/optimize/qng.py", line 201, in step_and_cost
    new_args = self.apply_grad(g, args)
  File "/opt/anaconda3/envs/qml-env/lib/python3.7/site-packages/pennylane/optimize/qng.py", line 260, in apply_grad
    x_new_flat = x_flat - self.stepsize * np.linalg.solve(self.metric_tensor, grad_flat)
  File "<__array_function__ internals>", line 6, in solve
  File "/opt/anaconda3/envs/qml-env/lib/python3.7/site-packages/numpy/linalg/linalg.py", line 393, in solve
    r = gufunc(a, b, signature=signature, extobj=extobj)
ValueError: solve1: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (m,m),(m)->(m) (size 1 is different from 2)

Is there a method I am unaware of that allows the QNGoptimizer to be applied to ansatzes with shared parameters, or is this incompatible in its common form?

josh146 commented 2 years ago

Hi @JoeGibbs88! To give you the short answer, this is a known restriction of the currently released version of PennyLane - you cannot include classical processing within a QNode if you want to compute the metric tensor, which is needed for the QNG optimizer. ('Repeating of parameters' here counts as classical processing, since it results in the product rule being required!).

However, the development version of PL has upgraded the metric tensor function to now support this workflow πŸ™‚ So if you install the latest version of PL from GitHub,

pip install git+https://github.com/PennyLaneAI/pennylane.git#egg=pennylane

then your code example with the second line uncommented will work well (I just tested this myself)! You can switch over to the development version now, or wait for the 0.19 release of PL (which will be coming soon).


In case you are interested in the slightly longer answer:

The metric tensor proper is only defined for the quantum circuit gate arguments, while the optimizer is instead optimizing the QNode arguments.

This is a bit of subtlety, and is caused by repeating of the parameter in your example. You have an array of parameters of shape (1,) as input to the QNode, but due to the parameter repitition, the resulting quantum circuit has 2 trainable gate arguments. As a result, the resulting metric tensor will be of size [2, 2]!

This will confuse the optimizer, which won't be able to apply the QNG update step due to the shape mismatch.

The reason it has been implemented like this is that the introductory paper https://arxiv.org/abs/1909.02108 does not consider QNG optimization in the context of classical pre-processing of parameters; convergence is only proven when optimizing the gate arguments directly.

However, as noted above, in the new PL development version, the qml.metric_tensor function has been modified to take into account classical processing between QNode args and gate args πŸ™‚

josh146 commented 2 years ago

@JoeGibbs88 let me know if the development PL version works for you, or if you have any other questions. In the meantime, I will close this issue, since the underlying issue is already solved in the codebase

ghost commented 2 years ago

Your solution also worked for me, thanks for the help :)