ket.gates

Quantum gate definitions.

All quantum gates accept one or more Quant objects as input and return them unchanged, enabling method chaining:

from ket import *

p = Process()
a, b = p.alloc(2)

S(X(a))           # Apply X then S on qubit `a`.
CNOT(H(a), b)     # Apply H on `a`, then CNOT with `a` as control.

For parameterized gates (e.g., rotation gates), partial application is supported: if the qubit argument is omitted, a gate callable is returned instead of being applied immediately:

from math import pi
from ket import *

# Create reusable gate instances with pre-set angles
s_gate = P(pi / 2)   # returns a callable, not applied yet
t_gate = P(pi / 4)

p = Process()
q = p.alloc()

s_gate(q)             # now applied
t_gate(q)

Gates that accept two-qubit arguments (e.g., RXX, CNOT) also support partial application: passing only the angle returns a two-qubit gate callable.

Observable mode (with obs():): Several single-qubit gate functions (X, Y, Z, I) have a dual role: inside an obs context manager block they construct Pauli objects for Hamiltonian building rather than applying the physical gate to the circuit.

Functions ket.gates

B(qubit)

Construct a binary-encoded QUBO observable for a qubit register.

CNOT(control_qubit, target_qubit)

Apply the Controlled NOT gate.

CZ(*qubits)

Apply the Multi-Controlled Z gate.

H(qubits)

Apply the Hadamard gate.

I(qubits)

Apply the Identity gate.

P(theta[, qubits])

Apply the Phase shift gate.

QFT(qubits[, do_swap])

Apply the Quantum Fourier Transform (QFT) to the given qubits.

RBS(theta[, qubits_a, qubits_b])

Apply the Reconfigurable Beam Splitter (RBS) gate.

RX(theta[, qubits])

Apply the X-axes rotation gate.

RXX(theta[, qubits_a, qubits_b])

Apply the XX rotation gate.

RY(theta[, qubits])

Apply the Y-axes rotation gate.

RYY(theta[, qubits_a, qubits_b])

Apply the RYY rotation gate.

RZ(theta[, qubits])

Apply the Z-axes rotation gate.

RZZ(theta[, qubits_a, qubits_b])

Apply the ZZ rotation gate.

S(qubits)

Apply the S gate.

SD(qubits)

Apply the S-dagger gate.

SWAP(qubit_a, qubit_b)

Apply the SWAP gate.

SX(qubits)

Apply the Sqrt X gate.

T(qubits)

Apply the T gate.

TD(qubits)

Apply the T-dagger gate.

U3(theta, phi, lambda_[, qubit])

Apply the U3 gate.

X(qubits)

Apply the Pauli X gate.

Y(qubits)

Apply the Pauli Y gate.

Z(qubits)

Apply the Pauli Z gate.

evolve(hamiltonian)

Time evolution \(e^{-iHt}\) for a Hamiltonian.

global_phase(theta)

Apply a global phase to a quantum operation.

is_diagonal(gate)

Decorator that marks a gate as diagonal in the computational basis.

is_permutation(gate)

Decorator that marks a gate as a permutation of computational basis states.

obs()

Context manager for constructing quantum observables in symbolic form.

B(qubit: Quant)

Construct a binary-encoded QUBO observable for a qubit register.

Returns a Hamiltonian with eigenvalue 0 for \(\left|0\right\rangle\) and eigenvalue 1 for \(\left|1\right\rangle\). When applied to a register, the result is the tensor product, giving eigenvalue equal to the binary integer encoded in the register:

\[B = \frac{\mathbf{1} - Z}{2}\]

This observable is essential for building QUBO Hamiltonians where the cost function is a polynomial over binary variables.

Example

from ket import *

p = Process()
q = p.alloc(3)

# QUBO cost: x0 + x1*x2 - 2*x0*x2
cost = B(q[0]) + B(q[1]) * B(q[2]) - 2 * B(q[0]) * B(q[2])
Parameters:

qubit – The qubit(s) to apply the observable to. If a multi-qubit register is passed, the result is the tensor product of \(B\) over all qubits.

