Quantum Gates & Circuits
Category: Quantum Computing
Difficulty: Intermediate
Time Complexity: O(2^n * g)
Space Complexity: O(2^n)
Overview
Section titled “Overview”Quantum gates are unitary operators that transform qubit states. Just as classical logic gates (AND, OR, NOT) manipulate bits, quantum gates manipulate qubits — but with the full power of superposition and entanglement. Each gate corresponds to a unitary matrix U satisfying U†U = I, which guarantees that probabilities are preserved. A quantum circuit composes gates sequentially: the state vector |psi> is updated by matrix multiplication at each step. Single-qubit gates (H, X, Y, Z, S, T) act on individual qubits, while multi-qubit gates (CNOT, CZ, SWAP) create correlations between qubits, including entanglement. This visualization lets you build a circuit gate by gate, observe how the full 2^n-dimensional state vector evolves, and see measurement probabilities update in real time.
Try It
Section titled “Try It”- Web: Open in Eigenvue →
- Python:
import eigenvueeigenvue.show("quantum-gates")
Default Inputs
Section titled “Default Inputs”{ "numQubits": 2, "gates": [ { "gate": "H", "qubits": [ 0 ] }, { "gate": "CNOT", "qubits": [ 0, 1 ] }, { "gate": "X", "qubits": [ 1 ] }, { "gate": "H", "qubits": [ 0 ] }, { "gate": "Z", "qubits": [ 1 ] } ]}Input Examples
Section titled “Input Examples”Bell state creation
Section titled “Bell state creation”{ "numQubits": 2, "gates": [ { "gate": "H", "qubits": [ 0 ] }, { "gate": "CNOT", "qubits": [ 0, 1 ] } ]}GHZ state (3 qubits)
Section titled “GHZ state (3 qubits)”{ "numQubits": 3, "gates": [ { "gate": "H", "qubits": [ 0 ] }, { "gate": "CNOT", "qubits": [ 0, 1 ] }, { "gate": "CNOT", "qubits": [ 0, 2 ] } ]}Rotation sequence
Section titled “Rotation sequence”{ "numQubits": 1, "gates": [ { "gate": "H", "qubits": [ 0 ] }, { "gate": "T", "qubits": [ 0 ] }, { "gate": "H", "qubits": [ 0 ] }, { "gate": "T", "qubits": [ 0 ] }, { "gate": "H", "qubits": [ 0 ] } ]}Quantum teleportation circuit
Section titled “Quantum teleportation circuit”{ "numQubits": 3, "gates": [ { "gate": "H", "qubits": [ 1 ] }, { "gate": "CNOT", "qubits": [ 1, 2 ] }, { "gate": "CNOT", "qubits": [ 0, 1 ] }, { "gate": "H", "qubits": [ 0 ] } ]}SWAP via CNOTs
Section titled “SWAP via CNOTs”{ "numQubits": 2, "gates": [ { "gate": "X", "qubits": [ 0 ] }, { "gate": "CNOT", "qubits": [ 0, 1 ] }, { "gate": "CNOT", "qubits": [ 1, 0 ] }, { "gate": "CNOT", "qubits": [ 0, 1 ] } ]}Phase kickback
Section titled “Phase kickback”{ "numQubits": 2, "gates": [ { "gate": "X", "qubits": [ 1 ] }, { "gate": "H", "qubits": [ 0 ] }, { "gate": "CNOT", "qubits": [ 0, 1 ] }, { "gate": "H", "qubits": [ 0 ] } ]}Pseudocode
Section titled “Pseudocode”function applyQuantumCircuit(numQubits, gates): // 1. Initialize state vector to |0...0> stateVector = [0] * 2^numQubits stateVector[0] = 1 // all amplitude on |00...0>
// 2. Apply each gate sequentially for each gate in gates: if gate is single-qubit: U = gateMatrix(gate.name, gate.angle) for each pair of amplitudes separated by 2^target: [a, b] = [stateVector[i], stateVector[j]] stateVector[i] = U[0][0]*a + U[0][1]*b stateVector[j] = U[1][0]*a + U[1][1]*b
if gate is two-qubit (e.g., CNOT): U = gateMatrix4x4(gate.name) for each group of 4 amplitudes: apply 4x4 unitary to the subspace
// 3. Verify normalization assert sum(|stateVector[k]|^2) == 1
// 4. Compute measurement probabilities probabilities[k] = |stateVector[k]|^2 for each k return stateVector, probabilitiesPython
Section titled “Python”import numpy as np
# Standard gate matricesH = np.array([[1, 1], [1, -1]]) / np.sqrt(2)X = np.array([[0, 1], [1, 0]])Y = np.array([[0, -1j], [1j, 0]])Z = np.array([[1, 0], [0, -1]])S = np.array([[1, 0], [0, 1j]])T = np.array([[1, 0], [0, np.exp(1j * np.pi / 4)]])CNOT = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]])
def apply_single_qubit_gate(state, gate, target, n_qubits): """Apply a 2x2 gate to target qubit in an n-qubit state.""" n = len(state) result = state.copy() step = 1 << target for i in range(n): if i & step == 0: j = i | step a, b = state[i], state[j] result[i] = gate[0,0]*a + gate[0,1]*b result[j] = gate[1,0]*a + gate[1,1]*b return result
def apply_cnot(state, control, target, n_qubits): """Apply CNOT: flip target when control is |1>.""" result = state.copy() for i in range(len(state)): if (i >> control) & 1: # control is |1> j = i ^ (1 << target) # flip target result[i], result[j] = state[j], state[i] return result
def run_circuit(n_qubits, gates): state = np.zeros(2**n_qubits, dtype=complex) state[0] = 1.0 # |00...0>
for g in gates: if g['gate'] in ('H','X','Y','Z','S','T'): mat = {'H':H,'X':X,'Y':Y,'Z':Z,'S':S,'T':T}[g['gate']] state = apply_single_qubit_gate(state, mat, g['qubits'][0], n_qubits) elif g['gate'] == 'CNOT': state = apply_cnot(state, g['qubits'][0], g['qubits'][1], n_qubits)
probs = np.abs(state)**2 assert abs(sum(probs) - 1.0) < 1e-9 return state, probsJavaScript
Section titled “JavaScript”// Standard gate matrices (row-major, complex as [re, im])const H = [[[0.7071,0],[0.7071,0]],[[0.7071,0],[-0.7071,0]]];const X = [[[0,0],[1,0]],[[1,0],[0,0]]];const Z = [[[1,0],[0,0]],[[0,0],[-1,0]]];
function applySingleQubitGate(state, gate, target, nQubits) { const result = state.map(([re, im]) => [re, im]); const step = 1 << target; for (let i = 0; i < state.length; i++) { if ((i & step) === 0) { const j = i | step; const [aRe, aIm] = state[i]; const [bRe, bIm] = state[j]; // result[i] = gate[0][0]*a + gate[0][1]*b result[i] = cAdd(cMul(gate[0][0], [aRe,aIm]), cMul(gate[0][1], [bRe,bIm])); // result[j] = gate[1][0]*a + gate[1][1]*b result[j] = cAdd(cMul(gate[1][0], [aRe,aIm]), cMul(gate[1][1], [bRe,bIm])); } } return result;}
function applyCNOT(state, control, target) { const result = state.map(([re, im]) => [re, im]); for (let i = 0; i < state.length; i++) { if ((i >> control) & 1) { const j = i ^ (1 << target); result[i] = [state[j][0], state[j][1]]; result[j] = [state[i][0], state[i][1]]; } } return result;}
function runCircuit(nQubits, gates) { let state = Array.from({ length: 1 << nQubits }, (_, i) => i === 0 ? [1, 0] : [0, 0] ); for (const g of gates) { if (['H','X','Y','Z','S','T'].includes(g.gate)) { const mat = { H, X, Z }[g.gate]; state = applySingleQubitGate(state, mat, g.qubits[0], nQubits); } else if (g.gate === 'CNOT') { state = applyCNOT(state, g.qubits[0], g.qubits[1]); } } const probs = state.map(([re, im]) => re*re + im*im); return { state, probs };}
// Complex arithmetic helpersfunction cMul([aR,aI], [bR,bI]) { return [aR*bR-aI*bI, aR*bI+aI*bR]; }function cAdd([aR,aI], [bR,bI]) { return [aR+bR, aI+bI]; }Key Concepts
Section titled “Key Concepts”Quantum Gates
Section titled “Quantum Gates”Quantum gates are the building blocks of quantum computation. Each gate is a unitary transformation that acts on one or more qubits. Common single-qubit gates include Hadamard (H), Pauli-X (bit flip), Pauli-Z (phase flip), and rotation gates (Rx, Ry, Rz).
Unitary Matrices
Section titled “Unitary Matrices”Every quantum gate is represented by a unitary matrix U satisfying U†U = UU† = I. This ensures that the total probability of all measurement outcomes always sums to 1. Unitarity also means every quantum operation is reversible.
Circuit Model
Section titled “Circuit Model”The quantum circuit model represents computation as a sequence of gates applied to qubits, drawn as horizontal wires. Gates are applied left to right. The circuit model is the most common framework for designing quantum algorithms, analogous to logic circuits in classical computing.
Multi-Qubit Gates
Section titled “Multi-Qubit Gates”Multi-qubit gates act on two or more qubits simultaneously. The CNOT (controlled-NOT) gate is the most important: it flips a target qubit only when the control qubit is |1>. CNOT is essential for creating entanglement and is, together with single-qubit gates, universal for quantum computation.
Common Pitfalls
Section titled “Common Pitfalls”- Gate ordering matters: Unlike some classical operations, quantum gate order is critical. Applying H then Z produces a different result from Z then H, because matrix multiplication is not commutative. Always read circuits from left to right.
- Global phase irrelevance: Two state vectors that differ only by a global phase factor e^{iγ} (e.g., |psi> and -|psi>) are physically indistinguishable. However, relative phase between amplitudes is observable and crucial for interference effects.
- Measurement destroys superposition: Measuring a qubit collapses its state to |0> or |1> probabilistically. After measurement, the superposition is lost and the qubit is in a definite classical state. This is irreversible, unlike gate operations.
Q1: What state does applying a Hadamard gate to |0> produce?
- A) |1>
- B) (|0> + |1>) / sqrt(2)
- C) (|0> - |1>) / sqrt(2)
- D) i|1>
Show answer
Answer: B) (|0> + |1>) / sqrt(2)
The Hadamard gate maps |0> to (|0> + |1>)/sqrt(2), which is the |+> state. This creates an equal superposition with a 50/50 probability of measuring 0 or 1.
Q2: Which gate pair, when applied to |00>, creates a Bell state (maximally entangled pair)?
- A) X then Z
- B) H on qubit 0, then CNOT(0,1)
- C) H on both qubits
- D) SWAP then H
Show answer
Answer: B) H on qubit 0, then CNOT(0,1)
Applying H to the first qubit creates (|0> + |1>)/sqrt(2) on qubit 0. Then CNOT entangles the qubits: |00> + |11>) / sqrt(2). This is the Bell state |Phi+>, a maximally entangled state.
Q3: Why must quantum gates be represented by unitary matrices?
- A) To make computation faster
- B) To preserve the normalization of the state vector (total probability = 1)
- C) To ensure gates can be manufactured physically
- D) To allow classical simulation
Show answer
Answer: B) To preserve the normalization of the state vector (total probability = 1)
Unitarity (U†U = I) guarantees that the norm of the state vector is preserved. Since measurement probabilities are the squared amplitudes, this ensures probabilities always sum to 1 after any gate operation.
Further Reading
Section titled “Further Reading”- Quantum Gates — Wikipedia (reference)
- Qiskit Textbook: Single Qubit Gates (tutorial)
- Qiskit Textbook: Multiple Qubits and Entanglement (tutorial)