-
Notifications
You must be signed in to change notification settings - Fork 571
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
**Context:** Adding documentation for the new debugger feature. --------- Co-authored-by: Mikhail Andrenkov <mikhail@xanadu.ai> Co-authored-by: Utkarsh <utkarshazad98@gmail.com> Co-authored-by: Diego <67476785+DSGuala@users.noreply.github.com> Co-authored-by: Josh Izaac <josh146@gmail.com> Co-authored-by: soranjh <40344468+soranjh@users.noreply.github.com> Co-authored-by: Diego <diego_guala@hotmail.com>
- Loading branch information
1 parent
66421f1
commit 88938c3
Showing
7 changed files
with
506 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
qml.debugging | ||
============= | ||
|
||
.. automodapi:: pennylane.debugging | ||
:no-heading: | ||
:no-inherited-members: | ||
:skip: PLDB | ||
:skip: pldb_device_manager | ||
|
||
Entering the Debugging Context | ||
------------------------------ | ||
|
||
The :func:`~pennylane.breakpoint` function provides an interface for interacting with and | ||
stepping through a quantum circuit during execution. It allows for faster debugging | ||
by providing access to the internal state of the circuit and the ``QuantumTape`` as | ||
the circuit operations are applied. The functionality is highlighted by the example | ||
circuit below. | ||
|
||
.. code-block:: python | ||
import pennylane as qml | ||
@qml.qnode(qml.device('default.qubit', wires=(0,1,2))) | ||
def circuit(x): | ||
qml.breakpoint() | ||
qml.Hadamard(wires=0) | ||
qml.CNOT(wires=(0,2)) | ||
for w in (0, 1, 2): | ||
qml.RX(2*x, wires=w) | ||
qml.breakpoint() | ||
qml.RX(-x, wires=1) | ||
return qml.sample() | ||
circuit(1.2345) | ||
Running the above python script opens up the interactive ``[pldb]:`` prompt in the terminal. | ||
When this code reaches ``qml.breakpoint()`` it will pause and launch an interactive | ||
debugging prompt. The prompt specifies the path to the script and the next line to be | ||
executed after the breakpoint: | ||
|
||
.. code-block:: console | ||
> /Users/your/path/to/script.py(7)circuit() | ||
-> qml.Hadamard(wires=0) | ||
[pldb]: | ||
Controlling Code Execution in the Debugging Context | ||
--------------------------------------------------- | ||
|
||
The Pennylane Debugger (PLDB) is built from the native python debugger (Pdb), as such | ||
it shares a similar interface. We can interact with the debugger using the | ||
builtin commands: ``list``, ``longlist``, ``next``, ``continue``, and ``quit``. Any | ||
variables defined in the scope of the quantum function can also be accessed from the | ||
debugger. | ||
|
||
.. code-block:: console | ||
[pldb]: print(x) | ||
1.2345 | ||
The ``list`` (and ``longlist``) command will print a section of code around the | ||
breakpoint, highlighting the next line to be executed. This can be used to determine | ||
the location of execution in the circuit. | ||
|
||
.. code-block:: console | ||
[pldb]: longlist | ||
3 @qml.qnode(qml.device('default.qubit', wires=(0,1,2))) | ||
4 def circuit(x): | ||
5 qml.breakpoint() | ||
6 | ||
7 -> qml.Hadamard(wires=0) | ||
8 qml.CNOT(wires=(0,2)) | ||
9 | ||
10 for w in (0, 1, 2): | ||
11 qml.RX(2*x, wires=w) | ||
12 | ||
13 qml.breakpoint() | ||
14 qml.RX(-x, wires=1) | ||
15 return qml.sample() | ||
The ``next`` command will execute the next line of code, and print the following | ||
line to be executed, e.g., the next operation to execute is ``CNOT``. | ||
|
||
.. code-block:: console | ||
[pldb]: next | ||
> /Users/your/path/to/script.py(8)circuit() | ||
-> qml.CNOT(wires=(0,2)) | ||
[pldb]: list | ||
3 @qml.qnode(qml.device('default.qubit', wires=(0,1,2))) | ||
4 def circuit(x): | ||
5 qml.breakpoint() | ||
6 | ||
7 qml.Hadamard(wires=0) | ||
8 -> qml.CNOT(wires=(0,2)) | ||
9 | ||
10 for w in (0, 1, 2): | ||
11 qml.RX(2*x, wires=w) | ||
12 | ||
13 qml.breakpoint() | ||
Alternative, the ``continue`` command allows for jumping between breakpoints. This command resumes | ||
code execution until the next breakpoint is reached. Finally, the ``quit`` command | ||
ends the debugging prompt. | ||
|
||
.. code-block:: console | ||
[pldb]: continue | ||
> /Users/your/path/to/script.py(14)circuit() | ||
-> qml.RX(-x, wires=1) | ||
[pldb]: list | ||
9 | ||
10 for w in (0, 1, 2): | ||
11 qml.RX(2*x, wires=w) | ||
12 | ||
13 qml.breakpoint() | ||
14 -> qml.RX(-x, wires=1) | ||
15 return qml.sample() | ||
16 | ||
17 circuit(1.2345) | ||
[EOF] | ||
[pldb]: quit | ||
Extracting Circuit Information | ||
------------------------------ | ||
|
||
While in the debugging prompt, we can extract information and perform measurements | ||
on the qunatum circuit. Specifically we can make measurements using | ||
:func:`~pennylane.debug_expval`, :func:`~pennylane.debug_state`, | ||
:func:`~pennylane.debug_probs`, and access the gates in the circuit using | ||
:func:`~pennylane.debug_tape`. | ||
|
||
Consider the circuit from above, | ||
|
||
.. code-block:: console | ||
> /Users/your/path/to/script.py(7)circuit() | ||
-> qml.Hadamard(wires=0) | ||
[pldb]: longlist | ||
3 @qml.qnode(qml.device('default.qubit', wires=(0,1,2))) | ||
4 def circuit(x): | ||
5 qml.breakpoint() | ||
6 | ||
7 -> qml.Hadamard(wires=0) | ||
8 qml.CNOT(wires=(0,2)) | ||
9 | ||
10 for w in (0, 1, 2): | ||
11 qml.RX(2*x, wires=w) | ||
12 | ||
13 qml.breakpoint() | ||
14 qml.RX(-x, wires=1) | ||
15 return qml.sample() | ||
[pldb]: next | ||
> /Users/your/path/to/script.py(8)circuit() | ||
-> qml.CNOT(wires=(0,2)) | ||
[pldb]: next | ||
> /Users/your/path/to/script.py(10)circuit() | ||
-> for w in (0, 1, 2): | ||
[pldb]: | ||
All of the operations applied so far are tracked in the circuit's ``QuantumTape`` | ||
which is accessible using :func:`~pennylane.debug_tape`. This can be used to | ||
*visually* debug the circuit. | ||
|
||
.. code-block:: console | ||
[pldb]: qtape = qml.debug_tape() | ||
[pldb]: qtape.operations | ||
[Hadamard(wires=[0]), CNOT(wires=[0, 2])] | ||
[pldb]: print(qtape.draw()) | ||
0: ──H─╭●─┤ | ||
2: ────╰X─┤ | ||
The quantum state of the circuit at this point can be extracted using | ||
:func:`~pennylane.debug_state`. The associated probability distribution | ||
for the wires of interest can be probed using :func:`~pennylane.debug_probs`. | ||
|
||
.. code-block:: console | ||
[pldb]: qml.debug_state() | ||
array([0.70710678+0.j, 0. +0.j, 0. +0.j, 0. +0.j, | ||
0. +0.j, 0.70710678+0.j, 0. +0.j, 0. +0.j]) | ||
[pldb]: qml.debug_probs(wires=(0,2)) | ||
array([0.5, 0. , 0. , 0.5]) | ||
Another method for probing the system is by measuring observables via | ||
:func:`~pennylane.debug_expval`. | ||
|
||
.. code-block:: console | ||
[pldb]: qml.debug_expval(qml.Z(0)) | ||
0.0 | ||
[pldb]: qml.debug_expval(qml.X(0)@qml.X(2)) | ||
0.9999999999999996 | ||
Additionally, the quantum circuit can be dynamically updated by adding gates directly | ||
from the prompt. This allows users to modify the circuit *on-the-fly*! | ||
|
||
.. code-block:: console | ||
[pldb]: continue | ||
> /Users/your/path/to/script.py(14)circuit() | ||
-> qml.RX(-x, wires=1) | ||
[pldb]: qtape = qml.debug_tape() | ||
[pldb]: print(qtape.draw(wire_order=(0,1,2))) | ||
0: ──H─╭●──RX─┤ | ||
1: ────│───RX─┤ | ||
2: ────╰X──RX─┤ | ||
[pldb]: qml.RZ(0.5*x, wires=0) | ||
RZ(0.61725, wires=[0]) | ||
[pldb]: qml.CZ(wires=(1,2)) | ||
CZ(wires=[1, 2]) | ||
[pldb]: qtape = qml.debug_tape() | ||
[pldb]: print(qtape.draw(wire_order=(0,1,2))) | ||
0: ──H─╭●──RX──RZ─┤ | ||
1: ────│───RX─╭●──┤ | ||
2: ────╰X──RX─╰Z──┤ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.