Returns:

The binary-encoded observable.

CNOT(control_qubit: Quant, target_qubit: Quant) tuple[Quant, Quant]

Apply the Controlled NOT gate.

Matrix

Effect

\(\begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0\end{bmatrix}\)

\(\begin{matrix}\text{CNOT}\left|00\right> = & \left|00\right> \\\text{CNOT}\left|01\right> = & \left|01\right> \\\text{CNOT}\left|10\right> = & \left|11\right> \\\text{CNOT}\left|11\right> = & \left|10\right> \\\text{CNOT}\left|\text{c}\right>\left|\text{t}\right> =& \left|\text{c}\right> \left|\text{c}\oplus\text{t}\right>\end{matrix}\)

CZ(*qubits: Quant) tuple[Quant, ...]

Apply the Multi-Controlled Z gate.

Matrix

Effect

\(\begin{bmatrix}1 & 0 & \cdots & 0 & 0 \\ 0 & 1 & \cdots & 0 & 0 \\\vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & \cdots & 1 & 0 \\0 & 0 & \cdots & 0 & -1\end{bmatrix}\)

\(\begin{matrix}\text{CZ}\left|0\cdots0\right> = & \left|0\cdots0\right> \\\text{CZ}\left|0\cdots1\right> = & \left|0\cdots1\right> \\\text{CZ}\left|1\cdots0\right> = & \left|1\cdots0\right> \\\text{CZ}\left|1\cdots1\right> = & -\left|1\cdots1\right> \\\end{matrix}\)

H(qubits: Quant) Quant

Apply the Hadamard gate.

Matrix

Effect

\(\frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}\)

\(\begin{matrix}H\left|0\right> = & \frac{1}{\sqrt{2}}\left(\left|0\right> + \left|1\right>\right) \\H\left|1\right> = & \frac{1}{\sqrt{2}}\left(\left|0\right> - \left|1\right>\right)\end{matrix}\)

I(qubits: Quant) Quant

Apply the Identity gate.

Matrix

Effect

\(\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}\)

\(\begin{matrix} I\left|0\right> = & \left|0\right> \\I\left|1\right> = & \left|1\right> \end{matrix}\)

P(theta: float | Parameter, qubits: Quant | None = None) Quant | Callable[[Quant], Quant]

Apply the Phase shift gate.

Matrix

Effect

\(\begin{bmatrix} 1 & 0 \\ 0 & e^{i\theta} \end{bmatrix}\)

\(\begin{matrix} P\left|0\right> = & \left|0\right> \\P\left|1\right> = & e^{i\theta}\left|1\right> \end{matrix}\)

QFT(qubits, do_swap: bool = True)

Apply the Quantum Fourier Transform (QFT) to the given qubits.

Implements the standard recursive QFT circuit:

\[\text{QFT}\left|x\right\rangle = \frac{1}{\sqrt{N}} \sum_{k=0}^{N-1} e^{2\pi i x k / N} \left|k\right\rangle\]

where \(N = 2^n\) and \(n\) is the number of qubits.

The circuit consists of Hadamard gates and controlled phase rotations, followed by an optional SWAP network that puts the output in the standard bit-order (most-significant qubit first). Set do_swap=False when the SWAP is handled externally.

Example

from ket import *

p = Process(simulator="dense", num_qubits=4)
q = p.alloc(4)

# Initialize to |1⟩ and apply QFT
X(q[3])
QFT(q)

state = dump(q)
print(state.show())
Parameters:
  • qubits – The register to apply the QFT to. Must have at least 1 qubit.

  • do_swap – If True (default), applies the qubit-reversal SWAP network at the end so the output is in standard bit order.

RBS(theta: float, qubits_a: Quant | None = None, qubits_b: Quant | None = None) tuple[Quant, Quant] | Callable[[Quant, Quant], tuple[Quant, Quant]]

Apply the Reconfigurable Beam Splitter (RBS) gate.

Matrix

