Weird output. How is qml.RY getting executed

Hi,

I am studying the Iris classification part of this tutorial: Variational classifier — PennyLane documentation

I am trying to figure out the complete encoding process by adding some print() in Pennylane’s source code:

    @staticmethod
    def compute_matrix(theta):  # pylint: disable=arguments-differ
        r"""Representation of the operator as a canonical matrix in the computational basis (static method).

        The canonical matrix is the textbook matrix representation that does not consider wires.
        Implicitly, this assumes that the wires of the operator correspond to the global wire order.

        .. seealso:: :meth:`~.RY.matrix`


        Args:
            theta (tensor_like or float): rotation angle

        Returns:
            tensor_like: canonical matrix

        **Example**

        >>> qml.RY.compute_matrix(torch.tensor(0.5))
        tensor([[ 0.9689, -0.2474],
                [ 0.2474,  0.9689]])
        """
        print("Operation: RY")
        print("theta: ", theta)
        c = qml.math.cos(theta / 2)
        s = qml.math.sin(theta / 2)
        if qml.math.get_interface(theta) == "tensorflow":
            c = qml.math.cast_like(c, 1j)
            s = qml.math.cast_like(s, 1j)
        # The following avoids casting an imaginary quantity to reals when backpropagating
        c = (1 + 0j) * c
        s = (1 + 0j) * s
        print("RY matrix: ", qml.math.stack([stack_last([c, -s]), stack_last([s, c])], axis=-2))
        return qml.math.stack([stack_last([c, -s]), stack_last([s, c])], axis=-2)

and in the tutorial code where it does the encoding:

def statepreparation(a):
    print("encoding.....")

    qml.RY(a[0], wires=0)
    qml.CNOT(wires=[0, 1])
    qml.RY(a[1], wires=1)
    qml.CNOT(wires=[0, 1])
    qml.RY(a[2], wires=1)
    qml.PauliX(wires=0)
    qml.CNOT(wires=[0, 1])
    qml.RY(a[3], wires=1)
    qml.CNOT(wires=[0, 1])
    qml.RY(a[4], wires=1)
    qml.PauliX(wires=0)
    print("encoding done!")

I expected the output would be something like this:

encoding...
theta and RY matrix
encoding done!

but instead I had this:


How can I get expected output? Why did I get output from qml.RYafter statepreparation() is done?

Hi @pennyRocie, thanks for coming to the forum!

The execution order of QNodes can definitely be rather confusing. The Architectural Overview document can help clarify the bits and pieces that go into executing a quantum circuit with PennyLane, but I can give a quick summary of what’s going on here.

When you call the QNode (by calling test(ang)), it first constructs a tape by creating instances of each of the operations listed in the statepreparation function and saving them to a fresh tape. Once that tape is created, it’s passed to a device (in this case, default.qubit), and the device will execute it by iterating over the tape and computing the matrix of each operation. Your “encoding…” and “encoding done!” messages surround the first part, aka tape construction. The print statements from compute_matrix only come later, when the device iterates over the tape.

Hope that clears things up!

1 Like

Hi @timmysilv, thanks for your answer!

Is there a way for me access this “tape”? I would like to know where operations like qml.RY, qml.CNOT are actually getting executed, and print out the entire encoding process.
Also, is it possible to access intermediate quantum state matrix if everything happens on a simulator? Something like print(dev.state) in both encoding and ansatz. This may help me understand how everything works more clearly.

You can definitely look at the tape, it’s saved on the QNode itself. You can see it with test.tape. Note that it won’t be populated until you actually execute the QNode.

As for observing the state, the best thing to do would be to stick a Snapshot operation into your circuit wherever you’re curious.

Hope that helps, and happy hacking!

1 Like

Thanks for the help!

I inserted qml.Snapshot() in between gates and did qml.snapshots(circuit)(weights, angles) + bias at the end, but it was giving me errors which seems complicated and nested.

Is there other ways to extract quantum state matrix in between gates? Something like

    qml.RY(a[1], wires=1)
    print("quantum state: ", dev.state)

Sorry to hear you’ve hit more snags :confused: unfortunately you can’t print the device state for similar reasons to why the print statements appeared in a weird order for your original question; it’s just a consequence of the way operations are executed in PennyLane.

If Snapshot is causing trouble for you, please open an issue on our GitHub repo with additional details and we can help look into it for you there.