Quantum Gates
A reference for the quantum gates used in qcfront — what they do mathematically and when to use them. For how gates map to physical hardware operations (microwave pulses, lasers, etc.), see GatePhysics.md.
All gates are available in roqoqo as roqoqo::operations::*.
Qubit Basics
A qubit has two basis states: |0⟩ and |1⟩. A general qubit state is α|0⟩ + β|1⟩ where α and β are complex numbers with |α|² + |β|² = 1. |α|² is the probability of measuring 0, |β|² of measuring 1.
The Bloch sphere visualizes a qubit as a point on a unit sphere:
- |0⟩ is the north pole
- |1⟩ is the south pole
- |+⟩ = (|0⟩+|1⟩)/√2 is on the equator
Gates are rotations and reflections on this sphere.
Bloch Sphere
Open bloch.html for an interactive 3D visualization. Drag to rotate, scroll to zoom, apply gates to see how they move the state vector.
- Z axis: |0⟩ (north) ↔ |1⟩ (south). Rz rotates around this axis.
- X axis: |+⟩ ↔ |−⟩. Rx rotates around this axis.
- Y axis: |+i⟩ ↔ |−i⟩. Ry rotates around this axis.
- Hadamard: reflects through the XZ plane (swaps Z and X axes).
Single-Qubit Gates
Pauli Gates
PauliX (X gate, NOT gate, bit-flip)
Flips the qubit: , . Like a classical NOT gate. On the Bloch sphere: 180° rotation around X.
#![allow(unused)] fn main() { circuit += PauliX::new(0); // flip qubit 0 }
PauliY (Y gate)
Flips the qubit and adds a phase: , . 180° rotation around Y axis. Rarely used directly; appears in decompositions.
PauliZ (Z gate, phase-flip)
Doesn't change measurement probabilities — only flips the phase of |1⟩. , . 180° rotation around Z.
Key insight: Z does nothing to basis states individually (they're eigenstates). It matters in superposition: .
Hadamard Gate
Hadamard (H gate)
Creates superposition from a basis state: , .
The most important gate in quantum computing — almost every algorithm starts with H on all qubits. (self-inverse).
#![allow(unused)] fn main() { // Create equal superposition over all 3-qubit states for q in 0..3 { circuit += Hadamard::new(q); } }
Used in: Grover (initialization), Shor/QPE (counting register), Deutsch-Jozsa, Bernstein-Vazirani, teleportation.
Rotation Gates
RotateX(θ), RotateY(θ), RotateZ(θ)
Rotate the qubit by angle θ around the X, Y, or Z axis of the Bloch sphere. These are the continuous-parameter gates — any single-qubit gate can be decomposed into a sequence of rotations.
changes amplitudes (measurement probabilities). changes only phases (no effect on probabilities). This is why Möttönen state preparation uses for amplitude trees and for phase trees.
How rotations move states on the Bloch sphere
Try these in bloch.html: start from |0⟩ and apply gates.
Key intuition:
- Ry(θ) changes how much |0⟩ vs |1⟩ — it moves the state between the poles. This controls measurement probabilities. Ry(π/2) takes |0⟩ → |+⟩ → |1⟩ → |−⟩ → |0⟩.
- Rz(θ) changes the phase between |0⟩ and |1⟩ without changing probabilities. It spins the state around the equator. Rz(π/2) takes |+⟩ → |+i⟩ → |−⟩ → |−i⟩ → |+⟩.
- Rx(θ) is like Ry but in the Z-Y plane.
This is why Möttönen state preparation uses Ry for amplitudes (setting probabilities) and Rz for phases (setting interference patterns).
Common rotation angles
| Angle | effect | effect |
|---|---|---|
| Identity | Identity | |
| Slight tilt toward equator | 45° phase rotation | |
| (equal superposition) | ||
| (full flip) | (like Z) | |
| Back to start (with phase) | Back to start (with phase) |
Note: is the rotation angle, but the state-vector coefficients use (half-angle). produces .
Special cases:
- (same as X up to global phase)
#![allow(unused)] fn main() { use qoqo_calculator::CalculatorFloat; // Rotate qubit 0 by π/4 around Y axis: tilt toward equator circuit += RotateY::new(0, CalculatorFloat::Float(std::f64::consts::PI / 4.0)); // Rotate qubit 1 by π/2 around Z axis: add 90° relative phase circuit += RotateZ::new(1, CalculatorFloat::Float(std::f64::consts::FRAC_PI_2)); }
Used in: State preparation (Möttönen decomposition uses Ry and Rz trees).
Phase Gates
SGate (√Z, phase gate)
Adds a phase to |1⟩. .
TGate (π/8 gate)
Adds a phase to |1⟩. . Important for universal gate sets and fault-tolerant quantum computing (T gate is the expensive one to implement with error correction).
PhaseShiftGate1(θ)
General phase shift. , , .
Two-Qubit Gates
CNOT (Controlled-NOT, CX)
Flips the target qubit if the control qubit is : . The fundamental entangling gate.
#![allow(unused)] fn main() { circuit += CNOT::new(0, 1); // control=0, target=1 }
Bell state creation: then creates . This is the "hello world" of entanglement.
Used in: Everything — Bell states, teleportation, Grover diffusion, QPE controlled unitaries, state preparation (Möttönen decomposition), error correction.
ControlledPauliZ (CZ)
Phase-flips only . Symmetric: . .
#![allow(unused)] fn main() { circuit += ControlledPauliZ::new(0, 1); }
Used in: Grover phase oracle (multi-CZ marks solutions).
SWAP
Exchanges two qubit states: . Built from 3 CNOTs: .
Used in: Shor (controlled modular multiplication swaps work qubits).
Three-Qubit Gates
Toffoli (CCX, CCNOT)
Flips the target only when both controls are . Classical AND gate made reversible. Universal for classical computation.
#![allow(unused)] fn main() { // roqoqo convention: first arg is TARGET circuit += Toffoli::new(2, 0, 1); // target=2, ctrl1=0, ctrl2=1 }
⚠️ roqoqo convention: Toffoli::new(target, control_1, control_2) —
the first argument is the target, not a control. This differs from
some other frameworks.
Used in: SAT oracle (clause evaluation), modular arithmetic.
ControlledControlledPauliZ (CCZ)
Phase-flips only . Symmetric in all three qubits. .
Used in: Multi-target Grover oracle (marks multiple solutions).
Composite Operations
QFT (Quantum Fourier Transform)
Not a single gate but a built-in roqoqo operation that emits the full QFT circuit (Hadamards + controlled phase rotations + swaps).
#![allow(unused)] fn main() { let qubits = vec![0, 1, 2, 3]; circuit += QFT::new(qubits, true, true); // inverse=true, swap=true }
Used in: Shor/QPE (inverse QFT extracts phase from counting register).
MeasureQubit
Collapses a qubit to |0⟩ or |1⟩ and records the classical result. Irreversible — destroys superposition.
#![allow(unused)] fn main() { circuit += MeasureQubit::new(0, "result".to_string(), 0); // qubit register_name bit_index }
PragmaGetStateVector
QuEST-specific: extracts the full state vector without measurement. Deterministic (no collapse). Used for verification/debugging.
#![allow(unused)] fn main() { circuit += DefinitionComplex::new("sv".to_string(), dim, true); circuit += PragmaGetStateVector::new("sv".to_string(), None); }
Ancilla Qubits
An ancilla (Latin: "servant") is a helper qubit added to a circuit that doesn't hold input or output data. Ancillas serve as scratch space for computations that can't be done directly on the data qubits.
Why ancillas are needed
Quantum gates are reversible — every gate has an inverse. But many useful operations (like AND, OR, multi-controlled gates) are irreversible classically. To make them reversible for a quantum circuit, we store intermediate results in ancilla qubits and uncompute them afterward.
Example: a 5-qubit controlled-Z can't be built from 1- and 2-qubit gates alone. The V-chain decomposition uses 3 ancilla qubits as a "Toffoli ladder" to cascade the AND of controls:
controls: ─●──●─────────────────●──●─
│ │ │ │
├──┤ ├──┤
controls: ─●──┼──●──────────●──┼──●─
│ │ │ │
ancilla₀: ───⊕──●──────────●──⊕─── (back to |0⟩)
│ │ │ │
ancilla₁: ──────⊕──●────●──⊕────── (back to |0⟩)
│ │
ancilla₂: ─────────⊕─CZ─⊕──────── (back to |0⟩)
│
target: ────────────●──────────── (phase flipped)
forward ↑ reverse
pass gate pass
The golden rule: clean up after yourself
Ancillas must be returned to |0⟩ after use. If an ancilla is left entangled with the data qubits, subsequent operations (like the diffuser in Grover's algorithm) will act on the wrong subspace, silently producing wrong results.
The standard pattern is compute → use → uncompute:
- Compute: fill ancillas with intermediate results
- Use: apply the target operation (e.g., phase flip)
- Uncompute: run the compute steps in reverse to erase ancillas
Since every quantum gate is its own inverse or has a known inverse, uncomputation is always possible — just replay the gates backward.
Common uses in qcfront
| Where | Ancilla purpose | Count |
|---|---|---|
build_multi_cz | Toffoli V-chain for n-qubit CZ | max(0, n−2) |
build_multi_cx | Toffoli V-chain for n-qubit CNOT | max(0, n−2) |
CnfOracle | Clause evaluation + MCZ/MCX scratch | c + max(mcx, mcz) |
| Grover diffuser | Shares MCZ pattern with oracle | max(0, n−2) |
Ancilla vs workspace vs scratch
These terms are used interchangeably in the literature. In qcfront:
- ancilla = any non-data qubit
- The Oracle trait's
num_ancillas()reports total scratch needed - The driver allocates ancillas and passes them via
apply()
Gate Universality
Any quantum computation can be built from:
- — universal gate set (discrete)
- — universal gate set (continuous)
qcfront's state preparation uses . The algorithms use for clarity.
Quick Reference
| Gate | Qubits | roqoqo | Effect |
|---|---|---|---|
| X | 1 | PauliX | Bit flip |
| Y | 1 | PauliY | Bit + phase flip |
| Z | 1 | PauliZ | Phase flip |
| H | 1 | Hadamard | Create superposition |
| S | 1 | SGate | π/2 phase |
| T | 1 | TGate | π/4 phase |
| Ry(θ) | 1 | RotateY | Y-axis rotation |
| Rz(θ) | 1 | RotateZ | Z-axis rotation |
| CNOT | 2 | CNOT | Controlled NOT |
| CZ | 2 | ControlledPauliZ | Controlled phase |
| SWAP | 2 | SWAP | Exchange qubits |
| Toffoli | 3 | Toffoli | Doubly-controlled NOT |
| CCZ | 3 | ControlledControlledPauliZ | Doubly-controlled phase |