\(\begin{bmatrix}1 & 0 & 0 & 0 \\0 & \cos\theta & \sin\theta & 0 \\0 & -\sin\theta & \cos\theta & 0 \\0 & 0 & 0 & 1\end{bmatrix}\)

RX(theta: float | Parameter, qubits: Quant | None = None) Quant | Callable[[Quant], Quant]

Apply the X-axes rotation gate.

Matrix

Effect

\(\begin{bmatrix}\cos(\theta/2) & -i\sin(\theta/2) \\ -i\sin(\theta/2) & \cos(\theta/2)\end{bmatrix}\)

\(\begin{matrix}R_x\left|0\right> = & \cos(\theta/2)\left|0\right> - i\sin(\theta/2)\left|1\right> \\R_x\left|1\right> = & -i\sin(\theta/2)\left|0\right> + \cos(\theta/2)\left|1\right>\end{matrix}\)

RXX(theta: float, qubits_a: Quant | None = None, qubits_b: Quant | None = None) tuple[Quant, Quant] | Callable[[Quant, Quant], tuple[Quant, Quant]]

Apply the XX rotation gate.

Matrix

\(\begin{bmatrix} \cos\frac{\theta}{2} & 0 & 0 & -i\sin\frac{\theta}{2} \\0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} & 0 \\0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} & 0 \\-i\sin\frac{\theta}{2} & 0 & 0 & \cos\frac{\theta}{2} \end{bmatrix}\)

RY(theta: float | Parameter, qubits: Quant | None = None) Quant | Callable[[Quant], Quant]

Apply the Y-axes rotation gate.

Matrix

Effect

\(\begin{bmatrix}\cos(\theta/2) & -\sin(\theta/2) \\ \sin(\theta/2) & \cos(\theta/2)\end{bmatrix}\)

\(\begin{matrix}R_y\left|0\right> = & \cos(\theta/2)\left|0\right> + \sin(\theta/2)\left|1\right> \\R_y\left|1\right> = & -\sin(\theta/2)\left|0\right> + \cos(\theta/2)\left|1\right>\end{matrix}\)

RYY(theta: float, qubits_a: Quant | None = None, qubits_b: Quant | None = None) tuple[Quant, Quant] | Callable[[Quant, Quant], tuple[Quant, Quant]]

Apply the RYY rotation gate.

Matrix

\(\begin{bmatrix}\cos\frac{\theta}{2} & 0 & 0 & i\sin\frac{\theta}{2} \\0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} & 0 \\0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} & 0 \\i\sin\frac{\theta}{2} & 0 & 0 & \cos\frac{\theta}{2}\end{bmatrix}\)

RZ(theta: float | Parameter, qubits: Quant | None = None) Quant | Callable[[Quant], Quant]

Apply the Z-axes rotation gate.

Matrix

Effect

\(\begin{bmatrix} e^{-i\theta/2} & 0 \\ 0 & e^{i\theta/2} \end{bmatrix}\)

\(\begin{matrix} R_z\left|0\right> = & e^{-i\theta/2}\left|0\right> \\R_z\left|1\right> = & e^{i\theta/2}\left|1\right> \end{matrix}\)

RZZ(theta: float, qubits_a: Quant | None = None, qubits_b: Quant | None = None) tuple[Quant, Quant] | Callable[[Quant, Quant], tuple[Quant, Quant]]

Apply the ZZ rotation gate.

Matrix

\(\begin{bmatrix} e^{-i \frac{\theta}{2}} & 0 & 0 & 0 \\0 & e^{i \frac{\theta}{2}} & 0 & 0\\ 0 & 0 & e^{i \frac{\theta}{2}} & 0 \\0 & 0 & 0 & e^{-i \frac{\theta}{2}} \end{bmatrix}\)

S(qubits: Quant) Quant

Apply the S gate.

Matrix

Effect

\(\begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix}\)

\(\begin{matrix} S\left|0\right> = & \left|0\right> \\S\left|1\right> = & i\left|1\right> \end{matrix}\)

SD(qubits: Quant) Quant

Apply the S-dagger gate.

Matrix

Effect

