mirror of
https://github.com/saymrwulf/QuantumLearning.git
synced 2026-05-14 20:58:00 +00:00
1363 lines
78 KiB
Python
1363 lines
78 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_DIR = NOTEBOOKS / "foundations" / "module_01_principles_and_circuit_literacy"
|
||
|
||
|
||
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,
|
||
}
|
||
|
||
|
||
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 (
|
||
bell_circuit,
|
||
counts_to_probabilities,
|
||
draw_circuit,
|
||
editable_circuit_lab,
|
||
load_curriculum,
|
||
plot_counts,
|
||
quiz_block,
|
||
reflection_box,
|
||
simulate_counts,
|
||
statevector_probabilities,
|
||
step_reference_table,
|
||
)
|
||
"""
|
||
|
||
|
||
LECTURE_STEP_REFS = [
|
||
{
|
||
"marker": "[1]",
|
||
"code_focus": "Prepare qubit 0 with a Hadamard gate.",
|
||
"diagram_effect": "The upper wire branches into a superposition-generating event.",
|
||
"why_it_matters": "This is the first step where the circuit stops behaving like a deterministic classical path.",
|
||
},
|
||
{
|
||
"marker": "[2]",
|
||
"code_focus": "Use CNOT from qubit 0 to qubit 1.",
|
||
"diagram_effect": "The second wire becomes correlated with the branching created above.",
|
||
"why_it_matters": "This is the moment where local gate syntax becomes shared circuit structure.",
|
||
},
|
||
{
|
||
"marker": "[3]",
|
||
"code_focus": "Measure both qubits into matching classical bits.",
|
||
"diagram_effect": "The diagram turns a latent correlation into an empirical question.",
|
||
"why_it_matters": "Measurement is not a camera; it is the question being asked of the prepared state.",
|
||
},
|
||
]
|
||
|
||
|
||
BELL_EDITABLE = """
|
||
circuit = QuantumCircuit(2, 2)
|
||
# [1] Prepare the branch point.
|
||
circuit.h(0)
|
||
# [2] Correlate the second qubit with the first.
|
||
circuit.cx(0, 1)
|
||
# [3] Ask the question in the computational basis.
|
||
circuit.measure([0, 1], [0, 1])
|
||
"""
|
||
|
||
|
||
BASIS_EDITABLE = """
|
||
circuit = QuantumCircuit(2, 2)
|
||
# [1] Create the same Bell-style preparation.
|
||
circuit.h(0)
|
||
circuit.cx(0, 1)
|
||
# [2] Rotate qubit 0 before asking the measurement question.
|
||
circuit.h(0)
|
||
# [3] Measure both qubits and compare the change.
|
||
circuit.measure([0, 1], [0, 1])
|
||
"""
|
||
|
||
|
||
GHZ_EDITABLE = """
|
||
circuit = QuantumCircuit(3, 3)
|
||
# [1] Start the branching on the first qubit.
|
||
circuit.h(0)
|
||
# [2] Fan the correlation outward.
|
||
circuit.cx(0, 1)
|
||
circuit.cx(0, 2)
|
||
# [3] Measure all wires in the computational basis.
|
||
circuit.measure([0, 1, 2], [0, 1, 2])
|
||
"""
|
||
|
||
|
||
LECTURE_QUIZ_A = [
|
||
{
|
||
"prompt": "Which sentence best describes what a circuit diagram is trying to show you?",
|
||
"options": [
|
||
"A list of independent gate icons that happen to share a page",
|
||
"A time-ordered argument about how a state is being prepared, transformed, and questioned",
|
||
"A decorative rendering of code that mainly helps with presentation",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The course treats a circuit as a time-ordered process whose meaning must be narrated, not just executed.",
|
||
},
|
||
{
|
||
"prompt": "Why is the spinning coin analogy useful but limited?",
|
||
"options": [
|
||
"Because it proves that quantum states are really just classical ignorance",
|
||
"Because it helps introduce non-binary intuition but cannot capture amplitudes, phase, and measurement structure faithfully",
|
||
"Because it is mainly a historical story with no teaching value",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The analogy helps at the doorway, but quantum states require more disciplined language than classical randomness.",
|
||
},
|
||
{
|
||
"prompt": "What is the main teaching reason to keep code, circuit graphic, and counts together?",
|
||
"options": [
|
||
"So the notebook feels more interactive",
|
||
"So the same idea is forced to survive multiple representations",
|
||
"So matplotlib gets used early in the course",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "Robust understanding survives translation across representations.",
|
||
},
|
||
]
|
||
|
||
|
||
LECTURE_QUIZ_B = [
|
||
{
|
||
"prompt": "In a Bell-style circuit, what conceptual role does the CNOT play after the Hadamard?",
|
||
"options": [
|
||
"It measures the first qubit before the circuit finishes",
|
||
"It copies classical information from one wire to another",
|
||
"It turns the earlier branching into a structured correlation between wires",
|
||
],
|
||
"correct_index": 2,
|
||
"explanation": "The circuit is not copying a classical bit; it is creating structured correlation from the prepared branch.",
|
||
},
|
||
{
|
||
"prompt": "What changes when you insert a basis rotation before measurement?",
|
||
"options": [
|
||
"The underlying prepared state is reinterpreted through a different question",
|
||
"Nothing important changes because measurement is always the same",
|
||
"The qubit becomes classical before the rotation happens",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "Measurement answers a basis-relative question, so basis changes matter profoundly.",
|
||
},
|
||
{
|
||
"prompt": "Which habit is most aligned with professional circuit-design growth?",
|
||
"options": [
|
||
"Run first, explain later",
|
||
"Predict, run, compare, and revise the story explicitly",
|
||
"Memorize gate names until the diagrams feel familiar",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "Prediction and explanation are the key habits that distinguish passive exposure from design training.",
|
||
},
|
||
]
|
||
|
||
|
||
LAB_QUIZ_A = [
|
||
{
|
||
"prompt": "If you remove the Hadamard from a Bell circuit but leave the CNOT, what broad result should you expect?",
|
||
"options": [
|
||
"Only one deterministic outcome from the all-zero input",
|
||
"The same balanced Bell histogram as before",
|
||
"A completely uniform distribution over all bitstrings",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "Without the branch point, the circuit stays on a single classical-looking path from the ground state.",
|
||
},
|
||
{
|
||
"prompt": "Why does the lab ask you to compare the graphic and text rendering of the same circuit?",
|
||
"options": [
|
||
"Because they reveal different structural truths and catch different mistakes",
|
||
"Because one of them is usually wrong and the other is correct",
|
||
"Because Qiskit requires both before simulation",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "The pretty diagram and the text rendering support different kinds of inspection.",
|
||
},
|
||
]
|
||
|
||
|
||
LAB_QUIZ_B = [
|
||
{
|
||
"prompt": "What should a useful lab reflection contain?",
|
||
"options": [
|
||
"Only whether the code ran successfully",
|
||
"A prediction, an observed result, and a revised explanation if the prediction failed",
|
||
"Mostly notes about notebook formatting and display quality",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The reflection is for diagnosing the model in your head, not merely logging execution success.",
|
||
},
|
||
{
|
||
"prompt": "What is the most important consequence of inserting a Hadamard immediately before measuring qubit 0 in the Bell circuit?",
|
||
"options": [
|
||
"You change the question being asked of that wire",
|
||
"You remove the need for the CNOT",
|
||
"You make the circuit noiseless",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "A basis rotation before measurement changes the question, not just the syntax.",
|
||
},
|
||
]
|
||
|
||
|
||
PROBLEMS_QUIZZES = [
|
||
{
|
||
"heading": "Problem Set A",
|
||
"questions": [
|
||
{
|
||
"prompt": "Which statement best distinguishes superposition from classical ignorance in this course?",
|
||
"options": [
|
||
"Superposition is just not knowing which classical value is present",
|
||
"Superposition requires amplitude and phase language, not just hidden classical values",
|
||
"They are the same idea described by different communities",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The course insists on the amplitude-and-phase distinction rather than collapsing quantum reasoning into classical uncertainty.",
|
||
},
|
||
{
|
||
"prompt": "Why is a barrier sometimes pedagogically useful?",
|
||
"options": [
|
||
"It changes the quantum state substantially",
|
||
"It marks conceptual checkpoints in a circuit story",
|
||
"It is required before every measurement",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The barrier is often a reading aid that marks stages in the explanation.",
|
||
},
|
||
{
|
||
"prompt": "What does the histogram of a measured circuit tell you directly?",
|
||
"options": [
|
||
"The exact pre-measurement statevector",
|
||
"The empirical distribution produced by the chosen measurement question",
|
||
"The coupling map of the backend",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "Counts summarize answers to the chosen measurement question, not the full underlying state by themselves.",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
"heading": "Problem Set B",
|
||
"questions": [
|
||
{
|
||
"prompt": "What is the most dangerous beginner misreading of CNOT in an entangling circuit?",
|
||
"options": [
|
||
"Treating it as a classical copy operation with no dependence on context",
|
||
"Thinking it always increases circuit depth",
|
||
"Assuming it cannot be simulated locally",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "The gate’s meaning depends on the prepared input, not just on its classical truth-table summary.",
|
||
},
|
||
{
|
||
"prompt": "Why do we ask for predictions before running the code?",
|
||
"options": [
|
||
"Because predictions make the simulator faster",
|
||
"Because wrong predictions reveal the exact point where understanding is unstable",
|
||
"Because the notebook should avoid plotting too often",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "Prediction creates diagnostic value when the result disagrees with your model.",
|
||
},
|
||
{
|
||
"prompt": "Which description of measurement is most aligned with this module?",
|
||
"options": [
|
||
"Measurement is a neutral camera that simply reads whatever is already there",
|
||
"Measurement is the final irreversible question chosen by the circuit designer",
|
||
"Measurement is mostly a plotting convenience for notebooks",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The chosen basis and readout structure determine which question is being asked.",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
"heading": "Problem Set C",
|
||
"questions": [
|
||
{
|
||
"prompt": "If a circuit prepares strong correlation but your counts disagree strongly with the intended story, what should you inspect first in this module?",
|
||
"options": [
|
||
"Whether the register mapping, basis rotation, or measurement wiring changed the question",
|
||
"Only the color theme of the notebook",
|
||
"Whether the Hadamard symbol is drawn correctly",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "The first debugging step is to inspect the question being asked, not to assume the preparation story survived unchanged.",
|
||
},
|
||
{
|
||
"prompt": "What does it mean to own a circuit rather than merely see it?",
|
||
"options": [
|
||
"You can execute it on your machine",
|
||
"You can reconstruct the design intention, alter it deliberately, and explain what changed",
|
||
"You can recognize the gate icons quickly",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "Ownership means explanatory and design control, not simple familiarity.",
|
||
},
|
||
{
|
||
"prompt": "Why is the Bell circuit used repeatedly in this module?",
|
||
"options": [
|
||
"Because repetition around a sharp mechanism is stronger than shallow novelty",
|
||
"Because no other circuits exist at this level",
|
||
"Because Qiskit only supports two-qubit examples in beginner notebooks",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "A recurring anchor example lets the same idea be revisited through richer lenses.",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
"heading": "Problem Set D",
|
||
"questions": [
|
||
{
|
||
"prompt": "What is the best reason to annotate code with numbered reference markers?",
|
||
"options": [
|
||
"To force translation between source code, circuit picture, and conceptual explanation",
|
||
"To reduce file size",
|
||
"To satisfy a Jupyter formatting requirement",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "The markers make cross-representation reading deliberate instead of accidental.",
|
||
},
|
||
{
|
||
"prompt": "Why does the course separate lecture, lab, problems, and studio?",
|
||
"options": [
|
||
"Because one notebook cannot adequately train reading, manipulation, retrieval, and design at the same time",
|
||
"Because Jupyter does not allow long notebooks",
|
||
"Because the user asked for more files",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "Different notebook types carry different pedagogical burdens.",
|
||
},
|
||
{
|
||
"prompt": "What should happen after you miss a multiple-choice question in this course?",
|
||
"options": [
|
||
"You should ignore it because the code matters more",
|
||
"You should use it to locate the exact distinction the prose or circuit story must reinforce",
|
||
"You should skip the rest of the module",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "Missed retrieval is a diagnostic event, not just a score event.",
|
||
},
|
||
],
|
||
},
|
||
]
|
||
|
||
|
||
STUDIO_QUIZ = [
|
||
{
|
||
"prompt": "Which sentence best captures the purpose of the studio notebook?",
|
||
"options": [
|
||
"To replay the lecture passively with nicer formatting",
|
||
"To make design choices under constraints and justify them in review language",
|
||
"To collect more plots without changing the circuits",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The studio is where explanation becomes design responsibility.",
|
||
},
|
||
{
|
||
"prompt": "What distinguishes a design brief from a worked example?",
|
||
"options": [
|
||
"A design brief leaves decisions open and expects justification",
|
||
"A design brief never includes code",
|
||
"A design brief avoids metrics completely",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "In the studio, the learner must decide and defend, not just replay.",
|
||
},
|
||
]
|
||
|
||
|
||
def build_course_blueprint() -> dict:
|
||
return notebook(
|
||
[
|
||
markdown_cell(
|
||
"""
|
||
# Course Blueprint
|
||
|
||
This notebook is the new front door of the platform. The earlier version of the project had ambition, interactivity, and a serious mastery model, but it still behaved too much like a set of topic notebooks. A world-class lecture series needs a stronger spine. The spine now comes from a hybrid design: textbook sequence for coherence, apprenticeship pressure for professional growth, and local-first Jupyter execution for sustained practice.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Why The Architecture Changed
|
||
|
||
A beginner does not merely need more text. A beginner needs a trustworthy order. The PDF backbone that now informs this project moves from principles to qubits to gates to Qiskit engineering to optimization to simulation to algorithms and finally to workflow patterns. That sequence is strong because it makes later ideas feel earned rather than arbitrary.
|
||
|
||
Our previous curriculum had a different strength: it was already clearer than most tutorials about the professional destination. It said that the end-state is not “ran some Qiskit notebooks” but “independent hardware-aware circuit designer.” That was the right ambition, but it was acting like a top-heavy staircase. The new architecture keeps the ambition and fixes the staircase.
|
||
|
||
The result is a hybrid model:
|
||
|
||
- the book-like spine provides canonical order
|
||
- the apprenticeship layer provides mastery gates and design pressure
|
||
- the notebook bundle pattern provides deliberate pedagogy instead of one giant mixed notebook
|
||
|
||
This notebook is not here to motivate you vaguely. It is here to tell you exactly how the course is organized so the rest of the series becomes legible.
|
||
"""
|
||
),
|
||
code_cell(SETUP),
|
||
code_cell(
|
||
COMMON_IMPORTS
|
||
+ """
|
||
|
||
curriculum = load_curriculum()
|
||
[
|
||
{
|
||
"band": band.title,
|
||
"module_count": len(band.modules),
|
||
"rationale": band.rationale,
|
||
}
|
||
for band in curriculum.bands
|
||
]
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## The Four Technical Bands
|
||
|
||
The technical mainline now has four bands:
|
||
|
||
1. **Foundations**: principles, qubits, gates, measurement, and the first disciplined understanding of circuits as arguments rather than raw syntax.
|
||
2. **Qiskit Engineering**: construction, analysis, transpilation, visualization, simulation, and noise models.
|
||
3. **Algorithmic Design**: foundational and applied algorithm families used as reusable circuit motifs, not just as curiosities.
|
||
4. **Professional Design**: workflow patterns, hardware-aware redesign, verification, mitigation thinking, and capstone review.
|
||
|
||
Orientation still exists, but it is not the whole course. It is now treated like course navigation and diagnostic framing. Once that framing is clear, the course should feel like a real lecture series rather than a manifesto.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## The Bundle Pattern
|
||
|
||
Every serious module will be rebuilt as a four-notebook bundle:
|
||
|
||
- **Lecture**: deep explanation, canonical worked examples, misconceptions, and transfer language
|
||
- **Lab**: editable circuits, graphics, measurements, and representation shifts
|
||
- **Problems**: retrieval, prediction, debugging, and short written explanation
|
||
- **Studio**: open-ended design brief, comparison, critique, and review language
|
||
|
||
The reason for this separation is simple. One notebook cannot cleanly teach, drill, diagnose, and evaluate design judgment all at once. Tutorials often collapse those roles into a single stream of cells, and the result feels busy but pedagogically blurry. The bundle pattern makes the burden of each notebook explicit.
|
||
|
||
If you use the bundle correctly, you will move through four modes of learning:
|
||
|
||
- understand
|
||
- manipulate
|
||
- retrieve
|
||
- design
|
||
|
||
That sequence is closer to serious engineering education than a single mixed notebook could be.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Textbook Sequence And Apprenticeship Pressure
|
||
|
||
The new architecture is easiest to understand if you separate two design questions that most learning platforms blur together. The first question is sequencing: in what order should ideas appear so that later ones feel intelligible rather than arbitrary? The second question is performance: what kind of work must the learner do so the ideas become capabilities instead of impressions? A textbook usually answers the first question well. An apprenticeship usually answers the second question well. This course is trying to answer both.
|
||
|
||
The textbook influence can be seen in the chapter order that now sits underneath the curriculum. Principles come before qubits, qubits before gates, gates before serious Qiskit engineering, engineering before algorithmic reuse, and algorithms before professional workflow patterns. That order matters because it lets each stage inherit stable language from the stage before it. The apprenticeship influence can be seen in the mastery gates, the prediction prompts, the debugging emphasis, and the requirement to compare candidate designs instead of worshipping the first one that runs.
|
||
|
||
If you remember only one phrase from this notebook, remember this one: the spine provides order, the apprenticeship provides pressure. Both are necessary.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Why The Main Path Remains Local-First
|
||
|
||
The source book includes IBM-platform tooling and cloud usage because it is written for a broad audience. That context is useful, but the main path in this repository remains local-first on purpose. Local-first is a teaching decision. It keeps the beginner loop short, reproducible, and under your control. When a circuit drawing fails, a dependency is missing, or a measurement plot looks wrong, the problem should be close enough that you can inspect it without a cloud account, network request, or moving API target getting in the way.
|
||
|
||
This does not mean hardware awareness is optional. It means hardware awareness is introduced in the right place. First you build the clean story locally. Then you watch compilation, connectivity, or noise distort that story. That order is what protects conceptual clarity. If you begin inside distortion, you never get a clean enough picture of what the circuit was even trying to mean.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## What Counts As Progress
|
||
|
||
Progress in this course is not “finished notebook.” It is:
|
||
|
||
- explained a mechanism cleanly
|
||
- predicted behavior before running
|
||
- modified a circuit without losing the story
|
||
- debugged a mismatch without hand-waving
|
||
- compared two designs with explicit criteria
|
||
|
||
This is why the course keeps the mastery model. The mastery model is not being replaced; it is being placed where it belongs. The textbook spine tells you what order to learn things in. The mastery gates tell you whether the capability is actually landing.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
quiz_block(
|
||
[
|
||
{
|
||
"prompt": "What is the main function of the new bundle pattern?",
|
||
"options": [
|
||
"To split one topic across several notebook types that each carry a different pedagogical burden",
|
||
"To make the repository look larger",
|
||
"To avoid using long-form writing in notebooks",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "Lecture, lab, problems, and studio are intentionally different forms of training.",
|
||
},
|
||
{
|
||
"prompt": "Why is the textbook spine important?",
|
||
"options": [
|
||
"Because beginners need a canonical order so later topics feel earned and coherent",
|
||
"Because it removes the need for mastery gates",
|
||
"Because it guarantees all chapters are equally important",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "The spine supplies sequence and legibility; the apprenticeship layer supplies performance pressure.",
|
||
},
|
||
{
|
||
"prompt": "What is the purpose of the professional-design band?",
|
||
"options": [
|
||
"To defer all serious engineering until the end",
|
||
"To convert earlier circuit knowledge into review, redesign, mitigation, and capstone decision-making",
|
||
"To replace algorithms with workflow prose",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The final band is where competence becomes engineering judgment.",
|
||
},
|
||
],
|
||
heading="Blueprint Quiz A",
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## What To Open Next
|
||
|
||
The full technical mainline is now rebuilt. Start with **Principles and Circuit Literacy**, continue through the rest of the foundations modules, then move into **Circuit Construction and Analysis**, **Transpilation and Visualization**, and **Simulation and Noise Models**, then continue into **Deutsch Family and Oracle Thinking**, **Bernstein-Vazirani and Structured Oracles**, **QFT and Periodic Structure**, and **Grover and Amplitude Amplification**, and finally complete the professional band with **Qiskit Patterns and Workflow Design**, **Hardware-Aware Redesign Studio**, **Noise-Aware Verification and Mitigation**, and **Capstone Circuit Design Review**. Inside each module, read the lecture notebook first. Then move into the lab, then problems, then the studio. Keep that order.
|
||
|
||
The sequence matters. If you jump straight into the studio, you may produce activity without comprehension. If you stop after the lecture, you may feel recognition without control. The four-notebook loop is the point.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
quiz_block(
|
||
[
|
||
{
|
||
"prompt": "What is the intended first complete rebuilt module?",
|
||
"options": [
|
||
"Principles and Circuit Literacy",
|
||
"Capstone Circuit Design Review",
|
||
"Noise-Aware Verification and Mitigation",
|
||
],
|
||
"correct_index": 0,
|
||
"explanation": "The foundations band is the correct place to establish the new standard.",
|
||
},
|
||
{
|
||
"prompt": "What should happen after you finish a lecture notebook?",
|
||
"options": [
|
||
"Move directly to the next lecture so momentum stays high",
|
||
"Use the lab, problems, and studio notebooks to convert explanation into capability",
|
||
"Treat the rest of the module as optional",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The bundle is designed as a full cycle, not as four unrelated files.",
|
||
},
|
||
{
|
||
"prompt": "Where does the mastery model now sit in the architecture?",
|
||
"options": [
|
||
"It is replaced by the textbook sequence",
|
||
"It operates as the assessment and apprenticeship layer on top of the textbook sequence",
|
||
"It appears only in the capstone",
|
||
],
|
||
"correct_index": 1,
|
||
"explanation": "The hybrid design keeps both sequence and performance standards.",
|
||
},
|
||
],
|
||
heading="Blueprint Quiz B",
|
||
)
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"Write down the main reason this architecture should teach better than a flat list of topic notebooks."
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Immediate Route
|
||
|
||
1. Open `notebooks/foundations/module_01_principles_and_circuit_literacy/lecture.ipynb`
|
||
2. Complete the full `lecture -> lab -> problems -> studio` loop for module 1
|
||
3. Repeat the same loop in `module_02_qubit_and_statevector_intuition`
|
||
4. Repeat the same loop in `module_03_gates_and_measurement`
|
||
5. Continue with `qiskit_engineering/module_01_circuit_construction_and_analysis`
|
||
6. Then complete `module_02_transpilation_and_visualization` and `module_03_simulation_and_noise_models`
|
||
7. Continue following the explicit next-notebook handoff until `COURSE_COMPLETE.ipynb`
|
||
|
||
That is the new mainline.
|
||
"""
|
||
),
|
||
]
|
||
)
|
||
|
||
|
||
def build_lecture() -> dict:
|
||
return notebook(
|
||
[
|
||
markdown_cell(
|
||
"""
|
||
# Principles and Circuit Literacy Lecture
|
||
|
||
This lecture is the first rebuilt module of the new course architecture. Its purpose is not merely to introduce a few gates. Its purpose is to install the habits of reading that make later circuit design possible. The module sits at the foundation of the entire lecture series because nearly every later failure in algorithmic design, transpilation reasoning, or verification can be traced back to weak early literacy: weak vocabulary, weak diagram reading, weak distinction between preparation and measurement, or weak ability to narrate what a circuit is doing.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Learning Objective
|
||
|
||
By the end of this lecture, you should be able to do four things with a small Bell-style circuit. First, you should be able to explain its role in plain language without waving your hands and saying that the circuit does “a quantum thing.” Second, you should be able to move between code and diagram without losing your place in time. Third, you should be able to say why a measurement result is the answer to a chosen question rather than a neutral readout of an already classical object. Fourth, you should be able to modify one part of the circuit and state what you expect to change before you run it.
|
||
|
||
That last requirement is important. A course becomes serious at the exact moment it insists that you predict. Prediction is the first practical signal that explanation has started turning into design control.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Why Foundations Need More Than Syntax
|
||
|
||
Beginners are often told that the first task is just to “get familiar with Qiskit syntax.” That advice is incomplete. Syntax matters, but professional circuit design is not built from syntax alone. Syntax is the surface form of a deeper activity: preparing states, creating structure across wires, changing the basis of the question, and reading the consequences of those changes. If you study only syntax, every later notebook feels like memorizing new incantations. If you study mechanism, later notebooks start to look like recombinations of a much smaller set of structural moves.
|
||
|
||
The first structural move in this module is the branch. In a simple circuit, a Hadamard gate is not merely a symbol you type. It is the move that destroys the naive single classical path and forces you to think in alternatives, amplitudes, and later interference. The second structural move is correlation. A two-qubit gate placed after a preparation step is not just an instruction on the second wire. It is a statement about how the meaning of that wire now depends on the story already in flight. The third structural move is the question. Measurement tells you what the circuit designer chose to ask of the prepared state. These three moves — branch, correlate, ask — form the skeleton of the first module.
|
||
|
||
A world-class course needs to slow those moves down enough that you can name them. Otherwise the first circuits feel magical, and magic does not scale to engineering.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Classical Randomness Versus Quantum Superposition
|
||
|
||
The temptation at this stage is to use a classical analogy and never let go of it. The spinning coin is the usual example. It is useful because it breaks the rigid “either 0 or 1” intuition. But it is dangerous when learners mistake the analogy for the thing itself. A spinning coin is still a classical object with hidden details. If you knew the force, the surface, the air resistance, the exact initial conditions, and enough mechanics, you would describe its behavior in classical terms. Quantum superposition is not simply ignorance of a classical hidden value. The language of amplitudes, basis states, and phase is not decorative. It is what makes the quantum story structurally different.
|
||
|
||
This matters for design because the wrong analogy produces the wrong debugging behavior. If you secretly believe that a qubit always had a classical value and measurement merely exposed it, then many circuits will look nonsensical. You will wonder why basis rotations before measurement matter so much, why interference can strengthen some outcomes and suppress others, and why a correlation pattern can emerge that does not reduce cleanly to classical uncertainty. The lecture therefore uses analogy only as a doorway. Once you step through it, the course insists on more precise language.
|
||
|
||
The correct beginner move is not to pretend you already understand amplitudes fully. The correct move is to stop using classical language in places where it no longer fits. A professional designer is not someone who abandoned intuition. A professional designer is someone whose intuition became precise enough to know where an analogy stops helping.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## How To Read A Circuit
|
||
|
||
A circuit should be read as a time-ordered argument. The vertical dimension tells you which wires are involved. The horizontal dimension tells you what happens earlier and later. The mistake many amateurs make is to see only symbols. They notice that there is an `h` here, a `cx` there, and a measurement symbol at the end. That is symbol recognition, not circuit literacy. Circuit literacy begins when you can narrate the causal burden of each step.
|
||
|
||
Consider the Bell-style circuit that anchors this module. The first step places the first qubit into a nontrivial preparation. The second step spreads the consequence of that preparation into a relationship with the second qubit. The final step chooses a measurement basis and stores the answers in classical memory. When learners say “the circuit creates entanglement,” they are not wrong, but they are still skipping the explanation that makes the statement useful. Which line created the branching? Which line turned that branching into a shared relationship? Which line turned the relationship into an empirical result? Those are the questions that convert a diagram from ornament into argument.
|
||
|
||
This is also why code and graphics must be cross-referenced. A world-class notebook cannot assume that a learner will automatically map one to the other. It must force the translation until it becomes a habit. That is the reason for the marker table and editable lab below.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Why The Bell Circuit Is The Right Anchor
|
||
|
||
The Bell circuit is small enough to inspect completely and rich enough to train serious habits. It contains a branch point, a structural relationship between wires, and an interpretable measurement signature. That makes it a nearly perfect first anchor. If a learner cannot narrate this circuit cleanly, then larger circuits will only multiply the confusion. If a learner *can* narrate it cleanly, later modules can reuse the same reading habits with harder material.
|
||
|
||
The deeper reason the Bell circuit matters is that it refuses to tolerate vague explanation. “This creates entanglement” is not useless, but it is too compressed for a learner. Which line creates the branch structure? Which line turns that branch structure into a two-wire relationship? Which line converts the relationship into data? Those more granular questions are the ones that support editing, comparison, and later review.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Representation Switching Is Part Of The Subject
|
||
|
||
Many technical courses treat multiple representations as a convenience. Quantum computing does not permit that luxury. Even in an introductory module you are already moving between code, circuit picture, histogram, probability dictionary, and explanatory prose. That can feel like too much at first, but the discomfort is pointing at a real feature of the field. Good circuit designers do not live inside one representation. They move among several and use each one for a different purpose.
|
||
|
||
This is why the notebook keeps translating the same circuit across several forms. The code tells you what was specified. The diagram tells you the structural ordering across wires. The counts tell you what repeated measurement returned. The prose tells you whether you can actually say what the first three views mean. When the same idea survives all four views, it starts becoming stable.
|
||
"""
|
||
),
|
||
code_cell(SETUP),
|
||
code_cell(COMMON_IMPORTS),
|
||
markdown_cell(
|
||
"""
|
||
## Code-To-Diagram Anchor
|
||
|
||
The next table pins the anchor circuit to three numbered markers. Read the table before touching the editable cell. The objective is to form a clear translation cycle: code line -> diagram change -> conceptual role. If you cannot move through that cycle without hesitation, you have not yet earned the phrase “I understand the circuit.”
|
||
"""
|
||
),
|
||
code_cell(f"step_reference_table({LECTURE_STEP_REFS!r})"),
|
||
markdown_cell(
|
||
"""
|
||
## Editable Anchor Circuit
|
||
|
||
This first editable circuit is intentionally small. The point is not size. The point is control. Change one thing at a time and explain the effect before you click render. If you do not state a prediction first, you lose most of the pedagogical value of the cell.
|
||
"""
|
||
),
|
||
code_cell(
|
||
f"""
|
||
editable_code = {BELL_EDITABLE!r}
|
||
editable_circuit_lab(
|
||
initial_code=editable_code,
|
||
context={{"QuantumCircuit": __import__("qiskit").QuantumCircuit, "simulate_counts": simulate_counts}},
|
||
title="Bell Anchor Lab",
|
||
instructions="Alter one marker at a time, re-render, and compare your prediction to the updated diagram and counts.",
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Guided Interpretation
|
||
|
||
Use the anchor circuit to answer a deeper question: what exactly is the relationship between preparation and measurement? The state prepared before measurement is not the same thing as the histogram returned after many shots. The state is a mathematical object that supports many possible questions. The histogram is the answer to one specific question asked many times. This distinction is subtle enough that many beginners gloss over it, but it is foundational. If you do not internalize it now, later work on basis changes, tomography-like reasoning, or noise diagnostics becomes much harder.
|
||
|
||
The distinction is also why one circuit can give very different empirical stories after a basis rotation. The prepared object may be the same or closely related, but the question has changed. Measurement is therefore part of the design, not an afterthought tacked onto the end of a circuit.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
anchor = bell_circuit(measure=True)
|
||
counts = simulate_counts(anchor, shots=512)
|
||
probabilities = counts_to_probabilities(counts)
|
||
{
|
||
"counts": counts,
|
||
"probabilities": probabilities,
|
||
}
|
||
"""
|
||
),
|
||
code_cell(
|
||
f"quiz_block({LECTURE_QUIZ_A!r}, heading='Lecture Checkpoint A')"
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Measurement As A Question
|
||
|
||
The phrase “measurement collapses the state” is standard, but on its own it is too coarse to guide design. A better beginner question is: collapse into what, after which transformation, and relative to which basis? If you insert a basis-changing gate immediately before measurement, you have not merely changed notebook syntax. You have changed the operational meaning of the readout. This fact is one of the strongest arguments for teaching circuits through code-diagram-analysis loops rather than through isolated definitions.
|
||
|
||
In practice, this means you should look at a measurement instruction and ask what precedes it immediately. Are you measuring directly in the computational basis? Have you rotated one wire? Are you asking the same question of both wires or different questions of each? Even in tiny circuits, these distinctions matter. They are the seeds of later professional habits: identifying what the experiment is actually probing, what the output can justify, and where a misleading interpretation would enter.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Common Misconceptions To Kill Early
|
||
|
||
The first misconception is that measurement simply reports a hidden classical value that was there all along. This destroys your ability to reason about basis dependence. The second misconception is that CNOT always means “copy.” In classical logic that shortcut can work; in quantum circuits it becomes misleading as soon as the control wire is not in a classical basis state. The third misconception is that if the histogram looks right, the circuit is therefore understood. Histograms can look plausible for the wrong reason, especially once noise, compilation, or accidental basis changes enter the picture.
|
||
|
||
The fourth misconception is more emotional than technical: learners think confusion means failure. In reality, confusion becomes useful the moment it is specific. “I do not understand why the inserted Hadamard changed the counts even though the earlier preparation looked the same” is a productive sentence. It contains the exact place where study should deepen. Vague overwhelm does not help. Specific confusion does.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## What Professional Attention Already Looks Like
|
||
|
||
It is tempting to imagine that professional attention begins only once the circuits become large. It does not. Professional attention begins the first time you ask which line is carrying the main design burden, what evidence would falsify your story, and how a basis change would alter the meaning of the result. Those are already professional questions. They simply happen to be asked here on a small circuit where every move is still visible enough to discuss.
|
||
|
||
This is also why the lecture is more text-heavy than a standard tutorial. The text is not padding. It is attention training. It keeps naming the distinctions that matter so your eye can learn to notice them quickly later.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"Write the full story of the Bell anchor circuit in your own words. Do not just name the gates; explain what each stage is doing."
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Transfer Forward
|
||
|
||
You might reasonably ask why this lecture is so intense about such a small example. The answer is transfer. Later, when you study oracle circuits, QFT substructures, or hardware-constrained rewrites, you will still need the same reading habits. You will still need to identify branch points, structural relationships across wires, measurement choices, and mismatches between your story and the result. The circuits will grow, but the habits remain.
|
||
|
||
This is the real professional lesson of the module: the scale of the circuit is not the measure of the sophistication of the thinking. A designer can practice sophisticated attention on a tiny circuit. In fact, that is where the practice should begin, because it is the only place where every move is still visible enough to narrate cleanly.
|
||
|
||
As you move to the lab, treat the lecture as a set of commitments. You have been told what the mechanism is. The lab will test whether that mechanism survives modification. The problems notebook will test whether the mechanism survives retrieval. The studio will test whether the mechanism survives design pressure. That is the full loop.
|
||
"""
|
||
),
|
||
code_cell(
|
||
f"quiz_block({LECTURE_QUIZ_B!r}, heading='Lecture Checkpoint B')"
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"Name one mistaken sentence about quantum circuits that this lecture forced you to retire, and replace it with a better sentence."
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Mastery Gate
|
||
|
||
You have finished the lecture only if you can take a Bell-style circuit, explain it from code to diagram to counts, modify one gate intentionally, and defend what should change before you run the experiment. If that still feels unstable, the correct next move is not to rush ahead. It is to use the lab properly.
|
||
"""
|
||
),
|
||
]
|
||
)
|
||
|
||
|
||
def build_lab() -> dict:
|
||
return notebook(
|
||
[
|
||
markdown_cell(
|
||
"""
|
||
# Principles and Circuit Literacy Lab
|
||
|
||
The lecture gave you the vocabulary and the main circuit story. The lab turns that story into manipulation. This notebook is not for admiring outputs. It is for making controlled changes and checking whether your explanation survives contact with variation.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Lab Protocol
|
||
|
||
For every editable cell in this notebook, use the same cycle:
|
||
|
||
1. state a prediction in words
|
||
2. change one thing only
|
||
3. render the circuit and inspect both the graphical and text view
|
||
4. compare the new counts or state story to your prediction
|
||
5. revise your explanation if needed
|
||
|
||
The “one thing only” rule matters. Random edits create noise in your own learning. Controlled edits create evidence.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Why A Lab Notebook Exists Separately From The Lecture
|
||
|
||
In a weak course, the lab is a place where the learner replays the lecture with a little more clicking. In a strong course, the lab carries a distinct burden. The lecture builds the mental model. The lab threatens the mental model by changing the object in controlled ways. That threat is constructive. It is the place where the learner discovers whether an explanation is robust enough to survive variation.
|
||
|
||
This matters especially in quantum computing because the surface syntax can be deceptively simple. A one-line change can mean “removed the branch structure,” “changed the measurement question,” or “destroyed the intended relationship between wires.” If you are not used to tracing those distinctions deliberately, the circuit will simply look different and the counts will simply look different. The lab is trying to teach you to say more than that. It is trying to teach you to say *why* the different result deserves the explanation you are giving it.
|
||
|
||
Another reason the lab is separate is emotional. When people are still new, they often treat every mismatch as a disaster. The lab normalizes mismatch. A failed prediction is not a reason to panic. It is a reason to locate the exact sentence in your internal explanation that must now be repaired. That is a much healthier and much more professional relationship to error.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## What To Notice While You Experiment
|
||
|
||
The lab becomes much more powerful if you decide in advance what kinds of changes you are looking for. There are at least three categories to track. The first category is **preparation changes**. These alter the circuit before any relationship is created across wires. Removing an initial Hadamard belongs here. The second category is **structural relationship changes**. These alter how one wire depends on another, which is why controlled operations carry more conceptual weight than they first appear to. The third category is **question changes**. These do not necessarily change the prepared object in the same way as the first two categories, but they can drastically change what the readout means. Final basis rotations often belong here.
|
||
|
||
If you learn to classify edits into those three categories, your explanations become sharper almost immediately. Instead of saying “the circuit changed,” you can say “the preparation changed,” “the relationship changed,” or “the readout question changed.” That is a much stronger sentence, and stronger sentences are one of the quiet engines of stronger reasoning.
|
||
"""
|
||
),
|
||
code_cell(SETUP),
|
||
code_cell(COMMON_IMPORTS),
|
||
markdown_cell(
|
||
"""
|
||
## Lab 1: Bell Anchor Variation
|
||
|
||
Start with the anchor circuit. Remove or move one ingredient at a time and ask which part of the story breaks. This is the fastest way to detect whether you truly know the burden of each line.
|
||
"""
|
||
),
|
||
code_cell(f"step_reference_table({LECTURE_STEP_REFS!r})"),
|
||
code_cell(
|
||
f"""
|
||
editable_code = {BELL_EDITABLE!r}
|
||
editable_circuit_lab(
|
||
initial_code=editable_code,
|
||
context={{"QuantumCircuit": __import__("qiskit").QuantumCircuit, "simulate_counts": simulate_counts}},
|
||
title="Lab 1: Bell Anchor Variation",
|
||
instructions="Delete, move, or replace exactly one marked step and explain the result before you render.",
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
The first lab should make one principle concrete: circuit meaning is distributed across steps. If you remove the Hadamard, you do not merely delete a gate. You collapse the branch structure the rest of the circuit depends on. If you remove the CNOT, you do not merely simplify the circuit. You destroy the correlation mechanism. If you change the measurement wiring, you change what question is being answered. Those distinctions are the whole point.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
The reason this matters is that most learners overestimate how well they understand a worked example. Variation is the corrective. A design that only makes sense in the exact original arrangement is not yet understood as a design. It is merely remembered as a pattern. By making one local change at a time, the lab forces the remembered pattern to either survive as an explanation or break visibly.
|
||
"""
|
||
),
|
||
code_cell(
|
||
f"quiz_block({LAB_QUIZ_A!r}, heading='Lab Checkpoint A')"
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"Which single edit most strongly changed the circuit story, and why did that change matter more than the others?"
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Lab 2: Basis-Change Experiment
|
||
|
||
The next lab tests whether you really believe the sentence “measurement is a question.” Insert, remove, or move the final Hadamard on qubit 0 and watch what that does to the meaning of the readout. Keep the circuit small. The point is not complexity. The point is basis awareness.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
This is the lab where many learners realize that they had been treating measurement as a passive camera. Good. That realization is one of the real achievements of the module. Once basis awareness lands, you are no longer merely running circuits. You are beginning to think experimentally: what question did I ask, what object did I prepare, and what evidence do these counts actually justify?
|
||
"""
|
||
),
|
||
code_cell(
|
||
f"""
|
||
editable_code = {BASIS_EDITABLE!r}
|
||
editable_circuit_lab(
|
||
initial_code=editable_code,
|
||
context={{"QuantumCircuit": __import__("qiskit").QuantumCircuit, "simulate_counts": simulate_counts}},
|
||
title="Lab 2: Basis Change Before Measurement",
|
||
instructions="Alter the final basis rotation and explain how the measurement question changes.",
|
||
)
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
basis_demo = __import__("qiskit").QuantumCircuit(2, 2)
|
||
basis_demo.h(0)
|
||
basis_demo.cx(0, 1)
|
||
basis_demo.h(0)
|
||
basis_demo.measure([0, 1], [0, 1])
|
||
simulate_counts(basis_demo, shots=512)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
A basis-change lab is often where a learner’s hidden classical assumptions become visible. If you expected the same histogram as the unrotated Bell circuit, you just found a useful weakness. Good. The notebook did its job. Fix the language, not just the code.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
Basis awareness is one of the earliest serious engineering habits. Once you really believe that a final rotation changes the question rather than merely decorating the circuit, many later topics become easier: interference explanations, tomography-like reasoning, oracle interpretation, and even some debugging of noisy behavior. That is why the lab spends so much energy on what might look like a tiny final gate.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"Describe the difference between changing the prepared state and changing the question asked of that state."
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Lab 3: Extend The Pattern
|
||
|
||
The final lab asks you to extend the same branch-correlate-measure pattern to three wires. This is not yet advanced algorithm design. It is a transfer check. Can you still recognize the mechanism after the surface gets slightly bigger?
|
||
"""
|
||
),
|
||
code_cell(
|
||
f"""
|
||
editable_code = {GHZ_EDITABLE!r}
|
||
editable_circuit_lab(
|
||
initial_code=editable_code,
|
||
context={{"QuantumCircuit": __import__("qiskit").QuantumCircuit, "simulate_counts": simulate_counts}},
|
||
title="Lab 3: Three-Qubit Extension",
|
||
instructions="Extend or simplify the branch-correlate-measure pattern and explain how the new wire changes the diagram and the resulting distribution.",
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
The three-qubit extension is valuable because it reveals whether you were memorizing a two-wire picture or learning a design pattern. The actual professional skill is the second one.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
Leave the lab with a sharper sentence than the one you entered with. A good candidate is: “I can now distinguish changes to preparation, changes to correlation structure, and changes to the measurement question.” If that sentence feels true when you look at your own edits, the lab has started doing real work.
|
||
"""
|
||
),
|
||
code_cell(
|
||
f"quiz_block({LAB_QUIZ_B!r}, heading='Lab Checkpoint B')"
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Lab Exit Standard
|
||
|
||
Leave this notebook only when you can look at a small circuit edit and say, before running anything, whether the change affects preparation, correlation, or the measurement question. That sentence is a small but meaningful piece of circuit literacy.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
A good lab exit feeling is not comfort. It is sharper control. You should feel more able to inspect a circuit line and tell whether it changes the prepared state, the structure across wires, or the readout question. If you feel that increased sharpness, the lab has done its work even if some details still need repetition.
|
||
"""
|
||
),
|
||
]
|
||
)
|
||
|
||
|
||
def build_problems() -> dict:
|
||
cells = [
|
||
markdown_cell(
|
||
"""
|
||
# Principles and Circuit Literacy Problems
|
||
|
||
This notebook is the retrieval and diagnosis layer of the module. The lecture and lab make ideas feel familiar. The problems notebook asks whether those ideas are actually available without the notebook whispering the answer to you.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## How To Use This Notebook
|
||
|
||
Do not click answers casually. Treat the multiple-choice blocks as retrieval tests. If a question feels surprisingly hard, that is exactly the point. Weakness discovered now is cheap. Weakness discovered during later algorithmic or hardware-aware modules is expensive.
|
||
|
||
Also notice that the problems here are not only about vocabulary. Some target mechanism, some target interpretation, and some target debugging language. That mix is intentional because professional circuit literacy is not one skill.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Why Retrieval Matters More Than It Feels Like It Should
|
||
|
||
Recognition is cheap. Retrieval is expensive. A learner can read a paragraph, nod along, and still be unable to produce the same distinction five minutes later without support. Engineering does not reward recognition nearly as much as it rewards availability under pressure. You need the right distinction at the moment a circuit surprises you, a review comment lands, or a design choice must be defended. That is why this notebook exists.
|
||
|
||
Good retrieval practice does not merely ask factual trivia. It asks questions that expose unstable edges in the learner’s model. That is why the problem sets mix vocabulary, mechanism, interpretation, and critique.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## How To Read Your Own Mistakes
|
||
|
||
A missed question does not always mean the same thing. Sometimes it means you forgot a term. Sometimes it means your mental picture is wrong. Sometimes it means two ideas that sounded similar in the lecture are not yet separated cleanly in your head. Good self-study depends on learning to distinguish these cases. If you miss a vocabulary question, reread the definitions. If you miss a mechanism question, redraw the circuit story. If you miss an interpretation question, compare the same circuit under two different measurement choices. The course becomes more efficient when your response to error is calibrated rather than generic.
|
||
|
||
The same principle applies to confidence. A correct answer obtained with hesitation still tells you something useful. It means the concept may be present but not yet fluent. Fluency matters because later modules will spend that conceptual budget quickly.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## The Role Of The Problems Notebook In The Full Bundle
|
||
|
||
The lecture gives you the clean explanation. The lab lets you test that explanation against controlled change. The problems notebook checks whether the explanation is now portable enough to survive away from its original context. That portability is what matters for later work. When you encounter oracles, QFT layers, or hardware-aware redesigns, nobody will stop the notebook every line and remind you of the basic distinctions. Those distinctions need to already be available.
|
||
|
||
This is why a problems notebook is not just an assessment add-on. It is a transfer device. It reveals whether the earlier parts of the module created a capability that can be carried forward or merely an experience that felt understandable in the moment.
|
||
"""
|
||
),
|
||
code_cell(SETUP),
|
||
code_cell(COMMON_IMPORTS),
|
||
]
|
||
|
||
for quiz in PROBLEMS_QUIZZES:
|
||
cells.append(
|
||
markdown_cell(
|
||
f"""
|
||
## {quiz['heading']}
|
||
|
||
Answer these from understanding, not from rhythm or familiarity. If two options sound almost correct, figure out which distinction the question is trying to expose.
|
||
"""
|
||
)
|
||
)
|
||
cells.append(
|
||
code_cell(
|
||
f"quiz_block({quiz['questions']!r}, heading={quiz['heading']!r})"
|
||
)
|
||
)
|
||
|
||
cells.extend(
|
||
[
|
||
markdown_cell(
|
||
"""
|
||
## Short Written Diagnostic
|
||
|
||
Multiple choice is useful, but it is not enough. Write directly now. A strong answer should name the mechanism, not just the gate labels. If the sentence feels awkward to write, that awkwardness is a diagnostic gift.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
Written explanation is harder because it removes scaffolding. That is precisely why it matters. If you can select the right option but cannot write the mechanism in your own language, your understanding is still partly borrowed from the notebook. The goal here is to make it less borrowed and more owned.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"In two or three tight sentences, explain why removing the initial Hadamard from a Bell circuit changes more than just the first wire."
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Mini Debugging Prompt
|
||
|
||
Imagine a peer tells you, “I inserted a Hadamard before measuring qubit 0, but I thought the Bell state would stay the same, so I expected the same counts.” Your task is not to mock the error. Your task is to diagnose it precisely. What sentence about measurement or basis did they fail to internalize?
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"Write the one sentence you would use to diagnose the peer's misunderstanding cleanly and respectfully."
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Exit Standard
|
||
|
||
You should now be able to answer: What is being prepared? What is being correlated? What question is being asked? What changed when the code changed? If those questions still feel slippery, revisit the lecture and the lab before you open the studio. The studio assumes you can retrieve the foundational language on demand.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
Think of the problems notebook as a mirror rather than a gatekeeper. Its job is to show you the present shape of your understanding. If the reflection is weaker than you hoped, that is not a verdict on your ability. It is a map for the next repetition.
|
||
"""
|
||
),
|
||
]
|
||
)
|
||
return notebook(cells)
|
||
|
||
|
||
def build_studio() -> dict:
|
||
return notebook(
|
||
[
|
||
markdown_cell(
|
||
"""
|
||
# Principles and Circuit Literacy Studio
|
||
|
||
The studio is where the module stops behaving like a class and starts behaving like a design environment. You are no longer being led step by step through a single canonical circuit. You are being given briefs and asked to make choices that must later be justified.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Studio Rules
|
||
|
||
Use the same discipline as in the lab, but with one new demand: justification. In the studio, it is not enough that the circuit runs. You must be able to say why you chose one arrangement over another and what evidence supports the choice. That is the first taste of professional review language.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
The studio differs from the lecture and the lab because the path is now partially open. In a worked example, the notebook mostly chooses the route. In a studio brief, the notebook chooses the objective and leaves more of the route in your hands. That small increase in freedom changes the cognitive burden dramatically. You now need to decide, compare, and justify instead of merely understand and modify.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Why The Studio Appears So Early
|
||
|
||
Some curricula postpone design work until the learner is supposedly “ready.” That sounds reasonable but often backfires. If design is delayed too long, the learner becomes excellent at replaying examples and weak at making choices. This course introduces studio work early at a small scale for the opposite reason: small design decisions are exactly where justification habits can begin.
|
||
|
||
You are not being asked to invent a novel algorithm here. You are being asked to choose among small candidate circuits, explain why one better serves the objective, and write a sentence another engineer could review. That is already authentic practice. It is simply beginner-scale authentic practice.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## How To Judge Your Own Studio Work
|
||
|
||
There are several weak ways to leave a studio brief and one strong way. A weak exit is: “I made something that runs.” Another weak exit is: “I made something that looks similar to the example from the lecture.” The strong exit is: “I selected a design because it better matched the stated objective, I compared it to an alternative, and I can name the evidence that supports the choice.” That is the standard you should hold yourself to while working here.
|
||
|
||
The good news is that this standard is available even at beginner scale. You do not need a thousand-gate circuit to practice comparison and justification. You need a clear objective, at least two candidate constructions, and the discipline to say what each one is doing.
|
||
"""
|
||
),
|
||
code_cell(SETUP),
|
||
code_cell(COMMON_IMPORTS),
|
||
markdown_cell(
|
||
"""
|
||
## Brief 1: Build A Quantum Coin
|
||
|
||
Design the cleanest possible one-qubit circuit that behaves like an ideal fair coin in the computational basis. Then create a close variation that is not a fair coin and explain why. The purpose of the brief is to make you distinguish preparation from measurement instead of treating the whole circuit as a black box.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
editable_code = '''\
|
||
circuit = QuantumCircuit(1, 1)
|
||
# Prepare your candidate coin here.
|
||
circuit.h(0)
|
||
# Ask the question in the computational basis.
|
||
circuit.measure([0], [0])
|
||
'''
|
||
editable_circuit_lab(
|
||
initial_code=editable_code,
|
||
context={"QuantumCircuit": __import__("qiskit").QuantumCircuit, "simulate_counts": simulate_counts},
|
||
title="Studio Brief 1: Quantum Coin",
|
||
instructions="Create a fair coin, then alter it into a non-fair coin and defend the difference.",
|
||
)
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"State the minimal design reason your fair coin works, and the minimal design reason your altered coin stops being fair."
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Brief 2: Two Candidate Correlation Circuits
|
||
|
||
Build two candidate two-qubit circuits. One should aim to create strong same-bit correlation in the computational basis. The other should fail to do so for a principled reason. The purpose of this brief is not to trick you. It is to force comparison. Design judgment grows faster when you compare plausible candidates than when you stare at one canonical answer.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
editable_code = '''\
|
||
circuit = QuantumCircuit(2, 2)
|
||
# Candidate A: intended to create strong same-bit correlation.
|
||
circuit.h(0)
|
||
circuit.cx(0, 1)
|
||
circuit.measure([0, 1], [0, 1])
|
||
'''
|
||
editable_circuit_lab(
|
||
initial_code=editable_code,
|
||
context={"QuantumCircuit": __import__("qiskit").QuantumCircuit, "simulate_counts": simulate_counts},
|
||
title="Studio Brief 2A: Correlation Candidate",
|
||
instructions="Defend whether the circuit truly supports the correlation claim you are making.",
|
||
)
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
editable_code = '''\
|
||
circuit = QuantumCircuit(2, 2)
|
||
# Candidate B: make a different choice and compare it honestly.
|
||
circuit.x(0)
|
||
circuit.cx(0, 1)
|
||
circuit.measure([0, 1], [0, 1])
|
||
'''
|
||
editable_circuit_lab(
|
||
initial_code=editable_code,
|
||
context={"QuantumCircuit": __import__("qiskit").QuantumCircuit, "simulate_counts": simulate_counts},
|
||
title="Studio Brief 2B: Comparison Candidate",
|
||
instructions="Create a contrasting candidate and explain why its story differs from Candidate A.",
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
In a professional setting, comparison is where vague understanding gets exposed. If you cannot tell why Candidate A deserves the label “correlated in the computational basis” more than Candidate B, then you are still leaning on pattern recognition rather than on mechanism.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
Notice that the review sentence you write is part of the exercise, not a final decoration. Collaboration happens in language. A circuit you cannot explain cleanly is a circuit you are not yet ready to defend. The studio therefore treats sentence quality as part of design quality.
|
||
"""
|
||
),
|
||
code_cell(
|
||
f"quiz_block({STUDIO_QUIZ!r}, heading='Studio Review Check')"
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"Write a short review memo: which candidate is better for the stated objective, what evidence supports that claim, and what weakness still remains?"
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Brief 3: Basis-Aware Critique
|
||
|
||
Return to one of your candidates and change the final measurement basis on one wire. Your job is to write a critique, not just to observe the new counts. Did you change the preparation, or did you change the question? Would a careless engineer misread the result? How would you prevent that in a code review?
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
This final brief is the bridge from local experimentation to review culture. Many engineering failures are not caused by impossible theory; they are caused by plausible-looking misreadings that nobody named in time. The critique you write here is practice for catching that class of mistake early and expressing it clearly enough that another person can act on it.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"Describe a basis-related misinterpretation that could happen in one of your circuits and how you would catch it in review."
|
||
)
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
## Studio Rubric
|
||
|
||
A good studio outcome at this stage is not “invented a novel quantum algorithm.” A good outcome is smaller and more demanding:
|
||
|
||
- your circuit choices are deliberate
|
||
- your language about preparation, correlation, and measurement is precise
|
||
- your comparison between candidates is evidence-based
|
||
- your critique names remaining weakness honestly
|
||
|
||
If you can do that consistently on small circuits, later algorithm and hardware modules will have something solid to stand on.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
This is how the first rebuilt module prepares the later course. The later bands will introduce oracle structure, phase reasoning, compilation pressure, mitigation choices, and capstone reviews. But every one of those harder themes still depends on the same core behaviors you are practicing here: state the objective, build candidates, inspect evidence, diagnose the mismatch, and justify the final sentence.
|
||
"""
|
||
),
|
||
markdown_cell(
|
||
"""
|
||
If the studio feels demanding, that is appropriate. The whole point of the new architecture is to stop pretending that mastery will emerge from passive familiarity alone. The studio is where familiarity begins turning into responsibility.
|
||
"""
|
||
),
|
||
code_cell(
|
||
"""
|
||
reflection_box(
|
||
"What part of circuit literacy now feels owned, and what part still feels fragile enough that it could break under a slightly harder example?"
|
||
)
|
||
"""
|
||
),
|
||
]
|
||
)
|
||
|
||
|
||
def write_notebook(path: Path, payload: dict) -> None:
|
||
path.parent.mkdir(parents=True, exist_ok=True)
|
||
path.write_text(json.dumps(payload, indent=2))
|
||
|
||
|
||
def main() -> None:
|
||
outputs = {
|
||
NOTEBOOKS / "COURSE_BLUEPRINT.ipynb": build_course_blueprint(),
|
||
MODULE_DIR / "lecture.ipynb": build_lecture(),
|
||
MODULE_DIR / "lab.ipynb": build_lab(),
|
||
MODULE_DIR / "problems.ipynb": build_problems(),
|
||
MODULE_DIR / "studio.ipynb": build_studio(),
|
||
}
|
||
|
||
for path, payload in outputs.items():
|
||
write_notebook(path, payload)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|