typewriter

PennyLane
Blog

May 14, 2021

How to visualize quantum circuits in PennyLane

Yuan Yao (Xanadu Resident)

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:

visualize_circuit_Qiskit_example

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.