Qubit Gates API Reference
This page documents the qubit gates available in the skq.gates.qubit
module.
Qubit Gate Base Class
The QubitGate
class serves as the foundation for all qubit-based quantum gates in SKQ.
skq.gates.qubit.base.QubitGate
Bases: BaseGate
Base class for Qubit gates.
A quantum system with 2 basis states (|0>, |1>).
Models spin-1/2 particles like electrons.
Source code in src/skq/gates/qubit/base.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 | class QubitGate(BaseGate):
"""
Base class for Qubit gates.
A quantum system with 2 basis states (|0>, |1>).
Models spin-1/2 particles like electrons.
"""
def __new__(cls, input_array):
obj = super().__new__(cls, input_array)
assert obj.is_at_least_nxn(n=2), "Gate must be at least a 2x2 matrix."
assert obj.is_power_of_n_shape(n=2), "Gate shape must be a power of 2."
return obj
@property
def num_qubits(self) -> int:
"""Return the number of qubits involved in the gate."""
return int(np.log2(self.shape[0]))
def is_multi_qubit(self) -> bool:
"""Check if the gate involves multiple qubits."""
return self.num_qubits > 1
def is_pauli(self) -> bool:
"""Check if the gate is a Pauli gate."""
# I, X, Y, Z Pauli matrices
if self.num_qubits == 1:
return any(np.allclose(self, pauli) for pauli in SINGLE_QUBIT_PAULI_MATRICES)
# Combinations of single-qubit Pauli matrices
elif self.num_qubits == 2:
return any(np.allclose(self, pauli) for pauli in TWO_QUBIT_PAULI_MATRICES)
else:
return NotImplementedError("Pauli check not supported for gates with more than 2 qubits")
def is_clifford(self) -> bool:
"""Check if the gate is a Clifford gate."""
# X, Y, Z, H and S
if self.num_qubits == 1:
return any(np.allclose(self, clifford) for clifford in SINGLE_QUBIT_CLIFFORD_MATRICES)
# Combinations of single-qubit Clifford gates + CNOT and SWAP
elif self.num_qubits == 2:
return any(np.allclose(self, clifford) for clifford in TWO_QUBIT_CLIFFORD_MATRICES)
else:
return NotImplementedError("Clifford check not supported for gates with more than 2 qubits")
def sqrt(self) -> "CustomQubitGate":
"""Compute the square root of the gate."""
sqrt_matrix = sp.linalg.sqrtm(self)
return CustomQubitGate(sqrt_matrix)
def kron(self, other: "QubitGate") -> "CustomQubitGate":
"""Compute the Kronecker product of two gates."""
kron_matrix = np.kron(self, other)
return CustomQubitGate(kron_matrix)
def convert_endianness(self) -> "QubitGate":
"""Convert a gate matrix from big-endian to little-endian and vice versa."""
if self.num_qubits == 1:
return self
permutation = np.arange(2**self.num_qubits).reshape([2] * self.num_qubits).transpose().flatten()
return self[permutation][:, permutation]
def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
"""
Convert gate to a Qiskit Gate object.
Qiskit using little endian convention, so we permute the order of the qubits.
:return: Qiskit UnitaryGate object
"""
gate_name = self.__class__.__name__
print(f"No to_qiskit defined for '{gate_name}'. Initializing as UnitaryGate.")
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label=gate_name)
@staticmethod
def from_qiskit(gate: qiskit.circuit.gate.Gate) -> "CustomQubitGate":
"""
Convert a Qiskit Gate to skq CustomGate.
Qiskit using little endian convention, so we permute the order of the qubits.
:param gate: Qiskit Gate object
"""
assert isinstance(gate, qiskit.circuit.gate.Gate), "Input must be a Qiskit Gate object"
return CustomQubitGate(gate.to_matrix()).convert_endianness()
def to_pennylane(self, wires: list[int] | int = None) -> qml.QubitUnitary:
"""
Convert gate to a PennyLane QubitUnitary.
PennyLane use the big endian convention, so no need to reverse the order of the qubits.
:param wires: List of wires the gate acts on
:return: PennyLane QubitUnitary object
"""
gate_name = self.__class__.__name__
print(f"No to_pennylane defined for '{gate_name}'. Initializing as QubitUnitary.")
wires = wires if wires is not None else list(range(self.num_qubits))
return qml.QubitUnitary(self, wires=wires)
@staticmethod
def from_pennylane(gate: qml.operation.Operation) -> "CustomQubitGate":
"""
Convert a PennyLane Operation to skqq CustomGate.
PennyLane use the big endian convention, so no need to reverse the order of the qubits.
:param gate: PennyLane Operation object
"""
assert isinstance(gate, qml.operation.Operation), "Input must be a PennyLane Operation object"
return CustomQubitGate(gate.matrix())
def to_qasm(self, qubits: list[int]) -> str:
"""
Convert gate to a OpenQASM string.
More information on OpenQASM (2.0): https://arxiv.org/pdf/1707.03429
OpenQASM specification: https://openqasm.com/intro.html
Gates should be part of the standard library.
OpenQASM 2.0 -> qelib1.inc
OpenQASM 3 -> stdgates.inc
:param qubits: List of qubit indices the gate acts on
:return: OpenQASM string representation of the gate
String representation should define gate, qubits it acts on and ;.
Example for Hadamard in 1st qubit -> "h q[0];"
"""
raise NotImplementedError("Conversion to OpenQASM is not implemented.")
@staticmethod
def from_qasm(qasm_string: str) -> "QubitGate":
"""Convert a OpenQASM string to scikit-q gate."""
raise NotImplementedError("Conversion from OpenQASM is not implemented.")
def draw(self, **kwargs):
"""Draw the gate using a Qiskit QuantumCircuit."""
qc = QuantumCircuit(self.num_qubits)
qc.append(self.to_qiskit(), range(self.num_qubits))
return qc.draw(**kwargs)
|
num_qubits
property
Return the number of qubits involved in the gate.
convert_endianness()
Convert a gate matrix from big-endian to little-endian and vice versa.
Source code in src/skq/gates/qubit/base.py
| def convert_endianness(self) -> "QubitGate":
"""Convert a gate matrix from big-endian to little-endian and vice versa."""
if self.num_qubits == 1:
return self
permutation = np.arange(2**self.num_qubits).reshape([2] * self.num_qubits).transpose().flatten()
return self[permutation][:, permutation]
|
draw(**kwargs)
Draw the gate using a Qiskit QuantumCircuit.
Source code in src/skq/gates/qubit/base.py
| def draw(self, **kwargs):
"""Draw the gate using a Qiskit QuantumCircuit."""
qc = QuantumCircuit(self.num_qubits)
qc.append(self.to_qiskit(), range(self.num_qubits))
return qc.draw(**kwargs)
|
from_pennylane(gate)
staticmethod
Convert a PennyLane Operation to skqq CustomGate.
PennyLane use the big endian convention, so no need to reverse the order of the qubits.
:param gate: PennyLane Operation object
Source code in src/skq/gates/qubit/base.py
129
130
131
132
133
134
135
136
137 | @staticmethod
def from_pennylane(gate: qml.operation.Operation) -> "CustomQubitGate":
"""
Convert a PennyLane Operation to skqq CustomGate.
PennyLane use the big endian convention, so no need to reverse the order of the qubits.
:param gate: PennyLane Operation object
"""
assert isinstance(gate, qml.operation.Operation), "Input must be a PennyLane Operation object"
return CustomQubitGate(gate.matrix())
|
from_qasm(qasm_string)
staticmethod
Convert a OpenQASM string to scikit-q gate.
Source code in src/skq/gates/qubit/base.py
| @staticmethod
def from_qasm(qasm_string: str) -> "QubitGate":
"""Convert a OpenQASM string to scikit-q gate."""
raise NotImplementedError("Conversion from OpenQASM is not implemented.")
|
from_qiskit(gate)
staticmethod
Convert a Qiskit Gate to skq CustomGate.
Qiskit using little endian convention, so we permute the order of the qubits.
:param gate: Qiskit Gate object
Source code in src/skq/gates/qubit/base.py
107
108
109
110
111
112
113
114
115 | @staticmethod
def from_qiskit(gate: qiskit.circuit.gate.Gate) -> "CustomQubitGate":
"""
Convert a Qiskit Gate to skq CustomGate.
Qiskit using little endian convention, so we permute the order of the qubits.
:param gate: Qiskit Gate object
"""
assert isinstance(gate, qiskit.circuit.gate.Gate), "Input must be a Qiskit Gate object"
return CustomQubitGate(gate.to_matrix()).convert_endianness()
|
is_clifford()
Check if the gate is a Clifford gate.
Source code in src/skq/gates/qubit/base.py
69
70
71
72
73
74
75
76
77
78 | def is_clifford(self) -> bool:
"""Check if the gate is a Clifford gate."""
# X, Y, Z, H and S
if self.num_qubits == 1:
return any(np.allclose(self, clifford) for clifford in SINGLE_QUBIT_CLIFFORD_MATRICES)
# Combinations of single-qubit Clifford gates + CNOT and SWAP
elif self.num_qubits == 2:
return any(np.allclose(self, clifford) for clifford in TWO_QUBIT_CLIFFORD_MATRICES)
else:
return NotImplementedError("Clifford check not supported for gates with more than 2 qubits")
|
is_multi_qubit()
Check if the gate involves multiple qubits.
Source code in src/skq/gates/qubit/base.py
| def is_multi_qubit(self) -> bool:
"""Check if the gate involves multiple qubits."""
return self.num_qubits > 1
|
is_pauli()
Check if the gate is a Pauli gate.
Source code in src/skq/gates/qubit/base.py
58
59
60
61
62
63
64
65
66
67 | def is_pauli(self) -> bool:
"""Check if the gate is a Pauli gate."""
# I, X, Y, Z Pauli matrices
if self.num_qubits == 1:
return any(np.allclose(self, pauli) for pauli in SINGLE_QUBIT_PAULI_MATRICES)
# Combinations of single-qubit Pauli matrices
elif self.num_qubits == 2:
return any(np.allclose(self, pauli) for pauli in TWO_QUBIT_PAULI_MATRICES)
else:
return NotImplementedError("Pauli check not supported for gates with more than 2 qubits")
|
kron(other)
Compute the Kronecker product of two gates.
Source code in src/skq/gates/qubit/base.py
| def kron(self, other: "QubitGate") -> "CustomQubitGate":
"""Compute the Kronecker product of two gates."""
kron_matrix = np.kron(self, other)
return CustomQubitGate(kron_matrix)
|
sqrt()
Compute the square root of the gate.
Source code in src/skq/gates/qubit/base.py
| def sqrt(self) -> "CustomQubitGate":
"""Compute the square root of the gate."""
sqrt_matrix = sp.linalg.sqrtm(self)
return CustomQubitGate(sqrt_matrix)
|
to_pennylane(wires=None)
Convert gate to a PennyLane QubitUnitary.
PennyLane use the big endian convention, so no need to reverse the order of the qubits.
:param wires: List of wires the gate acts on
:return: PennyLane QubitUnitary object
Source code in src/skq/gates/qubit/base.py
117
118
119
120
121
122
123
124
125
126
127 | def to_pennylane(self, wires: list[int] | int = None) -> qml.QubitUnitary:
"""
Convert gate to a PennyLane QubitUnitary.
PennyLane use the big endian convention, so no need to reverse the order of the qubits.
:param wires: List of wires the gate acts on
:return: PennyLane QubitUnitary object
"""
gate_name = self.__class__.__name__
print(f"No to_pennylane defined for '{gate_name}'. Initializing as QubitUnitary.")
wires = wires if wires is not None else list(range(self.num_qubits))
return qml.QubitUnitary(self, wires=wires)
|
to_qasm(qubits)
Convert gate to a OpenQASM string.
More information on OpenQASM (2.0): https://arxiv.org/pdf/1707.03429
OpenQASM specification: https://openqasm.com/intro.html
Gates should be part of the standard library.
OpenQASM 2.0 -> qelib1.inc
OpenQASM 3 -> stdgates.inc
:param qubits: List of qubit indices the gate acts on
:return: OpenQASM string representation of the gate
String representation should define gate, qubits it acts on and ;.
Example for Hadamard in 1st qubit -> "h q[0];"
Source code in src/skq/gates/qubit/base.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152 | def to_qasm(self, qubits: list[int]) -> str:
"""
Convert gate to a OpenQASM string.
More information on OpenQASM (2.0): https://arxiv.org/pdf/1707.03429
OpenQASM specification: https://openqasm.com/intro.html
Gates should be part of the standard library.
OpenQASM 2.0 -> qelib1.inc
OpenQASM 3 -> stdgates.inc
:param qubits: List of qubit indices the gate acts on
:return: OpenQASM string representation of the gate
String representation should define gate, qubits it acts on and ;.
Example for Hadamard in 1st qubit -> "h q[0];"
"""
raise NotImplementedError("Conversion to OpenQASM is not implemented.")
|
to_qiskit()
Convert gate to a Qiskit Gate object.
Qiskit using little endian convention, so we permute the order of the qubits.
:return: Qiskit UnitaryGate object
Source code in src/skq/gates/qubit/base.py
97
98
99
100
101
102
103
104
105 | def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
"""
Convert gate to a Qiskit Gate object.
Qiskit using little endian convention, so we permute the order of the qubits.
:return: Qiskit UnitaryGate object
"""
gate_name = self.__class__.__name__
print(f"No to_qiskit defined for '{gate_name}'. Initializing as UnitaryGate.")
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label=gate_name)
|
Single-Qubit Gates
Identity Gate (I)
The Identity gate leaves the qubit state unchanged.
Matrix Representation:
\[
\text{I} = \begin{pmatrix}
1 & 0 \\
0 & 1
\end{pmatrix}
\]
skq.gates.qubit.single.I
Bases: QubitGate
Identity gate:
[[1, 0][0, 1]]
Source code in src/skq/gates/qubit/single.py
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | class I(QubitGate):
"""
Identity gate:
[[1, 0]
[0, 1]]
"""
def __new__(cls):
return super().__new__(cls, np.eye(2))
def to_qiskit(self) -> qiskit.circuit.library.IGate:
return qiskit.circuit.library.IGate()
def to_pennylane(self, wires: list[int] | int) -> qml.I:
return qml.I(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"id q[{qubits[0]}];"
|
Pauli-X Gate (NOT)
The Pauli-X gate is the quantum equivalent of the classical NOT gate. It flips the state of the qubit.
Matrix Representation:
\[
\text{X} = \begin{pmatrix}
0 & 1 \\
1 & 0
\end{pmatrix}
\]
skq.gates.qubit.single.X
Bases: QubitGate
Pauli X (NOT) Gate.
Source code in src/skq/gates/qubit/single.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41 | class X(QubitGate):
"""Pauli X (NOT) Gate."""
def __new__(cls):
return super().__new__(cls, [[0, 1], [1, 0]])
def to_qiskit(self) -> qiskit.circuit.library.XGate:
return qiskit.circuit.library.XGate()
def to_pennylane(self, wires: list[int] | int) -> qml.X:
return qml.X(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"x q[{qubits[0]}];"
|
Pauli-Y Gate
The Pauli-Y gate rotates the qubit state around the Y-axis of the Bloch sphere.
Matrix Representation:
\[
\text{Y} = \begin{pmatrix}
0 & -i \\
i & 0
\end{pmatrix}
\]
skq.gates.qubit.single.Y
Bases: QubitGate
Pauli Y gate.
Source code in src/skq/gates/qubit/single.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57 | class Y(QubitGate):
"""Pauli Y gate."""
def __new__(cls):
return super().__new__(cls, [[0, -1j], [1j, 0]])
def to_qiskit(self) -> qiskit.circuit.library.YGate:
return qiskit.circuit.library.YGate()
def to_pennylane(self, wires: list[int] | int) -> qml.Y:
return qml.Y(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"y q[{qubits[0]}];"
|
Pauli-Z Gate
The Pauli-Z gate rotates the qubit state around the Z-axis of the Bloch sphere.
Matrix Representation:
\[
\text{Z} = \begin{pmatrix}
1 & 0 \\
0 & -1
\end{pmatrix}
\]
skq.gates.qubit.single.Z
Bases: QubitGate
Pauli Z gate.
Special case of a phase shift gate with phi = pi.
Source code in src/skq/gates/qubit/single.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 | class Z(QubitGate):
"""Pauli Z gate.
Special case of a phase shift gate with phi = pi.
"""
def __new__(cls):
return super().__new__(cls, [[1, 0], [0, -1]])
def to_qiskit(self) -> qiskit.circuit.library.ZGate:
return qiskit.circuit.library.ZGate()
def to_pennylane(self, wires: list[int] | int) -> qml.Z:
return qml.Z(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"z q[{qubits[0]}];"
|
Hadamard Gate (H)
The Hadamard gate creates a superposition of the |0⟩ and |1⟩ states.
Matrix Representation:
\[
\text{H} = \frac{1}{\sqrt{2}} \begin{pmatrix}
1 & 1 \\
1 & -1
\end{pmatrix}
\]
skq.gates.qubit.single.H
Bases: QubitGate
Hadamard gate. Used to create superposition.
|0> -> (|0> + |1>) / sqrt(2)
|1> -> (|0> - |1>) / sqrt(2)
Source code in src/skq/gates/qubit/single.py
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 | class H(QubitGate):
"""
Hadamard gate. Used to create superposition.
|0> -> (|0> + |1>) / sqrt(2)
|1> -> (|0> - |1>) / sqrt(2)
"""
def __new__(cls):
return super().__new__(cls, [[1, 1], [1, -1]] / np.sqrt(2))
def to_qiskit(self) -> qiskit.circuit.library.HGate:
return qiskit.circuit.library.HGate()
def to_pennylane(self, wires: list[int] | int) -> qml.Hadamard:
return qml.Hadamard(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"h q[{qubits[0]}];"
|
Phase Gate
The general Phase gate applies a phase shift to the |1⟩ state.
Matrix Representation:
\[
\text{Phase}(\phi) = \begin{pmatrix}
1 & 0 \\
0 & e^{i\phi}
\end{pmatrix}
\]
skq.gates.qubit.single.Phase
Bases: QubitGate
General phase shift gate.
Special cases of phase gates:
- S gate: phi = pi / 2
- T gate: phi = pi / 4
- Z gate: phi = pi
Source code in src/skq/gates/qubit/single.py
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 | class Phase(QubitGate):
"""General phase shift gate.
Special cases of phase gates:
- S gate: phi = pi / 2
- T gate: phi = pi / 4
- Z gate: phi = pi
"""
def __new__(cls, phi):
obj = super().__new__(cls, [[1, 0], [0, np.exp(1j * phi)]])
obj.phi = phi
return obj
def to_qiskit(self) -> qiskit.circuit.library.PhaseGate:
return qiskit.circuit.library.PhaseGate(self.phi)
def to_pennylane(self, wires: list[int] | int) -> qml.PhaseShift:
return qml.PhaseShift(phi=self.phi, wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"U(0, 0, {self.phi}) q[{qubits[0]}];"
|
S Gate (π/2 Phase)
The S gate is a special case of the Phase gate with φ = π/2.
Matrix Representation:
\[
\text{S} = \begin{pmatrix}
1 & 0 \\
0 & i
\end{pmatrix}
\]
skq.gates.qubit.single.S
Bases: Phase
S gate: phase shift gate with phi = pi / 2.
Source code in src/skq/gates/qubit/single.py
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 | class S(Phase):
"""S gate: phase shift gate with phi = pi / 2."""
def __new__(cls):
phi = np.pi / 2
return super().__new__(cls, phi=phi)
def to_qiskit(self) -> qiskit.circuit.library.SGate:
return qiskit.circuit.library.SGate()
def to_pennylane(self, wires: list[int] | int) -> qml.S:
return qml.S(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"s q[{qubits[0]}];"
|
T Gate (π/4 Phase)
The T gate is a special case of the Phase gate with φ = π/4.
Matrix Representation:
\[
\text{T} = \begin{pmatrix}
1 & 0 \\
0 & e^{i\pi/4}
\end{pmatrix}
\]
skq.gates.qubit.single.T
Bases: Phase
T gate: phase shift gate with phi = pi / 4.
Source code in src/skq/gates/qubit/single.py
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 | class T(Phase):
"""T gate: phase shift gate with phi = pi / 4."""
def __new__(cls):
phi = np.pi / 4
return super().__new__(cls, phi=phi)
def to_qiskit(self) -> qiskit.circuit.library.TGate:
return qiskit.circuit.library.TGate()
def to_pennylane(self, wires: list[int] | int) -> qml.PhaseShift:
return qml.T(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"t q[{qubits[0]}];"
|
RX Gate (X-Rotation)
The RX gate rotates the qubit state around the X-axis of the Bloch sphere.
Matrix Representation:
\[
\text{RX}(\phi) = \begin{pmatrix}
\cos(\phi/2) & -i\sin(\phi/2) \\
-i\sin(\phi/2) & \cos(\phi/2)
\end{pmatrix}
\]
skq.gates.qubit.single.RX
Bases: QubitGate
Generalized X rotation gate.
Source code in src/skq/gates/qubit/single.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 | class RX(QubitGate):
"""Generalized X rotation gate."""
def __new__(cls, phi):
obj = super().__new__(cls, [[np.cos(phi / 2), -1j * np.sin(phi / 2)], [-1j * np.sin(phi / 2), np.cos(phi / 2)]])
obj.phi = phi
return obj
def to_qiskit(self) -> qiskit.circuit.library.RXGate:
return qiskit.circuit.library.RXGate(self.phi)
def to_pennylane(self, wires: list[int] | int = None) -> qml.RX:
return qml.RX(phi=self.phi, wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"rx({self.phi}) q[{qubits[0]}];"
|
RY Gate (Y-Rotation)
The RY gate rotates the qubit state around the Y-axis of the Bloch sphere.
Matrix Representation:
\[
\text{RY}(\phi) = \begin{pmatrix}
\cos(\phi/2) & -\sin(\phi/2) \\
\sin(\phi/2) & \cos(\phi/2)
\end{pmatrix}
\]
skq.gates.qubit.single.RY
Bases: QubitGate
Generalized Y rotation gate.
Source code in src/skq/gates/qubit/single.py
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 | class RY(QubitGate):
"""Generalized Y rotation gate."""
def __new__(cls, phi):
obj = super().__new__(cls, [[np.cos(phi / 2), -np.sin(phi / 2)], [np.sin(phi / 2), np.cos(phi / 2)]])
obj.phi = phi
return obj
def to_qiskit(self) -> qiskit.circuit.library.RYGate:
return qiskit.circuit.library.RYGate(self.phi)
def to_pennylane(self, wires: list[int] | int) -> qml.RY:
return qml.RY(phi=self.phi, wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"ry({self.phi}) q[{qubits[0]}];"
|
RZ Gate (Z-Rotation)
The RZ gate rotates the qubit state around the Z-axis of the Bloch sphere.
Matrix Representation:
\[
\text{RZ}(\phi) = \begin{pmatrix}
e^{-i\phi/2} & 0 \\
0 & e^{i\phi/2}
\end{pmatrix}
\]
skq.gates.qubit.single.RZ
Bases: QubitGate
Generalized Z rotation gate.
Source code in src/skq/gates/qubit/single.py
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206 | class RZ(QubitGate):
"""Generalized Z rotation gate."""
def __new__(cls, phi):
obj = super().__new__(cls, [[np.exp(-1j * phi / 2), 0], [0, np.exp(1j * phi / 2)]])
obj.phi = phi
return obj
def to_qiskit(self) -> qiskit.circuit.library.RZGate:
return qiskit.circuit.library.RZGate(self.phi)
def to_pennylane(self, wires: list[int] | int) -> qml.RZ:
return qml.RZ(phi=self.phi, wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"rz({self.phi}) q[{qubits[0]}];"
|
R Gate (General Rotation)
The R gate implements a general rotation by composing RZ, RY, and RZ rotations.
Matrix Representation:
\[
\text{R}(\theta,\phi,\lambda) = \text{RZ}(\lambda) \cdot \text{RY}(\phi) \cdot \text{RZ}(\theta)
\]
skq.gates.qubit.single.R
Bases: QubitGate
Generalized 3-axis rotation gate.
Implements a rotation by composing: RZ(gamma) · RY(beta) · RZ(alpha)
Source code in src/skq/gates/qubit/single.py
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229 | class R(QubitGate):
"""Generalized 3-axis rotation gate.
Implements a rotation by composing: RZ(gamma) · RY(beta) · RZ(alpha)
"""
def __new__(cls, theta, phi, lam):
obj = super().__new__(cls, RZ(lam) @ RY(phi) @ RZ(theta))
obj.theta = theta
obj.phi = phi
obj.lam = lam
return obj
def to_qiskit(self) -> qiskit.circuit.library.UGate:
return qiskit.circuit.library.UGate(self.theta, self.phi, self.lam)
def to_pennylane(self, wires: list[int] | int) -> qml.Rot:
return qml.Rot(phi=self.theta, theta=self.phi, omega=self.lam, wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"U({self.theta}, {self.phi}, {self.lam}) q[{qubits[0]}];"
|
U3 Gate (Universal Rotation)
The U3 gate is a universal single-qubit gate that can represent any single-qubit operation.
Matrix Representation:
\[
\text{U3}(\theta,\phi,\delta) = \text{RZ}(\delta) \cdot \text{RY}(\phi) \cdot \text{RX}(\theta)
\]
skq.gates.qubit.single.U3
Bases: QubitGate
Rotation around 3-axes. Single qubit gate.
:param theta: Rotation angle around X-axis
:param phi: Rotation angle around Y-axis
:param delta: Rotation angle around Z-axis
Source code in src/skq/gates/qubit/single.py
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 | class U3(QubitGate):
"""
Rotation around 3-axes. Single qubit gate.
:param theta: Rotation angle around X-axis
:param phi: Rotation angle around Y-axis
:param delta: Rotation angle around Z-axis
"""
def __new__(cls, theta: float, phi: float, delta: float):
# Rotation matrices
Rx = RX(theta)
Ry = RY(phi)
Rz = RZ(delta)
combined_matrix = Rz @ Ry @ Rx
obj = super().__new__(cls, combined_matrix)
obj.theta = theta
obj.phi = phi
obj.delta = delta
return obj
def to_qiskit(self) -> qiskit.circuit.library.U3Gate:
return qiskit.circuit.library.U3Gate(self.theta, self.phi, self.delta)
def to_pennylane(self, wires: list[int] | int) -> qml.U3:
return qml.U3(theta=self.theta, phi=self.phi, delta=self.delta, wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return f"rx({self.theta}) q[{qubits[0]}];\nry({self.phi}) q[{qubits[0]}];\nrz({self.delta}) q[{qubits[0]}];"
|
Measure Gate
The Measure gate performs a measurement on the qubit.
skq.gates.qubit.single.Measure
Bases: QubitGate
Measurement gate that returns probabilities of measuring |0⟩ and |1⟩.
Source code in src/skq/gates/qubit/single.py
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287 | class Measure(QubitGate):
"""Measurement gate that returns probabilities of measuring |0⟩ and |1⟩."""
def __new__(cls):
return super().__new__(cls, np.eye(2))
def to_qiskit(self) -> qiskit.circuit.library.Measure:
return qiskit.circuit.library.Measure()
def to_pennylane(self, wires: list[int] | int) -> qml.measure:
return qml.measure(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
return "\n".join(f"measure q[{q}] -> c[{q}];" for q in range(len(qubits)))
def __call__(self, state: np.ndarray) -> np.ndarray:
"""
Apply measurement to a quantum state and return probabilities.
:param state: Quantum state vector.
:return: Array of probabilities for all possible measurement outcomes.
"""
return np.abs(state) ** 2
def encodes(self, x: np.ndarray) -> np.ndarray:
return self.__call__(x)
|
__call__(state)
Apply measurement to a quantum state and return probabilities.
:param state: Quantum state vector.
:return: Array of probabilities for all possible measurement outcomes.
Source code in src/skq/gates/qubit/single.py
278
279
280
281
282
283
284 | def __call__(self, state: np.ndarray) -> np.ndarray:
"""
Apply measurement to a quantum state and return probabilities.
:param state: Quantum state vector.
:return: Array of probabilities for all possible measurement outcomes.
"""
return np.abs(state) ** 2
|
Multi-Qubit Gates
CNOT (CX) Gate
The CNOT (Controlled-NOT) gate flips the target qubit if the control qubit is |1⟩.
Matrix Representation:
\[
\text{CX} = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0
\end{pmatrix}
\]
skq.gates.qubit.multi.CX
Bases: QubitGate
Controlled-X (CNOT) gate.
Used to entangle two qubits.
If the control qubit is |1>, the target qubit is flipped.
Source code in src/skq/gates/qubit/multi.py
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 | class CX(QubitGate):
"""
Controlled-X (CNOT) gate.
Used to entangle two qubits.
If the control qubit is |1>, the target qubit is flipped.
"""
def __new__(cls):
return super().__new__(cls, [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
def to_qiskit(self) -> qiskit.circuit.library.CXGate:
return qiskit.circuit.library.CXGate()
def to_pennylane(self, wires: list[int]) -> qml.CNOT:
assert len(wires) == 2, "PennyLane CX gate requires 2 wires."
return qml.CNOT(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 2, "OpenQASM CX gate requires 2 qubits."
return f"cx q[{qubits[0]}], q[{qubits[1]}];"
|
Controlled-Y (CY) Gate
The CY gate applies a Y gate to the target qubit if the control qubit is |1⟩.
Matrix Representation:
\[
\text{CY} = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & -i \\
0 & 0 & i & 0
\end{pmatrix}
\]
skq.gates.qubit.multi.CY
Bases: QubitGate
Controlled-Y gate.
Source code in src/skq/gates/qubit/multi.py
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 | class CY(QubitGate):
"""Controlled-Y gate."""
def __new__(cls):
return super().__new__(cls, [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]])
def to_qiskit(self) -> qiskit.circuit.library.CYGate:
return qiskit.circuit.library.CYGate()
def to_pennylane(self, wires: list[int]) -> qml.CY:
assert len(wires) == 2, "PennyLane CY gate requires 2 wires."
return qml.CY(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 2, "OpenQASM CY gate requires 2 qubits."
return f"cy q[{qubits[0]}], q[{qubits[1]}];"
|
Controlled-Z (CZ) Gate
The CZ gate applies a Z gate to the target qubit if the control qubit is |1⟩.
Matrix Representation:
\[
\text{CZ} = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & -1
\end{pmatrix}
\]
skq.gates.qubit.multi.CZ
Bases: QubitGate
Controlled-Z gate.
Source code in src/skq/gates/qubit/multi.py
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230 | class CZ(QubitGate):
"""Controlled-Z gate."""
def __new__(cls):
return super().__new__(cls, [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]])
def to_qiskit(self) -> qiskit.circuit.library.CZGate:
return qiskit.circuit.library.CZGate()
def to_pennylane(self, wires: list[int]) -> qml.CZ:
assert len(wires) == 2, "PennyLane CZ gate requires 2 wires."
return qml.CZ(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 2, "OpenQASM CZ gate requires 2 qubits."
return f"cz q[{qubits[0]}], q[{qubits[1]}];"
|
Controlled-H (CH) Gate
The CH gate applies a Hadamard gate to the target qubit if the control qubit is |1⟩.
Matrix Representation:
\[
\text{CH} = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\
0 & 0 & \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}}
\end{pmatrix}
\]
skq.gates.qubit.multi.CH
Bases: QubitGate
Controlled-Hadamard gate.
Source code in src/skq/gates/qubit/multi.py
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 | class CH(QubitGate):
"""Controlled-Hadamard gate."""
def __new__(cls):
return super().__new__(cls, [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1 / np.sqrt(2), 1 / np.sqrt(2)], [0, 0, 1 / np.sqrt(2), -1 / np.sqrt(2)]])
def to_qiskit(self) -> qiskit.circuit.library.CHGate:
return qiskit.circuit.library.CHGate()
def to_pennylane(self, wires: list[int]) -> qml.CH:
assert len(wires) == 2, "PennyLane CH gate requires 2 wires."
return qml.CH(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 2, "OpenQASM CH gate requires 2 qubits."
return f"ch q[{qubits[0]}], q[{qubits[1]}];"
|
Controlled-Phase (CPhase) Gate
The CPhase gate applies a phase shift to the |11⟩ state.
Matrix Representation:
\[
\text{CPhase}(\phi) = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & e^{i\phi}
\end{pmatrix}
\]
skq.gates.qubit.multi.CPhase
Bases: QubitGate
General controlled phase shift gate.
:param phi: The phase shift angle in radians.
Source code in src/skq/gates/qubit/multi.py
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270 | class CPhase(QubitGate):
"""General controlled phase shift gate.
:param phi: The phase shift angle in radians.
"""
def __new__(cls, phi: float):
obj = super().__new__(cls, [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp(1j * phi)]])
obj.phi = phi
return obj
def to_qiskit(self) -> qiskit.circuit.library.CPhaseGate:
return qiskit.circuit.library.CPhaseGate(self.phi)
def to_pennylane(self, wires: list[int]) -> qml.CPhase:
assert len(wires) == 2, "PennyLane CPhase gate requires 2 wires."
return qml.CPhase(phi=self.phi, wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 2, "OpenQASM CPhase gate requires 2 qubits."
return f"cp({self.phi}) q[{qubits[0]}], q[{qubits[1]}];"
|
Controlled-S (CS) Gate
The CS gate is a special case of the CPhase gate with φ = π/2.
Matrix Representation:
\[
\text{CS} = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & i
\end{pmatrix}
\]
skq.gates.qubit.multi.CS
Bases: CPhase
Controlled-S gate.
Source code in src/skq/gates/qubit/multi.py
273
274
275
276
277
278
279
280
281 | class CS(CPhase):
"""Controlled-S gate."""
def __new__(cls):
phi = np.pi / 2
return super().__new__(cls, phi=phi)
def to_qiskit(self) -> qiskit.circuit.library.CSGate:
return qiskit.circuit.library.CSGate()
|
Controlled-T (CT) Gate
The CT gate is a special case of the CPhase gate with φ = π/4.
Matrix Representation:
\[
\text{CT} = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & e^{i\pi/4}
\end{pmatrix}
\]
skq.gates.qubit.multi.CT
Bases: CPhase
Controlled-T gate.
Source code in src/skq/gates/qubit/multi.py
284
285
286
287
288
289
290
291
292 | class CT(CPhase):
"""Controlled-T gate."""
def __new__(cls):
phi = np.pi / 4
return super().__new__(cls, phi=phi)
def to_qiskit(self) -> qiskit.circuit.library.TGate:
return qiskit.circuit.library.TGate().control(1)
|
SWAP Gate
The SWAP gate exchanges the states of two qubits.
Matrix Representation:
\[
\text{SWAP} = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1
\end{pmatrix}
\]
skq.gates.qubit.multi.SWAP
Bases: QubitGate
Swap gate. Swaps the states of two qubits.
Source code in src/skq/gates/qubit/multi.py
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 | class SWAP(QubitGate):
"""Swap gate. Swaps the states of two qubits."""
def __new__(cls):
return super().__new__(cls, [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
def to_qiskit(self) -> qiskit.circuit.library.SwapGate:
return qiskit.circuit.library.SwapGate()
def to_pennylane(self, wires: list[int]) -> qml.SWAP:
assert len(wires) == 2, "PennyLane SWAP gate requires 2 wires."
return qml.SWAP(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 2, "OpenQASM SWAP gate requires 2 qubits."
return f"swap q[{qubits[0]}], q[{qubits[1]}];"
|
Controlled-SWAP (CSWAP) Gate
The CSWAP gate, also known as the Fredkin gate, swaps two qubits if the control qubit is |1⟩.
Matrix Representation:
\[
\text{CSWAP} = \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 & 0 & 1 & 0 \\
0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 1
\end{pmatrix}
\]
skq.gates.qubit.multi.CSwap
Bases: QubitGate
A controlled-SWAP gate. Also known as the Fredkin gate.
Source code in src/skq/gates/qubit/multi.py
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 | class CSwap(QubitGate):
"""A controlled-SWAP gate. Also known as the Fredkin gate."""
def __new__(cls):
return super().__new__(cls, [[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, 0], [0, 0, 0, 0, 0, 0, 0, 1]])
def to_qiskit(self) -> qiskit.circuit.library.CSwapGate:
return qiskit.circuit.library.CSwapGate()
def to_pennylane(self, wires: list[int]) -> qml.CSWAP:
return qml.CSWAP(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 3, "OpenQASM CSWAP gate requires 3 qubits."
return f"cswap q[{qubits[0]}], q[{qubits[1]}], q[{qubits[2]}];"
|
Toffoli (CCX) Gate
The Toffoli gate, or CCX gate, applies an X gate to the target qubit if both control qubits are |1⟩.
Matrix Representation:
\[
\text{CCX} = \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}
\]
skq.gates.qubit.multi.CCX
Bases: QubitGate
A 3-qubit controlled-controlled-X (CCX) gate. Also known as the Toffoli gate.
Source code in src/skq/gates/qubit/multi.py
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344 | class CCX(QubitGate):
"""A 3-qubit controlled-controlled-X (CCX) gate. Also known as the Toffoli gate."""
def __new__(cls):
return super().__new__(cls, [[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]])
def to_qiskit(self) -> qiskit.circuit.library.CCXGate:
return qiskit.circuit.library.CCXGate()
def to_pennylane(self, wires: list[int]) -> qml.Toffoli:
return qml.Toffoli(wires=wires)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 3, "OpenQASM CCX (Toffoli) gate requires 3 qubits."
return f"ccx q[{qubits[0]}], q[{qubits[1]}], q[{qubits[2]}];"
|
CCY Gate
The CCY gate applies a Y gate to the target qubit if both control qubits are |1⟩.
Matrix Representation:
\[
\text{CCY} = \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 & -i \\
0 & 0 & 0 & 0 & 0 & 0 & i & 0
\end{pmatrix}
\]
skq.gates.qubit.multi.CCY
Bases: QubitGate
A 3-qubit controlled-controlled-Y (CCY) gate.
Source code in src/skq/gates/qubit/multi.py
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361 | class CCY(QubitGate):
"""A 3-qubit controlled-controlled-Y (CCY) gate."""
def __new__(cls):
return super().__new__(cls, [[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, -1j], [0, 0, 0, 0, 0, 0, 1j, 0]])
def to_qiskit(self) -> qiskit.circuit.library.YGate:
# There is no native CCY gate in Qiskit so we construct it.
return qiskit.circuit.library.YGate().control(2)
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 3, "OpenQASM CCY gate requires 3 qubits."
# Custom OpenQASM implementation
# sdg is an inverse s gate
return f"""sdg q[{qubits[2]}];\ncx q[{qubits[1]}], q[{qubits[2]}];\ns q[{qubits[2]}];\ncx q[{qubits[0]}], q[{qubits[2]}];\nsdg q[{qubits[2]}];\ncx q[{qubits[1]}], q[{qubits[2]}];\ns q[{qubits[2]}];\ny q[{qubits[2]}];"""
|
CCZ Gate
The CCZ gate applies a Z gate to the target qubit if both control qubits are |1⟩.
Matrix Representation:
\[
\text{CCZ} = \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 & 1 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & -1
\end{pmatrix}
\]
skq.gates.qubit.multi.CCZ
Bases: QubitGate
A 3-qubit controlled-controlled-Z (CCZ) gate.
Source code in src/skq/gates/qubit/multi.py
364
365
366
367
368
369
370
371
372
373
374
375
376 | class CCZ(QubitGate):
"""A 3-qubit controlled-controlled-Z (CCZ) gate."""
def __new__(cls):
return super().__new__(cls, [[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, 1, 0], [0, 0, 0, 0, 0, 0, 0, -1]])
def to_qiskit(self) -> qiskit.circuit.library.CCZGate:
return qiskit.circuit.library.CCZGate()
def to_qasm(self, qubits: list[int]) -> str:
assert len(qubits) == 3, "OpenQASM CCZ gate requires 3 qubits."
# CCZ = CCX sandwiched between two H gates on last qubit.
return f"""h q[{qubits[2]}];\nccx q[{qubits[0]}], q[{qubits[1]}], q[{qubits[2]}];\nh q[{qubits[2]}];"""
|
Multi-Controlled X (MCX) Gate
The MCX gate applies an X gate to the target qubit if all control qubits are |1⟩.
skq.gates.qubit.multi.MCX
Bases: QubitGate
Multi controlled-X (MCX) gate.
:param num_ctrl_qubits: Number of control qubits.
Source code in src/skq/gates/qubit/multi.py
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409 | class MCX(QubitGate):
"""
Multi controlled-X (MCX) gate.
:param num_ctrl_qubits: Number of control qubits.
"""
def __new__(cls, num_ctrl_qubits: int):
assert num_ctrl_qubits >= 1, "MCX gate must have at least one control qubit."
cls.num_ctrl_qubits = num_ctrl_qubits
levels = 2 ** (num_ctrl_qubits + 1)
gate = np.identity(levels)
gate[-2:, -2:] = X()
return super().__new__(cls, gate)
def to_qiskit(self) -> qiskit.circuit.library.CXGate | qiskit.circuit.library.CCXGate | qiskit.circuit.library.C3XGate | qiskit.circuit.library.C4XGate | qiskit.circuit.library.MCXGate:
if self.num_ctrl_qubits == 1:
return qiskit.circuit.library.CXGate()
elif self.num_ctrl_qubits == 2:
return qiskit.circuit.library.CCXGate()
elif self.num_ctrl_qubits == 3:
return qiskit.circuit.library.C3XGate()
elif self.num_ctrl_qubits == 4:
return qiskit.circuit.library.C4XGate()
else:
return qiskit.circuit.library.MCXGate(num_ctrl_qubits=self.num_ctrl_qubits)
def to_pennylane(self, wires: list[int]) -> qml.CNOT | qml.QubitUnitary:
if self.num_ctrl_qubits == 1:
return qml.CNOT(wires=wires)
else:
return super().to_pennylane(wires)
|
Multi-Controlled Y (MCY) Gate
The MCY gate applies a Y gate to the target qubit if all control qubits are |1⟩.
skq.gates.qubit.multi.MCY
Bases: QubitGate
Multi controlled-Y (MCY) gate.
Source code in src/skq/gates/qubit/multi.py
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 | class MCY(QubitGate):
"""Multi controlled-Y (MCY) gate."""
def __new__(cls, num_ctrl_qubits: int):
assert num_ctrl_qubits >= 1, "MCY gate must have at least one control qubit."
cls.num_ctrl_qubits = num_ctrl_qubits
levels = 2 ** (num_ctrl_qubits + 1)
gate = np.identity(levels)
gate[-2:, -2:] = Y()
return super().__new__(cls, gate)
def to_qiskit(self) -> qiskit.circuit.library.YGate:
return qiskit.circuit.library.YGate().control(self.num_ctrl_qubits)
def to_pennylane(self, wires: list[int]) -> qml.CY | qml.QubitUnitary:
if self.num_ctrl_qubits == 1:
return qml.CY(wires=wires)
else:
return super().to_pennylane(wires)
|
Multi-Controlled Z (MCZ) Gate
The MCZ gate applies a Z gate to the target qubit if all control qubits are |1⟩.
skq.gates.qubit.multi.MCZ
Bases: QubitGate
Multi controlled-Z (MCZ) gate.
Source code in src/skq/gates/qubit/multi.py
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451 | class MCZ(QubitGate):
"""Multi controlled-Z (MCZ) gate."""
def __new__(cls, num_ctrl_qubits: int):
assert num_ctrl_qubits >= 1, "MCZ gate must have at least one control qubit."
cls.num_ctrl_qubits = num_ctrl_qubits
levels = 2 ** (num_ctrl_qubits + 1)
gate = np.identity(levels)
gate[-2:, -2:] = Z()
return super().__new__(cls, gate)
def to_qiskit(self) -> qiskit.circuit.library.ZGate:
return qiskit.circuit.library.ZGate().control(self.num_ctrl_qubits)
def to_pennylane(self, wires: list[int]) -> qml.CZ | qml.QubitUnitary:
if self.num_ctrl_qubits == 1:
return qml.CZ(wires=wires)
else:
return super().to_pennylane(wires)
|
The QFT gate implements the Quantum Fourier Transform, a key component in many quantum algorithms.
Matrix Representation (for n=2):
\[
\text{QFT} = \frac{1}{2} \begin{pmatrix}
1 & 1 & 1 & 1 \\
1 & i & -1 & -i \\
1 & -1 & 1 & -1 \\
1 & -i & -1 & i
\end{pmatrix}
\]
skq.gates.qubit.multi.QFT
Bases: QubitGate
n-qubit Quantum Fourier Transform gate.
:param n_qubits: The number of qubits in the system.
:param inverse: Whether to use the inverse QFT.
- For example, in Shor's algorithm we use the inverse QFT.
Source code in src/skq/gates/qubit/multi.py
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 | class QFT(QubitGate):
"""
n-qubit Quantum Fourier Transform gate.
:param n_qubits: The number of qubits in the system.
:param inverse: Whether to use the inverse QFT.
- For example, in Shor's algorithm we use the inverse QFT.
"""
def __new__(cls, n_qubits: int, inverse: bool = False):
dim = 2**n_qubits
matrix = np.zeros((dim, dim), dtype=complex)
# Use positive exponent for QFT, negative for QFT†
sign = -1 if inverse else 1
omega = np.exp(sign * 2j * np.pi / dim)
for i in range(dim):
for j in range(dim):
matrix[i, j] = omega ** (i * j) / np.sqrt(dim)
instance = super().__new__(cls, matrix)
instance.inverse = inverse
return instance
def to_qiskit(self):
"""Convert to a Qiskit circuit implementing QFT or QFT†."""
n = self.num_qubits
name = "QFT†" if self.inverse else "QFT"
def create_qft(n_qubits):
circuit = qiskit.QuantumCircuit(n_qubits, name=name)
for i in range(n_qubits):
circuit.h(i)
for j in range(i + 1, n_qubits):
circuit.cp(2 * np.pi / 2 ** (j - i + 1), i, j)
return circuit
qc = create_qft(n)
if self.inverse:
qc = qc.inverse()
qc.name = name
return qc
def to_qasm(self, qubits: list[int]) -> str:
"""Convert to OpenQASM code."""
n = self.num_qubits
assert len(qubits) == n, f"OpenQASM QFT requires {n} qubits."
name = "QFT†" if self.inverse else "QFT"
qasm_str = f"// {name} circuit (big-endian convention)\n"
if self.inverse:
for i in range(n // 2):
qasm_str += f"swap q[{qubits[i]}], q[{qubits[n-i-1]}];\n"
for i in range(n - 1, -1, -1):
for j in range(n - 1, i, -1):
angle = -np.pi / (2 ** (j - i))
qasm_str += f"cu1({angle}) q[{qubits[i]}], q[{qubits[j]}];\n"
qasm_str += f"h q[{qubits[i]}];\n"
else:
for i in range(n):
qasm_str += f"h q[{qubits[i]}];\n"
for j in range(i + 1, n):
angle = np.pi / (2 ** (j - i))
qasm_str += f"cu1({angle}) q[{qubits[i]}], q[{qubits[j]}];\n"
for i in range(n // 2):
qasm_str += f"swap q[{qubits[i]}], q[{qubits[n-i-1]}];\n"
qasm_str += f"// End of {name} circuit\n"
return qasm_str
|
to_qasm(qubits)
Convert to OpenQASM code.
Source code in src/skq/gates/qubit/multi.py
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 | def to_qasm(self, qubits: list[int]) -> str:
"""Convert to OpenQASM code."""
n = self.num_qubits
assert len(qubits) == n, f"OpenQASM QFT requires {n} qubits."
name = "QFT†" if self.inverse else "QFT"
qasm_str = f"// {name} circuit (big-endian convention)\n"
if self.inverse:
for i in range(n // 2):
qasm_str += f"swap q[{qubits[i]}], q[{qubits[n-i-1]}];\n"
for i in range(n - 1, -1, -1):
for j in range(n - 1, i, -1):
angle = -np.pi / (2 ** (j - i))
qasm_str += f"cu1({angle}) q[{qubits[i]}], q[{qubits[j]}];\n"
qasm_str += f"h q[{qubits[i]}];\n"
else:
for i in range(n):
qasm_str += f"h q[{qubits[i]}];\n"
for j in range(i + 1, n):
angle = np.pi / (2 ** (j - i))
qasm_str += f"cu1({angle}) q[{qubits[i]}], q[{qubits[j]}];\n"
for i in range(n // 2):
qasm_str += f"swap q[{qubits[i]}], q[{qubits[n-i-1]}];\n"
qasm_str += f"// End of {name} circuit\n"
return qasm_str
|
to_qiskit()
Convert to a Qiskit circuit implementing QFT or QFT†.
Source code in src/skq/gates/qubit/multi.py
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 | def to_qiskit(self):
"""Convert to a Qiskit circuit implementing QFT or QFT†."""
n = self.num_qubits
name = "QFT†" if self.inverse else "QFT"
def create_qft(n_qubits):
circuit = qiskit.QuantumCircuit(n_qubits, name=name)
for i in range(n_qubits):
circuit.h(i)
for j in range(i + 1, n_qubits):
circuit.cp(2 * np.pi / 2 ** (j - i + 1), i, j)
return circuit
qc = create_qft(n)
if self.inverse:
qc = qc.inverse()
qc.name = name
return qc
|
Deutsch Oracle
The Deutsch Oracle implements the oracle for the Deutsch algorithm.
skq.gates.qubit.multi.DeutschOracle
Bases: QubitGate
Oracle for Deutsch algorithm with ancilla qubit.
Implements |x,y⟩ -> |x, y⊕f(x)⟩
:param f: Function that takes an integer x (0 or 1) and returns 0 or 1
Source code in src/skq/gates/qubit/multi.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | class DeutschOracle(QubitGate):
"""
Oracle for Deutsch algorithm with ancilla qubit.
Implements |x,y⟩ -> |x, y⊕f(x)⟩
:param f: Function that takes an integer x (0 or 1) and returns 0 or 1
"""
def __new__(cls, f):
matrix = np.zeros((4, 4))
for x in [0, 1]:
matrix[x * 2 + f(x), x * 2] = 1 # |x,0⟩ -> |x,f(x)⟩
matrix[x * 2 + (1 - f(x)), x * 2 + 1] = 1 # |x,1⟩ -> |x,1-f(x)⟩
return super().__new__(cls, matrix)
def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
# Reverse the order of qubits for Qiskit's little-endian convention
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label="DeutschOracle")
|
Deutsch-Jozsa Oracle
The Deutsch-Jozsa Oracle implements the oracle for the Deutsch-Jozsa algorithm.
skq.gates.qubit.multi.DeutschJozsaOracle
Bases: QubitGate
Oracle for Deutsch-Jozsa algorithm.
For input x and output f(x), the oracle applies phase (-1)^f(x).
- Constant function: f(x) is same for all x
- Balanced function: f(x) = 1 for exactly half of inputs
:param f: Function that takes an integer x (0 to 2^n-1) and returns 0 or 1
:param n_bits: Number of input bits
Source code in src/skq/gates/qubit/multi.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 | class DeutschJozsaOracle(QubitGate):
"""
Oracle for Deutsch-Jozsa algorithm.
For input x and output f(x), the oracle applies phase (-1)^f(x).
- Constant function: f(x) is same for all x
- Balanced function: f(x) = 1 for exactly half of inputs
:param f: Function that takes an integer x (0 to 2^n-1) and returns 0 or 1
:param n_bits: Number of input bits
"""
def __new__(cls, f, n_bits: int):
n_states = 2**n_bits
outputs = [f(x) for x in range(n_states)]
if not all(v in [0, 1] for v in outputs):
raise ValueError("Function must return 0 or 1")
ones = sum(outputs)
if ones != 0 and ones != n_states and ones != n_states // 2:
raise ValueError("Function must be constant or balanced")
oracle_matrix = np.eye(n_states)
for x in range(n_states):
oracle_matrix[x, x] = (-1) ** f(x)
return super().__new__(cls, oracle_matrix)
def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
# Reverse the order of qubits for Qiskit's little-endian convention
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label="DeutschJozsaOracle")
|
Phase Oracle
The Phase Oracle marks a target state with a phase shift, as used in Grover's search algorithm.
skq.gates.qubit.multi.PhaseOracle
Bases: QubitGate
Phase Oracle as used in Grover's search algorithm.
:param target_state: The target state to mark.
target_state is assumed to be in Big-Endian format.
Source code in src/skq/gates/qubit/multi.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 | class PhaseOracle(QubitGate):
"""
Phase Oracle as used in Grover's search algorithm.
:param target_state: The target state to mark.
target_state is assumed to be in Big-Endian format.
"""
def __new__(cls, target_state: np.ndarray):
state = Statevector(target_state)
n_qubits = state.num_qubits
identity = np.eye(2**n_qubits)
oracle_matrix = identity - 2 * np.outer(target_state, target_state.conj())
return super().__new__(cls, oracle_matrix)
def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
# Reverse the order of qubits for Qiskit's little-endian convention
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label="PhaseOracle")
|
Grover Diffusion Operator
The Grover Diffusion Operator amplifies the amplitude of the marked state in Grover's search algorithm.
skq.gates.qubit.multi.GroverDiffusion
Bases: QubitGate
Grover Diffusion Operator Gate as used in Grover's search algorithm.
This gate amplifies the amplitude of the marked state.
:param n_qubits: The number of qubits in the system.
Source code in src/skq/gates/qubit/multi.py
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 | class GroverDiffusion(QubitGate):
"""
Grover Diffusion Operator Gate as used in Grover's search algorithm.
This gate amplifies the amplitude of the marked state.
:param n_qubits: The number of qubits in the system.
"""
def __new__(cls, n_qubits: int):
assert n_qubits >= 1, "GroverDiffusionGate must have at least one qubit."
# Equal superposition state vector
size = 2**n_qubits
equal_superposition = np.ones(size) / np.sqrt(size)
# Grover diffusion operator: 2|ψ⟩⟨ψ| - I
diffusion_matrix = 2 * np.outer(equal_superposition, equal_superposition) - np.eye(size)
return super().__new__(cls, diffusion_matrix)
def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
# Reverse the order of qubits for Qiskit's little-endian convention
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label="GroverDiffusion")
|
Controlled Unitary (CU) Gate
The CU gate applies a unitary operation conditionally based on a control qubit.
skq.gates.qubit.multi.CU
Bases: QubitGate
General Controlled-Unitary gate.
Applies a unitary operation conditionally based on a control qubit.
If the control qubit is |1>, the unitary is applied to the target qubit(s).
Only use this for custom unitaries. Else use standard controlled gates like CX, CY, CZ, CH, CS, CT, CPhase, etc.
:param unitary: The unitary gate to be controlled. Must be a QubitGate.
Source code in src/skq/gates/qubit/multi.py
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508 | class CU(QubitGate):
"""
General Controlled-Unitary gate.
Applies a unitary operation conditionally based on a control qubit.
If the control qubit is |1>, the unitary is applied to the target qubit(s).
Only use this for custom unitaries. Else use standard controlled gates like CX, CY, CZ, CH, CS, CT, CPhase, etc.
:param unitary: The unitary gate to be controlled. Must be a QubitGate.
"""
def __new__(cls, unitary: QubitGate):
assert isinstance(unitary, QubitGate), "Input must be a QubitGate"
n_target_qubits = unitary.num_qubits
dim = 2 ** (n_target_qubits + 1)
matrix = np.eye(dim, dtype=complex)
block_size = 2**n_target_qubits
matrix[block_size:, block_size:] = unitary
obj = super().__new__(cls, matrix)
obj.unitary = unitary
obj.n_target_qubits = n_target_qubits
return obj
def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
try:
base_gate = self.unitary.to_qiskit()
return base_gate.control(1)
except (AttributeError, TypeError, ValueError):
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label=f"c-{self.unitary.__class__.__name__}")
def to_pennylane(self, wires: list[int]) -> qml.QubitUnitary:
"""Convert to a PennyLane controlled gate."""
assert len(wires) == self.num_qubits, f"PennyLane CU gate requires {self.num_qubits} wires."
return qml.QubitUnitary(self, wires=wires)
|
to_pennylane(wires)
Convert to a PennyLane controlled gate.
Source code in src/skq/gates/qubit/multi.py
| def to_pennylane(self, wires: list[int]) -> qml.QubitUnitary:
"""Convert to a PennyLane controlled gate."""
assert len(wires) == self.num_qubits, f"PennyLane CU gate requires {self.num_qubits} wires."
return qml.QubitUnitary(self, wires=wires)
|
Multi-Controlled Unitary (MCU) Gate
The MCU gate applies a unitary operation conditionally based on multiple control qubits.
skq.gates.qubit.multi.MCU
Bases: QubitGate
Multi-Controlled Unitary gate.
Applies a unitary operation conditionally based on multiple control qubits.
The unitary is applied to target qubit(s) only if all control qubits are |1>.
Only use this for custom unitaries. Else use standard controlled gates like CX, CY, CZ, CH, CS, CT, CPhase, etc.
:param unitary: The unitary gate to be controlled. Must be a QubitGate.
:param num_ctrl_qubits: Number of control qubits.
Source code in src/skq/gates/qubit/multi.py
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551 | class MCU(QubitGate):
"""
Multi-Controlled Unitary gate.
Applies a unitary operation conditionally based on multiple control qubits.
The unitary is applied to target qubit(s) only if all control qubits are |1>.
Only use this for custom unitaries. Else use standard controlled gates like CX, CY, CZ, CH, CS, CT, CPhase, etc.
:param unitary: The unitary gate to be controlled. Must be a QubitGate.
:param num_ctrl_qubits: Number of control qubits.
"""
def __new__(cls, unitary: QubitGate, num_ctrl_qubits: int):
assert isinstance(unitary, QubitGate), "Input must be a QubitGate"
assert num_ctrl_qubits >= 1, "MCU gate must have at least one control qubit."
n_target_qubits = unitary.num_qubits
total_qubits = n_target_qubits + num_ctrl_qubits
dim = 2**total_qubits
matrix = np.eye(dim, dtype=complex)
unitary_size = 2**n_target_qubits
start_idx = dim - unitary_size
matrix[start_idx:, start_idx:] = unitary
obj = super().__new__(cls, matrix)
obj.unitary = unitary
obj.num_ctrl_qubits = num_ctrl_qubits
obj.n_target_qubits = n_target_qubits
return obj
def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
"""Convert to a Qiskit controlled gate."""
try:
base_gate = self.unitary.to_qiskit()
return base_gate.control(self.num_ctrl_qubits)
except (AttributeError, TypeError, ValueError):
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label=f"mc-{self.unitary.__class__.__name__}")
def to_pennylane(self, wires: list[int]) -> qml.QubitUnitary:
"""Convert to a PennyLane multi-controlled gate."""
assert len(wires) == self.num_qubits, f"PennyLane MCU gate requires {self.num_qubits} wires."
return qml.QubitUnitary(self, wires=wires)
|
to_pennylane(wires)
Convert to a PennyLane multi-controlled gate.
Source code in src/skq/gates/qubit/multi.py
| def to_pennylane(self, wires: list[int]) -> qml.QubitUnitary:
"""Convert to a PennyLane multi-controlled gate."""
assert len(wires) == self.num_qubits, f"PennyLane MCU gate requires {self.num_qubits} wires."
return qml.QubitUnitary(self, wires=wires)
|
to_qiskit()
Convert to a Qiskit controlled gate.
Source code in src/skq/gates/qubit/multi.py
540
541
542
543
544
545
546 | def to_qiskit(self) -> qiskit.circuit.library.UnitaryGate:
"""Convert to a Qiskit controlled gate."""
try:
base_gate = self.unitary.to_qiskit()
return base_gate.control(self.num_ctrl_qubits)
except (AttributeError, TypeError, ValueError):
return qiskit.circuit.library.UnitaryGate(self.convert_endianness(), label=f"mc-{self.unitary.__class__.__name__}")
|
Cross-Resonance (CR) Gate
The CR gate is a simple Cross-Resonance gate used in superconducting qubit architectures.
skq.gates.qubit.multi.CR
Bases: QubitGate
Simple Cross-Resonance gate.
Source code in src/skq/gates/qubit/multi.py
| class CR(QubitGate):
"""Simple Cross-Resonance gate."""
def __new__(cls, theta: float):
return super().__new__(cls, [[1, 0, 0, 0], [0, np.cos(theta), 0, -1j * np.sin(theta)], [0, 0, 1, 0], [0, -1j * np.sin(theta), 0, np.cos(theta)]])
|
Symmetric Echoed Cross-Resonance (SymmetricECR) Gate
The SymmetricECR gate is a symmetric echoed Cross-Resonance gate.
skq.gates.qubit.multi.SymmetricECR
Bases: QubitGate
Symmetric Echoed Cross-Resonance gate.
Source code in src/skq/gates/qubit/multi.py
| class SymmetricECR(QubitGate):
"""Symmetric Echoed Cross-Resonance gate."""
def __new__(cls, theta: float):
return super().__new__(cls, CR(theta) @ CR(-theta))
|
Asymmetric Echoed Cross-Resonance (AsymmetricECR) Gate
The AsymmetricECR gate is an asymmetric echoed Cross-Resonance gate.
skq.gates.qubit.multi.AsymmetricECR
Bases: QubitGate
Asymmetric Echoed Cross-Resonance gate.
Source code in src/skq/gates/qubit/multi.py
| class AsymmetricECR(QubitGate):
"""Asymmetric Echoed Cross-Resonance gate."""
def __new__(cls, theta1: float, theta2: float):
return super().__new__(cls, CR(theta1) @ CR(theta2))
|