Add control qubits to states

I want to add two control qubits to a statepreparation method. how can i do it? here is the code

import numpy as np
import pennylane as qml

num_qubits = 4
dev = qml.device('default.qubit', wires=num_qubits, shots=8192)

def Stateper(X):
	return qml.templates.MottonenStatePreparation(X, wires=[2, 3])

@qml.qnode(dev)
def circuit(X):
	qml.ControlledQubitUnitary(Stateper(X), control_wires=[0, 1], wires=[3, 4], control_values='11') # control qubits  = [0, 1] and target=[3, 4]
	return qml.state()

X = [1/2, 1/2, 1/2, 1/2]
print(circuit(X))

Hi @sassan_moradi, I’m not sure what’s the exact error you’re getting but I think the issue is that the wires has to be an iterable. This means that it needs to be something like wires=range(3). In your case for wires=[2,3] you would need wires=range(2,4).

Please let me know if this solves your problem! If not please share the error message you’re getting.

if len(U) != target_dim:
TypeError: object of type ‘MottonenStatePreparation’ has no len()

Hi @sassan_moradi,

I couldn’t replicate your error but using the ctrl function you can achieve the result you want in an easier way. The following code should work for you:

import pennylane as qml
from pennylane import numpy as np

num_qubits = 4
dev = qml.device('default.qubit', wires=num_qubits, shots=8192)

def Stateper(X):
    return qml.MottonenStatePreparation(X, wires=range(2,4))

op = qml.ctrl(Stateper,control=[0,1])

X = np.array([1/2, 1/2, 1/2, 1/2])

@qml.qnode(dev)
def circuit(X):
    op(X)
    return qml.state()

print(circuit(X))
print(qml.draw_mpl(circuit)(X))

You will notice a few things:

  • I imported numpy directly from PennyLane. This is important, specially when you need to set your parameters as trainable or not.
  • In the MottonenStatePreparation the wires are defined as a range because this value needs to be an iterable.
  • I used the ctrl function to specify the control qubits. This is equivalent to op1 = qml.ctrl(qml.ctrl(Stateper, 1), 0)
  • X is set as a numpy array. If you don’t set it this way it will still work but when you use qml.draw_mpl you won’t see the details of the circuit.

Please let me know if this is what you were looking for!

If this code doesn’t work try making sure that you’re using the latest PennyLane version. If it still doesn’t work please let me know.

many thanks for your useful response. i will try it and get back to you.

how can i use ctrl function, if i want to have control_value = ‘01’? but my problem is still with control value.

Hi @sassan_moradi, I’m not understanding your question. Did the code example show you an error? Or do you want a different functionality? In the example above the control qubits are ‘0’ and ‘1’. (op = qml.ctrl(Stateper,control=[0,1]))

The ctrl function receives a python function and the control wires as parameters and it returns the controlled version of the function.

You can read more about it here.

Please let me know if this answers your question or if it doesn’t please provide more details or an example of what you mean.

the example was true. i could run it successfully. But i want different functionality. for example, we know the quantum circuit for Möttonen state and as far as i know qml.ControlledQubitUnitary only take a matrix (gate) as an argument. Your example only consider control value = ‘11’. i want to also have control value = ‘01’. One way that i can do in qiskit is to design quantum circuit and then use convert to gate method which can convert a quantum circuit to a unitary matrix. I don’t know if Pennylane can do it or not.

Oh I see now @sassan_moradi.

You can use qml.matrix to get the matrix representation of your quantum circuit. Here in the “usage details” section you can see how to use it.

On the other hand, if you want your control value to be ‘01’ then you only need to add a PauliX gate to your first qubit before you apply the control. So the code above can remain the same except that your circuit function is now:

def circuit(X):
    qml.PauliX(0)
    op(X)
    return qml.state()

Please let me know if this helps!

many thanks. i think using PauliX gate can be the only solution for it at this moment.

Hi @sassan_moradi, you could always create a state-preparation function where you input a string and it performs the necessary PauliX gates according to your needs. It really depends on how automated you need this to be but you could even use an embedding template or a custom embedding to generate rotations according to the values that you want as a control.

The Basis Embedding in particular may be very useful for you.

Let me know if this helps!

Many thanks for your instructive responses. They were very helpful.

I’m glad I could help @sassan_moradi!