Skip to content

Commit 2f047c9

Browse files
author
Stephen Shao
committed
Updated mathematical concepts as comments to examples
1 parent 130c687 commit 2f047c9

35 files changed

+3327
-212
lines changed

examples/module1_fundamentals/01_classical_vs_quantum_bits.py

Lines changed: 186 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,38 @@
2727

2828

2929
def demonstrate_classical_bits():
30-
"""Demonstrate classical bit behavior and limitations."""
30+
"""
31+
Demonstrate classical bit behavior and limitations.
32+
33+
Mathematical Foundation:
34+
------------------------
35+
A classical bit is the fundamental unit of classical information theory.
36+
It can exist in exactly one of two states at any given time:
37+
- State 0: represents "false" or "off"
38+
- State 1: represents "true" or "on"
39+
40+
Mathematically, a classical bit can be represented as:
41+
- b ∈ {0, 1}
42+
43+
For n classical bits, there are 2^n possible distinct states,
44+
but the system can only be in ONE of these states at a time.
45+
For example, 8 bits (1 byte) can represent 2^8 = 256 different values.
46+
47+
Key Limitations:
48+
---------------
49+
1. Binary nature: only two discrete states possible
50+
2. No superposition: cannot be "partially 0 and partially 1"
51+
3. Deterministic: reading the bit doesn't change its state
52+
4. No entanglement: bits are independent of each other
53+
54+
Returns:
55+
list: A classical byte (8 bits) as a demonstration
56+
"""
3157
print("=== CLASSICAL BITS ===")
3258
print()
3359

34-
# Classical bit can only be 0 or 1
60+
# Classical bit can only be 0 or 1 - this is deterministic
61+
# Unlike quantum bits, there is no probability involved
3562
classical_bit = 0
3663
print(f"Classical bit value: {classical_bit}")
3764
print("Possible states: 0 or 1")
@@ -41,7 +68,9 @@ def demonstrate_classical_bits():
4168
print("- Independent: multiple bits don't influence each other")
4269
print()
4370

