# QuantumFunctionError using QNGOptimizer with QAOA

**URL:** <https://discuss.pennylane.ai/t/quantumfunctionerror-using-qngoptimizer-with-qaoa/587>\
**Category:** PennyLane Help\
**Created:** [September 25, 2020, 2:59pm UTC](https://discuss.pennylane.ai/t/quantumfunctionerror-using-qngoptimizer-with-qaoa/587 "2020-09-25T14:59:00Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Javier](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/javier/32/324_2.png) [@Javier](https://discuss.pennylane.ai/u/Javier)\
**Post date:** [September 25, 2020, 2:59pm UTC](https://discuss.pennylane.ai/t/quantumfunctionerror-using-qngoptimizer-with-qaoa/587/1 "2020-09-25T14:59:01Z")

</div>

Hi,

I’m trying to implement the QNGOptimizer in a QAOA circuit, but the following error arises when I start the optimization

`QuantumFunctionError: Can't generate metric tensor, operation MultiRZ: 1 params, wires [0, 1]has no defined generator`

The circuit I’m implementing has the following form

```
    def circuit(params, **kwargs):
        Initial_state(n_qubits)
        qml.layer(qaoa_layer, p, params[0], params[1])

```

where `Initial_state()` generates our initial state implementing the corresponding Hadamard gates, and `qaoa_layer` is defined as

```
def qaoa_layer(gamma, alpha):
    qaoa.cost_layer(gamma, cost_h)
    qaoa.mixer_layer(alpha, mixer_h)

```

where `cost_h` and `mixer_h` come from

```
cost_h, mixer_h = qaoa.maxcut(G)

```

And I do the optimization as

```
opt = qml.QNGOptimizer(stepsize = 0.1)
steps = 50
params = 0.01*np.random.rand(2, p)
for i in range(steps):
    params = opt.step(cost_function, params)
    print("Objective after step {:5d}: {: .7f}".format(i + 1, cost_function(params))

```

I’ve tried with other optimization methods like Adam or vanilla gradient descent and the optimization works nicely (it might get stucked in a local minima, but no errors appear). However, I don’t know exactly what is going on in this case when calculating the metric tensor. I’ve tried in other similar QAOA circuits where I directly define a function that implements the gates instead of loading them through the `qaoa` package, and the optimization works.

Thank you very much in advance!

P.D.: This is how I import the different packages

```
import pennylane as qml
from pennylane import qaoa
```

---

<div class="post-metadata">

**Author:** ![antalszava](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/antalszava/32/171_2.png) [@antalszava](https://discuss.pennylane.ai/u/antalszava)\
**Post date:** [September 25, 2020, 9:53pm UTC](https://discuss.pennylane.ai/t/quantumfunctionerror-using-qngoptimizer-with-qaoa/587/2 "2020-09-25T21:53:59Z")

</div>

Hi @Javier,

Thanks so much for your question! 🙂

The QAOA module indeed uses the `MultiRZ` operation of PennyLane. The generator referred to in the error message that you are facing is something that is missing for the `MultiRZ` operation. The generator of the operation is needed to compute the metric tensor of the quantum circuit. This metric tensor is used for optimization with the QNGOptimizer.

We are looking into adding support for the QAOA module when used with the QNGOptimizer and will get back to you on it. 🙂

---

<div class="post-metadata">

**Author:** ![josh](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/josh/32/100_2.png) [@josh](https://discuss.pennylane.ai/u/josh)\
**Post date:** [September 26, 2020, 3:18am UTC](https://discuss.pennylane.ai/t/quantumfunctionerror-using-qngoptimizer-with-qaoa/587/3 "2020-09-26T03:18:40Z")

</div>

Hi @Javier, as @antalszava noted, we currently do not support the `MultiRZ` gate for QNG optimization.

However, one way of forcing it to work now is to temporarily ‘remove’ the capability for `default.qubit` to accept `MultiRZ` gates:

```python
dev = qml.device('default.qubit', wires=len(wires))
dev.operations.remove("MultiRZ")

```

When executing a QNode on this device, PennyLane will now automatically decompose the `MultiRZ` gate into Pauli rotations.

Before removing `MultiRZ` from `default.qubit`:

```auto
 0: ──H──╭RZ(0.006)──╭RZ(0.006)───H──────────RZ(0.017)──H─────────────╭RZ(0.001)──╭RZ(0.001)───H──────────RZ(0.007)──H─────────────╭┤ ⟨Z ⊗ Z⟩
 1: ──H──╰RZ(0.006)──│───────────╭RZ(0.006)──H──────────RZ(0.017)──H──╰RZ(0.001)──│───────────╭RZ(0.001)──H──────────RZ(0.007)──H──╰┤ ⟨Z ⊗ Z⟩
 2: ──H──────────────╰RZ(0.006)──╰RZ(0.006)──H──────────RZ(0.017)──H──────────────╰RZ(0.001)──╰RZ(0.001)──H──────────RZ(0.007)──H───┤

```

After removing it, we can see that the `MultiRZ` gate has been decomposed:

```auto
 0: ──H──╭X──RZ(0.007)──╭X──╭X──RZ(0.007)──╭X───H──RZ(0.008)───H───────────────────╭X──RZ(0.008)──╭X──╭X──RZ(0.008)──╭X───H──RZ(0.007)───H───────────────────╭┤ ⟨Z ⊗ Z⟩
 1: ──H──╰C─────────────╰C──│──────────────│───╭X──RZ(0.007)──╭X──H──RZ(0.008)──H──╰C─────────────╰C──│──────────────│───╭X──RZ(0.008)──╭X──H──RZ(0.007)──H──╰┤ ⟨Z ⊗ Z⟩
 2: ──H─────────────────────╰C─────────────╰C──╰C─────────────╰C──H──RZ(0.008)──H─────────────────────╰C─────────────╰C──╰C─────────────╰C──H──RZ(0.007)──H───┤

```

---

<div class="post-metadata">

**Author:** ![Javier](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/javier/32/324_2.png) [@Javier](https://discuss.pennylane.ai/u/Javier)\
**Post date:** [September 26, 2020, 1:48pm UTC](https://discuss.pennylane.ai/t/quantumfunctionerror-using-qngoptimizer-with-qaoa/587/4 "2020-09-26T13:48:22Z")

</div>

Hi @antalszava and @josh, thank you very much for the answers! They were really helpful!

Please @antalszava, keep me updated about the new things with the QNGOptimizer related to the QAOA module.

@josh, thank you very much for the solution, now my code is working nicely with the QNGOptimizer.

---

<div class="post-metadata">

**Author:** ![Javier](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/javier/32/324_2.png) [@Javier](https://discuss.pennylane.ai/u/Javier)\
**Post date:** [September 28, 2020, 2:26pm UTC](https://discuss.pennylane.ai/t/quantumfunctionerror-using-qngoptimizer-with-qaoa/587/5 "2020-09-28T14:26:27Z")

</div>

Hi again,

I have another minor question. I was trying to implement noise in the system (bit flip operations concretely) using the `qml.device("cirq.mixedsimulator")` together with the `QNGOptimizer`. In this case, I didn’t have to implement the “MultiRZ” line @josh suggested. Do you know why? I just want to understand better the `qml.device` function.

Thank you very much!

Javier.

---

<div class="post-metadata">

**Author:** ![antalszava](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/antalszava/32/171_2.png) [@antalszava](https://discuss.pennylane.ai/u/antalszava)\
**Post date:** [September 28, 2020, 2:51pm UTC](https://discuss.pennylane.ai/t/quantumfunctionerror-using-qngoptimizer-with-qaoa/587/6 "2020-09-28T14:51:43Z")

</div>

Hi @Javier,

Nice find! When executing a QNode, PennyLane checks that the device supports each operation defined in the quantum function. Whenever an unsupported operation is encountered, PennyLane tries to decompose the operation into elementary gates that are pre-defined.

Josh’s suggestion helped with removing the support for the `MultiRZ` gate from the `'default.qubit'` device such that more elementary gates can be used, for which generators are defined.

The `"cirq.mixedsimulator"` device does not support the `MultiRZ` gate, so elementary gates are being used by default. The set of operations supported by the device can be checked by looking at the `dev.operations` dictionary. The reason for no direct support for the `MultiRZ` gate when using `"cirq.mixedsimulator"` is that there is no corresponding native Cirq operation that could be used. Therefore, the decomposition of the `MultiRZ` operation using elementary gates is used instead.

The following is an example of `MultiRZ` decomposition used internally:

```python
In [1]: qml.MultiRZ.decomposition(0.3, wires=[3,5])                                                                                         
Out[1]: [CNOT(wires=[5, 3]), RZ(0.3, wires=[3]), CNOT(wires=[5, 3])]

```

The `qml.device` function is a sort of global loader for every device that was installed with PennyLane and PennyLane plugins. In more details, this loading is achieved through using Python entry points and each device is registered by defining an entry point for the device in the `setup.py` file.

Hope this helps, let us know if you have further questions! 🙂
