2.2. Unitary gates#
In the following section, all unitary gates that are implemented in geqo are introduced along with a simple example. Several of these gates support parameters, e.g. rotation angles. Note that the parameters are specified by names only, e.g. Phase("φ")
denotes a phase gate with an angle, which has the name φ
.
The following unitary gates are currently defined in geqo. They are basic gates, which means that they are internally not decomposed into a sequence of other gates.
BasicGate and InverseBasicGate
CNOT
Hadamard
PauliX, PauliY and PauliZ
PermuteQubits
Phase and InversePhase
Rx and InverseRx
Ry and InverseRy
Rz and InverseRz
Rzz and InverseRzz
SGate and InverseSGate
SwapQubits
2.2.1. BasicGate and InverseBasicGate#
The BasicGate
and its inverse InverseBasicGate
are useful for defining custom unitary matrices. The arguments are a name for the corresponding unitary matrix and the number of qubits, which the gates are acting on.
For most simulators, the method setValue
must be used to assign a value to the name of the unitary matrix. In the following example, the SymPy based simulator simulatorUnitarySymPy
is used and it supports symbolic values for the entries of a matrix.
import sympy as sym
from geqo.core.basic import BasicGate, InverseBasicGate
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = BasicGate("a", 1) # Create a unitary gate on one qubit with the name a.
sim = simulatorUnitarySymPy(1)
sim.setValue(
"a", sym.Matrix([[1, 0], [0, sym.I]])
) # Assign a matrix to the name of the unitary matrix.
sim.apply(gate, [0])
display(sim.u)
The application of InverseBasicGate after BasicGate leads to the identity matrix. Since both gates have the same name for the unitary matrix, it is not necessary to use the setValue
a second time.
gate2 = InverseBasicGate("a", 1) # Create the inverse gate.
sim.apply(
gate2, [0]
) # Setting the value before calling this method is not necessary because it is already set.
display(sim.u)
2.2.2. CNOT#
The CNOT
gate is a two-qubit gate and it follows the standard definition of CNOT, also called CX in some cases.
from geqo.gates.fundamental_gates import CNOT
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = CNOT() # Create a CNOT gate.
sim = simulatorUnitarySymPy(2) # The gate operates on two qubits.
sim.apply(gate, [0, 1]) # Apply CNOT to two qubits.
display(sim.u) # Show the resulting unitary matrix
2.2.3. Hadamard#
The Hadamard operation acts on a single qubit and it generates equal superpositions of the computation basis states \(|0\rangle\) and \(|1\rangle\) when applied to one of these. The Hadamard operation is its own inverse and effectively performs the quantum Fourier transform on a single qubit.
from geqo.gates.fundamental_gates import Hadamard
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = Hadamard() # Create a Hadamard gate.
sim = simulatorUnitarySymPy(1) # The gate operates on one qubit.
sim.apply(gate, [0])
display(sim.u) # Show the resulting unitary matrix
2.2.4. PauliX, PauliY and PauliZ#
These operators correspond to the Pauli matrices \(\sigma_x\), \(\sigma_y\) and \(\sigma_z\). They operate on a single qubit.
from geqo.gates.fundamental_gates import PauliX
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = PauliX() # Create a PauliX gate.
sim = simulatorUnitarySymPy(1) # The gate operates on one qubit.
sim.apply(gate, [0])
display(sim.u) # Show the resulting unitary matrix
from geqo.gates.fundamental_gates import PauliY
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = PauliY() # Create a PauliY gate.
sim = simulatorUnitarySymPy(1) # The gate operates on one qubit.
sim.apply(gate, [0])
display(sim.u) # Show the resulting unitary matrix
from geqo.gates.fundamental_gates import PauliZ
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = PauliZ() # Create a PauliZ gate.
sim = simulatorUnitarySymPy(1) # The gate operates on one qubit.
sim.apply(gate, [0])
display(sim.u) # Show the resulting unitary matrix
2.2.5. PermuteQubits#
This operation allows to define a unitary operation that corresponds to a permutation of qubits. The argument is the target order of the permuted qubits, which are denoted by 0, …, n-1 for n qubits. For instance, the notation [1, 2, 0] means that the first qubit is mapped to the third position and the second qubit mapped to the first position, e.g. it is a cyclic permutation. The number of qubits is derived from the length of the list.
import sympy as sym
from geqo.algorithms.algorithms import PermuteQubits
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = PermuteQubits(
[1, 2, 0]
) # Create a permutation corresponding to a cyclic left shift of qubits.
sim = simulatorUnitarySymPy(3) # The gate is defined on three qubits.
sim.apply(gate, [0, 1, 2])
display(sim.u)
2.2.6. Phase and InversePhase#
The phase gate applies a phase to the state \(|1\rangle\) of a qubit. Its argument is a name for the phase.
For most simulators, the method setValue
must be used to assign a value to the name of the phase. In the following example, the SymPy based simulator simulatorUnitarySymPy
is used and it supports symbolic values for the phase.
import sympy as sym
from geqo.gates.fundamental_gates import Phase
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = Phase("φ") # Create a phase gate with a phase with the name φ.
sim = simulatorUnitarySymPy(1)
sim.setValue(
"φ", sym.sqrt(2)
) # Set the value of the phase with the name φ to a symbolic value.
sim.apply(
gate, [0]
) # Setting the value before calling this method is not necessary because it is already set.
display(sim.u)
2.2.7. Rx and InverseRx#
The Rx gate and its inverse are rotations around the x axis in the Bloch sphere representation of a qubit. The argument of these gates is a name for the rotation angle.
For most simulators, the method setValue
must be used to assign a value to the name of the rotation. In the following example, the SymPy based simulator simulatorUnitarySymPy
is used and it supports symbolic values for the phase.
import sympy as sym
from geqo.gates.rotation_gates import Rx, InverseRx
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = Rx("φ") # Create an Rx gate with an angle with the name φ.
sim = simulatorUnitarySymPy(1)
sim.setValue(
"φ", sym.sqrt(2)
) # Set the value of the rotation angle with the name φ to a symbolic value.
sim.apply(gate, [0])
display(sim.u)
Applying the InverseRx
after the Rx
gate with the same angle leads to the identity.
gate2 = InverseRx("φ") # Create an inverse Rx gate with an angle with the name φ.
sim.apply(
gate2, [0]
) # Setting the value before calling this method is not necessary because it is already set.
sim.u.simplify() # Simplify the expressions in the result matrix.
display(sim.u)
2.2.8. Ry and InverseRy#
The Ry gate and its inverse are rotations around the y axis in the Bloch sphere representation of a qubit. The argument of these gates is a name for the rotation angle.
For most simulators, the method setValue
must be used to assign a value to the name of the rotation. In the following example, the SymPy based simulator simulatorUnitarySymPy
is used and it supports symbolic values for the phase.
import sympy as sym
from geqo.gates.rotation_gates import Ry, InverseRy
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = Ry("φ") # Create an Ry gate with an angle with the name φ.
sim = simulatorUnitarySymPy(1)
sim.setValue(
"φ", sym.sqrt(2)
) # Set the value of the rotation angle with the name φ to a symbolic value.
sim.apply(gate, [0])
display(sim.u)
Applying the InverseRy
after the Ry
gate with the same angle leads to the identity.
gate2 = InverseRy("φ") # Create an inverse Ry gate with an angle with the name φ.
sim.apply(
gate2, [0]
) # Setting the value before calling this method is not necessary because it is already set.
sim.u.simplify() # Simplify the expressions in the result matrix.
display(sim.u)
2.2.9. Rz and InverseRz#
The Rz gate and its inverse are rotations around the z axis in the Bloch sphere representation of a qubit. The argument of these gates is a name for the rotation angle.
For most simulators, the method setValue
must be used to assign a value to the name of the rotation. In the following example, the SymPy based simulator simulatorUnitarySymPy
is used and it supports symbolic values for the phase.
import sympy as sym
from geqo.gates.rotation_gates import Rz, InverseRz
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = Rz("φ") # Create an Rz gate with an angle with the name φ.
sim = simulatorUnitarySymPy(1)
sim.setValue(
"φ", sym.sqrt(2)
) # Set the value of the rotation angle with the name φ to a symbolic value.
sim.apply(gate, [0])
display(sim.u)
Applying the InverseRz
after the Rz
gate with the same angle leads to the identity.
gate2 = InverseRz("φ") # Create an inverse Rz gate with an angle with the name φ.
sim.apply(
gate2, [0]
) # Setting the value before calling this method is not necessary because it is already set.
display(sim.u)
2.2.10. Rzz and InverseRzz#
The Rzz gate and its inverse are entangling gates on two qubits. The argument of the gates is the name of a rotation angle.
import sympy as sym
from geqo.gates.rotation_gates import Rzz, InverseRzz
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = Rzz("φ") # Create an Rzz gate with an angle with the name φ.
sim = simulatorUnitarySymPy(2)
sim.setValue(
"φ", sym.sqrt(2)
) # Set the value of the rotation angle with the name φ to a symbolic value.
sim.apply(gate, [0, 1])
display(sim.u)
Applying the InverseRzz
after the Rzz
gate with the same angle leads to the identity.
gate2 = InverseRzz("φ") # Create an inverse Rz gate with an angle with the name φ.
sim.apply(
gate2, [0, 1]
) # Setting the value before calling this method is not necessary because it is already set.
display(sim.u)
2.2.11. SGate and InverseSGate#
The S gate is the square root of the PauliZ
gate.
import sympy as sym
from geqo.gates.fundamental_gates import SGate, InverseSGate
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = SGate() # Create an SGate.
sim = simulatorUnitarySymPy(1)
sim.apply(gate, [0])
display(sim.u)
Applying the InverseSGate
after the SGate
gate leads to the identity.
gate2 = InverseSGate() # Create an InverseSGate.
sim.apply(gate2, [0])
display(sim.u)
2.2.12. SwapQubits#
This operation acts on two qubits and it corresponds to exchanging two qubits.
import sympy as sym
from geqo.gates.fundamental_gates import SwapQubits
from geqo.simulators.sympy import simulatorUnitarySymPy
gate = SwapQubits() # Create the SwapQubits gate
sim = simulatorUnitarySymPy(2) # The operation acts on two qubits.
sim.apply(gate, [0, 1])
display(sim.u) # Show the corresponding unitary operation.