Custom gate with a matrix

HI, I am creating a custom gate using a unitary matrix A.

class transform_matrix(Operation):

    num_params = 0
    num_wires = 10
    par_domain = None

    @staticmethod
    def _matrix(self):
        s1 = np.matrix([[0,1],[1,0]])
        ID = np.identity(2)
        A_1 = np.array(np.zeros((64, 64)))
        for i in range(0, 64, 1):
            if i//32 == 0:
                A_1[i, 2*i+1] = 1
            elif i//32 == 1:
                A_1[i, 64-2*(i%32)-2] = 1

        A = np.kron(A_1, np.kron(np.kron(s1, s1), np.kron(s1, s1)))
        return np.array(A)

Then I add it to the device using:

dev = qml.device('default.qubit', wires = 10)
dev.operations.add("transform_matrix")

When I call it as following

transform_matrix(wires=[i for i in range(10)])

it shows this error

pennylane.operation.MatrixUndefinedError

Can someone tell me where I am wrong?

Hey @sdas!

Quick aside: I’m running the most updated version of PennyLane (v0.33) and this code won’t work because of device API changes that were made a couple releases ago. If you decide to update (which I recommend that you do!) you just need to change your device to use the old default qubit:

dev = qml.device('default.qubit.legacy', wires = 10)

If I change that and run on v0.33, your code works and I get

transform_matrix(wires=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Having said that, I think you should create your custom operation differently :slight_smile:. Check out this documentation page for an example: Adding new operators — PennyLane 0.33.0 documentation.

Let me know if this helps!

Thanks Issacdevlugt. If I understood correctly, I upgraded pennylane to v0.33.1 and only changed “default.qubit” to “default.qubit.legacy”. But now it shows,

File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/init.py”, line 337, in device
raise DeviceError(“Device does not exist. Make sure the required plugin is installed.”)
pennylane._device.DeviceError: Device does not exist. Make sure the required plugin is installed.

Sorry there was a mistake in the upgrading process. Trying the solution now after correct upgrade.

So after I update the version and change “default.qubit” to “default.qubit.legacy” and run the code, it is showing same error,

pennylane.operation.MatrixUndefinedError

In detail,

File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/qnode.py”, line 1027, in call
res = qml.execute(
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/interfaces/execution.py”, line 616, in execute
results = inner_execute(tapes)
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/interfaces/execution.py”, line 249, in inner_execute
return cached_device_execution(tapes)
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/interfaces/execution.py”, line 371, in wrapper
res = list(fn(tuple(execution_tapes.values()), **kwargs))
File “/home/sd/anaconda3/lib/python3.9/contextlib.py”, line 79, in inner
return func(*args, **kwds)
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/_qubit_device.py”, line 460, in batch_execute
res = self.execute(circuit)
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/_qubit_device.py”, line 279, in execute
self.apply(circuit.operations, rotations=self._get_diagonalizing_gates(circuit), **kwargs)
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/devices/default_qubit_legacy.py”, line 296, in apply
self._state = self._apply_operation(self._state, operation)
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/devices/default_qubit_legacy.py”, line 338, in _apply_operation
matrix = self._asarray(self._get_unitary_matrix(operation), dtype=self.C_DTYPE)
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/devices/default_qubit_legacy.py”, line 682, in _get_unitary_matrix
return unitary.matrix()
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/operation.py”, line 775, in matrix
canonical_matrix = self.compute_matrix(*self.parameters, **self.hyperparameters)
File “/home/sd/anaconda3/lib/python3.9/site-packages/pennylane/operation.py”, line 744, in compute_matrix
raise MatrixUndefinedError
pennylane.operation.MatrixUndefinedError

Hi @sdas!

The following will work with the (non-legacy) default.qubit and the latest release of PennyLane:

import pennylane as qml
from pennylane.operation import Operation
from pennylane import numpy as np

class transform_matrix(Operation):

    num_params = 0
    num_wires = 10
    par_domain = None

    @staticmethod
    def compute_matrix():
        s1 = np.matrix([[0,1],[1,0]])
        ID = np.identity(2)
        A_1 = np.array(np.zeros((64, 64)))
        for i in range(0, 64, 1):
            if i//32 == 0:
                A_1[i, 2*i+1] = 1
            elif i//32 == 1:
                A_1[i, 64-2*(i%32)-2] = 1

        A = np.kron(A_1, np.kron(np.kron(s1, s1), np.kron(s1, s1)))
        return np.array(A)

dev = qml.device("default.qubit")

@qml.qnode(dev)
def f():
    transform_matrix(wires=range(10))
    return qml.state()

f()

Here, the trick is to override the compute_matrix() static method.

1 Like

Hi @Tom_Bromley
It is working now, thanks!

1 Like