qml.drawer.draw¶
-
draw
(qnode, wire_order=None, show_all_wires=False, decimals=2, max_length=100, show_matrices=True, expansion_strategy=None)[source]¶ Create a function that draws the given qnode or quantum function.
- Parameters
qnode (QNode or Callable) – the input QNode or quantum function that is to be drawn.
wire_order (Sequence[Any]) – the order (from top to bottom) to print the wires of the circuit
show_all_wires (bool) – If True, all wires, including empty wires, are printed.
decimals (int) – How many decimal points to include when formatting operation parameters.
None
will omit parameters from operation labels.max_length (int) – Maximum string width (columns) when printing the circuit
show_matrices=False (bool) – show matrix valued parameters below all circuit diagrams
expansion_strategy (str) –
The strategy to use when circuit expansions or decompositions are required. Note that this is ignored if the input is not a QNode.
gradient
: The QNode will attempt to decompose the internal circuit such that all circuit operations are supported by the gradient method.device
: The QNode will attempt to decompose the internal circuit such that all circuit operations are natively supported by the device.
- Returns
A function that has the same argument signature as
qnode
. When called, the function will draw the QNode/qfunc.
Example
@qml.qnode(qml.device('lightning.qubit', wires=2)) def circuit(a, w): qml.Hadamard(0) qml.CRX(a, wires=[0, 1]) qml.Rot(*w, wires=[1]) qml.CRX(-a, wires=[0, 1]) return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
>>> print(qml.draw(circuit)(a=2.3, w=[1.2, 3.2, 0.7])) 0: ──H─╭●─────────────────────────────╭●─────────┤ ╭<[email protected]> 1: ────╰RX(2.30)──Rot(1.20,3.20,0.70)─╰RX(-2.30)─┤ ╰<[email protected]>
Usage Details
By specifying the
decimals
keyword, parameters are displayed to the specified precision.>>> print(qml.draw(circuit, decimals=4)(a=2.3, w=[1.2, 3.2, 0.7])) 0: ──H─╭●─────────────────────────────────────╭●───────────┤ ╭<[email protected]> 1: ────╰RX(2.3000)──Rot(1.2000,3.2000,0.7000)─╰RX(-2.3000)─┤ ╰<[email protected]>
Parameters can be omitted by requesting
decimals=None
:>>> print(qml.draw(circuit, decimals=None)(a=2.3, w=[1.2, 3.2, 0.7])) 0: ──H─╭●───────╭●──┤ ╭<[email protected]> 1: ────╰RX──Rot─╰RX─┤ ╰<[email protected]>
If the parameters are not acted upon by classical processing like
-a
, thenqml.draw
can handle string-valued parameters as well:>>> @qml.qnode(qml.device('lightning.qubit', wires=1)) ... def circuit2(x): ... qml.RX(x, wires=0) ... return qml.expval(qml.PauliZ(0)) >>> print(qml.draw(circuit2)("x")) 0: ──RX(x)─┤ <Z>
When requested with
show_matrices=True
(the default), matrix valued parameters are printed below the circuit. Forshow_matrices=False
, they are not printed:>>> @qml.qnode(qml.device('default.qubit', wires=2)) ... def circuit3(): ... qml.QubitUnitary(np.eye(2), wires=0) ... qml.QubitUnitary(-np.eye(4), wires=(0,1)) ... return qml.expval(qml.Hermitian(np.eye(2), wires=1)) >>> print(qml.draw(circuit3)()) 0: ──U(M0)─╭U(M1)─┤ 1: ────────╰U(M1)─┤ <𝓗(M0)> M0 = [[1. 0.] [0. 1.]] M1 = [[-1. -0. -0. -0.] [-0. -1. -0. -0.] [-0. -0. -1. -0.] [-0. -0. -0. -1.]] >>> print(qml.draw(circuit3, show_matrices=False)()) 0: ──U(M0)─╭U(M1)─┤ 1: ────────╰U(M1)─┤ <𝓗(M0)>
The
max_length
keyword warps long circuits:rng = np.random.default_rng(seed=42) shape = qml.StronglyEntanglingLayers.shape(n_wires=3, n_layers=3) params = rng.random(shape) @qml.qnode(qml.device('lightning.qubit', wires=3)) def longer_circuit(params): qml.StronglyEntanglingLayers(params, wires=range(3)) return [qml.expval(qml.PauliZ(i)) for i in range(3)] print(qml.draw(longer_circuit, max_length=60)(params))
0: ──Rot(0.77,0.44,0.86)─╭●────╭X──Rot(0.45,0.37,0.93)─╭●─╭X 1: ──Rot(0.70,0.09,0.98)─╰X─╭●─│───Rot(0.64,0.82,0.44)─│──╰● 2: ──Rot(0.76,0.79,0.13)────╰X─╰●──Rot(0.23,0.55,0.06)─╰X─── ───Rot(0.83,0.63,0.76)──────────────────────╭●────╭X─┤ <Z> ──╭X────────────────────Rot(0.35,0.97,0.89)─╰X─╭●─│──┤ <Z> ──╰●────────────────────Rot(0.78,0.19,0.47)────╰X─╰●─┤ <Z>
The
wire_order
keyword specifies the order of the wires from top to bottom:>>> print(qml.draw(circuit, wire_order=[1,0])(a=2.3, w=[1.2, 3.2, 0.7])) 1: ────╭RX(2.30)──Rot(1.20,3.20,0.70)─╭RX(-2.30)─┤ ╭<[email protected]> 0: ──H─╰●─────────────────────────────╰●─────────┤ ╰<[email protected]>
If the device or
wire_order
has wires not used by operations, those wires are omitted unless requested withshow_all_wires=True
>>> empty_qfunc = lambda : qml.expval(qml.PauliZ(0)) >>> empty_circuit = qml.QNode(empty_qfunc, qml.device('lightning.qubit', wires=3)) >>> print(qml.draw(empty_circuit, show_all_wires=True)()) 0: ───┤ <Z> 1: ───┤ 2: ───┤
Drawing also works on batch transformed circuits:
@qml.gradients.param_shift(shifts=[(0.1,)]) @qml.qnode(qml.device('lightning.qubit', wires=1)) def transformed_circuit(x): qml.RX(x, wires=0) return qml.expval(qml.PauliZ(0)) print(qml.draw(transformed_circuit)(np.array(1.0, requires_grad=True)))
0: ──RX(1.10)─┤ <Z> 0: ──RX(0.90)─┤ <Z>
The function also accepts quantum functions rather than QNodes. This can be especially helpful if you want to visualize only a part of a circuit that may not be convertible into a QNode, such as a sub-function that does not return any measurements.
>>> def qfunc(x): ... qml.RX(x, wires=[0]) ... qml.CNOT(wires=[0, 1]) >>> print(qml.draw(qfunc)(1.1)) 0: ──RX(1.10)─╭●─┤ 1: ───────────╰X─┤