mirror of
https://github.com/saymrwulf/QuantumLearning.git
synced 2026-05-14 20:58:00 +00:00
1754 lines
92 KiB
Python
1754 lines
92 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
from textwrap import dedent
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
NOTEBOOKS = ROOT / "notebooks"
|
|
MODULE_02_DIR = NOTEBOOKS / "foundations" / "module_02_qubit_and_statevector_intuition"
|
|
MODULE_03_DIR = NOTEBOOKS / "foundations" / "module_03_gates_and_measurement"
|
|
|
|
|
|
def markdown_cell(text: str) -> dict:
|
|
cleaned = "\n".join(line.rstrip() for line in dedent(text).strip("\n").splitlines())
|
|
return {
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [line + "\n" for line in cleaned.splitlines()],
|
|
}
|
|
|
|
|
|
def code_cell(source: str) -> dict:
|
|
cleaned = dedent(source).strip("\n")
|
|
return {
|
|
"cell_type": "code",
|
|
"execution_count": None,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [line + "\n" for line in cleaned.splitlines()],
|
|
}
|
|
|
|
|
|
def _cell_id(index: int, cell: dict) -> str:
|
|
source = "".join(cell.get("source", []))
|
|
digest = hashlib.sha1(f"{cell.get('cell_type', 'cell')}:{index}:{source}".encode()).hexdigest()
|
|
return digest[:8]
|
|
|
|
|
|
def notebook(cells: list[dict]) -> dict:
|
|
normalized_cells = []
|
|
for index, cell in enumerate(cells):
|
|
payload = dict(cell)
|
|
payload.setdefault("id", _cell_id(index, payload))
|
|
normalized_cells.append(payload)
|
|
return {
|
|
"cells": normalized_cells,
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "QuantumLearning (.venv)",
|
|
"language": "python",
|
|
"name": "quantum-learning",
|
|
},
|
|
"language_info": {
|
|
"name": "python",
|
|
"version": "3.12",
|
|
},
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5,
|
|
}
|
|
|
|
|
|
def write_notebook(path: Path, payload: dict) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(json.dumps(payload, indent=2) + "\n")
|
|
|
|
|
|
def quiz_code(questions: list[dict], heading: str) -> dict:
|
|
return code_cell(f"quiz_block({questions!r}, heading={heading!r})")
|
|
|
|
|
|
def reflection_code(prompt: str) -> dict:
|
|
return code_cell(f"reflection_box({prompt!r})")
|
|
|
|
|
|
def editable_lab_code(
|
|
initial_code: str,
|
|
*,
|
|
title: str,
|
|
instructions: str,
|
|
shots: int = 256,
|
|
) -> dict:
|
|
return code_cell(
|
|
f"""
|
|
editable_code = {initial_code!r}
|
|
editable_circuit_lab(
|
|
initial_code=editable_code,
|
|
context={{"QuantumCircuit": QuantumCircuit, "simulate_counts": simulate_counts}},
|
|
title={title!r},
|
|
instructions={instructions!r},
|
|
shots={shots},
|
|
)
|
|
"""
|
|
)
|
|
|
|
|
|
SETUP = """
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
project_root = Path.cwd().resolve()
|
|
while not (project_root / "pyproject.toml").exists():
|
|
if project_root.parent == project_root:
|
|
raise RuntimeError("Could not locate the project root from this notebook.")
|
|
project_root = project_root.parent
|
|
|
|
src_path = project_root / "src"
|
|
if str(src_path) not in sys.path:
|
|
sys.path.insert(0, str(src_path))
|
|
"""
|
|
|
|
|
|
COMMON_IMPORTS = """
|
|
from quantum_learning import (
|
|
counts_to_probabilities,
|
|
editable_circuit_lab,
|
|
plot_counts,
|
|
plot_probabilities,
|
|
quiz_block,
|
|
reflection_box,
|
|
simulate_counts,
|
|
statevector_probabilities,
|
|
step_reference_table,
|
|
)
|
|
from qiskit import QuantumCircuit
|
|
from qiskit.quantum_info import Statevector
|
|
"""
|
|
|
|
|
|
STATEVECTOR_STEP_REFS = [
|
|
{
|
|
"marker": "[1]",
|
|
"code_focus": "Apply Hadamard to create equal-magnitude amplitudes on the computational basis states.",
|
|
"diagram_effect": "The single wire leaves the all-zero path and enters a balanced branch structure.",
|
|
"why_it_matters": "This is the first moment where the circuit meaning requires amplitude language rather than a hidden classical bit story.",
|
|
},
|
|
{
|
|
"marker": "[2]",
|
|
"code_focus": "Apply Z to flip the phase of the |1> component without changing computational-basis probabilities.",
|
|
"diagram_effect": "The diagram looks small, but the state description changes in a way that is invisible to a direct Z-basis probability check.",
|
|
"why_it_matters": "This is the cleanest beginner example of information that lives in phase rather than in raw support.",
|
|
},
|
|
{
|
|
"marker": "[3]",
|
|
"code_focus": "Apply a second Hadamard to convert the hidden phase difference into a visible population difference.",
|
|
"diagram_effect": "The final gate changes the basis in which the hidden structure becomes empirically legible.",
|
|
"why_it_matters": "The circuit teaches that phase can matter operationally even when it looked invisible one step earlier.",
|
|
},
|
|
{
|
|
"marker": "[4]",
|
|
"code_focus": "Measure into a classical bit only after the phase has been translated into a basis-dependent question.",
|
|
"diagram_effect": "The wire ends in a concrete experiment rather than an abstract state description.",
|
|
"why_it_matters": "Counts are answers to a chosen question, not a full dump of the statevector.",
|
|
},
|
|
]
|
|
|
|
|
|
PHASE_PROBE_EDITABLE = """
|
|
circuit = QuantumCircuit(1, 1)
|
|
# [1] Create equal-magnitude amplitudes.
|
|
circuit.h(0)
|
|
# [2] Flip the relative phase of the |1> branch.
|
|
circuit.z(0)
|
|
# [3] Turn that hidden phase into a visible basis difference.
|
|
circuit.h(0)
|
|
# [4] Ask the final measurement question.
|
|
circuit.measure(0, 0)
|
|
"""
|
|
|
|
|
|
BELL_SUPPORT_EDITABLE = """
|
|
circuit = QuantumCircuit(2, 2)
|
|
# [1] Start a balanced branch on qubit 0.
|
|
circuit.h(0)
|
|
# [2] Correlate qubit 1 with the branch.
|
|
circuit.cx(0, 1)
|
|
# [3] Measure both wires in the computational basis.
|
|
circuit.measure([0, 1], [0, 1])
|
|
"""
|
|
|
|
|
|
PHASE_PARITY_EDITABLE = """
|
|
circuit = QuantumCircuit(2, 2)
|
|
# [1] Prepare both qubits in the X basis.
|
|
circuit.h(0)
|
|
circuit.h(1)
|
|
# [2] Insert a controlled phase.
|
|
circuit.cz(0, 1)
|
|
# [3] Rotate back before measuring.
|
|
circuit.h(0)
|
|
circuit.h(1)
|
|
circuit.measure([0, 1], [0, 1])
|
|
"""
|
|
|
|
|
|
STATEVECTOR_QUIZ_A = [
|
|
{
|
|
"prompt": "What does a statevector give you that a histogram does not?",
|
|
"options": [
|
|
"Only prettier output formatting",
|
|
"Amplitude-level information before a particular measurement question is chosen",
|
|
"A direct picture of hardware noise",
|
|
],
|
|
"correct_index": 1,
|
|
"explanation": "Statevectors preserve amplitude structure that can be lost once you ask only one measurement question.",
|
|
},
|
|
{
|
|
"prompt": "If two basis states have equal probability, what is still missing from that statement?",
|
|
"options": [
|
|
"The relative phase information",
|
|
"The number of classical bits in the register",
|
|
"The transpiler optimization level",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Probability magnitudes alone do not tell you how amplitudes differ by phase.",
|
|
},
|
|
{
|
|
"prompt": "Why is the phrase 'the qubit is really 0 or 1 underneath' dangerous here?",
|
|
"options": [
|
|
"Because it blocks basis and phase reasoning by forcing a classical hidden-value story onto a quantum object",
|
|
"Because it makes circuits larger",
|
|
"Because it prevents plotting",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "The hidden-value story fails precisely where phase and basis dependence start to matter.",
|
|
},
|
|
]
|
|
|
|
|
|
STATEVECTOR_QUIZ_B = [
|
|
{
|
|
"prompt": "Why does the `Z` gate in the phase-probe circuit matter even though the intermediate probabilities stay balanced?",
|
|
"options": [
|
|
"Because it changes the relative phase, which later gates can turn into different measurement behavior",
|
|
"Because it secretly performs measurement",
|
|
"Because it increases the shot count",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Relative phase can be operationally silent in one basis and visible in another.",
|
|
},
|
|
{
|
|
"prompt": "What does the support of a statevector refer to in this course?",
|
|
"options": [
|
|
"The basis states with nonzero amplitude weight",
|
|
"The hardware backends that accept the circuit",
|
|
"The number of markdown explanations around the code",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Support is about which basis labels actually participate in the state description.",
|
|
},
|
|
{
|
|
"prompt": "Why is bitstring ordering worth discussing explicitly in a beginner module?",
|
|
"options": [
|
|
"Because label order affects how you read multi-qubit probability dictionaries and can create false debugging stories if ignored",
|
|
"Because Qiskit changes the number of qubits based on label order",
|
|
"Because it determines whether Hadamard is allowed",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Ambiguity about labels creates fake confusion that should be removed early.",
|
|
},
|
|
]
|
|
|
|
|
|
STATEVECTOR_LAB_QUIZ_A = [
|
|
{
|
|
"prompt": "What is the most useful first reaction when a modified circuit keeps the same probabilities but changes the statevector?",
|
|
"options": [
|
|
"Conclude that nothing important happened",
|
|
"Ask whether the edit changed relative phase rather than support",
|
|
"Assume the simulator failed",
|
|
],
|
|
"correct_index": 1,
|
|
"explanation": "A stable probability table can still hide a meaningful phase change.",
|
|
},
|
|
{
|
|
"prompt": "Why do the lab notebooks ask for one change at a time?",
|
|
"options": [
|
|
"To create diagnostic evidence about which design move caused the observed change",
|
|
"To satisfy a Qiskit restriction",
|
|
"To reduce notebook size",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Controlled variation is what makes the resulting explanation trustworthy.",
|
|
},
|
|
]
|
|
|
|
|
|
STATEVECTOR_LAB_QUIZ_B = [
|
|
{
|
|
"prompt": "What makes the Bell state a good support-pattern example?",
|
|
"options": [
|
|
"Its probability mass lives only on two basis labels, which makes the support structure easy to see and explain",
|
|
"It is the only two-qubit state Qiskit can draw",
|
|
"It avoids phase entirely",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "A sparse support pattern is easy to inspect and reason about carefully.",
|
|
},
|
|
{
|
|
"prompt": "What is the real lesson of the `CZ` parity lab?",
|
|
"options": [
|
|
"Controlled phase can create meaningful structure that only becomes visible after a basis change",
|
|
"Controlled phase is just another spelling of CNOT",
|
|
"Two-qubit gates always produce uniform distributions",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Phase structure often needs a carefully chosen probe before it becomes visible in counts.",
|
|
},
|
|
]
|
|
|
|
|
|
STATEVECTOR_PROBLEM_SETS = [
|
|
(
|
|
"Statevector Problem Set A",
|
|
[
|
|
{
|
|
"prompt": "Which statement best describes a basis amplitude?",
|
|
"options": [
|
|
"A numerical weight whose magnitude and phase help determine later behavior",
|
|
"A classical bit that has not been measured yet",
|
|
"A routing instruction for the transpiler",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Amplitude language is the right starting point for statevector reasoning.",
|
|
},
|
|
{
|
|
"prompt": "If a one-qubit state has support on both |0> and |1>, what can you already conclude?",
|
|
"options": [
|
|
"Only that more than one basis label participates; you still need phase and magnitude detail for a full story",
|
|
"That the qubit will always measure 50/50 in any basis",
|
|
"That the circuit must contain a two-qubit gate",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Support is only one layer of the state description.",
|
|
},
|
|
{
|
|
"prompt": "Why is prediction before simulation especially important in statevector work?",
|
|
"options": [
|
|
"Because wrong predictions reveal exactly where amplitude or basis language is still unstable",
|
|
"Because the simulator cannot run without a prediction",
|
|
"Because it changes the final state",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Prediction turns the notebook into a diagnostic instrument rather than a slideshow.",
|
|
},
|
|
],
|
|
),
|
|
(
|
|
"Statevector Problem Set B",
|
|
[
|
|
{
|
|
"prompt": "What does a relative phase change mean in practical terms?",
|
|
"options": [
|
|
"It can alter interference and later measurement behavior even when immediate probabilities look unchanged",
|
|
"It only affects how the code is formatted",
|
|
"It changes the number of qubits",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Relative phase is operational when a later circuit stage makes it visible.",
|
|
},
|
|
{
|
|
"prompt": "Why is global phase treated differently from relative phase?",
|
|
"options": [
|
|
"Because a global phase does not change observable predictions for the same experiment",
|
|
"Because global phase is bigger than relative phase",
|
|
"Because global phase can be measured directly with one shot",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Only relative phase differences affect observable structure in the same setup.",
|
|
},
|
|
{
|
|
"prompt": "If two circuits give the same Z-basis counts, what stronger check might distinguish them?",
|
|
"options": [
|
|
"Inspect the statevector or measure after a basis change",
|
|
"Rename the registers",
|
|
"Increase the font size in the plot",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Counts in one basis can hide differences that appear elsewhere.",
|
|
},
|
|
],
|
|
),
|
|
(
|
|
"Statevector Problem Set C",
|
|
[
|
|
{
|
|
"prompt": "Why does multi-qubit label order deserve attention?",
|
|
"options": [
|
|
"Because otherwise you may assign the wrong story to the right probability dictionary",
|
|
"Because label order determines the backend noise profile",
|
|
"Because it disables entanglement",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Reading labels incorrectly creates fake bugs and false confidence.",
|
|
},
|
|
{
|
|
"prompt": "What is the most honest summary of counts versus statevectors?",
|
|
"options": [
|
|
"Counts are empirical answers to one chosen question; statevectors are pre-measurement descriptions that support many questions",
|
|
"They are interchangeable in all contexts",
|
|
"Counts are always better because they come from shots",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Each representation serves a different explanatory burden.",
|
|
},
|
|
{
|
|
"prompt": "What is a support pattern?",
|
|
"options": [
|
|
"The set of basis labels carrying nonzero weight in the state description",
|
|
"The order of markdown cells in the notebook",
|
|
"The coupling map of a backend",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Support patterns are a clean first lens for reading small states.",
|
|
},
|
|
],
|
|
),
|
|
(
|
|
"Statevector Problem Set D",
|
|
[
|
|
{
|
|
"prompt": "What is the best beginner description of the second Hadamard in the phase-probe circuit?",
|
|
"options": [
|
|
"It changes basis so the earlier phase difference becomes visible to the final measurement question",
|
|
"It resets the qubit to zero",
|
|
"It copies the qubit into a classical bit",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "The gate is not decoration; it is the bridge from hidden phase to visible outcome.",
|
|
},
|
|
{
|
|
"prompt": "Which habit is most aligned with professional state reasoning?",
|
|
"options": [
|
|
"Naming the basis, the support, and the phase story explicitly before trusting the output",
|
|
"Trusting the first histogram that looks plausible",
|
|
"Avoiding multi-representation checks",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Professional attention is explicit about representation and basis.",
|
|
},
|
|
{
|
|
"prompt": "If your explanation works only for the exact worked example and breaks after a one-gate edit, what does that show?",
|
|
"options": [
|
|
"That you remembered a pattern but did not yet own the mechanism",
|
|
"That the notebook is invalid",
|
|
"That statevectors are impossible for beginners",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Robust understanding survives controlled variation.",
|
|
},
|
|
],
|
|
),
|
|
]
|
|
|
|
|
|
STATEVECTOR_STUDIO_QUIZ = [
|
|
{
|
|
"prompt": "What is the point of the statevector studio notebook?",
|
|
"options": [
|
|
"To turn amplitude language into deliberate preparation and probing choices",
|
|
"To avoid writing explanations",
|
|
"To replace statevectors with pure measurement counts",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "The studio asks for design responsibility, not passive recognition.",
|
|
},
|
|
{
|
|
"prompt": "Which design move best distinguishes `|+>` from `|->` experimentally?",
|
|
"options": [
|
|
"Insert a basis change before measurement so relative phase becomes visible",
|
|
"Rename the qubit",
|
|
"Add a barrier",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "The difference is not visible in the same basis unless you choose the right probe.",
|
|
},
|
|
]
|
|
|
|
|
|
MEASUREMENT_STEP_REFS = [
|
|
{
|
|
"marker": "[1]",
|
|
"code_focus": "Prepare a Bell-style correlated state with `H` and `CX`.",
|
|
"diagram_effect": "The first two operations create a structured two-wire object rather than two independent qubits.",
|
|
"why_it_matters": "Measurement interpretation depends on what was prepared before the final question is asked.",
|
|
},
|
|
{
|
|
"marker": "[2]",
|
|
"code_focus": "Rotate one qubit with `H` immediately before measurement.",
|
|
"diagram_effect": "The final question changes on that wire without erasing the rest of the preparation story.",
|
|
"why_it_matters": "Basis changes are part of the experiment design, not cosmetic extras.",
|
|
},
|
|
{
|
|
"marker": "[3]",
|
|
"code_focus": "Measure into explicitly chosen classical bits.",
|
|
"diagram_effect": "The circuit commits to a specific readout question and a specific reporting layout.",
|
|
"why_it_matters": "Classical wiring is part of the evidence trail and can itself become a source of confusion.",
|
|
},
|
|
]
|
|
|
|
|
|
BASIS_BELL_EDITABLE = """
|
|
circuit = QuantumCircuit(2, 2)
|
|
# [1] Prepare the correlated state.
|
|
circuit.h(0)
|
|
circuit.cx(0, 1)
|
|
# [2] Change the basis of the first measurement question.
|
|
circuit.h(0)
|
|
# [3] Measure both qubits into the matching classical bits.
|
|
circuit.measure([0, 1], [0, 1])
|
|
"""
|
|
|
|
|
|
SINGLE_QUBIT_GATE_EDITABLE = """
|
|
circuit = QuantumCircuit(1, 1)
|
|
# [1] Try changing the preparation gate sequence.
|
|
circuit.x(0)
|
|
circuit.h(0)
|
|
# [2] Optionally add Z or another H before measurement.
|
|
# circuit.z(0)
|
|
# circuit.h(0)
|
|
# [3] Measure the result.
|
|
circuit.measure(0, 0)
|
|
"""
|
|
|
|
|
|
WIRING_EDITABLE = """
|
|
circuit = QuantumCircuit(2, 2)
|
|
# [1] Prepare a Bell-style state.
|
|
circuit.h(0)
|
|
circuit.cx(0, 1)
|
|
# [2] Try swapping the classical wiring.
|
|
circuit.measure([0, 1], [1, 0])
|
|
"""
|
|
|
|
|
|
MEASUREMENT_QUIZ_A = [
|
|
{
|
|
"prompt": "What is the cleanest interpretation of a measurement basis change?",
|
|
"options": [
|
|
"It changes the question asked of the prepared state",
|
|
"It deletes the earlier gates",
|
|
"It is only a formatting step for counts",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Measurement basis is part of the experiment design and the story of the circuit.",
|
|
},
|
|
{
|
|
"prompt": "Why should classical register wiring be treated seriously?",
|
|
"options": [
|
|
"Because wrong wiring can make correct quantum behavior look incorrect in the reported bitstrings",
|
|
"Because it changes the quantum state directly",
|
|
"Because it forces extra transpilation",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Evidence can be misread if the mapping from qubits to reported bits is not tracked carefully.",
|
|
},
|
|
{
|
|
"prompt": "What does a shot-based histogram approximate?",
|
|
"options": [
|
|
"The empirical distribution of answers to the chosen measurement question",
|
|
"The exact statevector amplitudes",
|
|
"The coupling map of the device",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Counts are sampled evidence, not a direct amplitude dump.",
|
|
},
|
|
]
|
|
|
|
|
|
MEASUREMENT_QUIZ_B = [
|
|
{
|
|
"prompt": "Why is `H` often described as a basis bridge?",
|
|
"options": [
|
|
"Because it lets Z-basis measurement act like an X-basis probe",
|
|
"Because it adds extra classical bits",
|
|
"Because it removes phase from all circuits",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "The Hadamard is often the simplest way to express a different measurement question.",
|
|
},
|
|
{
|
|
"prompt": "What should you conclude if 64-shot and 4096-shot runs look similar but not identical?",
|
|
"options": [
|
|
"Sampling variation exists, but both runs can still support the same underlying probability story",
|
|
"One of the runs is invalid",
|
|
"The circuit changed between runs even if the code stayed the same",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Shot noise is normal and should be discussed rather than dramatized.",
|
|
},
|
|
{
|
|
"prompt": "What is the main beginner danger of treating gates as isolated icons?",
|
|
"options": [
|
|
"You miss how their meaning depends on context, basis, and surrounding preparation",
|
|
"You will always get syntax errors",
|
|
"You stop using notebooks",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Gate meaning is contextual, not merely symbolic.",
|
|
},
|
|
]
|
|
|
|
|
|
MEASUREMENT_LAB_QUIZ_A = [
|
|
{
|
|
"prompt": "What is the best reason to compare counts across different shot budgets?",
|
|
"options": [
|
|
"To separate stable probability claims from normal sampling fluctuation",
|
|
"To reduce circuit depth",
|
|
"To change the prepared state",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Shot scaling teaches you how much statistical noise to expect from the same circuit.",
|
|
},
|
|
{
|
|
"prompt": "What does swapping classical bit targets test?",
|
|
"options": [
|
|
"Whether your explanation tracks the reporting layer instead of only the quantum layer",
|
|
"Whether CNOT still works",
|
|
"Whether the backend supports measurement",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Good reasoning follows the evidence all the way into the bitstring labels.",
|
|
},
|
|
]
|
|
|
|
|
|
MEASUREMENT_LAB_QUIZ_B = [
|
|
{
|
|
"prompt": "If a final Hadamard changes the counts drastically, what is the first serious question to ask?",
|
|
"options": [
|
|
"Did I change the measurement basis rather than merely add decoration?",
|
|
"Did the notebook theme corrupt the circuit?",
|
|
"Did the number of qubits change automatically?",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "The basis question is the right first interpretation, not panic.",
|
|
},
|
|
{
|
|
"prompt": "Why keep counts and probabilities conceptually separate in the same notebook?",
|
|
"options": [
|
|
"Because one is sampled evidence and the other is an idealized expectation derived from the model",
|
|
"Because they should never be compared",
|
|
"Because counts are only for advanced users",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Serious measurement reasoning compares the ideal story with sampled evidence carefully.",
|
|
},
|
|
]
|
|
|
|
|
|
MEASUREMENT_PROBLEM_SETS = [
|
|
(
|
|
"Measurement Problem Set A",
|
|
[
|
|
{
|
|
"prompt": "What is a gate in the strongest sense used by this module?",
|
|
"options": [
|
|
"A transformation whose role depends on the circuit context and the question being asked",
|
|
"A decorative icon",
|
|
"Only a line of code with no conceptual content",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "This course treats gates as moves inside a structured argument.",
|
|
},
|
|
{
|
|
"prompt": "Why is the sequence of gates important?",
|
|
"options": [
|
|
"Because later operations act on the state produced by earlier ones",
|
|
"Because Qiskit sorts them alphabetically",
|
|
"Because measurement always happens first",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Circuit meaning is time ordered.",
|
|
},
|
|
{
|
|
"prompt": "What is the best beginner definition of a measurement protocol?",
|
|
"options": [
|
|
"The combined choice of basis, wiring, and shot-based evidence gathering",
|
|
"Only the final `measure` syntax",
|
|
"The color of the histogram bars",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Measurement is a designed protocol, not a final afterthought.",
|
|
},
|
|
],
|
|
),
|
|
(
|
|
"Measurement Problem Set B",
|
|
[
|
|
{
|
|
"prompt": "Why can the same prepared state yield different-looking results under different basis choices?",
|
|
"options": [
|
|
"Because the measurement question changed",
|
|
"Because the qubits became classical earlier",
|
|
"Because the simulator chooses random bases on its own",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Basis changes alter the question, so the evidence can change legitimately.",
|
|
},
|
|
{
|
|
"prompt": "What should a careful engineer write down alongside a histogram?",
|
|
"options": [
|
|
"What state was prepared, what basis was measured, and how qubits were mapped to classical bits",
|
|
"Only the backend name",
|
|
"Only whether the plot looked correct",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Evidence without protocol is easy to misread.",
|
|
},
|
|
{
|
|
"prompt": "Why are `X`, `Z`, and `H` enough for many early measurement lessons?",
|
|
"options": [
|
|
"They already expose preparation changes, phase changes, and basis changes cleanly",
|
|
"Because no other gates exist",
|
|
"Because two-qubit gates are illegal in beginner modules",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "A small gate vocabulary can already teach the important distinctions.",
|
|
},
|
|
],
|
|
),
|
|
(
|
|
"Measurement Problem Set C",
|
|
[
|
|
{
|
|
"prompt": "What does a mismatch between ideal probabilities and low-shot counts usually mean first?",
|
|
"options": [
|
|
"Sampling variation or a changed measurement protocol should be examined before inventing deeper explanations",
|
|
"The statevector is false",
|
|
"The qubit count changed",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Start with the ordinary explanations and inspect the protocol carefully.",
|
|
},
|
|
{
|
|
"prompt": "Why does swapped classical wiring deserve a dedicated exercise?",
|
|
"options": [
|
|
"Because reporting mistakes can mimic conceptual mistakes if the mapping is not tracked",
|
|
"Because it changes the quantum amplitudes",
|
|
"Because it improves the histogram automatically",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Evidence pipelines can fail at the reporting stage too.",
|
|
},
|
|
{
|
|
"prompt": "What professional habit is being built by basis-comparison exercises?",
|
|
"options": [
|
|
"Separating preparation claims from question claims",
|
|
"Memorizing more gate names",
|
|
"Avoiding reflection writing",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "A professional explanation states what changed and what stayed fixed.",
|
|
},
|
|
],
|
|
),
|
|
(
|
|
"Measurement Problem Set D",
|
|
[
|
|
{
|
|
"prompt": "What should you do after a missed quiz question in this course?",
|
|
"options": [
|
|
"Identify the exact distinction that failed and reinforce it in your written explanation",
|
|
"Ignore the mistake if the code ran",
|
|
"Skip the rest of the notebook",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Missed retrieval is a diagnostic event, not just a score event.",
|
|
},
|
|
{
|
|
"prompt": "Which sentence most clearly marks measurement maturity?",
|
|
"options": [
|
|
"I can describe what question this circuit asks and why the returned bitstrings count as evidence for that question",
|
|
"I can recognize the measurement symbol",
|
|
"I know that more shots are always better no matter the question",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "The course is training explanation quality, not icon recognition.",
|
|
},
|
|
{
|
|
"prompt": "What is the danger of trusting a plausible-looking Bell histogram without further thought?",
|
|
"options": [
|
|
"You may miss basis mistakes, wiring mistakes, or a false story about what was actually measured",
|
|
"There is no danger once the bars look right",
|
|
"It guarantees a hardware failure later",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Good-looking evidence can still be incorrectly interpreted.",
|
|
},
|
|
],
|
|
),
|
|
]
|
|
|
|
|
|
MEASUREMENT_STUDIO_QUIZ = [
|
|
{
|
|
"prompt": "What does the measurement studio demand that the lecture does not?",
|
|
"options": [
|
|
"Deliberate protocol design and explicit justification of why a chosen measurement reveals what you claim",
|
|
"Less writing",
|
|
"No circuit edits",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "The studio is where you own the protocol rather than merely understand it.",
|
|
},
|
|
{
|
|
"prompt": "What is the hallmark of a good studio answer?",
|
|
"options": [
|
|
"It separates preparation, basis choice, wiring, and evidence instead of blurring them together",
|
|
"It uses the most gates possible",
|
|
"It avoids comparison between alternatives",
|
|
],
|
|
"correct_index": 0,
|
|
"explanation": "Review language should make the protocol legible and falsifiable.",
|
|
},
|
|
]
|
|
|
|
|
|
def build_statevector_lecture() -> dict:
|
|
return notebook(
|
|
[
|
|
markdown_cell(
|
|
"""
|
|
# Qubit and Statevector Intuition Lecture
|
|
|
|
This module exists because a circuit designer who cannot think in state language becomes trapped at the surface of the diagrams. You can memorize gate names, execute code, and even produce attractive histograms while still being unable to explain what object the circuit is preparing. That gap becomes fatal later. It makes phase look mystical, it makes basis changes look arbitrary, and it makes algorithmic circuits feel like collections of clever tricks instead of understandable constructions. The role of this lecture is to close that gap early.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Learning Objective
|
|
|
|
By the end of this lecture, you should be able to describe a small quantum state in a disciplined way. That means naming its basis labels, identifying its support, saying what the amplitudes are doing at a high level, and explaining which information survives or disappears when you finally measure it. The lecture is not trying to make you a full mathematical formalist in one sitting. It is trying to make your intuition precise enough that you can stop hiding behind vague sentences such as “the qubit is in both states at once” or “the phase changed somehow.”
|
|
|
|
The working target is practical. When you look at a short circuit, you should be able to say not only what gates appear in it, but what state description the circuit is building toward. That change in attention is one of the first major steps from amateur exposure to professional circuit thinking.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Why Statevectors Matter
|
|
|
|
A histogram is evidence. A statevector is a model. Those two sentences do a lot of work in this course. A histogram tells you what happened after you asked one particular measurement question many times. A statevector tells you what pre-measurement object the circuit prepared, at least in the ideal noiseless story. If you confuse those two layers, you will constantly misread what later circuits are doing. You will think that the histogram is the state. You will forget that another basis could reveal a different face of the same preparation. You will treat phase as a decorative nuisance instead of as a structural part of the description.
|
|
|
|
This lecture therefore treats the statevector as a literacy tool. It is not here so you can perform heroic linear algebra by hand on large systems. It is here so you can learn the right descriptive habits on small systems where every basis label is still visible enough to inspect. If that inspection habit becomes normal now, larger circuits later will feel like scale rather than magic.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Support, Amplitude, And Probability
|
|
|
|
The first useful distinction is between support and full description. The support of a state is the set of basis labels that actually carry weight. That is already informative. A Bell state, for example, has support on only two of the four computational basis labels. But support is not the entire story. It does not yet tell you the exact amplitudes, and it certainly does not tell you the relative phases between them. If you stop at support, you have only learned where the state lives, not how it lives there.
|
|
|
|
The second distinction is between amplitude magnitude and probability. Probabilities come from amplitude magnitudes, but the amplitude also carries phase information. Beginners often understand the probability part first because it is easy to connect to histograms. Good. Keep that connection. But do not let it erase the phase story. Some circuits differ only by phase until a later basis change makes that phase visible in counts. That is one of the most important pieces of maturity installed by this module.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Relative Phase Is The First Serious Shock
|
|
|
|
The cleanest beginner shock in this subject is the discovery that two states can have the same computational-basis probabilities and still not be the same state. That is not a mathematical technicality. It is one of the reasons quantum circuit design is interesting at all. Relative phase changes how later gates interfere with the branches already present in the state. A phase change can be operationally silent in one basis and decisive in another.
|
|
|
|
This is why the lecture uses a one-qubit phase-probe circuit as its anchor. It is a tiny circuit with a very large teaching payoff. A Hadamard creates balanced support. A `Z` gate flips the relative phase of the `|1>` branch while leaving the computational-basis probabilities balanced. A second Hadamard then turns that previously hidden difference into a visible measurement effect. In one short line of reasoning, you get the main lesson: not all meaningful structure is immediately visible in the probabilities you happened to inspect first.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Multi-Qubit States And Label Reading
|
|
|
|
Multi-qubit states introduce a second challenge: reading the basis labels correctly. The problem is not advanced mathematics. The problem is bookkeeping discipline. Once you have two qubits, there are four computational basis labels. Once you have three, there are eight. The number grows quickly, but the real beginner danger is simpler than that growth. The danger is misreading the labels and telling the wrong story about the right data. If you swap the order in your head, you can create a fake bug where none exists or miss a real pattern that the circuit is clearly producing.
|
|
|
|
That is why this module takes time to talk about basis labels and support patterns explicitly. A professional designer cannot afford a fuzzy relationship to labeling. The more serious the circuit becomes, the more expensive those small confusions become.
|
|
"""
|
|
),
|
|
code_cell(SETUP),
|
|
code_cell(COMMON_IMPORTS),
|
|
markdown_cell(
|
|
"""
|
|
## Code-To-Diagram Anchor
|
|
|
|
Read the marker table first. The point is to see how a single quiet phase change can sit in the middle of a short circuit and still carry decisive explanatory weight. Notice that the table forces you to translate from code line to diagram effect to conceptual burden. That translation habit is part of the subject, not a supplementary study trick.
|
|
"""
|
|
),
|
|
code_cell(f"step_reference_table({STATEVECTOR_STEP_REFS!r})"),
|
|
markdown_cell(
|
|
"""
|
|
## Editable Phase-Probe Circuit
|
|
|
|
Start by altering exactly one line. Delete the `Z`, move the second `H`, or change the measurement position. Then say what story should survive and what story should break. The circuit is small on purpose. Small circuits make it impossible to hide weak reasoning behind size.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
PHASE_PROBE_EDITABLE,
|
|
title="Statevector Anchor: The Phase Probe",
|
|
instructions="Change one marked step at a time and explain which part of the state story changed: support, phase, or measurement question.",
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Looking Beneath The Counts
|
|
|
|
The widget above gives you the diagram and a quick measurement preview, but the main point of this module is that counts alone are not enough. The next code cell looks at the pre-measurement state directly. Read it carefully. The balanced support after the first Hadamard does not disappear when the `Z` gate is inserted, but the relative sign does change. That sign is exactly what the final Hadamard turns into a new measurement outcome.
|
|
"""
|
|
),
|
|
code_cell(
|
|
"""
|
|
phase_probe = QuantumCircuit(1)
|
|
phase_probe.h(0)
|
|
phase_probe.z(0)
|
|
|
|
state = Statevector.from_instruction(phase_probe)
|
|
{
|
|
"amplitudes": [complex(value) for value in state.data],
|
|
"probabilities": statevector_probabilities(phase_probe),
|
|
}
|
|
"""
|
|
),
|
|
code_cell(
|
|
"""
|
|
bell = QuantumCircuit(2)
|
|
bell.h(0)
|
|
bell.cx(0, 1)
|
|
|
|
bell_probabilities = statevector_probabilities(bell)
|
|
plot_probabilities(bell_probabilities, title="Bell-State Support Pattern")
|
|
bell_probabilities
|
|
"""
|
|
),
|
|
quiz_code(STATEVECTOR_QUIZ_A, "Statevector Checkpoint A"),
|
|
markdown_cell(
|
|
"""
|
|
## Why Counts Are A Lossy Compression
|
|
|
|
Once you measure, you compress the story. That compression is not a flaw; it is the nature of the experiment you chose to run. But it is still a compression. You no longer hold the full pre-measurement object in your hand. You hold evidence produced by one specific question. This is why the course keeps insisting on the phrase “measurement is a chosen question.” The question determines what information survives directly into the histogram and what information remains hidden unless you ask differently.
|
|
|
|
This is also why statevector intuition is not a luxury for people who like math. It is a practical defense against shallow interpretation. If you know only the counts, you can talk yourself into believing that two circuits are identical when they merely agree in one basis. If you know the state-level story, you are much less vulnerable to that mistake.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Common Misconceptions To Kill Here
|
|
|
|
The first misconception is that equal probabilities imply equal states. They do not. The second is that phase only matters in advanced algorithms. It already matters in one-qubit circuits. The third is that statevector inspection is somehow “less real” than measurement because it is a simulation object. In a local-first learning platform, statevector inspection is a teaching instrument. It gives you a clean view of the intended ideal object so that later distortions, noisy counts, and transpiled rewrites have something stable to be compared against.
|
|
|
|
The fourth misconception is that notation difficulties are a sign of weak intelligence. Usually they are a sign that the learner has not yet built enough bookkeeping habits. This course answers that problem by making the bookkeeping explicit: basis labels, support patterns, measurement questions, and reflection writing all exist so that confusion can become specific rather than vague.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## How To Read A Statevector Professionally
|
|
|
|
A professional reading of a small statevector follows a consistent order. First, identify the basis and the label convention so you know what the indices even mean. Second, identify the support. Which basis states actually appear? Third, inspect the relative magnitudes. Is the weight balanced or biased? Fourth, inspect the phase structure. Are some amplitudes negative, complex, or otherwise related in a way that could matter after another gate? Finally, ask what measurement protocol would expose or hide the distinction you care about.
|
|
|
|
That order matters because it prevents a common collapse of reasoning. Beginners often jump straight from “I see two nonzero entries” to “therefore I understand the state.” Not yet. Two nonzero entries only tell you part of the story. A good explanation keeps going until it can say what another gate or another basis would do with that state. In other words, a statevector is not just something to read statically; it is something to reason forward from.
|
|
|
|
This forward-looking habit is what turns state inspection into circuit design preparation. Once you can look at a state and ask what basis would reveal its structure, what gate would convert hidden phase into visible population, or what edit would destroy the intended support pattern, you have started moving beyond notation literacy into engineering literacy.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Transfer Forward
|
|
|
|
If this lecture lands correctly, later modules become dramatically easier to interpret. Basis changes before measurement stop feeling arbitrary. Oracle and phase-kickback circuits stop feeling like special magic. Transpilation and noise notebooks become easier because you can separate the ideal object from the distorted evidence. That is the real reason to take statevectors seriously. They are not the final destination of the course. They are the clean reference frame that later engineering work needs.
|
|
|
|
As you move to the lab, keep the following sentence in view: support tells you where the state lives, amplitudes tell you how it lives there, and measurement tells you which part of that story you decided to ask about.
|
|
"""
|
|
),
|
|
quiz_code(STATEVECTOR_QUIZ_B, "Statevector Checkpoint B"),
|
|
reflection_code(
|
|
"Write one paragraph that explains why two circuits can share the same probabilities in one basis and still be different states."
|
|
),
|
|
reflection_code(
|
|
"Describe the exact role of the second Hadamard in the phase-probe circuit without using the phrase 'it undoes the first gate.'"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Mastery Gate
|
|
|
|
You are ready to leave this lecture only if you can inspect a small circuit, name its support pattern, say whether phase is carrying essential information, and explain what a chosen measurement protocol will and will not reveal. That is the floor this module is trying to install.
|
|
"""
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
def build_statevector_lab() -> dict:
|
|
return notebook(
|
|
[
|
|
markdown_cell(
|
|
"""
|
|
# Qubit and Statevector Intuition Lab
|
|
|
|
The lecture taught the descriptive language. The lab tests whether that language survives controlled edits. The main threat in this module is not syntax. It is premature confidence. Many learners can repeat the sentence “phase matters” and still fail to notice when a circuit change altered only the phase story rather than the support story. The labs below are designed to expose that weakness cleanly and repair it.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab Protocol
|
|
|
|
Keep the protocol rigid. Predict first. Change one thing only. Render the circuit. Look at the counts preview. Then run the follow-up analysis cell and compare the statevector-side explanation with the measurement-side evidence. If your first explanation fails, revise the sentence, not just the code. This is how the notebook becomes an instrument for learning rather than a toy to click through.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab 1: The One-Qubit Phase Probe
|
|
|
|
This is the anchor from the lecture. Your job is to make the hidden phase story concrete. Delete the `Z`, move the second `H`, or replace the first `H` with `X`. In each case, classify the edit. Did you change support, phase, or the final question? That classification habit is what the module is really trying to train.
|
|
"""
|
|
),
|
|
code_cell(SETUP),
|
|
code_cell(COMMON_IMPORTS),
|
|
code_cell(f"step_reference_table({STATEVECTOR_STEP_REFS!r})"),
|
|
editable_lab_code(
|
|
PHASE_PROBE_EDITABLE,
|
|
title="Lab 1: One-Qubit Phase Probe",
|
|
instructions="Alter the support story, the phase story, or the measurement story one at a time and explain which category your edit belongs to.",
|
|
),
|
|
code_cell(
|
|
"""
|
|
probe = QuantumCircuit(1)
|
|
probe.h(0)
|
|
probe.z(0)
|
|
|
|
{
|
|
"statevector": [complex(value) for value in Statevector.from_instruction(probe).data],
|
|
"probabilities": statevector_probabilities(probe),
|
|
}
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
The important question after this first lab is not merely “what changed?” It is “what kind of thing changed?” If your answer stays at the level of “the histogram changed,” you are still reasoning too shallowly. A stronger answer identifies whether the edit changed the underlying state support, changed only the relative phase, or changed the basis in which the final measurement question was asked.
|
|
"""
|
|
),
|
|
quiz_code(STATEVECTOR_LAB_QUIZ_A, "Statevector Lab Checkpoint A"),
|
|
reflection_code(
|
|
"Which edit produced the biggest conceptual surprise for you, and which sentence in your earlier explanation turned out to be inadequate?"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab 2: Two-Qubit Support Patterns
|
|
|
|
Use the Bell circuit to practice support reading on a slightly larger object. Your first task is to predict which basis labels should carry weight before you render anything. Then use the widget and the probability cell below to compare the measurement evidence with the ideal state description. This is the fastest way to make multi-qubit support feel concrete rather than abstract.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
BELL_SUPPORT_EDITABLE,
|
|
title="Lab 2: Bell Support Pattern",
|
|
instructions="Keep the circuit small. Predict the support labels first, then edit one preparation line and explain how the support pattern changes.",
|
|
),
|
|
code_cell(
|
|
"""
|
|
bell = QuantumCircuit(2)
|
|
bell.h(0)
|
|
bell.cx(0, 1)
|
|
|
|
bell_probs = statevector_probabilities(bell)
|
|
plot_probabilities(bell_probs, title="Bell Support Pattern")
|
|
bell_probs
|
|
"""
|
|
),
|
|
code_cell(
|
|
"""
|
|
measured_bell = QuantumCircuit(2, 2)
|
|
measured_bell.h(0)
|
|
measured_bell.cx(0, 1)
|
|
measured_bell.measure([0, 1], [0, 1])
|
|
|
|
bell_counts = simulate_counts(measured_bell, shots=512)
|
|
plot_counts(bell_counts, title="Bell Counts Preview")
|
|
{
|
|
"counts": bell_counts,
|
|
"probabilities_from_counts": counts_to_probabilities(bell_counts),
|
|
"ideal_support": statevector_probabilities(measured_bell),
|
|
}
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
The Bell state is a good support-pattern exercise because it is sparse enough to inspect and rich enough to matter. If you remove the Hadamard, the support collapses. If you remove the CNOT, the support spreads differently and the cross-wire story disappears. That is exactly the kind of controlled comparison a serious course should force early.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab 3: Controlled Phase As A Hidden Structural Move
|
|
|
|
The next lab is deliberately chosen because it punishes shallow probability-only thinking. A controlled phase inserted between `|++>` preparation and a final return to the computational basis can change the observed behavior even though the intermediate support looked perfectly innocent. Your job is to make that sentence precise.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
PHASE_PARITY_EDITABLE,
|
|
title="Lab 3: Controlled-Phase Parity Probe",
|
|
instructions="Delete or move the `CZ` and explain why the final parity structure changes or fails to change.",
|
|
),
|
|
code_cell(
|
|
"""
|
|
phase_pair = QuantumCircuit(2)
|
|
phase_pair.h(0)
|
|
phase_pair.h(1)
|
|
phase_pair.cz(0, 1)
|
|
|
|
{
|
|
"statevector": [complex(value) for value in Statevector.from_instruction(phase_pair).data],
|
|
"probabilities": statevector_probabilities(phase_pair),
|
|
}
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
Controlled phase is where the statevector habit starts paying off loudly. If you look only at immediate probabilities, the circuit can seem boring. If you look at the amplitude structure and then at the final measurement protocol, the circuit becomes legible. That is the whole pedagogical point of this module.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab Debrief
|
|
|
|
If the three labs felt repetitive, that is intentional. Repetition around the same distinction is stronger than shallow novelty. The distinction being reinforced here is simple to state and difficult to own: support, phase, and measurement are related but not interchangeable explanations. A beginner who says “the state changed” after every edit is still reasoning too coarsely. A stronger learner can say “the support changed,” “the relative phase changed while the support stayed fixed,” or “the state may have stayed compatible with the earlier description, but the measurement question changed.”
|
|
|
|
This debrief matters because the notebook is training diagnostic language, not only technical facts. Good diagnostic language saves time later. It helps when a notebook result looks plausible but feels wrong. It helps when a later algorithm depends on a phase distinction that is easy to erase accidentally. And it helps when you need to explain to another person why a circuit edit was deep or superficial. Those are all professional activities hiding inside what looks like a beginner lab.
|
|
"""
|
|
),
|
|
quiz_code(STATEVECTOR_LAB_QUIZ_B, "Statevector Lab Checkpoint B"),
|
|
reflection_code(
|
|
"Explain the difference between a circuit that changed support and a circuit that changed only relative phase, using one concrete lab edit as evidence."
|
|
),
|
|
reflection_code(
|
|
"Write a short note on why counts should be treated as lossy evidence rather than as the full story of the state."
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
def build_statevector_problems() -> dict:
|
|
cells = [
|
|
markdown_cell(
|
|
"""
|
|
# Qubit and Statevector Intuition Problems
|
|
|
|
This notebook is for retrieval and discrimination. The lecture gave you the conceptual map. The lab gave you controlled variation. The problems notebook tests whether the distinctions remain available when the circuit is not right in front of you. That matters because professional design work depends on rapid, reliable recall of small conceptual differences: support versus probability, relative versus global phase, state description versus measurement evidence.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## How To Use This Notebook
|
|
|
|
Do not guess quickly and move on. If a question feels ambiguous, that is the signal to stop and name the ambiguity precisely. The goal is not score worship. The goal is concept sharpening. Missed retrieval tells you which sentence still needs to be rewritten in your own language.
|
|
"""
|
|
),
|
|
code_cell(SETUP),
|
|
code_cell(COMMON_IMPORTS),
|
|
]
|
|
|
|
for heading, questions in STATEVECTOR_PROBLEM_SETS:
|
|
cells.append(
|
|
markdown_cell(
|
|
f"""
|
|
## {heading}
|
|
|
|
Answer the questions first, then explain in one or two sentences why the wrong choices were attractive. That second step is where weak but plausible mental models become visible.
|
|
"""
|
|
)
|
|
)
|
|
cells.append(quiz_code(questions, heading))
|
|
|
|
cells.extend(
|
|
[
|
|
markdown_cell(
|
|
"""
|
|
## Mini Case: Same Counts, Different Story
|
|
|
|
Imagine two short circuits that return the same computational-basis histogram. A careless reader will conclude that they are the same circuit for all practical purposes. This notebook is trying to kill that conclusion. The stronger question is: what experiment was run, what basis was used, and what state-level distinctions might remain hidden from the current evidence? That is the shape of the reasoning you should be practicing while answering the quizzes above.
|
|
|
|
This case matters because it recurs throughout the whole field. Phase-sensitive algorithms, basis-dependent diagnostics, and later hardware investigations all rely on the same discipline. You must be able to say what evidence justifies and what evidence leaves open. Multiple-choice questions are only a tool for rehearsing that discipline. The real goal is to make your written explanations harder to fool.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Short Written Checks
|
|
|
|
Retrieval in this course is not purely multiple choice. Professional reasoning requires complete sentences. Use the prompts below to state distinctions without leaning on the notebook prose around you.
|
|
"""
|
|
),
|
|
reflection_code(
|
|
"Explain why equal computational-basis probabilities do not guarantee identical quantum states."
|
|
),
|
|
reflection_code(
|
|
"Write a two-part explanation of the phrase 'counts are evidence, statevectors are models.'"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Exit Condition
|
|
|
|
You should leave this notebook only when the distinctions feel available without peeking: support, amplitude, relative phase, basis choice, and measurement lossiness. If any of those words still blur together, return to the lecture or lab before moving on.
|
|
"""
|
|
),
|
|
]
|
|
)
|
|
return notebook(cells)
|
|
|
|
|
|
def build_statevector_studio() -> dict:
|
|
return notebook(
|
|
[
|
|
markdown_cell(
|
|
"""
|
|
# Qubit and Statevector Intuition Studio
|
|
|
|
The studio turns description into deliberate preparation and probing. The question is no longer “do you recognize the example?” The question is “can you build a small circuit to create a target state story, choose a measurement protocol that reveals the right feature, and explain why your design works?”
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Studio Briefing
|
|
|
|
Statevector competence is not complete when you can read a prepared example. It becomes real when you can design a small preparation and an equally deliberate probe. A world-class course has to train that shift early. Otherwise later algorithm notebooks become imitation exercises instead of acts of understanding.
|
|
"""
|
|
),
|
|
code_cell(SETUP),
|
|
code_cell(COMMON_IMPORTS),
|
|
markdown_cell(
|
|
"""
|
|
## Brief 1: Build A Distinguishing Probe
|
|
|
|
Design a one-qubit circuit whose pre-measurement state has balanced support but whose final measurement can still distinguish two cases because of phase. The starter below gives you the right shape. Your job is to justify every line, not just make the counts look neat.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
PHASE_PROBE_EDITABLE,
|
|
title="Studio Brief 1: Distinguishing `|+>` From `|->`",
|
|
instructions="Use the phase probe as a starting point. Explain how your circuit distinguishes support from phase.",
|
|
),
|
|
reflection_code(
|
|
"Why is your chosen probe actually sensitive to relative phase rather than merely to a different preparation support?"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Brief 2: Prepare A Sparse Two-Qubit State Deliberately
|
|
|
|
Use the Bell-style constructor as a seed, then modify it to produce a different sparse support pattern if possible. Your explanation should say what support you intended, why the gate sequence should create it, and which measurement basis makes that claim easiest to defend.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
BELL_SUPPORT_EDITABLE,
|
|
title="Studio Brief 2: Sparse Two-Qubit Support",
|
|
instructions="Change the preparation intentionally and defend the support pattern you expect before you render.",
|
|
),
|
|
reflection_code(
|
|
"Write a short design memo that names the intended support pattern and the weakest point in your current explanation."
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Brief 3: Make Hidden Phase Visible
|
|
|
|
Start from the controlled-phase lab and redesign the probe if needed. The goal is to expose phase structure without hand-waving. Treat the measurement basis as part of the design, not as an afterthought.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
PHASE_PARITY_EDITABLE,
|
|
title="Studio Brief 3: Hidden Phase To Visible Evidence",
|
|
instructions="Tune the basis changes and explain how your protocol reveals a phase-related claim rather than only a support claim.",
|
|
),
|
|
quiz_code(STATEVECTOR_STUDIO_QUIZ, "Statevector Studio Check"),
|
|
reflection_code(
|
|
"What would a careless reader misinterpret about one of your circuits, and how would you rewrite the explanation to prevent that?"
|
|
),
|
|
reflection_code(
|
|
"Which part of statevector reasoning now feels owned, and which part still feels too fragile for a larger circuit?"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Studio Rubric
|
|
|
|
Judge your work here with four questions. First, is the target state story explicit, or are you still relying on a vague phrase such as “made it quantum”? Second, does the chosen probe actually reveal the distinction you claim, or would another basis be required? Third, can another engineer read your circuit and predict the evidence without guessing what you meant? Fourth, did you identify a residual weakness honestly?
|
|
|
|
Those questions matter because studios are not performance theater. They are where notebook work begins to resemble engineering review. A well-designed tiny circuit accompanied by an honest explanation is far more valuable than a flashy but poorly justified one. If you can meet this rubric on a small state-design task, you are building the right habits for much harder circuit families later.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Studio Exit
|
|
|
|
A good outcome here is not novelty for its own sake. A good outcome is deliberate control over a small design: you can name the target state story, choose a probe, read the evidence, and defend the explanation with no magical language left over.
|
|
"""
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
def build_measurement_lecture() -> dict:
|
|
return notebook(
|
|
[
|
|
markdown_cell(
|
|
"""
|
|
# Gates and Measurement Lecture
|
|
|
|
This module turns two ideas into engineering habits. The first idea is that gates are not collectible icons; they are transformations whose meaning depends on what state has already been prepared and what measurement question will be asked later. The second idea is that measurement is not the neutral end of a circuit. It is a protocol: basis choice, classical wiring, repeated sampling, and interpretation. If those two ideas land properly, a large class of beginner confusion disappears.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Learning Objective
|
|
|
|
By the end of this lecture, you should be able to explain why the same prepared state can yield different-looking evidence under different basis choices, why classical wiring belongs in the explanatory story, and how to compare ideal probabilities with shot-based counts without exaggerating the role of sampling noise. You should also be able to speak about a small gate set in structural language rather than as a list of symbols to memorize.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Gates Are Transformations In Context
|
|
|
|
A gate becomes intelligible only inside a state story. `X` is not just “bit flip,” `Z` is not just “phase flip,” and `H` is not just “puts a qubit into superposition.” Those slogans are useful doorway phrases, but they are not enough for design. The real question is always: what transformation does this gate apply to the object currently on the wire, and how does that affect the experiment the rest of the circuit is building?
|
|
|
|
This contextual view matters because the same symbol can carry a different teaching burden in different places. A final Hadamard before measurement is not doing the same job as an initial Hadamard during preparation, even if the matrix is the same. The lecture therefore treats gates by role inside a circuit story rather than by symbol name alone.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Measurement Is A Protocol, Not A Punctuation Mark
|
|
|
|
Many beginners read the measurement symbol as if it were the period at the end of a sentence. That is too weak. A measurement stage contains real design choices. Which basis are you measuring in? Which classical bits record the results? How many shots are you taking? Are you comparing the sampled evidence to an ideal probability model or simply admiring the bars? These are protocol questions, and they change what you are justified in saying about the experiment.
|
|
|
|
Once you start seeing measurement this way, many later notebooks become easier. Basis rotation is no longer weird. Readout mapping is no longer bookkeeping trivia. Counts are no longer mistaken for the state itself. The whole evidence chain becomes more legible.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## The Small Gate Vocabulary That Already Matters
|
|
|
|
At this stage you do not need a zoo of gates to become dangerous in a good way. `X` lets you change preparation in a visibly classical-looking way. `Z` lets you change phase without changing computational-basis probabilities. `H` serves as a bridge between bases and therefore between hidden structure and visible evidence. `CX` lets one wire's story become part of another wire's story. That is already enough to build serious beginner insights.
|
|
|
|
A strong course resists the urge to flood the beginner with symbols too early. The point is not to shrink the field. The point is to make the field legible by keeping the vocabulary small enough that the important distinctions remain visible.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Counts, Probabilities, And Shot Noise
|
|
|
|
A probability model and a finite-shot histogram are related, but they are not the same object. The model says what outcomes are expected in the ideal story. The histogram says what repeated sampling returned in this run with this shot budget. Differences between the two can be conceptually meaningful, but they can also be ordinary sampling fluctuation. Professional reasoning does not panic about that distinction. It names it.
|
|
|
|
This is why the course keeps showing both the ideal description and the shot-based evidence. You need both. The ideal story gives you a reference. The sampled evidence tells you what the chosen protocol produced empirically.
|
|
"""
|
|
),
|
|
code_cell(SETUP),
|
|
code_cell(COMMON_IMPORTS),
|
|
markdown_cell(
|
|
"""
|
|
## Code-To-Diagram Anchor
|
|
|
|
The anchor circuit below is deliberately chosen to mix preparation, basis change, and final readout. Read the marker table before you touch the code. The objective is to keep the three layers separate in your head: what was prepared, what question was asked, and how the evidence was reported.
|
|
"""
|
|
),
|
|
code_cell(f"step_reference_table({MEASUREMENT_STEP_REFS!r})"),
|
|
editable_lab_code(
|
|
BASIS_BELL_EDITABLE,
|
|
title="Measurement Anchor: Bell Preparation With Basis Rotation",
|
|
instructions="Change the final basis rotation or the classical wiring and explain whether you changed the preparation story, the measurement question, or only the reporting layer.",
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Comparing The Same Preparation Under Different Questions
|
|
|
|
The fastest way to internalize basis dependence is to compare near-identical circuits that differ only by a final basis rotation. The prepared object is closely related, but the question changes. That alone can change the counts dramatically. This is not a contradiction. It is the intended behavior of a protocol-sensitive experiment.
|
|
"""
|
|
),
|
|
code_cell(
|
|
"""
|
|
z_basis = QuantumCircuit(1, 1)
|
|
z_basis.h(0)
|
|
z_basis.measure(0, 0)
|
|
|
|
x_basis_probe = QuantumCircuit(1, 1)
|
|
x_basis_probe.h(0)
|
|
x_basis_probe.h(0)
|
|
x_basis_probe.measure(0, 0)
|
|
|
|
z_counts = simulate_counts(z_basis, shots=512)
|
|
x_counts = simulate_counts(x_basis_probe, shots=512)
|
|
|
|
{
|
|
"z_basis_counts": z_counts,
|
|
"x_basis_counts": x_counts,
|
|
}
|
|
"""
|
|
),
|
|
code_cell(
|
|
"""
|
|
plot_counts(z_counts, title="Same Preparation, Z-Basis Readout")
|
|
plot_counts(x_counts, title="Same Preparation, X-Basis Readout")
|
|
"""
|
|
),
|
|
quiz_code(MEASUREMENT_QUIZ_A, "Measurement Checkpoint A"),
|
|
markdown_cell(
|
|
"""
|
|
## Classical Wiring Is Part Of The Explanation
|
|
|
|
There is a common beginner habit of stopping the explanation at the quantum wires and treating classical bits as a passive output tray. That is not good enough. Classical mapping can preserve the intended story, scramble it, or at least make it much harder to read. A correct quantum preparation with careless reporting can still produce misleading evidence. Good notebook pedagogy therefore keeps the classical bits visible and discussed.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Common Misreadings To Avoid
|
|
|
|
The first misreading is to treat the final Hadamard as if it “changes the state at the last minute” without asking what measurement basis it is inducing. The second is to treat counts as exact probabilities rather than samples. The third is to ignore classical bit order and then invent a wrong explanation for the resulting labels. The fourth is to describe `CX` as copy without checking what state sits on the control wire. Each of those mistakes can survive for a while if no notebook forces explicit writing. This course forces the writing so the mistakes become easier to catch.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## A Reviewer's Checklist For Measurement Claims
|
|
|
|
Suppose a teammate shows you a histogram and says the circuit “worked.” A weak review asks only whether the bars look plausible. A strong review asks at least five questions. What exactly was prepared? In what basis was the final question asked? How were qubits mapped onto classical bits? What shot count produced this evidence? And what competing interpretation would become visible if one of those protocol choices changed? That checklist sounds heavy for a beginner module, but it is precisely the right weight. The whole point of this lecture is to introduce professional suspicion early, before the circuits become large enough to hide sloppy reasoning.
|
|
|
|
Notice that none of those review questions require advanced hardware knowledge. They are conceptual hygiene. That is good news. It means you can practice real engineering discipline locally on small circuits right now. The habits do not need to wait for larger projects. They just need to be named and repeated until they become normal.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Why This Module Cares About Tiny Protocol Details
|
|
|
|
Some learners initially resent the amount of attention paid to basis labels, classical mappings, and shot budgets. They want the quantum part and regard the rest as bureaucracy. That instinct has to be corrected. In real circuit work, many bad conclusions are not caused by exotic quantum subtleties. They are caused by ordinary protocol sloppiness. A basis change was inserted and forgotten. A histogram was treated as if it were exact probability. A swapped classical mapping made the evidence look inconsistent. Those are not glamorous errors, but they are expensive ones. A good lecture series trains against them early.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## From Measurement Literacy To Design Judgment
|
|
|
|
The real long-term point of this module is not merely to make you careful around histograms. It is to prepare you for later design judgment. Once circuits become larger, you will constantly face questions such as: did the transpiler change only the routing structure or did it alter the effective question being asked at the end, is a mismatch between ideal and empirical behavior likely to come from noise or from a protocol mistake, and does a proposed optimization preserve the intended evidence path? Those are hard questions only if the current small questions are still blurry. If, however, you have already learned to separate preparation, basis, and reporting on tiny circuits, the larger versions become recognizable.
|
|
|
|
That is why the lecture is unapologetically detailed about matters that can look pedestrian. Professional competence is often the accumulation of correctly handled small distinctions. Basis discipline, count interpretation, and reporting clarity are part of that accumulation. They are not glamorous, but they are absolutely central.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Transfer Forward
|
|
|
|
Once you can separate preparation, question, and reporting, later modules on noisy evidence, verification, and hardware-aware redesign become much easier. You will know which part of the story changed and which part remained stable. That is the real payoff of this lecture. It is building disciplined measurement language before the course moves into more crowded engineering territory.
|
|
"""
|
|
),
|
|
quiz_code(MEASUREMENT_QUIZ_B, "Measurement Checkpoint B"),
|
|
reflection_code(
|
|
"Explain why a final Hadamard before measurement is often better described as a basis choice than as a mysterious last-minute state change."
|
|
),
|
|
reflection_code(
|
|
"Write a short paragraph on why classical bit mapping belongs in a professional explanation of a circuit result."
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Mastery Gate
|
|
|
|
Leave this lecture only when you can inspect a circuit and say, in separate sentences, what the gates prepared, what the measurement protocol asked, and how the reported counts should be interpreted. If those three sentences still blur together, stay with the module.
|
|
"""
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
def build_measurement_lab() -> dict:
|
|
return notebook(
|
|
[
|
|
markdown_cell(
|
|
"""
|
|
# Gates and Measurement Lab
|
|
|
|
This lab turns protocol language into concrete manipulation. The main question is not whether the circuit executes. The main question is whether you can change preparation, basis, or reporting one at a time and still keep the explanation stable.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab Protocol
|
|
|
|
Use the same lab cycle as before: predict, edit one thing, render, inspect, and revise. The only difference here is that you should now classify the edit even more explicitly. Did you change the prepared state, the measurement basis, or the classical reporting layer? If you cannot answer that, the edit was not conceptually controlled enough.
|
|
"""
|
|
),
|
|
code_cell(SETUP),
|
|
code_cell(COMMON_IMPORTS),
|
|
markdown_cell(
|
|
"""
|
|
## Lab 1: Small Gate Compositions
|
|
|
|
Start with a one-qubit circuit. Move `X`, `H`, and `Z` around and explain why the final counts change or fail to change. The purpose is to stop treating gate names as slogans and start treating them as transformations in sequence.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
SINGLE_QUBIT_GATE_EDITABLE,
|
|
title="Lab 1: Small Gate Composition",
|
|
instructions="Reorder or add one gate at a time and explain whether the change altered preparation, phase, or the measurement question.",
|
|
),
|
|
code_cell(
|
|
"""
|
|
low_shot = QuantumCircuit(1, 1)
|
|
low_shot.h(0)
|
|
low_shot.measure(0, 0)
|
|
|
|
counts_64 = simulate_counts(low_shot, shots=64)
|
|
counts_4096 = simulate_counts(low_shot, shots=4096)
|
|
{
|
|
"64_shots": counts_64,
|
|
"4096_shots": counts_4096,
|
|
}
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
The first lab makes a simple but essential point: the meaning of a gate sequence is not the sum of independent gate slogans. Order matters. Context matters. A `Z` in the middle of a sequence can be invisible in one immediate view and decisive in a later one.
|
|
"""
|
|
),
|
|
quiz_code(MEASUREMENT_LAB_QUIZ_A, "Measurement Lab Checkpoint A"),
|
|
reflection_code(
|
|
"Which one-qubit edit best exposed the difference between changing preparation and changing the final question?"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab 2: Basis Rotation On A Two-Qubit Circuit
|
|
|
|
Return to the Bell-style preparation and vary the final Hadamard placement. Ask the stronger question every time: what did this edit change in the protocol, and what evidence would support that claim?
|
|
"""
|
|
),
|
|
code_cell(f"step_reference_table({MEASUREMENT_STEP_REFS!r})"),
|
|
editable_lab_code(
|
|
BASIS_BELL_EDITABLE,
|
|
title="Lab 2: Bell Basis Rotation",
|
|
instructions="Move or delete the final Hadamard and explain whether your edit changed preparation or only the final measurement question.",
|
|
),
|
|
code_cell(
|
|
"""
|
|
bell_z = QuantumCircuit(2, 2)
|
|
bell_z.h(0)
|
|
bell_z.cx(0, 1)
|
|
bell_z.measure([0, 1], [0, 1])
|
|
|
|
bell_x_probe = QuantumCircuit(2, 2)
|
|
bell_x_probe.h(0)
|
|
bell_x_probe.cx(0, 1)
|
|
bell_x_probe.h(0)
|
|
bell_x_probe.measure([0, 1], [0, 1])
|
|
|
|
{
|
|
"z_basis_counts": simulate_counts(bell_z, shots=512),
|
|
"probe_counts": simulate_counts(bell_x_probe, shots=512),
|
|
}
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab 3: Reporting Layer Sanity Check
|
|
|
|
The last lab isolates classical wiring. Swapping the target classical bits should not be explained as a change in quantum preparation. It is a reporting change. That sounds obvious when written plainly, but many learners still misread the resulting bitstrings unless the notebook forces the distinction.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
WIRING_EDITABLE,
|
|
title="Lab 3: Classical Wiring Check",
|
|
instructions="Switch between direct and swapped classical mappings and explain how the evidence labels change even if the quantum preparation story does not.",
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
This exercise is professionally important because many debugging mistakes come from the reporting layer, not from the state preparation layer. A world-class lecture series should train that suspicion early rather than treating it as an advanced nuisance.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Lab Debrief
|
|
|
|
These three labs together teach a simple review pattern. First ask whether the preparation changed. If not, ask whether the measurement basis changed. If not, ask whether only the reporting layer changed. That sequence is powerful because it narrows explanation quickly. It also stops you from inventing dramatic quantum stories for what may only be a bookkeeping issue.
|
|
|
|
The debrief is worth reading carefully because many learners still default to a single undifferentiated sentence such as “the circuit output changed.” That sentence contains almost no engineering value. A stronger sentence might be: “The prepared Bell-style state stayed the same, but the added Hadamard changed the first qubit's measurement basis, so the empirical correlation pattern now answers a different question.” That is the level of explanation this lab is trying to normalize.
|
|
"""
|
|
),
|
|
quiz_code(MEASUREMENT_LAB_QUIZ_B, "Measurement Lab Checkpoint B"),
|
|
reflection_code(
|
|
"Write a short explanation of how you would distinguish a basis mistake from a classical-wiring mistake in a notebook review."
|
|
),
|
|
reflection_code(
|
|
"What does shot noise change in your interpretation, and what does it not change?"
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
def build_measurement_problems() -> dict:
|
|
cells = [
|
|
markdown_cell(
|
|
"""
|
|
# Gates and Measurement Problems
|
|
|
|
This notebook checks whether the protocol distinctions remain stable away from the worked examples. The questions are simple on purpose. If the simple distinctions fail, larger circuits will only hide the failure behind more syntax.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Problem-Solving Standard
|
|
|
|
Do not ask only whether an option is correct. Ask why the other options are tempting and why they fail. That is how you identify the beginner story you are outgrowing.
|
|
"""
|
|
),
|
|
code_cell(SETUP),
|
|
code_cell(COMMON_IMPORTS),
|
|
]
|
|
|
|
for heading, questions in MEASUREMENT_PROBLEM_SETS:
|
|
cells.append(
|
|
markdown_cell(
|
|
f"""
|
|
## {heading}
|
|
|
|
Treat each quiz as a short diagnostic review. The point is not speed. The point is clarity about which layer of the experiment you are describing.
|
|
"""
|
|
)
|
|
)
|
|
cells.append(quiz_code(questions, heading))
|
|
|
|
cells.extend(
|
|
[
|
|
markdown_cell(
|
|
"""
|
|
## Mini Case: A Plausible Histogram Can Still Be Misread
|
|
|
|
One of the central habits in this module is distrust of superficial plausibility. A Bell-like histogram can look comforting even when the explanation attached to it is wrong. Perhaps the basis changed and nobody said so. Perhaps the classical wiring was reversed. Perhaps the shot count was low enough that the learner over-interpreted noise as structure. These are exactly the kinds of mistakes the problem sets are training you to catch.
|
|
|
|
Keep that in mind while writing the reflections below. The real achievement is not getting every quiz right. The real achievement is being able to explain how an apparently reasonable interpretation could still fail and what extra protocol information would settle the matter.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Written Checks
|
|
|
|
Use the prompts below to produce complete measurement-language sentences. If you cannot explain basis, reporting, and evidence without looking back at the lecture, you are not ready to rely on the distinction later under noise or transpilation pressure.
|
|
"""
|
|
),
|
|
reflection_code(
|
|
"Explain the difference between changing a prepared state and changing the question asked of that state."
|
|
),
|
|
reflection_code(
|
|
"Write a short review note describing one way a correct circuit could still be misread because of classical register wiring."
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Exit Condition
|
|
|
|
Move on only when you can tell the story of a histogram without collapsing preparation, basis choice, and classical reporting into one vague sentence.
|
|
"""
|
|
),
|
|
]
|
|
)
|
|
return notebook(cells)
|
|
|
|
|
|
def build_measurement_studio() -> dict:
|
|
return notebook(
|
|
[
|
|
markdown_cell(
|
|
"""
|
|
# Gates and Measurement Studio
|
|
|
|
This studio asks for protocol design. You are no longer just interpreting prepared examples. You are choosing how to prepare, how to probe, and how to report. That is exactly the kind of ownership a professional circuit designer needs.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Studio Standard
|
|
|
|
Every answer should separate three layers explicitly: preparation, measurement basis, and reporting. If those layers remain fused in your language, the design is not yet under control.
|
|
"""
|
|
),
|
|
code_cell(SETUP),
|
|
code_cell(COMMON_IMPORTS),
|
|
markdown_cell(
|
|
"""
|
|
## Brief 1: One-Qubit Basis Contrast
|
|
|
|
Build a one-qubit protocol that produces a deterministic result in one basis and a non-deterministic result in another. The point is not novelty. The point is to justify why the contrast is caused by a changed question rather than by hand-waving.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
SINGLE_QUBIT_GATE_EDITABLE,
|
|
title="Studio Brief 1: Basis Contrast",
|
|
instructions="Use a small gate vocabulary to make one basis deterministic and another basis informative. Explain the protocol clearly.",
|
|
),
|
|
reflection_code(
|
|
"Why does your protocol count as a basis contrast rather than just a different state-preparation demo?"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Brief 2: Two-Qubit Correlation Probe
|
|
|
|
Start from the Bell preparation and decide which basis or readout change best tests the story you want to claim. Write your explanation as if another engineer had to review it.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
BASIS_BELL_EDITABLE,
|
|
title="Studio Brief 2: Correlation Probe",
|
|
instructions="Tune the basis choices and defend what kind of correlation evidence the circuit should produce.",
|
|
),
|
|
reflection_code(
|
|
"What evidence in the counts would actually support your claim, and what evidence would falsify it?"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Brief 3: Reporting-Layer Stress Test
|
|
|
|
Use swapped or altered classical wiring deliberately. The point is to produce a circuit whose quantum preparation is fine but whose reporting layer could mislead a careless reader. Then write the warning note that a reviewer should leave.
|
|
"""
|
|
),
|
|
editable_lab_code(
|
|
WIRING_EDITABLE,
|
|
title="Studio Brief 3: Reporting-Layer Stress Test",
|
|
instructions="Use classical wiring deliberately and then explain how a review note should prevent misinterpretation.",
|
|
),
|
|
quiz_code(MEASUREMENT_STUDIO_QUIZ, "Measurement Studio Check"),
|
|
reflection_code(
|
|
"What is the most subtle protocol mistake you can now imagine making in your own notebook work?"
|
|
),
|
|
reflection_code(
|
|
"Which part of measurement reasoning now feels reliable, and which part still feels too dependent on the exact example in front of you?"
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Studio Rubric
|
|
|
|
Use a strict rubric on yourself here. A good studio answer makes the preparation explicit, makes the basis choice explicit, makes the classical mapping explicit, and says what evidence would count as success or failure. It also admits uncertainty honestly. If you are unsure whether your chosen probe actually distinguishes two candidate explanations, write that uncertainty down and propose the next check. That is not weakness. That is proper review culture.
|
|
|
|
This rubric is intentionally demanding because measurement notebooks are where many people learn bad habits: overclaiming from too little evidence, blurring protocol choices together, or treating a nice-looking plot as proof. The studio exists to train the opposite behavior. Clear protocol, explicit evidence, and disciplined interpretation. Nothing less will scale to professional work.
|
|
"""
|
|
),
|
|
markdown_cell(
|
|
"""
|
|
## Studio Exit
|
|
|
|
A strong studio result is not the most elaborate circuit. It is the clearest protocol. If you can prepare, question, report, and defend the evidence chain cleanly, the module has done its job.
|
|
"""
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
outputs = {
|
|
MODULE_02_DIR / "lecture.ipynb": build_statevector_lecture(),
|
|
MODULE_02_DIR / "lab.ipynb": build_statevector_lab(),
|
|
MODULE_02_DIR / "problems.ipynb": build_statevector_problems(),
|
|
MODULE_02_DIR / "studio.ipynb": build_statevector_studio(),
|
|
MODULE_03_DIR / "lecture.ipynb": build_measurement_lecture(),
|
|
MODULE_03_DIR / "lab.ipynb": build_measurement_lab(),
|
|
MODULE_03_DIR / "problems.ipynb": build_measurement_problems(),
|
|
MODULE_03_DIR / "studio.ipynb": build_measurement_studio(),
|
|
}
|
|
|
|
for path, payload in outputs.items():
|
|
write_notebook(path, payload)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|