Control Unitary Gates

Hi! How can I design a controlled-U gate?

Hi @Leeseok_Kim,

Depending on what type of controlled-U gate you wish to apply, there are several different possible solutions to this.

If you simply want to create an arbitrary controlled-unitary gate you would need to write down the matrix representation of it and then use qml.QubitUnitary to apply it (see here for details). Then you could e.g. define a two qubit arbitrary controlled-unitary like this:

CU  = np.array([[1, 0, 0, 0],
                [0, 1, 0, 0],
                [0, 0, a, b],
                [0, 0, c, d]])

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

@qml.qnode(dev)
def my_cu(U):
    ...
    qml.QubitUnitary(U, wires=[0, 1])
    ...
    return qml.expval(qml.PauliZ(1))

print(my_cu(CU))

where a, b, c and d would be the unitary that you wish to apply to the target qubit and ... could be replaced by any other operations you wish to apply in the circuit. This can be expanded to include several control qubits and/or several target qubits, as well as changing which qubits are control/target. You would need to write down and define these specific unitaries though.

In the above case you could also use the qml.CRot gate (see here) since you only have 1 control qubit and 1 target qubit. If you want to have more complicated unitaries you would need to use the above QubitUnitary approach.

Thank you so much! What if I already set up the U gate through lists of quantum gates not in terms of matrix and try to make it to controlled_U that is controlled by some specific wire index?

Should I do something like decomposing the U gate into matrix form and change that matrix and then use QubitUnitary thing?

Hi @Leeseok_Kim,

Unfortunately, I think that extracting the matrix representation and then using QubitUnitary to define a new gate (adding the conditional qubit to it in-between) might be necessary.

It would definitely be nice to be able to add controls to already existing operations, but as of now it’s possible in PennyLane in a straight-forward manner.

1 Like

Thanks, It is very help to see your reply, I would like to ask how to design single control-2-qubit gate(the 2 qubit gate is the universal gate which has 15 parameters),the 2-qubit universal gate has given in Pennylane, however, I want to add a control on it, could you help me? Thanks very much!

Hi @zj-lucky,

The answer here is similar to above. For any 2-qubit unitary, you can be able to repeat the construction above, except the matrix you supply will be 8x8 (3 qubits):

CU = np.array([[1, 0, 0, 0, 0, 0, 0, 0], 
               [0, 1, 0, 0, 0, 0, 0, 0],
               [0, 0, 1, 0, 0, 0, 0, 0],
               [0, 0, 0, 1, 0, 0, 0, 0],
               [0, 0, 0, 0, a, b, c, d], 
               [0, 0, 0, 0, e, f, g, h],
               [0, 0, 0, 0, i, j, k, l],
               [0, 0, 0, 0, m, n, o, p]])

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

@qml.qnode(dev) 
def cu_circuit(U): 
    ... 
    qml.QubitUnitary(U, wires=[0, 1, 2]) 
    ... 
    return qml.expval(qml.PauliZ(1)) 

print(cu_circuit(CU))

Depending on what you would like to do, this might be sufficient.

But if you want the parameters of this circuit to be trainable (while still remaining unitary), that is a bit trickier. Even without a control, the general two-qubit gate requires additional effort to make trainable (e.g., decomposing it into single-qubit parametrized gates and two-qubit fixed gates, or using the stochastic-parameter-shift rule). That would be the nontrivial part. Once you had that, you could make a controlled-U gate by sandwiching control gates on either side, e.g., like you see here.

@nathan Thank you very much for your reply, but there is still no way to add control to U. How to edit the code to add C to U?
%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201223122451

Hi @zj-lucky,

Thanks for sharing the code example, it helps me understand better what you’re aiming for (i.e., creating a controlled gate out of a PennyLane template).

Currently we do not have this feature natively available. If you’d like to put in an official feature request, the best place to do that is our GitHub issues page.

You could also do this manually, but it will require some work obtaining the decomposition. You can check out this StackExchange question which seems to provide the most fleshed-out recipe for the case of creating a two-qubit controlled unitary. You already have a suitable decomposition for the (uncontrolled) unitary above, so that post seems to be tackling the exact same question as you.