\(\begin{bmatrix} 1 & 0 \\ 0 & -i \end{bmatrix}\)

\(\begin{matrix} S^\dagger\left|0\right> = & \left|0\right> \\S^\dagger\left|1\right> = & -i\left|1\right> \end{matrix}\)

SWAP(qubit_a: Quant, qubit_b: Quant) tuple[Quant, Quant]

Apply the SWAP gate.

Matrix

Effect

\(\begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1\end{bmatrix}\)

\(\begin{matrix}\text{SWAP}\left|00\right> = & \left|00\right> \\\text{SWAP}\left|01\right> = & \left|10\right> \\\text{SWAP}\left|10\right> = & \left|01\right> \\\text{SWAP}\left|11\right> = & \left|11\right> \\\text{SWAP}\left|\text{a}\right>\left|\text{b}\right> =& \left|\text{b}\right> \left|\text{a}\right>\end{matrix}\)

SX(qubits: Quant) Quant

Apply the Sqrt X gate.

Matrix

Effect

\(\frac{1}{2} \begin{bmatrix} 1+i & 1-i \\ 1-i & 1+i \end{bmatrix}\)

\(\begin{matrix}\sqrt{X}\left|0\right> = & \frac{1}{2} ((1+i)\left|0\right> + (1-i)\left|1\right>) \\\sqrt{X}\left|1\right> = & \frac{1}{2} ((1-i)\left|0\right> + (1+i)\left|1\right>)\end{matrix}\)

T(qubits: Quant) Quant

Apply the T gate.

Matrix

Effect

\(\begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/4} \end{bmatrix}\)

\(\begin{matrix} T\left|0\right> = & \left|0\right> \\T\left|1\right> = & e^{i\pi/4}\left|1\right> \end{matrix}\)

TD(qubits: Quant) Quant

Apply the T-dagger gate.

Matrix

Effect

\(\begin{bmatrix} 1 & 0 \\ 0 & e^{-i\pi/4} \end{bmatrix}\)

\(\begin{matrix} T^\dagger\left|0\right> = & \left|0\right> \\T^\dagger\left|1\right> = & e^{-i\pi/4}\left|1\right> \end{matrix}\)

U3(theta: float, phi: float, lambda_: float, qubit: Quant | None = None) Quant | Callable[[Quant], Quant]

Apply the U3 gate.

Matrix

Effect

\(\begin{bmatrix}e^{-i (\phi + \lambda)/2} \cos(\theta/2) & -e^{-i (\phi - \lambda)/2} \sin(\theta/2) \\e^{i (\phi - \lambda)/2} \sin(\theta/2) & e^{i (\phi + \lambda)/2} \cos(\theta/2)\end{bmatrix}\)

\(\begin{matrix}U3\left|0\right> = & e^{-i (\phi + \lambda)/2} \cos(\theta/2)\left|0\right>+ e^{i (\phi - \lambda)/2} \sin(\theta/2) \left|1\right> \\U3\left|1\right> = & -e^{-i (\phi - \lambda)/2} \sin(\theta/2)\left|0\right>+ e^{i (\phi + \lambda)/2} \cos(\theta/2)\left|1\right> \\\end{matrix}\)

X(qubits: Quant) Quant

Apply the Pauli X gate.

Matrix

Effect

\(\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}\)

\(\begin{matrix} X\left|0\right> = & \left|1\right> \\X\left|1\right> = & \left|0\right> \end{matrix}\)

Y(qubits: Quant) Quant

Apply the Pauli Y gate.

Matrix

Effect

\(\begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}\)

\(\begin{matrix} Y\left|0\right> = & i\left|1\right> \\Y\left|1\right> = & -i\left|0\right> \end{matrix}\)

Z(qubits: Quant) Quant

Apply the Pauli Z gate.

Matrix

Effect

\(\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}\)

\(\begin{matrix} Z\left|0\right> = & \left|0\right> \\Z\left|1\right> = & -\left|1\right> \end{matrix}\)

evolve(hamiltonian: Hamiltonian)

