Codexercise PF.4.1 (possible bug)

I have recently tried approaching codexercise PF.4.1 met a weird behavior. I tried this implementation:

dev = qp.device("default.qubit", wires = 3)

@qp.qnode(dev)
def circuit_as_function(params):
    """
    Implements the circuit shown in the codercise statement.
    Args:
    - params (np.ndarray): [theta_0, theta_1, theta_2, theta_3]
    Returns:
    - (np.tensor): <Z0>
    """

    weights = np.array([params[0], 0,0]).reshape(1,3)
    qp.BasicEntanglerLayers(weights=weights, wires = range(3))
    qp.RY(params[1], wires=0)
    qp.RY(params[2], wires=1)
    qp.RY(params[3], wires=2)

    return qp.expval(qp.PauliZ(0))

angles = np.linspace(0, 4 * np.pi, 200)
output_values = np.array([circuit_as_function([0.4, t, 0., 0.]) for t in angles])

and got a “Correct” result.

After that I commented out BasicEntanglerLayers and ran:

dev = qp.device("default.qubit", wires = 3)

@qp.qnode(dev)
def circuit_as_function(params):
    """
    Implements the circuit shown in the codercise statement.
    Args:
    - params (np.ndarray): [theta_0, theta_1, theta_2, theta_3]
    Returns:
    - (np.tensor): <Z0>
    """

    # weights = np.array([params[0], 0,0]).reshape(1,3)
    # qp.BasicEntanglerLayers(weights=weights, wires = range(3))
    qp.RY(params[1], wires=0)
    qp.RY(params[2], wires=1)
    qp.RY(params[3], wires=2)

    return qp.expval(qp.PauliZ(0))

angles = np.linspace(0, 4 * np.pi, 200)
output_values = np.array([circuit_as_function([0.4, t, 0., 0.]) for t in angles])

and got a “Correct” result as well. That seems to be weird, looks like a bug in the checking engine, but maybe my misunderstanding. Please advise.

Hi Anton, thanks for this feedback!

That’s odd indeed, although it can be the case that this is an exercise where multiple solutions are valid.
Let us take a deeper look into this and get back to you!

Hi @Anton_Naumov!
You were right that there is something off with this problem :rocket:
However, its not exactly a bug in the checking system.

What is going on in this exercise is that the output from the circuit (the measurement of Z on wire 0) is only dependent on the \theta_1 parameter, and mathematically equivalent to the \cos(\theta_1) function. The front part of the circuit with the RX gate that depends on \theta_0 and the 3-CNOT gates turns out to be effectively invisible to the measured Z_0 observable, as you were noticing from your submitted attempts. This is because after applying the RX and the CNOT gates, the wire 0 returns exactly to the 0 state (notice that this happens for any value of \theta_0).
Because the evaluation system is only verifying a single point from the output curve, any circuit that reproduces \cos(\theta_0) is passing the tests.

What I’d suggest in the meantime is to go ahead and implement the circuit exactly as drawn in the digram from the exercise with the RX and CNOT gates since this is the version the rest of the module assumes.

We’ll be adding a fix for the exercise so the checking system further verifies the intended circuit is being implemented rather than checking a single scalar output.

Thanks for catching and reporting this.

Hi @Anton_Naumov,
The update to this codercise is now active!

Just a note that the codercise has now a more tight verification that the expected circuit is implemented; as a reference here is a related post with clarification regarding the use of PennyLane templates in this problem.

Thanks for your feedback!