# PennyLane Challenge: Universality of single-qubit gates

**URL:** <https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505>\
**Category:** PennyLane Challenges\
**Created:** [April 24, 2024, 3:20pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505 "2024-04-24T15:20:16Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [April 24, 2024, 3:20pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/1 "2024-04-24T15:20:16Z")

</div>

Use this topic to ask your questions about the [PennyLane Challenge: Universality of single-qubit gates](https://pennylane.ai/challenges/universality_of_single_qubit_gates/).

---

<div class="post-metadata">

**Author:** ![LdBeth](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/ldbeth/32/2536_2.png) [@LdBeth](https://discuss.pennylane.ai/u/LdBeth)\
**Post date:** [June 7, 2024, 5:38pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/2 "2024-06-07T17:38:30Z")

</div>

I have implemented the error function as

```python
def error(U, params):
    matrix = get_matrix(params)
    z = np.ravel(np.square(np.abs(U - matrix)))
    z = np.sum(qml.math.toarray(z))
    return z.item()

```

which is \displaystyle\sum\_i\sum\_j|U\_{ij}-M\_{ij}|^2.

With the given seed, the optimization passes the `[[1, 0], [0, -1]]` case rather easily, but fo test case `[[0.70710678, 0.70710678], [0.70710678, -0.70710678]]` with this error function the optimization does not converge fast enough.

I have also tried with taking max instead of sum but still, even though they are good enough to pass the `[[1, 0], [0, -1]]` case the other case still does not converge.

```python
    matrix = get_matrix(list(params))
    z = qml.math.toarray(np.max(np.abs((np.ravel(U - matrix)))))
    return z.item()

```

Any hints would appreciated.

---

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [June 11, 2024, 2:30am UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/3 "2024-06-11T02:30:48Z")

</div>

Hi @LdBeth ,

It’s much simpler than that. You don’t need to use np.ravel or many of the other things you’re using. You want U and matrix to be the same. What’s the simplest way that you can calculate a single number that tells you how different these two matrices are? The solution isn’t fancy but it works!

I hope this helps.

---

<div class="post-metadata">

**Author:** ![LdBeth](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/ldbeth/32/2536_2.png) [@LdBeth](https://discuss.pennylane.ai/u/LdBeth)\
**Post date:** [June 11, 2024, 6:25am UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/4 "2024-06-11T06:25:56Z")

</div>

I have to hand roll these because the most obvious to me `np.linalg.norm` does not work here,

```auto
Runtime Error: Failed to execute run() function: loop of ufunc does not support argument 0 of type ArrayBox which has no callable sqrt method

```

If norm doesn’t work, I guess I should go for trace the of differences?

I think I know it is using the autograd package to compute the derivative but unfortunately I have no clue on where I can learn what functions are supported and apparently not all numpy function are included, for example sqrt.

---

<div class="post-metadata">

**Author:** ![LdBeth](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/ldbeth/32/2536_2.png) [@LdBeth](https://discuss.pennylane.ai/u/LdBeth)\
**Post date:** [June 11, 2024, 7:09pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/5 "2024-06-11T19:09:15Z")

</div>

Thanks, and it turns out the fault is not cause by my error function, in fact \sum\_i\sum\_j|U\_{ij}-M\_{ij}|^2 is the correct way to go and my first error function is almost correct. (and it is certainly fine to use `np.ravel`.

The issue is with my `get_matrix` implementation, for some strange beliefs I wrote `np.matmul(rz2, rx, rz1)`, although give a `(2, 2)` shaped array, which turns out is not the same as `(rz2 @ rx @ rz1)`, after fixed this all tests are passed.

_As a suggestion, maybe it would be better if additional checks to the `get_matrix` result is added_

---

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [June 11, 2024, 10:24pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/6 "2024-06-11T22:24:51Z")

</div>

I’m glad you solved it @LdBeth ! And thanks for the suggestion, I will share it with our team.

---

<div class="post-metadata">

**Author:** ![LdBeth](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/ldbeth/32/2536_2.png) [@LdBeth](https://discuss.pennylane.ai/u/LdBeth)\
**Post date:** [June 12, 2024, 12:27am UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/7 "2024-06-12T00:27:29Z")

</div>

Oh, I forget to check the private test, which failed without revealing the reason why it has failed, and I now I have really no clues. My implementation is attached below.

```python
def get_matrix(params):
    alpha, beta, gamma, phi = params

    a, b = np.cos(beta / 2), -1j * np.sin(beta / 2)
    rx = np.matrix([[a, b], [b, a]])
    rz1 = np.matrix([[np.exp(-1j * alpha / 2), 0], [0, np.exp(1j * alpha / 2)]])
    rz2 = np.matrix([[np.exp(-1j * gamma / 2), 0], [0, np.exp(1j * gamma / 2)]])
    return np.exp(1j * phi) * (rz2 @ rx @ rz1)

def error(U, params):
    # Put your code here #
    # Return the error
    return sum(sum(qml.math.toarray(np.square(np.abs(U-matrix)))))

```

---

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [June 12, 2024, 6:03pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/8 "2024-06-12T18:03:03Z")

</div>

Hi @LdBeth ,

For the get\_matrix function you can use qml.RZ() and qml.RX() to create a unitary. Then you can use qml.matrix() to turn that unitary into a matrix.

For the error you don’t need to square it or turn it into an array.

---

<div class="post-metadata">

**Author:** ![LdBeth](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/ldbeth/32/2536_2.png) [@LdBeth](https://discuss.pennylane.ai/u/LdBeth)\
**Post date:** [June 12, 2024, 10:07pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/9 "2024-06-12T22:07:07Z")

</div>

I see, thanks! So that is all because the matrices I manually computed has caused much worse autograd performance, which gives more than 0.01 difference in the optimized result and failed to converge for other tests.

---

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [June 13, 2024, 12:33am UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/10 "2024-06-13T00:33:34Z")

</div>

That could be it @LdBeth !

---

<div class="post-metadata">

**Author:** ![yoshypdf](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/yoshypdf/32/2818_2.png) [@yoshypdf](https://discuss.pennylane.ai/u/yoshypdf)\
**Post date:** [August 17, 2024, 6:53am UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/11 "2024-08-17T06:53:35Z")

</div>

Hello,  
My code outputs the wrong answer and I still pass the test ? Can someone help me understand why ?

Here is my get\_matrix

```auto
alpha, beta, gamma, phi = params

    # Put your code here #
    RX_matrix = qml.matrix(qml.RX(beta, 0))
    RZ_matrix_gamma = qml.matrix(qml.RZ(gamma, 0))
    RZ_matrix_alpha = qml.matrix(qml.RZ(alpha, 0))

    U = np.exp(1j*phi)*RZ_matrix_gamma@RX_matrix@RZ_matrix_alpha

    # Return the matrix
    return U

```

and my err

```auto
err = np.sum(np.abs(U-matrix))
    return err

```

This is my output

```auto
Test 1 of 2 passed! ✅
				Input: [[1, 0], [0, -1]]
				Expected output: [[1, 0], [0, -1]]
				Solution output: [1.6892801452045216, -0.0015257310053992737, 1.4371410130382238, 1.5707963267948966]
				Failure message: null

			Test 2 of 2 passed! ✅
				Input: [[0.70710678, 0.70710678], [0.70710678, -0.70710678]]
				Expected output: [[0.70710678, 0.70710678], [0.70710678, -0.70710678]]
				Solution output: [1.570570205712601, 1.5707931060347167, 1.5648959446953452, 1.5707944021778046]
				Failure message: null

```

---

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [August 21, 2024, 3:32am UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/12 "2024-08-21T03:32:03Z")

</div>

Hi @yoshypdf ,

Thank you for pointing this out!  
I think what’s happening is that the `Solution output` is showing the params while the `Expected output` is showing the matrix.

So even though your solution output and expected output don’t match, the solution seems indeed to be correct.

I’m not sure if/how we can fix it but at least it’s good to be aware of this issue. Thanks for making this post!

---

<div class="post-metadata">

**Author:** ![eigenname](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/eigenname/32/3930_2.png) [@eigenname](https://discuss.pennylane.ai/u/eigenname)\
**Post date:** [August 7, 2025, 7:48pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/13 "2025-08-07T19:48:36Z")

</div>

Hello,

With the previous replies in mind, it seems that the get\_matrix function can be implemented with qml.matrix() and that the Frobenius norm is the applicable matrix norm for the error function. However, my implementation for get\_matrix:

```python
return np.exp(1j *phi) * (qml.matrix(qml.RZ(gamma,0)) @ qml.matrix(qml.RX(beta,0)) @ qml.matrix(qml.RZ(alpha,0)))

```

along with my implementation of the error function:

```auto
return np.linalg.norm(U - matrix, ord="fro")

```

does not pass any of the public and private tests and I’m stumped.

It’s not as simple as just returning

```python
return np.array([[alpha, beta], [gamma, phi]]) 

```

from get\_matrix, is it?

---

<div class="post-metadata">

**Author:** ![daniela.murcillo](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/daniela.murcillo/32/3612_2.png) [@daniela.murcillo](https://discuss.pennylane.ai/u/daniela.murcillo)\
**Post date:** [August 8, 2025, 8:29pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/14 "2025-08-08T20:29:07Z")

</div>

Hi!  
no, your `get_matrix` function is actually correct. The problem is in the error function.  
I am not sure about the reason, but the measure that you are using `np.linalg.norm` does not allow the model to converge to the correct answer. I can provide a better reason for this next week. But for now, I can give you a hint about the one we used. We used a simpler version just by trying to calculate the sum of all elements of the subtraction of the two matrices, somewhat similar to what you have.

Let me know if this helps.

---

<div class="post-metadata">

**Author:** ![eigenname](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/eigenname/32/3930_2.png) [@eigenname](https://discuss.pennylane.ai/u/eigenname)\
**Post date:** [August 8, 2025, 9:14pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/15 "2025-08-08T21:14:21Z")

</div>

Huh, interesting. The hint that you had provided was indeed helpful, I caught on that it ought to be the sum of the matrix elements of absolute difference between the matrices. I’d still like to know why np.linalg.norm prohibits the model’s convergence whenever you figure it out.

---

<div class="post-metadata">

**Author:** ![daniela.murcillo](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/daniela.murcillo/32/3612_2.png) [@daniela.murcillo](https://discuss.pennylane.ai/u/daniela.murcillo)\
**Post date:** [August 11, 2025, 7:49pm UTC](https://discuss.pennylane.ai/t/pennylane-challenge-universality-of-single-qubit-gates/4505/16 "2025-08-11T19:49:57Z")

</div>

yeah, I am looking into it. But we believe it is a bug of `qml.grad()` because it is treating `return np.linalg.norm(U - matrix, ord="fro")` and `return np.linalg.norm(np.abs(U - matrix), ord="fro")` (this one converges) differently when theoretically they are the same. Thanks for helping us uncovering this issue. I’ll report it to the technical team so it can be resolved or clarified further.
