Please explain me this logic?
This is problem I.9.2 from the codebook.

##################
# YOUR CODE HERE #
##################
# WRITE A QUANTUM FUNCTION THAT PREPARES (1/2)|0> + i(sqrt(3)/2)|1>
def prepare_psi():
state = np.array([1/2, 1j*np.sqrt(3)/2])
qml.MottonenStatePreparation(state_vector= state, wires=0)
# WRITE A QUANTUM FUNCTION THAT SENDS BOTH |0> TO |y_+> and |1> TO |y_->
def y_basis_rotation():
qml.Hadamard(wires=0)
qml.S(wires=0)

Also, I having problem in I.9.3. I am not sure why are we doing adjoint.

dev = qml.device("default.qubit", wires=1)
@qml.qnode(dev)
def measure_in_y_basis():
##################
# YOUR CODE HERE #
##################
# PREPARE THE STATE
prepare_psi()
# PERFORM THE ROTATION BACK TO COMPUTATIONAL BASIS
qml.adjoint(qml.S)(wires=0)
qml.adjoint(qml.Hadamard)(wires=0)
# RETURN THE MEASUREMENT OUTCOME PROBABILITIES
return qml.probs(wires=0)
print(measure_in_y_basis())

It would be great if someone can explain me this and also its connection with the related theory in Section I.9

At the end of a quantum computation, we typically measure some physical observable relative to some basis (can sometimes be thought of as relative to some ‘orientation’ or axis). In many cases, these measurements are done in the computational basis, meaning relative to the |0 \rangle, |1 \rangle states.

For example, if we wanted to measure generic state |\psi \rangle in the computational basis, you can think of it as expressing |\psi \rangle as superposition of the computational basis states |\psi \rangle = c_{0} |0 \rangle + c_{1} |1 \rangle. Then doing a measurement on |\psi \rangle in the computational basis would yield the the state |0\rangle with probability |c_{0}|^{2} or it would yield the state |1\rangle with probability |c_{1}|^{2}.

In some cases, it is useful to do a measurement in a different basis. With our current example, that means you can also measure the state |\psi\rangle in a different basis, say the |y_{+}\rangle and |y_{+}\rangle states (which you should check/confirm form a basis). In that case, you can think of it as expressing |\psi \rangle as superposition of these new basis states |\psi \rangle = d_{0} |y_{+}\rangle + d_{1} |y_{-}\rangle. Your measurement would then be either the state |y_{+}\rangle with probability |d_{0}|^{2} or the state |y_{-}\rangle with probability |d_{1}|^{2}.

In the leadup to Codercise I.9.2, it tells you that to perform measurements in other bases, you need to rotate your states - this is what is shown in the Codebook in the case of rotating the Hadamard basis to the computational basis.

In the Codercise I.9.2, the y_basis rotation is performing the rotations needed to take the state |0 \rangle to the state |y_{+} \rangle as shown below:

and the rotations needed to take the state |1 \rangle to the state |y_{-} \rangle (I’ll let you draw the rotations for that one).

In Codercise I.9.3, you are taking the adjoint because you need to do the reverse rotation (take the state from the |y_{+} \rangle, |y_{-} \rangle basis states back to the |0 \rangle, |1\rangle states). I suggest you try to Exercise I.9.3 but for the |y_{+} \rangle, |y_{-} \rangle states instead of the Hadamard states and check that the numbers you get in Codercise I.9.3 match your calculations.

Thank you @DanielNino27.
What is Hadamard test? Somewhat it is related to expectation and mentioned at multiple places in pennylane documentation. Some small explanation on it will be great help.

Yes, the Hadamard test is a common subroutine that is used to estimate expectation values of unitary operators. There are a number of excellent online resources that give a detailed explanation of this. A resource that gives a good overview is section 6.2 of this pedagogical review article.

Often, the best way to understand these algorithms is to try to implement them yourself (in PennyLane for example ), so I would encourage you to try it out for yourself with the review article linked above as a guide. The struggle of going through the details of these algorithms will pay off in the long run.

The logic makes sense. However, I am a bit puzzled on why the following does not work.
First we define
def y_basis_rotation():
qml.Hadamard(wires = 0)
qml.S(wires = 0)

Then, I was expecting the following to work
def measure_in_y_basis():
prepare_psi()
qml.adjoint(y_basis_rotation) # Same as adjoint of S, followed by adjoint of H
return qml.probs(wires = 0)

You’re right that your method should work - I suspect the reason it doesn’t work for you is that you seem to have forgotten to specify that your y_basis_rotation function does not take an inputs when you use qml.adjoint.

You take a look at the documentation for qml.adjoint for an example of the format needed, but if you just add () after qml.adjoint(…), it should work.

Please let me know if that works!

As you explore PennyLane more @ksuresh, we have a PennyLane survey that you may be interested in if you would like to provide some feedback on your experience using PennyLane. We are always interested in collecting feedback from users on how we can keep improving PennyLane so that we can keep implementing great features.