Time evolution \(e^{-iHt}\) for a Hamiltonian.

For each Pauli term \(c_k P_k\) in the Hamiltonian, applies the corresponding single-step Trotter evolution gate \(e^{-i c_k P_k}\) to the qubits in that term.

Note

This implements a single Trotter step, not a full time evolution. For accurate dynamics, you may need to call evolve multiple times with a small coefficient or compose it with other techniques.

Example

from ket import *

p = Process()
q = p.alloc(2)

with obs():
    # Transverse-field Ising: -J Z0Z1 - h X0
    H_ising = -1.0 * Z(q[0]) * Z(q[1]) - 0.5 * X(q[0])

evolve(H_ising)   # one Trotter step with t encoded in the coefficients
Parameters:

hamiltonian – The Hamiltonian to simulate. The coefficient of each term serves as the rotation angle.

global_phase(theta: float) Callable[[Callable[[Any], Any]], Callable[[Any], Any]]

Apply a global phase to a quantum operation.

Decorator that adds a global phase \(e^{i\theta}\) to a quantum gate \(U\), creating the gate \(e^{i\theta}U\).

In quantum computation, global phases are overall factors that can be applied to quantum states without affecting the measurement outcomes. Mathematically, they represent rotations in the complex plane and are usually ignored because they have no observable consequences. However, in certain contexts, such as controlled quantum operations, the global phase can affect the behavior of the operation.

The addition of a global phase can be important for maintaining consistency in quantum algorithms, particularly when dealing with controlled operations where relative phase differences between different components of the quantum state can impact the computation.

Example

@global_phase(pi / 2)
def my_z_gate(qubit):
    return RZ(pi, qubit)

This example defines a custom quantum gate equivalent to a Pauli Z operation, where \(Z = e^{i\frac{\pi}{2}}R_z(\pi)\).

Parameters:

theta – The \(\theta\) angle of the global phase \(e^{i\theta}\).

is_diagonal(gate: Callable) Callable

Decorator that marks a gate as diagonal in the computational basis.

This tells the Ket runtime that the gate only adds phases to basis states without permuting them, which relaxes certain uncomputation safety checks.

Use this decorator when you have implemented a custom gate that is provably diagonal (e.g., a phase oracle or a controlled-phase network) and you want the runtime to recognize and exploit that property.

Example

from ket import *

@is_diagonal
def phase_oracle(qubits):
    # Flips the phase of the |111> state.
    ctrl(qubits[:-1], Z)(qubits[-1])
Parameters:

gate – The quantum gate function to decorate.

Returns:

A wrapped version of gate whose block is flagged as diagonal.

is_permutation(gate: Callable) Callable

Decorator that marks a gate as a permutation of computational basis states.

This tells the Ket runtime that the gate maps each basis state to exactly one other basis state (i.e., it is a classical reversible function), which enables optimizations and loosens uncomputation restrictions on auxiliary qubits written by permutations.

Use this decorator for gates that implement reversible classical logic (e.g., arithmetic adders, LUT-based oracles, swap networks).

Example

from ket import *

@is_permutation
def increment(qubits):
    # Increment a binary register modulo 2^n.
    for i, q in enumerate(qubits):
        ctrl(qubits[:i], X)(q)
Parameters:

gate – The quantum gate function to decorate.

Returns:

A wrapped version of gate whose block is flagged as a permutation.

obs()

Context manager for constructing quantum observables in symbolic form.

Inside a with obs(): block, the Pauli gate functions (X, Y, Z, I) return Pauli objects instead of applying the physical gate to the circuit. These objects can be combined with arithmetic operators to build Hamiltonian objects suitable for exp_value.

This approach mirrors the mathematical notation for observables and avoids manually constructing Pauli instances.

Example

from ket import *

p = Process()
q = p.alloc(4)

edges = [(q[0], q[1]), (q[1], q[2]), (q[2], q[3])]

with obs():
    # MaxCut QUBO cost Hamiltonian
    h_c = -0.5 * sum(1 - Z(i) * Z(j) for i, j in edges)

ev = exp_value(h_c)