Multi-qubit gates act on two or more wires simultaneously. All wires passed to a multi-qubit gate must be distinct — passing the same wire twice raises DSLValidationError. Like single-qubit gates, multi-qubit gates route automatically to the exact or broad IR path depending on which decorator wraps the calling function. Parametric two-qubit gates (cry, crz) are only available in @parametric and @adaptive programs.
Gate overview
| Gate | Operation | Exact context | Compute block | Phase block |
|---|
cx | CNOT | Yes | Yes | No |
cz | Controlled-Z | Yes | No | Yes |
swap | SWAP | Yes | Yes | No |
cry | Controlled-RY(θ) | No | No | No |
crz | Controlled-RZ(θ) | No | No | No |
ccx | Toffoli (CCX) | Yes | Yes | No |
ccz | Controlled-Controlled-Z | Yes | No | Yes |
mcx | Multi-controlled X | Yes | Yes | No |
mcz | Multi-controlled Z | Yes | No | Yes |
from b01t import cx
cx(control: Wire, target: Wire) -> None
Controlled-NOT (CNOT) gate. Flips the target qubit when the control qubit is |1⟩. cx is self-inverse.
Allowed in: exact programs, compute blocks.
The target qubit wire. Must be distinct from control.
from b01t import coherent, QReg, h, cx
@coherent
def bell(a: QReg, b: QReg) -> None:
h(a[0])
cx(a[0], b[0])
prog = bell.build_exact(("a", 1), ("b", 1))
from b01t import cz
cz(control: Wire, target: Wire) -> None
Controlled-Z gate. Applies a Z gate to the target when the control is |1⟩. Equivalent to applying Z then CX, or H · CX · H on the target. cz is self-inverse and symmetric: cz(a, b) == cz(b, a).
Allowed in: exact programs, phase blocks.
The target qubit wire. Must be distinct from control.
from b01t import coherent, QReg, h, cz
from b01t import ancilla, compute, phase, uncompute, cx
@coherent
def cz_via_anc(sys: QReg) -> None:
with ancilla(1) as anc:
compute(lambda: cx(sys[0], anc[0]))
phase(lambda: cz(anc[0], sys[1]))
uncompute()
prog = cz_via_anc.build_exact(("sys", 2))
swap
from b01t import swap
swap(a: Wire, b: Wire) -> None
SWAP gate. Exchanges the states of two qubits. swap is self-inverse.
Allowed in: exact programs, compute blocks.
The second qubit wire. Must be distinct from a.
from b01t import coherent, QReg, swap
@coherent
def reverse_reg(sys: QReg) -> None:
swap(sys[0], sys[2])
prog = reverse_reg.build_exact(("sys", 3))
cry
from b01t import cry
cry(theta: float, control: Wire, target: Wire) -> None
Controlled-RY gate. Applies ry(theta) to the target when the control is |1⟩. Parametric — not in the exact gate set.
Allowed in: @parametric and @adaptive programs only.
Rotation angle in radians.
The target qubit wire. Must be distinct from control.
from b01t import parametric, QReg, cry
import math
@parametric
def conditional_rot(ctrl: QReg, tgt: QReg) -> None:
cry(math.pi / 4, ctrl[0], tgt[0])
prog = conditional_rot.build(("ctrl", 1), ("tgt", 1))
crz
from b01t import crz
crz(theta: float, control: Wire, target: Wire) -> None
Controlled-RZ gate. Applies rz(theta) to the target when the control is |1⟩. Parametric — not in the exact gate set.
Allowed in: @parametric and @adaptive programs only.
Rotation angle in radians.
The target qubit wire. Must be distinct from control.
from b01t import parametric, QReg, crz
import math
@parametric
def qaoa_zz(q: QReg) -> None:
crz(math.pi / 2, q[0], q[1])
prog = qaoa_zz.build(("q", 2))
ccx
from b01t import ccx
ccx(c0: Wire, c1: Wire, target: Wire) -> None
Toffoli gate (CCX). Flips the target qubit when both c0 and c1 are |1⟩. ccx is self-inverse and is the canonical three-qubit gate for reversible classical computation.
Allowed in: exact programs, compute blocks.
The first control qubit wire.
The second control qubit wire.
The target qubit wire. Must be distinct from c0 and c1.
from b01t import coherent, QReg, ccx
from b01t import ancilla, compute, phase, uncompute, z
@coherent
def and_gate(a: QReg, b: QReg) -> None:
with ancilla(1) as anc:
compute(lambda: ccx(a[0], b[0], anc[0]))
phase(lambda: z(anc[0]))
uncompute()
prog = and_gate.build_exact(("a", 1), ("b", 1))
ccz
from b01t import ccz
ccz(c0: Wire, c1: Wire, target: Wire) -> None
Controlled-Controlled-Z gate. Applies Z to the target when both controls are |1⟩. ccz is self-inverse and a diagonal gate.
Allowed in: exact programs, phase blocks.
The first control qubit wire.
The second control qubit wire.
The target qubit wire. Must be distinct from both controls.
from b01t import coherent, QReg, cx, ccz
from b01t import ancilla, compute, phase, uncompute
@coherent
def controlled_cz(ctrl: QReg, sys: QReg) -> None:
with ancilla(1) as anc:
compute(lambda: cx(ctrl[0], anc[0]))
phase(lambda: ccz(anc[0], sys[0], sys[1]))
uncompute()
prog = controlled_cz.build_exact(("ctrl", 1), ("sys", 2))
mcx
from b01t import mcx
mcx(controls: Sequence[Wire], target: Wire) -> None
Multi-controlled X gate. Flips the target qubit when all control qubits are |1⟩. Requires at least one control wire. mcx generalises cx (one control) and ccx (two controls) to any number of controls.
Allowed in: exact programs, compute blocks.
A sequence of one or more control qubit wires. All wires must be distinct from each other and from target.
from b01t import coherent, QReg, mcx
from b01t import ancilla, compute, phase, uncompute, z
@coherent
def multi_and(ctrl: QReg, out: QReg) -> None:
with ancilla(1) as anc:
compute(lambda: mcx(list(ctrl), anc[0]))
phase(lambda: z(anc[0]))
uncompute()
prog = multi_and.build_exact(("ctrl", 3), ("out", 1))
mcz
from b01t import mcz
mcz(controls: Sequence[Wire], target: Wire) -> None
Multi-controlled Z gate. Applies Z to the target when all control qubits are |1⟩. Requires at least one control wire. mcz is a diagonal gate.
Allowed in: exact programs, phase blocks.
A sequence of one or more control qubit wires. All wires must be distinct from each other and from target.
from b01t import coherent, QReg, mcx, mcz
from b01t import ancilla, compute, phase, uncompute
@coherent
def grover_oracle(ctrl: QReg, tgt: QReg) -> None:
with ancilla(1) as anc:
compute(lambda: mcx(list(ctrl), anc[0]))
phase(lambda: mcz([anc[0]], tgt[0]))
uncompute()
prog = grover_oracle.build_exact(("ctrl", 3), ("tgt", 1))