In this how-to, we’ll show you how to visualize your quantum circuits in different ways. Whether you build your quantum circuit via PennyLane or you obtain it by using other frameworks, you’ll find a way to visualize your circuits in this how-to guide.
Visualize PennyLane circuits
Consider the following circuit:
import pennylane as qml dev = qml.device("default.qubit", wires=2) @qml.qnode(dev) def circuit(params): qml.RY(params[0], wires=0) qml.RY(params[1], wires=1) qml.CNOT(wires=[0, 1]) return qml.expval(qml.PauliZ(1)) params = [0.1, 0.3]
In order to visualize your circuit, you can define a drawer that comes from your corresponding circuit by using qml.draw()
, and visualize your circuit by passing it the circuit parameters.
>>> drawer = qml.draw(circuit) >>> print(drawer(params)) 0: ──RY(0.1)──╭C──┤ 1: ──RY(0.3)──╰X──┤ ⟨Z⟩
Or you can also visualize it directly by providing your circuit and parameters:
> > > print(qml.draw(circuit)(params)) 0: ──RY(0.1)──╭C──┤ 1: ──RY(0.3)──╰X──┤ ⟨Z⟩
There are also some interesting keyword arguments available in the function draw()
. You can:
- choose the
wire_order
to print your circuit - visualize all wires or discard empty wires by setting
show_all_wires
import pennylane as qml dev = qml.device("default.qubit", wires=4) @qml.qnode(dev) def circuit(params): qml.RY(params[0], wires=0) qml.RY(params[1], wires=1) qml.CNOT(wires=[0, 1]) return qml.expval(qml.PauliZ(1)) params = [0.1, 0.3] drawer = qml.draw(circuit, show_all_wires=True, wire_order=[2,1,0,3]) print(drawer(params))
Here is how your circuit looks:
2: ───────────────┤ 1: ──RY(0.3)──╭X──┤ ⟨Z⟩ 0: ──RY(0.1)──╰C──┤ 3: ───────────────┤
Visualize circuits from other frameworks
You can also extract visual representations of your circuits when using other frameworks, such as the PennyLane-Cirq plugin and the PennyLane-Qiskit plugin.
We must first change the type of the device from default.qubit
to one of the types provided by the plugin. For example, the PennyLane-Cirq plugin integrates the Cirq quantum computing framework with PennyLane’s quantum machine learning capabilities. It provides four Cirq devices for PennyLane to use. We will use the simulator, cirq.simulator
, below.
After choosing the type of device, you can simply visualize your circuit using PennyLane’s operation qml.draw()
:
import pennylane as qml import numpy as np dev = qml.device("cirq.simulator", wires=4) @qml.qnode(dev) def circuit(weights): qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1, 2, 3]) return qml.expval(qml.PauliX(0) @ qml.PauliZ(2)) weight_shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4) weights = np.random.random(weight_shape) print(qml.draw(circuit)(weights))
Then you can visualize your circuit in the same format as in PennyLane:
0: ──Rot(0.428, 0.885, 0.374)───╭C────────────────────────────────────────────────────────────╭X──Rot(0.589, 0.0384, 0.381)──────╭C──────╭X──╭┤ ⟨X ⊗ Z⟩ 1: ──Rot(0.0992, 0.112, 0.375)──╰X──╭C───Rot(0.141, 0.864, 0.747)─────────────────────────────│──────────────────────────────╭C──│───╭X──│───│┤ 2: ──Rot(0.411, 0.204, 0.432)───────╰X──╭C─────────────────────────Rot(0.568, 0.0134, 0.528)──│──────────────────────────────│───╰X──│───╰C──╰┤ ⟨X ⊗ Z⟩ 3: ──Rot(0.0688, 0.709, 0.658)──────────╰X────────────────────────────────────────────────────╰C──Rot(0.252, 0.0321, 0.263)──╰X──────╰C───────┤
You can also utilize the method embedded in the corresponding plugin device. For the Cirq library, you can run your circuit once with the desired parameters, then get the corresponding Cirq circuit from the dev.circuit
attribute directly.
import pennylane as qml import numpy as np dev = qml.device("cirq.simulator", wires=4) @qml.qnode(dev) def circuit(weights): qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1, 2, 3]) return qml.expval(qml.PauliX(0) @ qml.PauliZ(2)) weight_shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4) weights = np.random.random(weight_shape) print(dev.circuit)
The output circuit is here:
┌───────────┐ ┌──┐ ┌──┐ 0: ───Rz(0.049π)───Ry(0.139π)───Rz(0.28π)────@─────────────────────X──────────────Rz(0.284π)───Ry(0.237π)───Rz(0.065π)────@──────X─────H───I─── │ │ │ │ 1: ───Rz(0.164π)───Ry(0.229π)───Rz(0.013π)───X───@───Rz(0.272π)────┼Ry(0.229π)────Rz(0.156π)──────────────────────────────┼@─────┼X────I─────── │ │ ││ ││ 2: ───Rz(0.181π)───Ry(0.303π)───Rz(0.142π)───────X───@─────────────┼Rz(0.193π)────Ry(0.265π)───Rz(0.314π)─────────────────X┼─────@┼────I─────── │ │ │ │ 3: ───Rz(0.011π)───Ry(0.083π)───Rz(0.066π)───────────X─────────────@──────────────Rz(0.27π)────Ry(0.162π)───Rz(0.16π)──────X──────@────I─────── └───────────┘ └──┘ └──┘
Furthermore, you can choose your device type as qiskit.aer
and use the embedded method dev._circuit.draw()
(from the Qiskit library) to visualize your circuits when accessing Qiskit devices through PennyLane.
import pennylane as qml import numpy as np dev = qml.device("qiskit.aer", wires=4) @qml.qnode(dev) def circuit(weights): qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1, 2, 3]) return qml.expval(qml.PauliX(0) @ qml.PauliZ(2)) weight_shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4) weights = np.random.random(weight_shape) dev._circuit.draw()
By default, you can obtain your text output circuit:
┌─────────────┐┌─────────────┐┌─────────────┐ ┌───┐» q_0: ┤ RZ(0.52063) ├┤ RY(0.57803) ├┤ RZ(0.85435) ├──■─────────────────────┤ X ├» ├─────────────┤├─────────────┤├─────────────┤┌─┴─┐ ┌────────────┐└─┬─┘» q_1: ┤ RZ(0.28045) ├┤ RY(0.17518) ├┤ RZ(0.92676) ├┤ X ├──■──┤ RZ(0.4218) ├──┼──» ├─────────────┤├─────────────┤├─────────────┤└───┘┌─┴─┐└────────────┘ │ » q_2: ┤ RZ(0.17531) ├┤ RY(0.90968) ├┤ RZ(0.18642) ├─────┤ X ├──────■─────────┼──» └┬────────────┤├─────────────┤└┬────────────┤ └───┘ ┌─┴─┐ │ » q_3: ─┤ RZ(0.2362) ├┤ RY(0.30919) ├─┤ RZ(0.6536) ├──────────────┤ X ├───────■──» └────────────┘└─────────────┘ └────────────┘ └───┘ » c: 4/══════════════════════════════════════════════════════════════════════════» » « ┌─────────────┐┌─────────────┐┌─────────────┐ ┌───┐┌───┐ » «q_0: ┤ RZ(0.80999) ├┤ RY(0.98599) ├┤ RZ(0.56135) ├───■───────┤ X ├┤ H ├──────» « └┬────────────┤├─────────────┤└─────────────┘ │ └─┬─┘├───┤┌─┐ » «q_1: ─┤ RY(0.2122) ├┤ RZ(0.44942) ├──────────────────┼────■────┼──┤ X ├┤M├───» « ┌┴────────────┤├─────────────┤┌─────────────┐ ┌─┴─┐ │ │ └─┬─┘└╥┘┌─┐» «q_2: ┤ RZ(0.14738) ├┤ RY(0.83984) ├┤ RZ(0.38866) ├─┤ X ├──┼────■────┼───╫─┤M├» « ├─────────────┤├─────────────┤├─────────────┴┐└───┘┌─┴─┐ │ ║ └╥┘» «q_3: ┤ RZ(0.79052) ├┤ RY(0.94253) ├┤ RZ(0.012706) ├─────┤ X ├───────■───╫──╫─» « └─────────────┘└─────────────┘└──────────────┘ └───┘ ║ ║ » «c: 4/═══════════════════════════════════════════════════════════════════╩══╩═» « 1 2 » « ┌─┐ «q_0: ───┤M├ « └╥┘ «q_1: ────╫─ « ║ «q_2: ────╫─ « ┌─┐ ║ «q_3: ┤M├─╫─ « └╥┘ ║ «c: 4/═╩══╩═ « 3 0
However, Qiskit gives you two more options for the quantum circuit: one uses matplotlib, and the other uses LaTex. You can use either mpl
and latex
for the output
kwarg in your draw()
function like this:
>>> dev._circuit.draw(output="mpl")
Here mpl
stands for the matplotlib drawing:
There are also some interesting keyword arguments available in the function draw()
of Qiskit. You can:
- set the
reverse_bits=True
to draw your circuit with reversed bit order - remove the barrier in your circuit by configuring
plot_barriers=False
if you have defined it
In PennyLane, we provide a rich ecosystem integrating lots of popular quantum software development libraries. In addition to PennyLane-Cirq and PennyLane-Qiskit, there is the (PennyLane-Qulacs plugin), (PennyLane-Q# plugin), and (PennyLane-Forest plugin), and more. The visualization of the circuit depends on the draw function inside the plugin you have chosen, therefore be sure to refer to the plugin documentation.
About the author
Yuan Yao
Wanna be the BEST CSer among physicists and the BEST physicist among CSers.