Skip to content

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
90
91
92
93
94
95
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
159
160
161
162
163
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
154
155
156
157
@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
54
55
56
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
85
86
87
88
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
80
81
82
83
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)

Quantum Fourier Transform (QFT) Gate

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
505
506
507
508
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
548
549
550
551
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
454
455
456
457
458
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
461
462
463
464
465
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
468
469
470
471
472
class AsymmetricECR(QubitGate):
    """Asymmetric Echoed Cross-Resonance gate."""

    def __new__(cls, theta1: float, theta2: float):
        return super().__new__(cls, CR(theta1) @ CR(theta2))