Portfolio record 003 · interactive project · July 2026
BLACK OPAL COMPLETION VERIFIED JUL 2026
Focus · Quantum fundamentals, circuits, noise, control, and codingPortfolio · Hana EmariCredential · Black Opal Quantum FundamentalsStatus · verified completion / applied demonstration
PROJECT 000
Interactive project
Three-qubit error correction using Qiskit concepts
A browser-based reconstruction of a three-qubit error-correction experiment,
combining circuit logic, controlled noise injection, syndrome measurement,
and interactive simulation.
RUN THE EXPERIMENTINSPECT THE CIRCUITCOMPARE OUTPUTSREVIEW THE IMPLEMENTATION
ENTRY 001
What is a qubit?
A two-state quantum system that cannot be fully described until observed
A classical bit holds one of two values: 0 or 1. A qubit is different in a fundamental way — it exists in a superposition of both states simultaneously, represented as a weighted sum of |0〉 and |1〉. The weights are complex numbers called amplitudes, and their squared magnitudes must sum to one.
The state cannot be read directly. Measurement collapses the superposition to a definite outcome — 0 or 1 — with probability equal to the squared amplitude. Every measurement is destructive. The original superposition is gone.
FIG. 1.1 — The Bloch sphere represents the full state space of a single qubit. Rx and Rz gates rotate the state vector around the X and Z axes respectively. Noise is an unintended rotation.
In Qiskit, the Statevector class stores this exactly. |0〉 is [1+0j, 0j]. |1〉 is [0j, 1+0j]. Initializing to a specific state at the start of a circuit means telling the simulator which point on the sphere to begin from.
# Basis states defined as complex vectors
zero = Statevector(np.array([1.0 + 0j, 0j]))
one = Statevector(np.array([0j, 1.0 + 0j]))
# 5-qubit circuit: 3 data + 2 ancilla
qc = QuantumCircuit(5, 5)
qc.initialize(states[0], 0) # data qubit q0
qc.initialize(states[1], 1) # data qubit q1
qc.initialize(states[2], 2) # data qubit q2
ENTRY 002
Why noise matters
Unintended rotations shift the qubit off its intended state
Real quantum hardware is noisy. External magnetic fields, temperature fluctuations, stray photons — each pushes the qubit’s state slightly off course. In the Bloch sphere picture, noise is an unintended rotation: a small Rx or Rz operation that nobody asked for.
The consequence is probabilistic. A qubit initialized to |0〉 that has been rotated by angle θ will now measure as |1〉 with probability sin²(θ/2). A 45° rotation gives approximately a 15% error rate. A 90° rotation produces a coin flip.
Noise cannot be seen until measurement — and measurement destroys the state. This is the core difficulty. Classical error correction assumes you can read and compare bits. Quantum mechanics forbids that assumption entirely.
FIG. 2.1 — Error probability as a function of rotation angle. P(error) = sin²(θ/2). Even small unintended rotations accumulate across a multi-gate computation.
The solution is not to prevent noise — that is an engineering problem that has not been fully solved. The solution is to detect and correct errors after they occur, without ever directly measuring the corrupted qubit. This is quantum error correction.
ENTRY 003
Injecting random errors
The corrupt() function models what hardware does accidentally
To test an error correction system, one needs a reliable source of errors. In this experiment, noise is simulated by selecting a random qubit, a random rotation plane (YZ via Rx, or XY via Rz), and a random angle between 0° and 90°.
The corrupt() function builds a single-qubit circuit containing only the rotation gate, converts it to a unitary operator via Qiskit’s Operator class, and evolves the qubit’s statevector through it. The corrupted state is then passed into the full circuit as the initialization for that qubit.
def corrupt(angle_deg, q, plane):
qc_err = QuantumCircuit(1)
if plane == 'yz':
qc_err.rx(angle_deg * np.pi / 180, 0) # Rx rotationelse:
qc_err.rz(angle_deg * np.pi / 180, 0) # Rz rotationreturn q.evolve(Operator(qc_err))
# Random noise parameters chosen before each run:
which_qubit = rng.integers(0, 3) # which of q0, q1, q2
which_plane = rng.integers(0, 2) # YZ or XY plane
angle_deg = rng.uniform(0.0, 90.0) # continuous angle
The noise parameters are sampled fresh for every run. This means neither the experimenter nor the error correction system knows in advance which qubit was corrupted or by how much. The correction must be inferred entirely from the syndrome measurement.
→ Part 3 of the notebook runs N = 20–40 randomized rounds, cycling between |0〉³ and |1〉³ initial states. Each round samples new noise parameters. This stress-tests the correction logic across the full range of possible error scenarios.
ENTRY 004
Building a correction system
Syndrome measurement identifies the error without collapsing the data
The 3-qubit bit-flip code uses five qubits: three data qubits (q0, q1, q2) and two ancilla qubits (q3, q4). The ancilla qubits are used only for measurement — they are reset and never carry computational information.
The key operation is the CNOT gate. Applied from a data qubit to an ancilla qubit, it flips the ancilla if and only if the data qubit is |1〉. By applying two CNOTs from different data qubits to the same ancilla, the ancilla ends up encoding the parity of that pair — without revealing either individual value.
FIG. 4.1 — The QEC circuit. Four CNOT gates entangle the ancilla qubits with pairs of data qubits. Ancilla measurement produces a 2-bit syndrome. Three CCX (Toffoli) gates then conditionally flip the identified qubit back.
anc0 (q0⊕q1)
anc1 (q1⊕q2)
interpretation
correction
0
0
no error detected
none
1
1
q1 flipped
X on q1
1
0
q0 flipped
X on q0
0
1
q2 flipped
X on q2
Table 4.1 — Syndrome decoding. Each 2-bit pattern uniquely identifies one error location. The data qubits are never measured during this process.
The XGate().control(2) instruction creates a Toffoli gate — a NOT gate controlled by two input qubits simultaneously. Three such gates handle the three possible error locations. The ancilla qubits are reset to |0〉 after correction before the final data readout.
ENTRY 005
Experimental results
Run the simulation. Record the outcome.
The following reproduces the core experiment from the notebook. Select a qubit, noise plane, initial state, and corruption angle, then record an observation. Each run samples 1024 shots — matching the notebook’s sim.run(qc, shots=1024) calls.
Experiment 005 — Active
45°
Without error correction — raw noisy output
With QEC — syndrome detected & corrected
→ The notebook’s Part 3 runs 20–40 rounds of this experiment with fresh random noise each time, alternating between |0〉³ and |1〉³. The QEC circuit recovers the correct state in nearly every round regardless of which qubit was targeted.
CREDENTIAL 007
Verified learning
Black Opal Quantum Fundamentals
I completed the Black Opal Quantum Fundamentals program issued by Q-CTRL on July 6, 2026. The credential supports the concepts demonstrated throughout this portfolio page.