Stuck on Codercise I.7.2

I am not able to find the correct RX and RZ operators for this qubit. For Y I have used the decomposition Y = S \ RX(-\pi) \ S^{\dagger}

Hey @AvanishM! Super close! The first two operators are correct. You should only need 4 gates. We know from the previous exercise that the Hadamard gate is:

phi, theta, omega = np.pi/2, np.pi/2, np.pi/2

@qml.qnode(dev)
def hadamard_with_rz_rx():
    qml.RZ(phi, wires=0)
    qml.RX(theta, wires=0)
    qml.RZ(omega, wires=0)

I would do the same exercise for S, T^\dagger, and Y individually and then put it all together! Let me know if this helps.

Hello @isaacdevlugt ! Thank you for the response. Here are my decompositions for S, T^{\dagger}, Y. Let me know where I am going wrong :smiley:

def S_with_rz_rx():
    qml.RZ(np.pi/2, wires=0)
   
def adj_T_with_rz_rx():
    qml.RZ(-np.pi/4, wires=0)

def Y_with_rz_rx():
    qml.RZ(np.pi/2, wires=0) # S
    qml.RX(-np.pi, wires=0)
    qml.RZ(-np.pi/2, wires=0) # adj S

where I have used the fact Y = RY(\pi) = S \ RX(-\pi) \ S^{\dagger}. Collating these into one function:

def convert_to_rz_rx():
    qml.RZ(np.pi/2, wires=0)
    qml.RX(np.pi/2, wires=0)
    qml.RZ(np.pi/2 + np.pi/2 - np.pi/4 + np.pi/2, wires=0)
    qml.RX(-np.pi, wires=0)
    qml.RZ(-np.pi/2, wires=0)

Close! I can give you the answer here, but definitely try and understand why this is the case:

    qml.RZ(np.pi / 2, wires=0)
    qml.RX(np.pi / 2, wires=0)
    qml.RZ(7 * np.pi / 4, wires=0)
    qml.RX(np.pi, wires=0)

Another thing to note here as well is that you can try to check each operation by doing something like this:

@qml.qnode(dev)
def my_op_with_rx_rz():
    qml.RZ(np.pi/2, wires=0) # your proposed S gate
    qml.adjoint(qml.S(wires=0)) # the adjoint of S should "undo" the previous operation
    return qml.probs(wires=0) # resulting state should just be |0>, or [1, 0] as an array

Hope this helps!

Thank you @isaacdevlugt for your assistance! I understand how you arrived at that answer, using the decomposition Y= Z \ RX(\pi)

I have also tried your hint to see why my code was failing, and I got some insight by running:

@qml.qnode(dev)
def my_op_with_rx_rz():
    qml.RZ(np.pi/2, wires=0) 
    qml.RX(-np.pi, wires=0)
    qml.RZ(-np.pi/2, wires=0) # my different decomposition of Y
    qml.adjoint(qml.PauliY(wires=0)) # adjoint of Y
    return qml.probs(wires=0)

Instead of getting [1,0] I got [1, 3e-33]. So is it right to conclude my method was correct but was less efficient and thus introduced some machine error?

3e-33 is very small :sweat_smile:. That shouldn’t be causing a problem.

Hm, if that’s the case then my function for the Y operator should be correct, and I’m still not sure why my circuit was incorrect.

I found the reason my old circuit was incorrect, coming from a core ordering mistake :sweat_smile:
I forgot to reverse the ordering of the matrix multiplication when building the circuit so my old function:

def Y_with_rz_rx():
    qml.RZ(np.pi/2, wires=0) # S
    qml.RX(-np.pi, wires=0)
    qml.RZ(-np.pi/2, wires=0) # adj S

should actually be:

def Y_with_rz_rx():
    qml.RZ(-np.pi/2, wires=0) # adj S
    qml.RX(-np.pi, wires=0)
    qml.RZ(np.pi/2, wires=0) # S

# this collated function now works
def convert_to_rz_rx():
    qml.RZ(np.pi/2, wires=0)
    qml.RX(np.pi/2, wires=0)
    qml.RZ(np.pi/2 + np.pi/2 - np.pi/4 - np.pi/2, wires=0)
    qml.RX(-np.pi, wires=0)
    qml.RZ(np.pi/2, wires=0)

However, there is still one thing I’m thinking about. When I implemented the circuit in the wrong order and and called the adjoint, the resulting state was still \vert 0 \rangle, so would this also be a valid decomposition? I’m guessing up to a global phase.

Ah! Nice catch :+1:.

When I implemented the circuit in the wrong order and and called the adjoint, the resulting state was still …

If I’m understanding your statement correctly, if you apply any unitary operator and then apply its adjoint, the result will be as if you did nothing :slight_smile:. No global phases, even!