Author: Anubhav Vardhan (anubhavvardhan@gmail.com)
User-defined gate added by: Boxi Li (etamin1201@gmail.com)
For more information about QuTiP see http://qutip.org
The circuit image visualization requires LaTeX and ImageMagick for display. The module automatically process the LaTeX code for plotting the circuit, generate the pdf and convert it to the png format.
On Mac and Linux, ImageMagick can be easily installed with the command conda install imagemagick
if you have conda installed.
Otherwise, please follow the installation instructions on the ImageMagick documentation.
On windows, you need to download and install ImageMagick installer. In addition, you also need perl (for pdfcrop) and Ghostscript (additional dependency of ImageMagick for png conversion).
To test if the installation is complete, try the following three commands working correctly in Command Prompt: pdflatex
, pdfcrop
and magick anypdf.pdf antpdf.png
, where anypdf.pdf
is any pdf file you have.
import numpy as np
from numpy import pi
from qutip import Qobj, about
from qutip_qip.circuit import QubitCircuit
from qutip_qip.operations import (Gate, berkeley, cnot, cphase, csign, fredkin,
gate_sequence_product, globalphase, iswap,
molmer_sorensen, phasegate, qrot, rx, ry, rz,
snot, sqrtiswap, sqrtnot, sqrtswap, swap,
swapalpha, toffoli)
%matplotlib inline
cphase(pi / 2)
q = QubitCircuit(2, reverse_states=False)
q.add_gate("CSIGN", controls=[0], targets=[1])
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
rx(pi / 2)
q = QubitCircuit(1, reverse_states=False)
q.add_gate("RX", targets=[0], arg_value=pi / 2, arg_label=r"\frac{\pi}{2}")
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
ry(pi / 2)
q = QubitCircuit(1, reverse_states=False)
q.add_gate("RY", targets=[0], arg_value=pi / 2, arg_label=r"\frac{\pi}{2}")
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
rz(pi / 2)
q = QubitCircuit(1, reverse_states=False)
q.add_gate("RZ", targets=[0], arg_value=pi / 2, arg_label=r"\frac{\pi}{2}")
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
cnot()
q = QubitCircuit(2, reverse_states=False)
q.add_gate("CNOT", controls=[0], targets=[1])
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
csign()
q = QubitCircuit(2, reverse_states=False)
q.add_gate("CSIGN", controls=[0], targets=[1])
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
berkeley()
q = QubitCircuit(2, reverse_states=False)
q.add_gate("BERKELEY", targets=[0, 1])
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
swapalpha(pi / 2)
fredkin()
toffoli()
swap()
q = QubitCircuit(2, reverse_states=False)
q.add_gate("SWAP", targets=[0, 1])
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
iswap()
q = QubitCircuit(2, reverse_states=False)
q.add_gate("ISWAP", targets=[0, 1])
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
sqrtiswap()
sqrtswap()
sqrtnot()
snot()
phasegate(pi / 2)
globalphase(pi / 2)
molmer_sorensen(pi / 2)
qrot(pi / 2, pi / 4)
The example above show how to generate matrice representations of the gates implemented in QuTiP, in their minimal qubit requirements. If the same gates is to be represented in a qubit register of size $N$, the optional keywork argument N
can be specified when calling the gate function. For example, to generate the matrix for the CNOT gate for a $N=3$ bit register:
cnot(N=3)
q = QubitCircuit(3, reverse_states=False)
q.add_gate("CNOT", controls=[1], targets=[2])
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
Furthermore, the control and target qubits (when applicable) can also be similarly specified using keyword arguments control
and target
(or in some cases controls
or targets
):
cnot(N=3, control=2, target=0)
q = QubitCircuit(3, reverse_states=False)
q.add_gate("CNOT", controls=[0], targets=[2])
q.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
The gates implemented in QuTiP can be used to build any qubit circuit using the class QubitCircuit. The output can be obtained in the form of a unitary matrix or a latex representation.
In the following example, we take a SWAP gate. It is known that a swap gate is equivalent to three CNOT gates applied in the given format.
N = 2
qc0 = QubitCircuit(N)
qc0.add_gate("ISWAP", [0, 1], None)
qc0.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U_list0 = qc0.propagators()
U0 = gate_sequence_product(U_list0)
U0
qc1 = QubitCircuit(N)
qc1.add_gate("CNOT", 0, 1)
qc1.add_gate("CNOT", 1, 0)
qc1.add_gate("CNOT", 0, 1)
qc1.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U_list1 = qc1.propagators()
U1 = gate_sequence_product(U_list1)
U1
In place of manually converting the SWAP gate to CNOTs, it can be automatically converted using an inbuilt function in QubitCircuit
qc2 = qc0.resolve_gates("CNOT")
qc2.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U_list2 = qc2.propagators()
U2 = gate_sequence_product(U_list2)
U2
From QuTiP 4.4, we can also add gate at arbitrary position in a circuit.
qc1.add_gate("CSIGN", index=[1], targets=[0], controls=[1])
qc1.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
qc3 = QubitCircuit(3)
qc3.add_gate("CNOT", 1, 0)
qc3.add_gate("RX", 0, None, pi / 2, r"\pi/2")
qc3.add_gate("RY", 1, None, pi / 2, r"\pi/2")
qc3.add_gate("RZ", 2, None, pi / 2, r"\pi/2")
qc3.add_gate("ISWAP", [1, 2])
qc3.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U3 = gate_sequence_product(qc3.propagators())
U3
qc4 = qc3.resolve_gates("CNOT")
qc4.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U4 = gate_sequence_product(qc4.propagators())
U4
qc5 = qc3.resolve_gates("ISWAP")
qc5.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U5 = gate_sequence_product(qc5.propagators())
U5
qc6 = qc3.resolve_gates(["ISWAP", "RX", "RY"])
qc6.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U6 = gate_sequence_product(qc6.propagators())
U6
qc7 = qc3.resolve_gates(["CNOT", "RZ", "RX"])
qc7.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U7 = gate_sequence_product(qc7.propagators())
U7
Interactions between non-adjacent qubits can be resolved by QubitCircuit to a series of adjacent interactions, which is useful for systems such as spin chain models.
qc8 = QubitCircuit(3)
qc8.add_gate("CNOT", 2, 0)
qc8.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U8 = gate_sequence_product(qc8.propagators())
U8
qc9 = qc8.adjacent_gates()
qc9.gates
[Gate(SWAP, targets=[0, 1], controls=None, classical controls=None, control_value=None, classical_control_value=None), Gate(CNOT, targets=[2], controls=[1], classical controls=None, control_value=None, classical_control_value=None), Gate(SWAP, targets=[0, 1], controls=None, classical controls=None, control_value=None, classical_control_value=None)]
U9 = gate_sequence_product(qc9.propagators())
U9
qc10 = qc9.resolve_gates("CNOT")
qc10.png
/usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip_qip/circuit/circuit_latex.py:95: UserWarning: Could not locate system 'pdfcrop': image output may have additional margins. warnings.warn(
U10 = gate_sequence_product(qc10.propagators())
U10
From QuTiP 4.4 one can add a gate at an arbitrary position of a circuit. All one needs to do is to specify the parameter index. With this, we can also add the same gate at multiple positions at the same time.
qc = QubitCircuit(1)
qc.add_gate("RX", targets=1, arg_value=np.pi / 2)
qc.add_gate("RX", targets=1, arg_value=np.pi / 2)
qc.add_gate("RY", targets=1, arg_value=np.pi / 2, index=[0])
qc.gates
[Gate(RY, targets=[1], controls=None, classical controls=None, control_value=None, classical_control_value=None), Gate(RX, targets=[1], controls=None, classical controls=None, control_value=None, classical_control_value=None), Gate(RX, targets=[1], controls=None, classical controls=None, control_value=None, classical_control_value=None)]
From QuTiP 4.4 on, user defined gates can be defined by a python function that takes at most one parameter and return a Qobj
, the dimension of the Qobj
has to match the qubit system.
def user_gate1(arg_value):
# controlled rotation X
mat = np.zeros((4, 4), dtype=complex)
mat[0, 0] = mat[1, 1] = 1.0
mat[2:4, 2:4] = rx(arg_value).full()
return Qobj(mat, dims=[[2, 2], [2, 2]])
def user_gate2():
# S gate
mat = np.array([[1.0, 0], [0.0, 1.0j]])
return Qobj(mat, dims=[[2], [2]])
To let the QubitCircuit
process those gates, we need to modify its attribute QubitCircuit.user_gates
, which is a python dictionary in the form {name: gate_function}
.
qc = QubitCircuit(2)
qc.user_gates = {"CTRLRX": user_gate1, "S": user_gate2}
When calling the add_gate
method, the target qubits and the argument need to be given.
# qubit 0 controls qubit 1
qc.add_gate("CTRLRX", targets=[0, 1], arg_value=pi / 2)
# qubit 1 controls qubit 0
qc.add_gate("CTRLRX", targets=[1, 0], arg_value=pi / 2)
# a gate can also be added using the Gate class
g_T = Gate("S", targets=[1])
qc.add_gate("S", targets=[1])
props = qc.propagators()
props[0] # qubit 0 controls qubit 1
props[1] # qubit 1 controls qubit 0
props[2] # S gate acts on qubit 1
about()
QuTiP: Quantum Toolbox in Python ================================ Copyright (c) QuTiP team 2011 and later. Current admin team: Alexander Pitchford, Nathan Shammah, Shahnawaz Ahmed, Neill Lambert, Eric Giguère, Boxi Li, Jake Lishman, Simon Cross, Asier Galicia, Paul Menczel, and Patrick Hopf. Board members: Daniel Burgarth, Robert Johansson, Anton F. Kockum, Franco Nori and Will Zeng. Original developers: R. J. Johansson & P. D. Nation. Previous lead developers: Chris Granade & A. Grimsmo. Currently developed through wide collaboration. See https://github.com/qutip for details. QuTiP Version: 5.1.0.dev0+c874c4a Numpy Version: 1.22.4 Scipy Version: 1.13.1 Cython Version: 3.0.10 Matplotlib Version: 3.5.2 Python Version: 3.10.4 Number of CPUs: 4 BLAS Info: Generic INTEL MKL Ext: False Platform Info: Linux (x86_64) Installation path: /usr/share/miniconda3/envs/test-environment/lib/python3.10/site-packages/qutip ================================================================================ Please cite QuTiP in your publication. ================================================================================ For your convenience a bibtex reference can be easily generated using `qutip.cite()`