Toggle Light / Dark / Auto color theme
Toggle table of contents sidebar
Source code for guppylang.std.quantum
"""Guppy standard module for quantum operations."""
# mypy: disable-error-code="empty-body, misc, valid-type"
from typing import no_type_check
from guppylang_internals.decorator import custom_function , custom_type , hugr_op
from guppylang_internals.std._internal.compiler.quantum import (
InoutMeasureCompiler ,
RotationCompiler ,
)
from guppylang_internals.std._internal.util import quantum_op
from hugr import tys as ht
from guppylang import guppy
from guppylang.std.angles import angle , pi
from guppylang.std.array import array
from guppylang.std.lang import owned
from guppylang.std.option import Option
[docs]
@custom_type ( ht . Qubit , copyable = False , droppable = False )
class qubit :
[docs]
@hugr_op ( quantum_op ( "QAlloc" ))
@no_type_check
def __new__ () -> "qubit" : ...
[docs]
@guppy
@no_type_check
def measure ( self : "qubit" @ owned ) -> bool :
return measure ( self )
[docs]
@guppy
@no_type_check
def project_z ( self : "qubit" ) -> bool :
return project_z ( self )
[docs]
@guppy
@no_type_check
def discard ( self : "qubit" @ owned ) -> None :
discard ( self )
[docs]
@hugr_op ( quantum_op ( "TryQAlloc" ))
@no_type_check
def maybe_qubit () -> Option [ qubit ]:
"""Try to allocate a qubit, returning `some(qubit)`
if allocation succeeds or `nothing` if it fails."""
[docs]
@hugr_op ( quantum_op ( "H" ))
@no_type_check
def h ( q : qubit ) -> None :
r """Hadamard gate command
.. math::
\mathrm{H}= \frac{1}{\sqrt{2}}
\begin{pmatrix}
1 & 1 \\
1 & -1
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "CZ" ))
@no_type_check
def cz ( control : qubit , target : qubit ) -> None :
r """Controlled-Z gate command.
cz(control, target)
Qubit ordering: [control, target]
.. math::
\mathrm{CZ}=
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & -1
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "CY" ))
@no_type_check
def cy ( control : qubit , target : qubit ) -> None :
r """Controlled-Y gate command.
cy(control, target)
Qubit ordering: [control, target]
.. math::
\mathrm{CY}=
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & -i \\
0 & 0 & i & 0
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "CX" ))
@no_type_check
def cx ( control : qubit , target : qubit ) -> None :
r """Controlled-X gate command.
cx(control, target)
Qubit ordering: [control, target]
.. math::
\mathrm{CX}=
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "T" ))
@no_type_check
def t ( q : qubit ) -> None :
r """T gate.
.. math::
\mathrm{T}=
\begin{pmatrix}
1 & 0 \\
0 & e^{i \frac{\pi}{4}}
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "S" ))
@no_type_check
def s ( q : qubit ) -> None :
r """S gate.
.. math::
\mathrm{S}=
\begin{pmatrix}
1 & 0 \\
0 & i
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "V" ))
@no_type_check
def v ( q : qubit ) -> None :
r """V gate.
.. math::
\mathrm{V}= \frac{1}{\sqrt{2}}
\begin{pmatrix}
1 & -i \\
-i & 1
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "X" ))
@no_type_check
def x ( q : qubit ) -> None :
r """X gate.
.. math::
\mathrm{X}=
\begin{pmatrix}
0 & 1 \\
1 & 0
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "Y" ))
@no_type_check
def y ( q : qubit ) -> None :
r """Y gate.
.. math::
\mathrm{Y}=
\begin{pmatrix}
0 & -i \\
i & 0
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "Z" ))
@no_type_check
def z ( q : qubit ) -> None :
r """Z gate.
.. math::
\mathrm{Z}=
\begin{pmatrix}
1 & 0 \\
0 & -1
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "Tdg" ))
@no_type_check
def tdg ( q : qubit ) -> None :
r """Tdg gate.
.. math::
\mathrm{T}^\dagger=
\begin{pmatrix}
1 & 0 \\
0 & e^{-i \frac{\pi}{4}}
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "Sdg" ))
@no_type_check
def sdg ( q : qubit ) -> None :
r """Sdg gate.
.. math::
\mathrm{S}^\dagger=
\begin{pmatrix}
1 & 0 \\
0 & -i
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "Vdg" ))
@no_type_check
def vdg ( q : qubit ) -> None :
r """Vdg gate.
.. math::
\mathrm{V}^\dagger= \frac{1}{\sqrt{2}}
\begin{pmatrix}
1 & i \\
i & 1
\end{pmatrix}
"""
[docs]
@custom_function ( RotationCompiler ( "Rz" ))
@no_type_check
def rz ( q : qubit , angle : angle ) -> None :
r """Rz gate.
.. math::
\mathrm{Rz}(\theta)=
\exp(\frac{- i \theta}{2} Z)=
\begin{pmatrix}
e^{-\frac{1}{2}i \theta} & 0 \\
0 & e^{\frac{1}{2}i \theta}
\end{pmatrix}
"""
[docs]
@custom_function ( RotationCompiler ( "Rx" ))
@no_type_check
def rx ( q : qubit , angle : angle ) -> None :
r """Rx gate.
.. math::
\mathrm{Rx}(\theta)=
\begin{pmatrix}
\cos(\frac{ \theta}{2}) & -i\sin(\frac{ \theta}{2}) \\
-i\sin(\frac{ \theta}{2}) & \cos(\frac{ \theta}{2})
\end{pmatrix}
"""
[docs]
@custom_function ( RotationCompiler ( "Ry" ))
@no_type_check
def ry ( q : qubit , angle : angle ) -> None :
r """Ry gate.
.. math::
\mathrm{Ry}(\theta)=
\begin{pmatrix}
\cos(\frac{\theta}{2}) & -\sin(\frac{ \theta}{2}) \\
\sin(\frac{ \theta}{2}) & \cos(\frac{ \theta}{2})
\end{pmatrix}
"""
[docs]
@custom_function ( RotationCompiler ( "CRz" ))
@no_type_check
def crz ( control : qubit , target : qubit , angle : angle ) -> None :
r """Controlled-Rz gate command.
crz(control, target, theta)
Qubit ordering: [control, target]
.. math::
\mathrm{CRz}(\theta)=
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & e^{-\frac{1}{2}i \theta} & 0 \\
0 & 0 & 0 & e^{\frac{1}{2}i \theta}
\end{pmatrix}
"""
[docs]
@hugr_op ( quantum_op ( "Toffoli" ))
@no_type_check
def toffoli ( control1 : qubit , control2 : qubit , target : qubit ) -> None :
r """A Toffoli gate command. Also sometimes known as a CCX gate.
toffoli(control1, control2, target)
Qubit ordering: [control1, control2 target]
.. math::
\mathrm{Toffoli}=
\begin{pmatrix}
1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\
0 & 0 & 0 & 0 & 0 & 0 & 1 & 0
\end{pmatrix}
"""
[docs]
@custom_function ( InoutMeasureCompiler ())
@no_type_check
def project_z ( q : qubit ) -> bool :
"""Project a single qubit into the Z-basis (a non-destructive measurement)."""
[docs]
@hugr_op ( quantum_op ( "QFree" ))
@no_type_check
def discard ( q : qubit @ owned ) -> None :
"""Discard a single qubit."""
[docs]
@hugr_op ( quantum_op ( "MeasureFree" ))
@no_type_check
def measure ( q : qubit @ owned ) -> bool :
"""Measure a single qubit destructively."""
[docs]
@hugr_op ( quantum_op ( "Reset" ))
@no_type_check
def reset ( q : qubit ) -> None :
"""Reset a single qubit to the :math:`|0\rangle` state."""
N = guppy . nat_var ( "N" )
[docs]
@guppy
@no_type_check
def measure_array ( qubits : array [ qubit , N ] @ owned ) -> array [ bool , N ]:
"""Measure an array of qubits, returning an array of bools."""
return array ( measure ( q ) for q in qubits )
[docs]
@guppy
@no_type_check
def discard_array ( qubits : array [ qubit , N ] @ owned ) -> None :
"""Discard an array of qubits."""
for q in qubits :
discard ( q )
# -------NON-PRIMITIVE-------
[docs]
@guppy
@no_type_check
def ch ( control : qubit , target : qubit ) -> None :
r """Controlled-H gate command.
ch(control, target)
Qubit ordering: [control, target]
.. math::
\mathrm{CH} = \frac{1}{\sqrt{2}}
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 1 \\
0 & 0 & 1 & -1
\end{pmatrix}
"""
# based on https://quantumcomputing.stackexchange.com/a/15737
ry ( target , - pi / 4 )
cz ( control , target )
ry ( target , pi / 4 )