44-
# Multiple classical bits
71+
# Multiple classical bits store information in binary
72+
# Each bit position represents a power of 2: 2^0, 2^1, 2^2, ..., 2^7
73+
# Total value = Σ(bit_i × 2^i) for i from 0 to 7
4574
classical_byte = [0, 1, 1, 0, 1, 0, 0, 1]
4675
print(f"Classical byte: {classical_byte}")
4776
print(
@@ -53,64 +82,159 @@ def demonstrate_classical_bits():
5382

5483

5584
def demonstrate_quantum_bits():
56-
"""Demonstrate quantum bit (qubit) behavior and capabilities."""
85+
"""
86+
Demonstrate quantum bit (qubit) behavior and capabilities.
87+
88+
Mathematical Foundation:
89+
------------------------
90+
A qubit is the fundamental unit of quantum information. Unlike classical bits,
91+
a qubit can exist in a superposition of states |0⟩ and |1⟩.
92+
93+
General qubit state representation:
94+
|ψ⟩ = α|0⟩ + β|1⟩
95+
96+
where:
97+
- |ψ⟩ (psi) is the quantum state vector (using Dirac "ket" notation)
98+
- α (alpha) is the complex probability amplitude for state |0⟩
99+
- β (beta) is the complex probability amplitude for state |1⟩
100+
- α, β ∈ ℂ (complex numbers)
101+
102+
Normalization Constraint:
103+
-------------------------
104+
The total probability must equal 1, so:
105+
|α|² + |β|² = 1
106+
107+
where |α|² is the probability of measuring 0, and |β|² is the probability of measuring 1.
108+
109+
Important Quantum States:
110+
-------------------------
111+
1. |0⟩ = [1, 0]ᵀ - computational basis state (like classical 0)
112+
2. |1⟩ = [0, 1]ᵀ - computational basis state (like classical 1)
113+
3. |+⟩ = (|0⟩ + |1⟩)/√2 - equal superposition (50% chance of 0 or 1)
114+
4. |-⟩ = (|0⟩ - |1⟩)/√2 - equal superposition with negative phase
115+
5. |i⟩ = (|0⟩ + i|1⟩)/√2 - superposition with imaginary phase
116+
117+
The factor 1/√2 ensures normalization: (1/√2)² + (1/√2)² = 1/2 + 1/2 = 1
118+
119+
Returns:
120+
dict: Dictionary of quantum circuits demonstrating different qubit states
121+
"""
57122
print("=== QUANTUM BITS (QUBITS) ===")
58123
print()
59124

60125
# Create quantum circuits for different qubit states
61126
circuits = {}
62127

63-
# |0⟩ state (classical-like)
128+
# |0⟩ state (computational basis state)
129+
# Statevector: [1, 0]ᵀ means 100% probability of measuring 0
130+
# This is equivalent to a classical bit with value 0
64131
qc_0 = QuantumCircuit(1)
65132
circuits["|0⟩"] = qc_0
66133

67-
# |1⟩ state (classical-like)
134+
# |1⟩ state (computational basis state)
135+
# The X gate is a quantum NOT gate that flips |0⟩ to |1⟩
136+
# Matrix representation: X = [[0, 1], [1, 0]]
137+
# X|0⟩ = |1⟩, giving statevector [0, 1]ᵀ (100% probability of measuring 1)
68138
qc_1 = QuantumCircuit(1)
69139
qc_1.x(0) # Apply X gate to flip |0⟩ to |1⟩
70140
circuits["|1⟩"] = qc_1
71141

72-
# |+⟩ state (superposition)
142+
# |+⟩ state (equal superposition - positive phase)
143+
# The Hadamard gate (H) creates equal superposition from |0⟩
144+
# H|0⟩ = (|0⟩ + |1⟩)/√2
145+
# Matrix: H = (1/√2)[[1, 1], [1, -1]]
146+
# Measurement gives 50% chance of 0 and 50% chance of 1
73147
qc_plus = QuantumCircuit(1)
74148
qc_plus.h(0) # Apply Hadamard gate to create superposition
75149
circuits["|+⟩ = (|0⟩ + |1⟩)/√2"] = qc_plus
76150

77-
# |-⟩ state (superposition)
151+
# |-⟩ state (equal superposition - negative phase)
152+
# Created by X then H: H(X|0⟩) = H|1⟩ = (|0⟩ - |1⟩)/√2
153+
# The minus sign is a relative phase between |0⟩ and |1⟩
154+
# Measurement still gives 50/50, but phase matters for interference
78155
qc_minus = QuantumCircuit(1)
79156
qc_minus.x(0)
80157
qc_minus.h(0)
81158
circuits["|-⟩ = (|0⟩ - |1⟩)/√2"] = qc_minus
82159

83-
# |i⟩ state (complex superposition)
160+
# |i⟩ state (complex superposition with imaginary phase)
161+
# The S gate adds a 90° phase rotation
162+
# S = [[1, 0], [0, i]] where i = √(-1)
163+
# S(H|0⟩) = S((|0⟩ + |1⟩)/√2) = (|0⟩ + i|1⟩)/√2
164+
# The 'i' represents a complex phase - a purely quantum property!
84165
qc_i = QuantumCircuit(1)
85166
qc_i.h(0)
86-
qc_i.s(0) # Apply S gate to add phase
167+
qc_i.s(0) # Apply S gate to add π/2 phase
87168
circuits["|i⟩ = (|0⟩ + i|1⟩)/√2"] = qc_i
88169

89170
return circuits
90171

91172

92173
def visualize_qubit_states(circuits, verbose=False):
93-
"""Visualize qubit states on the Bloch sphere."""
174+
"""
175+
Visualize qubit states on the Bloch sphere.
176+
177+
Mathematical Foundation - The Bloch Sphere:
178+
-------------------------------------------
179+
The Bloch sphere is a geometrical representation of a single qubit state.
180+
Any pure qubit state can be represented as a point on the surface of a unit sphere.
181+
182+
Parametric representation:
183+
|ψ⟩ = cos(θ/2)|0⟩ + e^(iφ) sin(θ/2)|1⟩
184+
185+
where:
186+
- θ (theta) ∈ [0, π] is the polar angle (latitude)
187+
- φ (phi) ∈ [0, 2π) is the azimuthal angle (longitude)
188+
189+
Geometric Interpretation:
190+
-------------------------
191+
- North pole (θ=0): |0⟩ state
192+
- South pole (θ=π): |1⟩ state
193+
- Equator (θ=π/2): Equal superposition states like |+⟩, |-⟩, |i⟩, etc.
194+
- X-axis (θ=π/2, φ=0): |+⟩ = (|0⟩ + |1⟩)/√2
195+
- Y-axis (θ=π/2, φ=π/2): |i⟩ = (|0⟩ + i|1⟩)/√2
196+
- Z-axis: measures computational basis (|0⟩/|1⟩)
197+
198+
Probability Calculation:
199+
------------------------
200+
For a state |ψ⟩ = α|0⟩ + β|1⟩:
201+
- Probability of measuring |0⟩: P(0) = |α|² = (α × α*)
202+
- Probability of measuring |1⟩: P(1) = |β|² = (β × β*)
203+
where α* denotes the complex conjugate of α
204+
205+
Note: P(0) + P(1) = 1 (normalization)
206+
207+
Args:
208+
circuits (dict): Dictionary of quantum circuits to visualize
209+
verbose (bool): If True, print detailed state information
210+
211+
Returns:
212+
dict: Dictionary of statevectors for each circuit
213+
"""
94214
print("=== QUBIT STATE VISUALIZATION ===")
95215
print()
96216

97217
states = {}
98218
bloch_figures = []
99219

100220
for i, (label, circuit) in enumerate(circuits.items()):
101-
# Get the statevector
221+
# Get the statevector representation of the quantum state
222+
# Statevector is a complex vector [α, β] where |ψ⟩ = α|0⟩ + β|1⟩
102223
state = Statevector.from_instruction(circuit)
103224
states[label] = state
104225

105226
if verbose:
106227
print(f"State {label}:")
107228
print(f" Statevector: {state}")
229+
# Calculate measurement probabilities using Born rule: P = |amplitude|²
230+
# This is computed as amplitude × complex_conjugate(amplitude)
108231
print(
109232
f" Probabilities: |0⟩: {abs(state[0])**2:.3f}, |1⟩: {abs(state[1])**2:.3f}"
110233
)
111234
print()
112235

113236
# Plot individual Bloch sphere (Qiskit 2.x doesn't support ax parameter)
237+
# The Bloch sphere visualization shows where this state lies on the unit sphere
114238
try:
115239
bloch_fig = plot_bloch_multivector(state, title=f"Qubit State: {label}")
116240
bloch_figures.append(bloch_fig)
@@ -130,7 +254,49 @@ def visualize_qubit_states(circuits, verbose=False):
130254

131255

132256
def measure_qubits(circuits, shots=1000):
133-
"""Demonstrate measurement of different qubit states."""
257+
"""
258+
Demonstrate measurement of different qubit states.
259+
260+
Mathematical Foundation - Quantum Measurement (Born Rule):
261+
----------------------------------------------------------
262+
When we measure a qubit in state |ψ⟩ = α|0⟩ + β|1⟩ in the computational basis:
263+
264+
- Probability of outcome 0: P(0) = |α|²
265+
- Probability of outcome 1: P(1) = |β|²
266+
267+
where |α|² means α × α* (amplitude times its complex conjugate).
268+
269+
Key Properties of Quantum Measurement:
270+
--------------------------------------
271+
1. Probabilistic: Cannot predict individual outcome, only probabilities
272+
2. Irreversible: Measurement destroys the superposition (wave function collapse)
273+
3. Post-measurement state: After measuring outcome k, state becomes |k⟩
274+
4. Born Rule: Probability is the squared magnitude of the amplitude
275+
276+
Why Multiple Shots?
277+
-------------------
278+
Since measurement is probabilistic, we need many repetitions (shots) to
279+
estimate the true probability distribution. With N shots:
280+
- Expected count for outcome k ≈ N × P(k)
281+
- Statistical error decreases as 1/√N
282+
283+
Example: For |+⟩ = (|0⟩ + |1⟩)/√2:
284+
- |α|² = |(1/√2)|² = 1/2 = 50% chance of measuring 0
285+
- |β|² = |(1/√2)|² = 1/2 = 50% chance of measuring 1
286+
- With 1000 shots, expect ~500 zeros and ~500 ones
287+
288+
Measurement Basis:
289+
------------------
290+
This function measures in the computational (Z) basis {|0⟩, |1⟩}.
291+
Other bases are possible (X-basis, Y-basis) and give different results!
292+
293+
Args:
294+
circuits (dict): Dictionary of quantum circuits to measure
295+
shots (int): Number of times to repeat each measurement
296+
297+
Returns:
298+
dict: Dictionary of measurement counts for each circuit
299+
"""
134300
print("=== MEASUREMENT RESULTS ===")
135301
print()
136302

@@ -145,14 +311,20 @@ def measure_qubits(circuits, shots=1000):
145311

146312
for i, (label, circuit) in enumerate(circuits.items()):
147313
# Create measurement circuit with proper classical register
314+
# Classical register stores measurement outcomes (0 or 1)
148315
qc_measure = QuantumCircuit(circuit.num_qubits, circuit.num_qubits)
149316
qc_measure = qc_measure.compose(circuit)
317+
# measure_all() performs computational basis measurement on all qubits
150318
qc_measure.measure_all()
151319

152320
# Run simulation
321+
# Each "shot" represents one complete experiment: prepare state → measure
322+
# We need multiple shots because quantum measurement is probabilistic
153323
try:
154324
job = simulator.run(transpile(qc_measure, simulator), shots=shots)
155325
result = job.result()
326+
# counts is a dictionary: {'0': count_0, '1': count_1}
327+
# The counts should follow the Born rule probabilities
156328
counts = result.get_counts()
157329
results[label] = counts
158330

@@ -170,7 +342,7 @@ def measure_qubits(circuits, shots=1000):
170342
results[label] = {}
171343
continue
172344

173-
# Print results
345+
# Print results - compare empirical frequencies to theoretical probabilities
174346
if label in results and results[label]:
175347
print(f"State {label} measured {shots} times:")
176348
for outcome, count in results[label].items():

0 commit comments

Comments
 (0)