Create an Operation with several registers as inputs/outputs

In Pennylane, we can create a custom operation by creating a class inheriting pennylane.operation.Operation.
One point is that it is then possible to draw this operation as a block in a given circuit.

However, the operation I am working on is a modular multiplication that takes as input one register for an operand, another for the other operand, a third one for the result, a fourth one for a modulo and a fifth one for the auxiliary qubits. I could also add a control qubit…

I want to implement this operation but the way to specify these registers is problematic.
I already saw 2 possibilities to do that, however they are not satisfying:

  • Put everything in the wires but as each register can have a varying size it may not work (we don’t know which wire does what)
  • Add the registers sizes as parameters, but the problem is that when I draw my operation, all these sizes will appear and if there is a real parameter (e.g. an angle) to display it will be lost in the crowd

How could I do ?

Hi @Asimonu, could you please share your code for option 2? I think we may find how to fix your problem from there but it’s hard to troubleshoot without seeing your code.

Also, if possible, please share the output you’re getting!

Thanks for your answer!
Sure, here is the whole class:

class modularMultiply(qml.operation.Operation):
    num_params = 6
    par_domain = "R"
    num_wires = AnyWires

    def compute_decomposition(a, m, b, aux, res, ctrl, wires):
        wires = list(wires)
        return [modular_multiply(a,m,wires[:b],wires[b:b+aux],wires[b+aux:b+aux+res],

modular_multiply is a circuit defined as a simple function, a and m are 2 external parameters (“true parameters”), aux, res and ctrl are used to tell how many of which kind of wires there are.
I find the overall way I did it quite dirty, because if I want to display the drawing of the circuit with parameters, I get something like that:

which is confusing because the only parameters I am interested in viewing are a and m.

Hi @Asimonu! I don’t know the logic of the function but you are probably calculating the values of b, aux and res a priori from a and m, right? In that case, you could do those calculations inside def compute_decomposition so you don’t need to pass them as an attribute. The only thing you would have to do is the estimation of the wires you are going to need to tell the operator.
I hope this helps!

1 Like

Hi !
Okay, right, I didn’t think at it but it’s a good idea. I would say however that computing the order of the wires at two different points in the code (call of the class and method compute_decomposition) can be dangerous (or require another function), but it’s indeed better for the drawing.
Thanks !

No worries! Let me know if you have any problem :wink: