quairkit.circuit¶
The source file of the Circuit class.
-
class quairkit.circuit.Circuit(num_systems=
None
, system_dim=2
, physical_idx=None
)¶ Class for quantum circuit.
- Parameters:¶
- num_systems : int | None¶
number of systems in the circuit. Defaults to None. Alias of
num_qubits
.- system_dim : int | List[int] | None¶
dimension of systems of this circuit. Can be a list of system dimensions or an int representing the dimension of all systems. Defaults to be qubit case.
- physical_idx : List[int] | None¶
physical indices of systems. Defaults to be the same as the logical indices.
Note
when the number of system is unknown and system_dim is an int, the circuit is a dynamic quantum circuit.
Examples
qc = Circuit(1) # A quantum circuit with 1 qubit qc.h() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{H}
-
to_latex(style=
'standard'
, decimal=2
)¶ The LaTeX representation of the circuit, written in Quantikz format.
- Parameters:¶
Examples
qc = Circuit(2) qc.h() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{H} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{H} & {} & {}
-
plot(style=
'standard'
, decimal=2
, dpi=300
, print_code=False
, show_plot=True
, include_empty=False
, latex=True
, **kwargs)¶ Display the circuit using Quantikz if
latex
is True, otherwise using matplotlib.- Parameters:¶
- style : str¶
the style of the plot, can be ‘standard’, ‘compact’ or ‘detailed’. Defaults to
standard
.- decimal : int¶
number of decimal places to display. Defaults to 2.
- dpi : int¶
dots per inches of plot image. Defaults to 300.
- print_code : bool¶
whether print the LaTeX code of the circuit, default to
False
.- show_plot : bool¶
whether show the plotted circuit, default to
True
.- include_empty : bool¶
whether include empty lines, default to
False
.- latex : bool¶
whether use Quantikz, a LaTeX package, to plot circuits , default to
True
.- **kwargs¶
additional parameters for matplotlib plot.
- Returns:¶
None, or a
matplotlib.figure.Figure
instance depending onlatex
andoutput
.- Return type:¶
Figure | None
Notes
If
latex
is True, the circuit will be displayed in LaTeX format; iflatex
is False, the circuit will be displayed in matplotlib format, in which case we have three additional parameters: - output_plot: whether output the plot instance, default toFalse
. - save_path: the save path of image. Defaults to None. - scale: scale coefficient of figure. Default to 1.0.Examples
qc = Circuit(2) qc.h() qc.plot()
(Displays the plotted circuit using Quantikz or matplotlib)
Warning
Starting from QuAIRKit 2.5.0, Circuit.plot now defaults to using QuantiKz, a LaTeX package powered by TikZ, for rendering quantum circuit diagrams commonly used in academic publications. Support for plotting circuits with Matplotlib will be deprecated in the near future.
To fully utilize this feature, please ensure that a TeX distribution, such as [TeX Live](https://www.tug.org/texlive), is installed on your system. This will enhance your experience with QuAIRKit and quantum computing visualization.
-
h(qubits_idx=
'full'
)¶ Add single-qubit Hadamard gates.
The matrix form of such a gate is:
\[\begin{split}H = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | int | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘full’.
Examples
qc = Circuit(2) qc.h() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{H} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{H} & {} & {}
-
s(qubits_idx=
'full'
)¶ Add single-qubit S gates.
The matrix form of such a gate is:
\[\begin{split}S = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | int | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘full’.
Examples
qc = Circuit(2) qc.s() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{S} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{S} & {} & {}
-
sdg(qubits_idx=
'full'
)¶ Add single-qubit S dagger (S inverse) gates.
The matrix form of such a gate is:
\[\begin{split}S^\dagger = \begin{bmatrix} 1 & 0 \\ 0 & -i \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | int | str¶
Indices of the qubits on which the gates are applied. Defaults to
'full'
.
Examples
qc = Circuit(2) qc.sdg() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{S^\dagger} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{S^\dagger} & {} & {}
-
t(qubits_idx=
'full'
)¶ Add single-qubit T gates.
The matrix form of such a gate is:
\[\begin{split}T = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/4} \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | int | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘full’.
Examples
qc = Circuit(2) qc.t() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{T} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{T} & {} & {}
-
tdg(qubits_idx=
'full'
)¶ Add single-qubit T dagger (T inverse) gates.
The matrix form of such a gate is:
\[\begin{split}T^\dagger = \begin{bmatrix} 1 & 0 \\ 0 & e^{-i\pi/4} \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | int | str¶
Indices of the qubits on which the gates are applied. Defaults to
'full'
.
Examples
qc = Circuit(2) qc.tdg() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{T^\dagger} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{T^\dagger} & {} & {}
-
x(qubits_idx=
'full'
)¶ Add single-qubit X gates.
The matrix form of such a gate is:
\[\begin{split}X = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | int | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘full’.
Examples
qc = Circuit(2) qc.x() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{X} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{X} & {} & {}
-
y(qubits_idx=
'full'
)¶ Add single-qubit Y gates.
The matrix form of such a gate is:
\[\begin{split}Y = \begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | int | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘full’.
Examples
qc = Circuit(2) qc.y() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{Y} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{Y} & {} & {}
-
z(qubits_idx=
'full'
)¶ Add single-qubit Z gates.
The matrix form of such a gate is:
\[\begin{split}Z = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | int | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘full’.
Examples
qc = Circuit(2) qc.z() qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{Z} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{Z} & {} & {}
-
p(qubits_idx=
'full'
, param=None
, param_sharing=False
)¶ Add single-qubit P gates.
The matrix form of such a gate is:
\[\begin{split}P(\theta) = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\theta} \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.p([0], torch.pi/2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{P(1.57)} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
rx(qubits_idx=
'full'
, param=None
, param_sharing=False
)¶ Add single-qubit rotation gates about the x-axis.
The matrix form of such a gate is:
\[\begin{split}R_X(\theta) = \begin{bmatrix} \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\ -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.rx([0], torch.pi/2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{R_{x}(1.57)} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
ry(qubits_idx=
'full'
, param=None
, param_sharing=False
)¶ Add single-qubit rotation gates about the y-axis.
The matrix form of such a gate is:
\[\begin{split}R_Y(\theta) = \begin{bmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.ry([0], torch.pi/2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{R_{y}(1.57)} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
rz(qubits_idx=
'full'
, param=None
, param_sharing=False
)¶ Add single-qubit rotation gates about the z-axis.
The matrix form of such a gate is:
\[\begin{split}R_Z(\theta) = \begin{bmatrix} e^{-i\theta/2} & 0 \\ 0 & e^{i\theta/2} \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.rz([0], torch.pi/2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{R_{z}(1.57)} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
u3(qubits_idx=
'full'
, param=None
, param_sharing=False
)¶ Add single-qubit rotation gates.
The matrix form of such a gate is:
\[\begin{split}U_3(\theta, \phi, \lambda) = \begin{bmatrix} \cos\frac\theta2 & -e^{i\lambda}\sin\frac\theta2 \\ e^{i\phi}\sin\frac\theta2 & e^{i(\phi+\lambda)}\cos\frac\theta2 \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.u3([0], torch.pi/2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{U(1.57, 1.57, 1.57)} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
cnot(qubits_idx=
'cycle'
)¶ Add CNOT gates.
For a 2-qubit circuit, when qubits_idx is [0, 1], the matrix form is:
\[\mathit{CNOT} = |0\rangle \langle 0|\otimes I + |1\rangle \langle 1|\otimes X\]- Parameters:¶
- qubits_idx : Iterable[int] | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘cycle’.
Examples
qc = Circuit(2) qc.cnot([0, 1]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \targ{} & {} & {}
-
cy(qubits_idx=
'cycle'
)¶ Add controlled Y gates.
For a 2-qubit circuit, when qubits_idx is [0, 1], the matrix form is:
\[\mathit{CY} = |0\rangle \langle 0|\otimes I + |1\rangle \langle 1|\otimes Y\]- Parameters:¶
- qubits_idx : Iterable[int] | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘cycle’.
Examples
qc = Circuit(2) qc.cy([0, 1]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{Y} & {} & {}
-
cz(qubits_idx=
'linear'
)¶ Add controlled Z gates.
For a 2-qubit circuit, when qubits_idx is [0, 1], the matrix form is:
\[\mathit{CZ} = |0\rangle \langle 0|\otimes I + |1\rangle \langle 1|\otimes Z\]- Parameters:¶
- qubits_idx : Iterable[int] | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘linear’.
Examples
qc = Circuit(2) qc.cz([0, 1]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{Z} & {} & {}
-
swap(qubits_idx=
'linear'
)¶ Add SWAP gates.
The matrix form is:
\[\begin{split}\mathit{SWAP} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘linear’.
Examples
qc = Circuit(2) qc.swap([0, 1]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[2,style={draw=none}]{\permute{2,1}} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
cp(qubits_idx=
'cycle'
, param=None
, param_sharing=False
)¶ Add controlled P gates.
For a 2-qubit circuit, when qubits_idx is [0, 1], the matrix form is:
\[\begin{split}\mathit{CP}(\theta) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & e^{i\theta} \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.cp([0, 1], torch.pi / 2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{P(1.57)} & {} & {}
-
crx(qubits_idx=
'cycle'
, param=None
, param_sharing=False
)¶ Add controlled rotation gates about the x-axis.
For a 2-qubit circuit, when qubits_idx is [0, 1], the matrix form is:
\[\mathit{CR_X} = |0\rangle \langle 0|\otimes I + |1\rangle \langle 1|\otimes R_X\]- Parameters:¶
Examples
qc = Circuit(2) qc.crx([0, 1], torch.pi / 2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{R_{x}(1.57)} & {} & {}
-
cry(qubits_idx=
'cycle'
, param=None
, param_sharing=False
)¶ Add controlled rotation gates about the y-axis.
For a 2-qubit circuit, when qubits_idx is [0, 1], the matrix form is:
\[\mathit{CR_Y} = |0\rangle \langle 0|\otimes I + |1\rangle \langle 1|\otimes R_Y\]- Parameters:¶
Examples
qc = Circuit(2) qc.cry([0, 1], torch.pi / 2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{R_{y}(1.57)} & {} & {}
-
crz(qubits_idx=
'cycle'
, param=None
, param_sharing=False
)¶ Add controlled rotation gates about the z-axis.
For a 2-qubit circuit, when qubits_idx is [0, 1], the matrix form is:
\[\mathit{CR_Z} = |0\rangle \langle 0|\otimes I + |1\rangle \langle 1|\otimes R_Z\]- Parameters:¶
Examples
qc = Circuit(2) qc.crz([0, 1], torch.pi / 2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{R_{z}(1.57)} & {} & {}
-
cu(qubits_idx=
'cycle'
, param=None
, param_sharing=False
)¶ Add controlled single-qubit rotation gates.
For a 2-qubit circuit, when qubits_idx is [0, 1], the matrix form is given by a controlled-U gate.
- Parameters:¶
Examples
qc = Circuit(2) qc.cu([0, 1], torch.pi / 2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{U(1.57, ...)} & {} & {}
-
rxx(qubits_idx=
'linear'
, param=None
, param_sharing=False
)¶ Add RXX gates.
The matrix form is:
\[\begin{split}R_{XX}(\theta) = \begin{bmatrix} \cos\frac{\theta}{2} & 0 & 0 & -i\sin\frac{\theta}{2} \\ 0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} & 0 \\ 0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} & 0 \\ -i\sin\frac{\theta}{2} & 0 & 0 & \cos\frac{\theta}{2} \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.rxx([0, 1], torch.pi / 2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[2]{R_{xx}(1.57)} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
ryy(qubits_idx=
'linear'
, param=None
, param_sharing=False
)¶ Add RYY gates.
The matrix form is:
\[\begin{split}R_{YY}(\theta) = \begin{bmatrix} \cos\frac{\theta}{2} & 0 & 0 & i\sin\frac{\theta}{2} \\ 0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} & 0 \\ 0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} & 0 \\ i\sin\frac{\theta}{2} & 0 & 0 & \cos\frac{\theta}{2} \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.ryy([0, 1], torch.pi / 2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[2]{R_{yy}(1.57)} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
rzz(qubits_idx=
'linear'
, param=None
, param_sharing=False
)¶ Add RZZ gates.
The matrix form is:
\[\begin{split}R_{ZZ}(\theta) = \begin{bmatrix} e^{-i\theta/2} & 0 & 0 & 0 \\ 0 & e^{i\theta/2} & 0 & 0 \\ 0 & 0 & e^{i\theta/2} & 0 \\ 0 & 0 & 0 & e^{-i\theta/2} \end{bmatrix}\end{split}\]- Parameters:¶
Examples
qc = Circuit(2) qc.rzz([0, 1], torch.pi / 2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[2]{R_{zz}(1.57)} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
ms(qubits_idx=
'cycle'
)¶ Add Mølmer-Sørensen (MS) gates.
The matrix form is:
\[\begin{split}\mathit{MS} = R_{XX}(-\pi/2) = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 0 & 0 & i \\ 0 & 1 & i & 0 \\ 0 & i & 1 & 0 \\ i & 0 & 0 & 1 \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘cycle’.
Examples
qc = Circuit(2) qc.ms([0, 1]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[2]{\text{MS}} & \meter[2]{} & {} \\ \lstick{} & {} & {} & {}
-
cswap(qubits_idx=
'cycle'
)¶ Add CSWAP (Fredkin) gates.
The matrix form is:
\[\begin{split}\mathit{CSWAP} = \begin{bmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & & 0 \\ \vdots & & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘cycle’.
Examples
qc = Circuit(3) qc.cswap([0, 1, 2]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{1} & \meter[3]{} & {} \\ \lstick{} & \gate[2,style={draw=gray, dashed}]{\permute{2,1}} & {} & {} \\ \lstick{} & {} & {} & {}
-
ccx(qubits_idx=
'cycle'
)¶ Add CCX (Toffoli) gates.
The matrix form is:
\[\begin{split}\mathit{CCX} = \begin{bmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & & 0 \\ \vdots & & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{bmatrix}\end{split}\]- Parameters:¶
- qubits_idx : Iterable[int] | str¶
Indices of the qubits on which the gates are applied. Defaults to ‘cycle’.
Examples
qc = Circuit(3) qc.ccx([0, 1, 2]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \ctrl[]{2} & \meter[3]{} & {} \\ \lstick{} & \control{} & {} & {} \\ \lstick{} & \targ{} & {} & {}
-
universal_two_qubits(qubits_idx=
None
, param=None
)¶ Add universal two-qubit gates. One such gate requires 15 parameters.
- Parameters:¶
Examples
qc = Circuit(2) qc.universal_two_qubits([0, 1]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
(The output latex code shows a universal 2-qubit layer.)
-
universal_three_qubits(qubits_idx=
None
, param=None
)¶ Add universal three-qubit gates. One such gate requires 81 parameters.
- Parameters:¶
Examples
qc = Circuit(3) qc.universal_three_qubits([0, 1, 2]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
(The output latex code shows a universal 3-qubit layer.)
-
universal_qudits(system_idx, param=
None
, param_sharing=False
)¶ Add universal qudit gates. One such gate requires \(d^2 - 1\) parameters, where \(d\) is the gate dimension.
- Parameters:¶
Examples
qc = Circuit(1, 3) qc.universal_qudits([0]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\operatorname{UNI}_{3}} & \meter[1]{} & {}
- permute(perm, system_idx)¶
Add a permutation gate.
- Parameters:¶
Examples
qc = Circuit(3) qc.permute([1, 0, 2], [0, 1, 2]) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[3,style={draw=none}]{\permute{2,1,3}} & \meter[3]{} & {} \\ \lstick{} & {} & {} & {} \\ \lstick{} & {} & {} & {}
-
control_permute(perm, system_idx, control_idx=
-1
)¶ Add a controlled permutation gate.
- Parameters:¶
Examples
qc = Circuit(4) qc.control_permute([1, 0, 2], [3, 0, 1, 2], 1) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[3,style={draw=gray, dashed}]{\permute{2,1,3}} & \meter[4]{} & {} \\ \lstick{} & {} & {} & {} \\ \lstick{} & {} & {} & {} \\ \lstick{} & \ctrl[]{-1} & {} & {}
-
oracle(oracle, system_idx, control_idx=
None
, gate_name='oracle'
, latex_name=None
)¶ Add an oracle gate.
- Parameters:¶
- oracle : Tensor¶
Unitary oracle.
- system_idx : List[int | List[int]] | int¶
Indices of the systems on which the gate is applied.
- control_idx : int | None¶
the index that controls the oracle. Defaults to None.
- gate_name : str | None¶
name of the oracle.
- latex_name : str | None¶
LaTeX name of the gate. Defaults to gate_name.
Examples
qc = Circuit(2) qc.oracle(oracle=eye(2), system_idx=[0], latex_name=r'$Identity$') qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{$Identity$}
-
control_oracle(oracle, system_idx, control_idx=
-1
, gate_name='oracle'
, latex_name=None
)¶ Add a controlled oracle gate.
- Parameters:¶
Examples
qc = Circuit(2) qc.control_oracle(oracle=eye(2), system_idx=[0, 1], control_idx=0, latex_name=r'$Identity$') qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \octrl[]{1} & \meter[2]{} & {} \\ \lstick{} & \gate[1]{$Identity$} & {} & {}
-
param_oracle(generator, num_acted_param, system_idx, control_idx=
None
, param=None
, gate_name='param-oracle'
, latex_name=None
, support_batch=False
)¶ Add a parameterized oracle gate.
- Parameters:¶
- generator : Callable[[Tensor], Tensor]¶
Function to generate the oracle.
- num_acted_param : int¶
Number of parameters required.
- system_idx : List[int] | int¶
Indices of the systems on which the gate acts.
- control_idx : int | None¶
The index that controls the oracle. Defaults to None.
- param : Tensor | float¶
Input parameters for the gate. Defaults to None.
- gate_name : str | None¶
Name of the oracle.
- latex_name : str | None¶
LaTeX name of the gate.
- support_batch : bool¶
Whether generator supports batched input.
Examples
def rotation_generator(params: torch.Tensor) -> torch.Tensor: theta = params[..., 0] cos_theta = torch.cos(theta / 2).unsqueeze(-1) sin_theta = torch.sin(theta / 2).unsqueeze(-1) matrix = torch.cat([ torch.cat([cos_theta, -1j * sin_theta], dim=-1), torch.cat([-1j * sin_theta, cos_theta], dim=-1) ], dim=-2) return matrix qc = Circuit(2) qc.param_oracle( generator=rotation_generator, num_acted_param=1, system_idx=[0, 1], control_idx=0, param=None, gate_name="ControlledRotation", support_batch=True ) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \octrl[]{1} \\ \lstick{} & \gate[1]{ControlledRotation(0.36)}
-
measure(system_idx=
None
, post_selection=None
, if_print=False
, measure_basis=None
)¶ Perform a measurement on the specified systems.
- Parameters:¶
Examples
qc = Circuit(2) qc.measure() print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \meter[2]{} & {} \\ \lstick{} & {} & {}
-
locc(local_unitary, system_idx, label=
'M'
, latex_name='O'
)¶ Add a one-way LOCC protocol comprised of unitary operations.
- Parameters:¶
Examples
qc = Circuit(2) qc.locc(local_unitary=x(), system_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \meter{} & \push{M} \wireoverride{c} & \ctrl[vertical wire=c]{1}\wireoverride{c} \\ \lstick{} & {} & {} & \gate[1]{O^{(M)}}
-
param_locc(generator, num_acted_param, system_idx, param=
None
, label='M'
, latex_name='U'
, support_batch=False
)¶ Add a one-way LOCC protocol comprised of unitary operations, where the applied unitary is parameterized.
- Parameters:¶
- generator : Callable[[Tensor], Tensor]¶
Function to generate the oracle.
- num_acted_param : int¶
Number of parameters required.
- system_idx : List[int | List[int]]¶
Systems on which the protocol is applied. The first element indicates the measure system.
- param : Tensor | float¶
Input parameters for the gate. Defaults to None.
- label : str¶
Label for measurement. Defaults to ‘M’.
- latex_name : str¶
LaTeX name for the applied operator. Defaults to ‘U’.
- support_batch : bool¶
Whether generator supports batched input.
-
linear_entangled_layer(qubits_idx=
None
, depth=1
, param=None
)¶ Add linear entangled layers consisting of Ry gates, Rz gates, and CNOT gates.
- Parameters:¶
Examples
qc = Circuit(2) qc.linear_entangled_layer([0, 1], depth=4) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
(The output latex code shows a linear entangled layer.)
-
real_entangled_layer(qubits_idx=
None
, depth=1
, param=None
)¶ Add strongly entangled layers consisting of Ry gates and CNOT gates.
- Parameters:¶
Examples
qc = Circuit(2) qc.real_entangled_layer([0, 1], depth=4) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
(The output latex code shows a real entangled layer.)
-
complex_entangled_layer(qubits_idx=
None
, depth=1
, param=None
)¶ Add strongly entangled layers consisting of single-qubit rotation gates and CNOT gates.
- Parameters:¶
Examples
qc = Circuit(2) qc.complex_entangled_layer([0, 1], depth=4) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
(The output latex code shows a complex entangled layer.)
-
real_block_layer(qubits_idx=
None
, depth=1
, param=None
)¶ Add weakly entangled layers consisting of Ry gates and CNOT gates.
- Parameters:¶
Examples
qc = Circuit(2) qc.real_block_layer([0, 1], depth=4) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
(The output latex code shows a real block layer.)
-
complex_block_layer(qubits_idx=
None
, depth=1
, param=None
)¶ Add weakly entangled layers consisting of single-qubit rotation gates and CNOT gates.
- Parameters:¶
Examples
qc = Circuit(2) qc.complex_block_layer([0, 1], depth=4) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
(The output latex code shows a complex block layer.)
-
trotter(hamiltonian, time, qubits_idx=
None
, num_steps=1
, order=1
, name='H'
)¶ Add Trotter decompositions of a Hamiltonian evolution operator.
- Parameters:¶
- hamiltonian : Hamiltonian¶
Hamiltonian of the system whose time evolution is to be simulated.
- time : float¶
Total evolution time.
- qubits_idx : List[int] | None¶
Indices of the qubits on which the layer is applied. Defaults to
None
.- num_steps : int¶
Number of trotter blocks. Defaults to 1.
- order : int¶
Order of the Trotter-Suzuki decomposition. Defaults to 1.
- name : str¶
Name of the Hamiltonian. Defaults to ‘H’.
-
bit_flip(prob, qubits_idx=
'full'
)¶ Add bit flip channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.bit_flip(prob=0.5, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{E}_{p = 0.5}^{\textrm{\tiny{(BF)}}}} \\ \lstick{} & \gate[1]{\mathcal{E}_{p = 0.5}^{\textrm{\tiny{(BF)}}}}
-
phase_flip(prob, qubits_idx=
'full'
)¶ Add phase flip channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.phase_flip(prob=0.5, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{E}_{p = 0.5}^{\textrm{\tiny{(PF)}}}} \\ \lstick{} & \gate[1]{\mathcal{E}_{p = 0.5}^{\textrm{\tiny{(PF)}}}}
-
bit_phase_flip(prob, qubits_idx=
'full'
)¶ Add bit phase flip channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.bit_phase_flip(prob=0.5, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{E}_{p = 0.5}^{\textrm{\tiny{(BPF)}}}} \\ \lstick{} & \gate[1]{\mathcal{E}_{p = 0.5}^{\textrm{\tiny{(BPF)}}}}
-
amplitude_damping(gamma, qubits_idx=
'full'
)¶ Add amplitude damping channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.amplitude_damping(gamma=0.5, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{E}_{\gamma = 0.5}^{\textrm{\tiny{(AD)}}}} \\ \lstick{} & \gate[1]{\mathcal{E}_{\gamma = 0.5}^{\textrm{\tiny{(AD)}}}}
-
generalized_amplitude_damping(gamma, prob, qubits_idx=
'full'
)¶ Add generalized amplitude damping channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.generalized_amplitude_damping(gamma=0.5, prob=0.5, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{E}_{\gamma = 0.5, p = 0.5}^{\textrm{\tiny{(GAD)}}}} \\ \lstick{} & \gate[1]{\mathcal{E}_{\gamma = 0.5, p = 0.5}^{\textrm{\tiny{(GAD)}}}}
-
phase_damping(gamma, qubits_idx=
'full'
)¶ Add phase damping channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.phase_damping(gamma=0.5, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{E}_{\gamma = 0.5}^{\textrm{\tiny{(PD)}}}} \\ \lstick{} & \gate[1]{\mathcal{E}_{\gamma = 0.5}^{\textrm{\tiny{(PD)}}}}
-
depolarizing(prob, qubits_idx=
'full'
)¶ Add depolarizing channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.depolarizing(prob=0.5, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{D}_{p = 0.5}} \\ \lstick{} & \gate[1]{\mathcal{D}_{p = 0.5}}
- generalized_depolarizing(prob, qubits_idx)¶
Add a general depolarizing channel.
- Parameters:¶
Examples
qc = Circuit(2) qc.generalized_depolarizing(prob=0.5, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[2]{\mathcal{D}_{p = 0.5}} \\ \lstick{} & {}
-
pauli_channel(prob, qubits_idx=
'full'
)¶ Add Pauli channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.pauli_channel(prob=[0.1, 0.3, 0.5]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{N}} \\ \lstick{} & \gate[1]{\mathcal{N}}
-
reset_channel(prob, qubits_idx=
'full'
)¶ Add reset channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.reset_channel(prob=[0.5, 0.4], qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{N}} \\ \lstick{} & \gate[1]{\mathcal{N}}
-
thermal_relaxation(const_t, exec_time, qubits_idx=
'full'
)¶ Add thermal relaxation channels.
- Parameters:¶
Examples
qc = Circuit(2) qc.thermal_relaxation(const_t=[600, 300], exec_time=500, qubits_idx=[0, 1]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{N}} \\ \lstick{} & \gate[1]{\mathcal{N}}
- choi_channel(choi_repr, system_idx)¶
Add custom channels in the Choi representation.
- Parameters:¶
Examples
qc = Circuit(2) X = torch.tensor(x(), dtype=torch.complex64) choi = X.kron(X) / 2 qc.choi_channel(choi_repr=choi, system_idx=[0]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{N}}
- kraus_channel(kraus_oper, system_idx)¶
Add custom channels in the Kraus representation.
- Parameters:¶
Examples
qc = Circuit(2) qc.kraus_channel(kraus_oper=eye(2), system_idx=[0]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{N}}
- stinespring_channel(stinespring_repr, system_idx)¶
Add custom channels in the Stinespring representation.
- Parameters:¶
Examples
qc = Circuit(2) qc.stinespring_channel(stinespring_repr=eye(2), system_idx=[0]) print(f'The latex code of this circuit is:\n{qc.to_latex()}')
The latex code of this circuit is: \lstick{} & \gate[1]{\mathcal{N}}