2026-04-15 08:21:41 +00:00
#!/usr/bin/env python3
from __future__ import annotations
2026-04-15 09:14:19 +00:00
import hashlib
2026-04-15 08:21:41 +00:00
import json
from pathlib import Path
from textwrap import dedent
ROOT = Path ( __file__ ) . resolve ( ) . parents [ 1 ]
NOTEBOOKS = ROOT / " notebooks "
MODULE_01_DIR = (
NOTEBOOKS / " qiskit_engineering " / " module_01_circuit_construction_and_analysis "
)
MODULE_02_DIR = (
NOTEBOOKS / " qiskit_engineering " / " module_02_transpilation_and_visualization "
)
MODULE_03_DIR = (
NOTEBOOKS / " qiskit_engineering " / " module_03_simulation_and_noise_models "
)
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 ( ) ] ,
}
2026-04-15 09:14:19 +00:00
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 ]
2026-04-15 08:21:41 +00:00
def notebook ( cells : list [ dict ] ) - > dict :
2026-04-15 09:14:19 +00:00
normalized_cells = [ ]
for index , cell in enumerate ( cells ) :
payload = dict ( cell )
payload . setdefault ( " id " , _cell_id ( index , payload ) )
normalized_cells . append ( payload )
2026-04-15 08:21:41 +00:00
return {
2026-04-15 09:14:19 +00:00
" cells " : normalized_cells ,
2026-04-15 08:21:41 +00:00
" 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} ) " )
2026-04-15 09:14:19 +00:00
def compose_code ( * blocks : str ) - > str :
cleaned_blocks = [ ]
for block in blocks :
cleaned = dedent ( block ) . strip ( " \n " )
if cleaned :
cleaned_blocks . append ( cleaned )
return " \n \n " . join ( cleaned_blocks )
2026-04-15 08:21:41 +00:00
def editable_lab_code (
initial_code : str ,
* ,
title : str ,
instructions : str ,
context_source : str = " " ,
context_name : str = " simulate_counts " ,
shots : int = 256 ,
) - > dict :
return code_cell (
2026-04-15 09:14:19 +00:00
compose_code (
context_source ,
f """
editable_code = { initial_code ! r }
editable_circuit_lab (
initial_code = editable_code ,
context = { { " QuantumCircuit " : QuantumCircuit , " simulate_counts " : { context_name } } } ,
title = { title ! r } ,
instructions = { instructions ! r } ,
shots = { shots } ,
)
""" ,
2026-04-15 08:21:41 +00:00
)
)
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 (
build_demo_noise_model ,
counts_to_probabilities ,
draw_circuit ,
editable_circuit_lab ,
line_coupling_map ,
load_experiment_defaults ,
plot_counts ,
plot_probabilities ,
quiz_block ,
reflection_box ,
simulate_counts ,
statevector_probabilities ,
step_reference_table ,
transpile_summary ,
)
from qiskit import ClassicalRegister , QuantumCircuit , QuantumRegister
from qiskit . providers . basic_provider import BasicSimulator
"""
CONSTRUCTION_STEP_REFS = [
{
" marker " : " [1] " ,
" code_focus " : " Declare named quantum and classical registers that express circuit roles instead of anonymous wire positions. " ,
" diagram_effect " : " The rendered circuit now carries semantic names such as data, syndrome, and readout. " ,
" why_it_matters " : " Named registers turn diagrams into interfaces and make later review far less error prone. " ,
} ,
{
" marker " : " [2] " ,
" code_focus " : " Build a preparation layer that creates the main data-state relationship. " ,
" diagram_effect " : " The first part of the diagram clearly separates state preparation from later bookkeeping. " ,
" why_it_matters " : " Good engineering keeps the causal burden of each region readable. " ,
} ,
{
" marker " : " [3] " ,
" code_focus " : " Use a dedicated wire for a parity-style check rather than mixing all roles onto one register. " ,
" diagram_effect " : " The circuit exposes intent: data wires store the payload, the extra wire stores a check. " ,
" why_it_matters " : " Role separation is the start of reusable circuit architecture. " ,
} ,
{
" marker " : " [4] " ,
" code_focus " : " Measure into an explicitly ordered classical register. " ,
" diagram_effect " : " The reporting layer is visible and auditable rather than implicit. " ,
" why_it_matters " : " Engineering quality includes the evidence path, not only the quantum body of the circuit. " ,
} ,
]
CONSTRUCTION_ANCHOR = """
from qiskit import ClassicalRegister , QuantumCircuit , QuantumRegister
data = QuantumRegister ( 2 , " data " )
syndrome = QuantumRegister ( 1 , " syndrome " )
readout = ClassicalRegister ( 3 , " readout " )
circuit = QuantumCircuit ( data , syndrome , readout )
# [1] Prepare a named two-qubit data block.
circuit . h ( data [ 0 ] )
circuit . cx ( data [ 0 ] , data [ 1 ] )
# [2] Route a parity-style question into the syndrome wire.
circuit . cx ( data [ 0 ] , syndrome [ 0 ] )
circuit . cx ( data [ 1 ] , syndrome [ 0 ] )
# [3] Keep the reporting layer explicit.
circuit . measure ( data [ 0 ] , readout [ 0 ] )
circuit . measure ( data [ 1 ] , readout [ 1 ] )
circuit . measure ( syndrome [ 0 ] , readout [ 2 ] )
"""
CONSTRUCTION_BLOCK_EDITABLE = """
from qiskit import QuantumCircuit
def bell_block ( ) - > QuantumCircuit :
block = QuantumCircuit ( 2 , name = " bell_prep " )
# [1] Encapsulate the preparation story.
block . h ( 0 )
block . cx ( 0 , 1 )
return block
def readout_block ( ) - > QuantumCircuit :
block = QuantumCircuit ( 2 , 2 , name = " readout " )
# [2] Keep the question and the reporting layer reusable too.
block . measure ( [ 0 , 1 ] , [ 0 , 1 ] )
return block
circuit = QuantumCircuit ( 2 , 2 )
# [3] Compose blocks instead of retyping the same logic inline.
circuit . compose ( bell_block ( ) , inplace = True )
circuit . compose ( readout_block ( ) , inplace = True )
"""
CONSTRUCTION_METRICS_EDITABLE = """
from qiskit import QuantumCircuit
def candidate ( extra_layer : bool = False ) - > QuantumCircuit :
circuit = QuantumCircuit ( 3 , 3 )
# [1] Create a clean backbone.
circuit . h ( 0 )
circuit . cx ( 0 , 1 )
circuit . cx ( 1 , 2 )
# [2] Toggle the extra layer to inspect the cost of a design choice.
if extra_layer :
circuit . cx ( 0 , 2 )
# [3] Keep the reporting layer stable while you compare.
circuit . measure ( [ 0 , 1 , 2 ] , [ 0 , 1 , 2 ] )
return circuit
circuit = candidate ( extra_layer = True )
"""
TRANSPILATION_STEP_REFS = [
{
" marker " : " [1] " ,
" code_focus " : " Write the abstract circuit in the cleanest form for the algorithmic intention. " ,
" diagram_effect " : " The first diagram expresses what you want, not yet what a constrained backend can host. " ,
" why_it_matters " : " Design begins with intent, but intent is not the end of the story. " ,
} ,
{
" marker " : " [2] " ,
" code_focus " : " Declare a basis-gate set and a line coupling map that mimic local hardware pressure. " ,
" diagram_effect " : " The implicit device assumptions become explicit engineering constraints. " ,
" why_it_matters " : " Transpilation only becomes intelligible when the constraints are visible. " ,
} ,
{
" marker " : " [3] " ,
" code_focus " : " Compile the circuit and inspect how the depth, size, and gate counts changed. " ,
" diagram_effect " : " The compiled diagram usually has more structure than the abstract one. " ,
" why_it_matters " : " Routing and basis conversion create real implementation cost. " ,
} ,
{
" marker " : " [4] " ,
" code_focus " : " Compare the compiled rewrite to a topology-aware redesign. " ,
" diagram_effect " : " You can see whether the compiler had to rescue a poor abstract layout. " ,
" why_it_matters " : " Professional design does not stop at letting the compiler suffer in silence. " ,
} ,
]
TRANSPILATION_ABSTRACT_EDITABLE = """
from qiskit import QuantumCircuit
circuit = QuantumCircuit ( 4 , 4 )
# [1] Express a non-local interaction cleanly at the abstract level.
circuit . h ( 0 )
circuit . cx ( 0 , 3 )
circuit . cx ( 3 , 1 )
# [2] Keep the measurement layer simple so the compilation changes are easy to inspect.
circuit . measure ( [ 0 , 1 , 2 , 3 ] , [ 0 , 1 , 2 , 3 ] )
"""
TRANSPILATION_COMPILED_EDITABLE = """
from qiskit import QuantumCircuit
from qiskit . providers . basic_provider import BasicSimulator
from quantum_learning import line_coupling_map , load_experiment_defaults , transpile_summary
defaults = load_experiment_defaults ( )
abstract = QuantumCircuit ( 4 , 4 )
# [1] Start from a circuit with routing pressure.
abstract . h ( 0 )
abstract . cx ( 0 , 3 )
abstract . cx ( 3 , 1 )
abstract . measure ( [ 0 , 1 , 2 , 3 ] , [ 0 , 1 , 2 , 3 ] )
# [2] Compile to IBM-style basis gates on a line.
summary = transpile_summary (
abstract ,
BasicSimulator ( ) ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( 4 ) ,
optimization_level = 0 ,
)
# [3] Render the compiled circuit directly.
circuit = summary [ " compiled_circuit " ]
"""
TRANSPILATION_TOPOLOGY_AWARE_EDITABLE = """
from qiskit import QuantumCircuit
circuit = QuantumCircuit ( 4 , 4 )
# [1] Build a version that respects the line from the start.
circuit . h ( 0 )
circuit . cx ( 0 , 1 )
circuit . cx ( 1 , 2 )
circuit . cx ( 2 , 3 )
# [2] Keep the final question fixed while you compare cost.
circuit . measure ( [ 0 , 1 , 2 , 3 ] , [ 0 , 1 , 2 , 3 ] )
"""
NOISE_STEP_REFS = [
{
" marker " : " [1] " ,
" code_focus " : " Prepare a small circuit with a clean ideal story that can be simulated exactly. " ,
" diagram_effect " : " The circuit is shallow enough that the intended behavior is easy to articulate. " ,
" why_it_matters " : " Noise reasoning is impossible if the ideal reference story is already blurry. " ,
} ,
{
" marker " : " [2] " ,
" code_focus " : " Choose the right view: statevector, shot counts, or a noisy local model. " ,
" diagram_effect " : " The diagram may stay the same while the lens on it changes. " ,
" why_it_matters " : " Different questions require different simulators and evidence forms. " ,
} ,
{
" marker " : " [3] " ,
" code_focus " : " Inject a local noise profile and compare the distribution to the ideal result. " ,
" diagram_effect " : " The circuit picture is unchanged, but the evidence becomes visibly distorted. " ,
" why_it_matters " : " Noise belongs in the interpretation layer even when the diagram looks familiar. " ,
} ,
{
" marker " : " [4] " ,
" code_focus " : " Stress the design with extra two-qubit structure and see how robustness changes. " ,
" diagram_effect " : " A slightly deeper circuit may look only a little larger but degrade much more under noise. " ,
" why_it_matters " : " Structure and robustness are coupled design questions. " ,
} ,
]
NOISE_IDEAL_EDITABLE = """
from qiskit import QuantumCircuit
circuit = QuantumCircuit ( 2 , 2 )
# [1] Prepare the clean Bell-style reference.
circuit . h ( 0 )
circuit . cx ( 0 , 1 )
# [2] Keep the reporting layer fixed.
circuit . measure ( [ 0 , 1 ] , [ 0 , 1 ] )
"""
NOISE_STRESSED_EDITABLE = """
from qiskit import QuantumCircuit
circuit = QuantumCircuit ( 3 , 3 )
# [1] Prepare a shallow correlated backbone.
circuit . h ( 0 )
circuit . cx ( 0 , 1 )
circuit . cx ( 1 , 2 )
# [2] Add an extra entangling layer to stress the design.
circuit . cx ( 0 , 2 )
# [3] Measure all wires consistently.
circuit . measure ( [ 0 , 1 , 2 ] , [ 0 , 1 , 2 ] )
"""
NOISE_ROBUST_EDITABLE = """
from qiskit import QuantumCircuit
circuit = QuantumCircuit ( 3 , 3 )
# [1] Build the leaner candidate.
circuit . h ( 0 )
circuit . cx ( 0 , 1 )
circuit . cx ( 1 , 2 )
# [2] Leave the extra long-range entangler out and compare the evidence.
circuit . measure ( [ 0 , 1 , 2 ] , [ 0 , 1 , 2 ] )
"""
CONSTRUCTION_QUIZ_A = [
{
" prompt " : " What is the main engineering value of named registers? " ,
" options " : [
" They turn wires into role-bearing interfaces instead of anonymous positions " ,
" They always reduce depth " ,
" They remove the need for measurements " ,
] ,
" correct_index " : 0 ,
" explanation " : " Named registers improve legibility and make later review far cleaner. " ,
} ,
{
" prompt " : " Why separate a syndrome-style wire from the data wires in an introductory engineering example? " ,
" options " : [
" To make the role structure visible early " ,
" Because Qiskit requires one extra qubit in every circuit " ,
" Only to make the diagram longer " ,
] ,
" correct_index " : 0 ,
" explanation " : " Role separation is the foundation of reusable circuit architecture. " ,
} ,
{
" prompt " : " What does a circuit metric such as depth help you talk about? " ,
" options " : [
" The implementation cost of a design choice " ,
" The color of the plotted bars " ,
" Whether the statevector exists " ,
] ,
" correct_index " : 0 ,
" explanation " : " Metrics are evidence for engineering tradeoffs, not decoration. " ,
} ,
]
CONSTRUCTION_QUIZ_B = [
{
" prompt " : " What is the strongest reason to refactor repeated gate sequences into builder functions or blocks? " ,
" options " : [
" To make intent, reuse, and comparison explicit " ,
" To avoid ever reading the circuit diagram again " ,
" To bypass measurement wiring " ,
] ,
" correct_index " : 0 ,
" explanation " : " Abstraction should clarify the design and reduce fragile duplication. " ,
} ,
{
" prompt " : " When is abstraction boundary design going wrong? " ,
" options " : [
" When the helper hides the causal burden so thoroughly that the circuit story becomes harder to review " ,
" When the circuit becomes shorter " ,
" When a block has a name " ,
] ,
" correct_index " : 0 ,
" explanation " : " Good abstractions compress repetition without erasing meaning. " ,
} ,
{
" prompt " : " Why keep the classical register explicit in a construction module? " ,
" options " : [
" Because engineering includes how evidence is reported, not only how states are prepared " ,
" Because classical bits change the quantum state directly " ,
" Because count previews need more memory " ,
] ,
" correct_index " : 0 ,
" explanation " : " The evidence path is part of circuit design quality. " ,
} ,
]
CONSTRUCTION_LAB_QUIZ_A = [
{
" prompt " : " What is the best use of a first editable construction lab? " ,
" options " : [
" Change one role-bearing design decision and inspect how the structure and evidence respond " ,
" Randomly add gates until the diagram looks complicated " ,
" Avoid metrics until the capstone " ,
] ,
" correct_index " : 0 ,
" explanation " : " Engineering grows through controlled edits, not decorative complexity. " ,
} ,
{
" prompt " : " Why compare a flat circuit and a block-based circuit for the same behavior? " ,
" options " : [
" To judge whether the abstraction actually earned its existence " ,
" Because one of them must be numerically wrong " ,
" Because Qiskit disallows reuse otherwise " ,
] ,
" correct_index " : 0 ,
" explanation " : " Abstractions should be reviewed, not assumed good by default. " ,
} ,
]
CONSTRUCTION_LAB_QUIZ_B = [
{
" prompt " : " What should stay fixed while you compare candidate constructions? " ,
" options " : [
" The intended behavior and reporting layer " ,
" The exact number of comments " ,
" The notebook theme " ,
] ,
" correct_index " : 0 ,
" explanation " : " Comparison only works when the engineering objective stays stable. " ,
} ,
{
" prompt " : " What is a useful first explanation after circuit metrics worsen? " ,
" options " : [
" Name the structural choice that caused the cost increase " ,
" Assume Qiskit made a mistake " ,
" Ignore the metrics if the counts still look plausible " ,
] ,
" correct_index " : 0 ,
" explanation " : " Metrics should be tied back to concrete design moves. " ,
} ,
]
CONSTRUCTION_PROBLEM_SETS = [
(
" Construction Problem Set A " ,
[
{
" prompt " : " Why does this course treat registers as more than container objects? " ,
" options " : [
" They help express circuit roles and interfaces clearly " ,
" They force circuits to be noisy " ,
" They replace the need for helper functions " ,
] ,
" correct_index " : 0 ,
" explanation " : " Register naming is part of diagram legibility and review quality. " ,
} ,
{
" prompt " : " What does circuit size count in a rough engineering sense? " ,
" options " : [
" The number of operations in the circuit " ,
" The number of markdown cells in the notebook " ,
" Only the number of qubits " ,
] ,
" correct_index " : 0 ,
" explanation " : " Size is one lens on cost and implementation complexity. " ,
} ,
{
" prompt " : " What is the risk of copy-paste circuit construction? " ,
" options " : [
" Intent drifts silently across duplicated fragments " ,
" The simulator stops working " ,
" All diagrams become identical " ,
] ,
" correct_index " : 0 ,
" explanation " : " Duplication is fragile precisely because review becomes harder. " ,
} ,
] ,
) ,
(
" Construction Problem Set B " ,
[
{
" prompt " : " What should a helper block preserve? " ,
" options " : [
" A clear local purpose that can still be explained in the larger circuit story " ,
" Only a short line count " ,
" A guarantee of minimal depth " ,
] ,
" correct_index " : 0 ,
" explanation " : " Abstractions should compress without becoming opaque. " ,
} ,
{
" prompt " : " Why compare count previews after refactoring? " ,
" options " : [
" To check that the cleaner structure preserved the intended behavior " ,
" Because refactoring should always change the output " ,
" Because counts replace code review " ,
] ,
" correct_index " : 0 ,
" explanation " : " Refactoring is only good if intent and behavior survive together. " ,
} ,
{
" prompt " : " What is an honest use of circuit metrics? " ,
" options " : [
" As evidence in a tradeoff discussion " ,
" As a replacement for explanation " ,
" As proof that one circuit is always superior " ,
] ,
" correct_index " : 0 ,
" explanation " : " Metrics inform judgment; they do not end it automatically. " ,
} ,
] ,
) ,
(
" Construction Problem Set C " ,
[
{
" prompt " : " What is the best sign that a design is still too flat? " ,
" options " : [
" You cannot name any stable substructure worth reusing or reviewing separately " ,
" The circuit fits on one screen " ,
" It contains only two qubits " ,
] ,
" correct_index " : 0 ,
" explanation " : " Engineering maturity includes seeing stable blocks inside a larger circuit. " ,
} ,
{
" prompt " : " Why keep measurement wiring explicit in a builder? " ,
" options " : [
" Because the reporting layer is part of the design contract " ,
" Because measurements have no relation to evidence " ,
" Because builders only exist for classical bits " ,
] ,
" correct_index " : 0 ,
" explanation " : " Good builders preserve the evidence path, not just the quantum gates. " ,
} ,
{
" prompt " : " What should happen if an abstraction hides a key design burden? " ,
" options " : [
" Refine or split the abstraction so the burden becomes reviewable again " ,
" Keep it because shorter code is always better " ,
" Remove all helper functions forever " ,
] ,
" correct_index " : 0 ,
" explanation " : " The point is clarity, not abstraction for its own sake. " ,
} ,
] ,
) ,
(
" Construction Problem Set D " ,
[
{
" prompt " : " What is the strongest beginner-to-engineer transition in this module? " ,
" options " : [
" Moving from line-by-line execution toward deliberate block design and metric-aware comparison " ,
" Using more qubits " ,
" Avoiding diagrams " ,
] ,
" correct_index " : 0 ,
" explanation " : " This module is about workflow quality and design control. " ,
} ,
{
" prompt " : " How should you compare two circuit builders? " ,
" options " : [
" Against the same objective, with the same reporting layer, and with explicit cost evidence " ,
" Only by code length " ,
" Only by how familiar the gate names look " ,
] ,
" correct_index " : 0 ,
" explanation " : " Fair comparison requires stable objectives and explicit evidence. " ,
} ,
{
" prompt " : " What belongs in a short design memo for a reusable circuit block? " ,
" options " : [
" Intent, interface, cost, and the main tradeoff " ,
" Only the final counts " ,
" Only the block name " ,
] ,
" correct_index " : 0 ,
" explanation " : " A reusable block needs an auditable engineering story. " ,
} ,
] ,
) ,
]
CONSTRUCTION_STUDIO_QUIZ = [
{
" prompt " : " What distinguishes a studio construction task from a lecture example? " ,
" options " : [
" You must choose and defend an abstraction boundary instead of merely reading one " ,
" It uses more markdown " ,
" It avoids circuit metrics " ,
] ,
" correct_index " : 0 ,
" explanation " : " The studio asks for design responsibility, not passive recognition. " ,
} ,
{
" prompt " : " What is the strongest sign that a block earned its place? " ,
" options " : [
" Its interface and role stay clear when another engineer reviews it in a larger circuit " ,
" It has the shortest possible name " ,
" It uses the most gates " ,
] ,
" correct_index " : 0 ,
" explanation " : " A good block remains understandable and reusable under review. " ,
} ,
]
TRANSPILATION_QUIZ_A = [
{
" prompt " : " Why is a clean abstract circuit still worth writing before compilation? " ,
" options " : [
" Because intent should be explicit before constraint-handling enters " ,
" Because transpilation always improves the algorithm " ,
" Because basis gates do not matter " ,
] ,
" correct_index " : 0 ,
" explanation " : " The abstract circuit states the target behavior in the clearest form. " ,
} ,
{
" prompt " : " What does a coupling map tell you? " ,
" options " : [
" Which two-qubit interactions are directly allowed by the local topology " ,
" How many markdown cells the notebook should contain " ,
" The final shot count " ,
] ,
" correct_index " : 0 ,
" explanation " : " Topology pressure is one of the main reasons compilation rewrites circuits. " ,
} ,
{
" prompt " : " Why do compiled circuits often get deeper? " ,
" options " : [
" Routing and basis conversion add implementation work " ,
" The statevector got larger " ,
" Measurements duplicate gates automatically " ,
] ,
" correct_index " : 0 ,
" explanation " : " Compilation cost is usually structural, not mysterious. " ,
} ,
]
TRANSPILATION_QUIZ_B = [
{
" prompt " : " What is the main reason to inspect the compiled circuit directly? " ,
" options " : [
" To see what tradeoffs the transpiler actually paid on your behalf " ,
" To replace all analysis with pictures " ,
" To avoid basis gates altogether " ,
] ,
" correct_index " : 0 ,
" explanation " : " The compiled diagram is engineering evidence, not decoration. " ,
} ,
{
" prompt " : " When should you redesign a circuit instead of only accepting the compiler output? " ,
" options " : [
" When the compiled rewrite reveals avoidable topology hostility in the abstract design " ,
" Never, because the transpiler is always optimal " ,
" Only after hardware access " ,
] ,
" correct_index " : 0 ,
" explanation " : " Topology-aware redesign is part of professional circuit work. " ,
} ,
{
" prompt " : " Why compare optimization levels in a teaching notebook? " ,
" options " : [
" To learn that compilation is a design space with tradeoffs, not a single magic button " ,
" Because optimization level changes the number of qubits " ,
" Because lower levels disable measurement " ,
] ,
" correct_index " : 0 ,
" explanation " : " Compilation choices are part of the engineering story. " ,
} ,
]
TRANSPILATION_LAB_QUIZ_A = [
{
" prompt " : " What is the key question after a non-local circuit compiles poorly on a line? " ,
" options " : [
" Which abstract design choice created avoidable routing pressure " ,
" Whether Jupyter plotted it correctly " ,
" Whether the Bell state stopped existing " ,
] ,
" correct_index " : 0 ,
" explanation " : " The first move is to identify the topology-hostile part of the design. " ,
} ,
{
" prompt " : " Why keep the measurement layer simple in early transpilation exercises? " ,
" options " : [
" So the compile-time consequences stay easy to attribute " ,
" Because measurements block transpilation " ,
" Because counts do not matter " ,
] ,
" correct_index " : 0 ,
" explanation " : " Clean experiments make routing cost easier to read. " ,
} ,
]
TRANSPILATION_LAB_QUIZ_B = [
{
" prompt " : " What is a topology-aware rewrite trying to do? " ,
" options " : [
" Move some of the compiler ' s rescue work back into the original design " ,
" Eliminate all two-qubit gates " ,
" Make every circuit look like a line " ,
] ,
" correct_index " : 0 ,
" explanation " : " A good rewrite cooperates with the topology instead of fighting it. " ,
} ,
{
" prompt " : " What should remain stable when you compare two compiled candidates? " ,
" options " : [
" The intended behavior and measurement protocol " ,
" The exact gate names in the abstract source " ,
" The order of markdown headings " ,
] ,
" correct_index " : 0 ,
" explanation " : " Fair comparison requires stable objectives. " ,
} ,
]
TRANSPILATION_PROBLEM_SETS = [
(
" Transpilation Problem Set A " ,
[
{
" prompt " : " What does basis-gate restriction usually force? " ,
" options " : [
" Decomposition of higher-level operations into the target gate vocabulary " ,
" Automatic noise mitigation " ,
" Fewer measurements " ,
] ,
" correct_index " : 0 ,
" explanation " : " Basis-gate sets are part of the implementation contract. " ,
} ,
{
" prompt " : " What is the main beginner danger in transpilation work? " ,
" options " : [
" Treating the compiled circuit as arbitrary instead of as a response to explicit constraints " ,
" Using a coupling map at all " ,
" Plotting the compiled diagram " ,
] ,
" correct_index " : 0 ,
" explanation " : " The compiled rewrite should always be read as a constrained response. " ,
} ,
{
" prompt " : " Why compare depth before and after compilation? " ,
" options " : [
" To quantify part of the cost of fitting the circuit to the target constraints " ,
" Because depth determines the statevector size directly " ,
" Because depth replaces code review " ,
] ,
" correct_index " : 0 ,
" explanation " : " Depth is one concrete lens on compile-time inflation. " ,
} ,
] ,
) ,
(
" Transpilation Problem Set B " ,
[
{
" prompt " : " What does a line coupling map make expensive? " ,
" options " : [
" Long-range interactions that skip intermediate qubits " ,
" Single-qubit gates " ,
" Classical registers " ,
] ,
" correct_index " : 0 ,
" explanation " : " Non-local interactions create routing pressure on a line. " ,
} ,
{
" prompt " : " Why is a compiled diagram worth discussing with prose? " ,
" options " : [
" Because the picture alone does not tell you which cost came from basis conversion and which came from routing " ,
" Because prose replaces the diagram " ,
" Because the compiled circuit never changes the metrics " ,
] ,
" correct_index " : 0 ,
" explanation " : " The review story should tie visible changes back to their causes. " ,
} ,
{
" prompt " : " What is the point of a topology-aware redesign exercise? " ,
" options " : [
" To compare compiler rescue with human foresight " ,
" To avoid compilation entirely " ,
" To force all circuits into identical shapes " ,
] ,
" correct_index " : 0 ,
" explanation " : " This is exactly where design judgment starts to matter. " ,
} ,
] ,
) ,
(
" Transpilation Problem Set C " ,
[
{
" prompt " : " What should a good transpilation memo include? " ,
" options " : [
" Constraint set, pre/post metrics, and the main structural reason for the rewrite " ,
" Only the final counts " ,
" Only the number of qubits " ,
] ,
" correct_index " : 0 ,
" explanation " : " The memo should make the compile-time story auditable. " ,
} ,
{
" prompt " : " Why is optimization level a teaching lever here? " ,
" options " : [
" Because it shows that compilation choices affect the final structure and cost " ,
" Because it changes the algorithmic goal itself " ,
" Because it disables two-qubit gates " ,
] ,
" correct_index " : 0 ,
" explanation " : " Optimization level is part of the engineering design space. " ,
} ,
{
" prompt " : " What is the danger of ignoring the compiled circuit and looking only at counts? " ,
" options " : [
" You may miss severe structural inflation that matters for any realistic implementation " ,
" Counts already encode the full coupling map " ,
" There is no danger if the output looks correct " ,
] ,
" correct_index " : 0 ,
" explanation " : " Functional correctness is not the whole implementation story. " ,
} ,
] ,
) ,
(
" Transpilation Problem Set D " ,
[
{
" prompt " : " What is the strongest sentence about transpilation maturity? " ,
" options " : [
" I can explain what the compiler changed, why it changed it, and what I would redesign upstream " ,
" I can run transpile without errors " ,
" I can recognize a SWAP symbol " ,
] ,
" correct_index " : 0 ,
" explanation " : " Maturity means explanatory control and redesign judgment. " ,
} ,
{
" prompt " : " Which comparison is most useful after compilation? " ,
" options " : [
" Abstract intent versus compiled form under stated constraints " ,
" Markdown versus code cell counts " ,
" Notebook title versus file path " ,
] ,
" correct_index " : 0 ,
" explanation " : " The entire point is to compare intent with constrained realization. " ,
} ,
{
" prompt " : " What should happen after you identify avoidable routing pressure? " ,
" options " : [
" Propose a topology-aware alternative and compare the metrics honestly " ,
" Ignore it because the transpiler handled it " ,
" Delete the coupling map " ,
] ,
" correct_index " : 0 ,
" explanation " : " The engineering response is redesign, not resignation. " ,
} ,
] ,
) ,
]
TRANSPILATION_STUDIO_QUIZ = [
{
" prompt " : " What is the core job of the transpilation studio? " ,
" options " : [
" Compare compiler rescue with human redesign under explicit constraints " ,
" Avoid compiled diagrams " ,
" Reduce everything to one metric " ,
] ,
" correct_index " : 0 ,
" explanation " : " The studio asks for engineering judgment, not only observation. " ,
} ,
{
" prompt " : " When is a redesign claim convincing? " ,
" options " : [
" When it states the objective, the constraints, and the evidence for why the new structure is better " ,
" When the circuit looks simpler at first glance " ,
" When it uses fewer comments " ,
] ,
" correct_index " : 0 ,
" explanation " : " Convincing redesign requires a reviewable argument. " ,
} ,
]
NOISE_QUIZ_A = [
{
" prompt " : " What is the main difference between a statevector view and a shot-count view? " ,
" options " : [
" One describes the ideal pre-measurement object, the other gives sampled evidence from a chosen question " ,
" One uses qubits and the other uses classical bits only " ,
" They are interchangeable in all contexts " ,
] ,
" correct_index " : 0 ,
" explanation " : " The right simulator depends on what question you are asking. " ,
} ,
{
" prompt " : " Why keep an ideal reference before discussing noise? " ,
" options " : [
" Because you need a clean story to compare the distortion against " ,
" Because noise models cannot be local " ,
" Because counts are not allowed without it " ,
] ,
" correct_index " : 0 ,
" explanation " : " Noise interpretation collapses if the ideal target is already vague. " ,
} ,
{
" prompt " : " What kind of structural choice often hurts robustness first? " ,
" options " : [
" Extra two-qubit depth " ,
" Using markdown reflections " ,
" Naming registers " ,
] ,
" correct_index " : 0 ,
" explanation " : " Two-qubit structure is usually the first place local noise hurts visibly. " ,
} ,
]
NOISE_QUIZ_B = [
{
" prompt " : " Why compare ideal counts, sampled counts, and noisy counts in one module? " ,
" options " : [
" To separate model, sampling variation, and distortion caused by the noise profile " ,
" Because one view is never enough to be valid " ,
" Because the noisy view replaces the ideal one " ,
] ,
" correct_index " : 0 ,
" explanation " : " The three-way comparison clarifies what kind of deviation you are seeing. " ,
} ,
{
" prompt " : " What is the point of a local demo noise model in this course? " ,
" options " : [
" To teach disciplined comparison without requiring cloud access " ,
" To imitate every hardware detail exactly " ,
" To avoid discussing readout error " ,
] ,
" correct_index " : 0 ,
" explanation " : " The model is pedagogical and local-first, not a claim of perfect realism. " ,
} ,
{
" prompt " : " When is a deviation likely structural rather than mere sampling noise? " ,
" options " : [
" When it persists at high shot count and lines up with the noise-sensitive parts of the circuit " ,
" When a single 64-shot run looks strange " ,
" Whenever a histogram is not perfectly balanced " ,
] ,
" correct_index " : 0 ,
" explanation " : " Persistent, structure-aligned deviations deserve deeper explanation. " ,
} ,
]
NOISE_LAB_QUIZ_A = [
{
" prompt " : " What should you compare first in a noise lab? " ,
" options " : [
" The ideal story and the empirical story under the same measurement protocol " ,
" Only the noisy plot " ,
" Only the circuit title " ,
] ,
" correct_index " : 0 ,
" explanation " : " Noise reasoning starts from a stable protocol comparison. " ,
} ,
{
" prompt " : " Why use a wrapper preview with a noise profile in an editable lab? " ,
" options " : [
" So the same circuit edits can be inspected under a consistent distortion model " ,
" Because noise removes the need for explanation " ,
" Because widgets cannot show ideal counts " ,
] ,
" correct_index " : 0 ,
" explanation " : " The wrapper keeps the experiment local and comparable. " ,
} ,
]
NOISE_LAB_QUIZ_B = [
{
" prompt " : " What does the stressed-circuit comparison teach first? " ,
" options " : [
" That small structural changes can create large robustness differences " ,
" That noisy simulation is random and therefore useless " ,
" That extra entanglers are always good " ,
] ,
" correct_index " : 0 ,
" explanation " : " Robustness is a design consequence, not merely a hardware complaint. " ,
} ,
{
" prompt " : " Why keep the measurement protocol fixed when comparing a shallow and a stressed circuit? " ,
" options " : [
" So the robustness difference can be attributed to structure rather than to a changed question " ,
" Because measurement gates cannot be edited " ,
" Because counts always stay identical " ,
] ,
" correct_index " : 0 ,
" explanation " : " Stable protocol is essential for fair comparison. " ,
} ,
]
NOISE_PROBLEM_SETS = [
(
" Noise Problem Set A " ,
[
{
" prompt " : " What is the cleanest role of a statevector in a noise module? " ,
" options " : [
" It supplies the ideal reference description before noisy evidence is considered " ,
" It models readout error directly " ,
" It replaces the need for shots " ,
] ,
" correct_index " : 0 ,
" explanation " : " Ideal reference and noisy evidence serve different explanatory roles. " ,
} ,
{
" prompt " : " Why can a histogram drift even when the circuit did not change? " ,
" options " : [
" Finite-shot sampling introduces ordinary variation " ,
" The measurement basis changes on its own " ,
" The qubit count increases during execution " ,
] ,
" correct_index " : 0 ,
" explanation " : " Sampling noise should be named before deeper causes are assumed. " ,
} ,
{
" prompt " : " What does a local noise model help you ask? " ,
" options " : [
" How a circuit ' s structure reacts to a controlled distortion pattern " ,
" Which cloud token to request " ,
" How to avoid statevectors forever " ,
] ,
" correct_index " : 0 ,
" explanation " : " The model is for comparison and interpretation, not remote access. " ,
} ,
] ,
) ,
(
" Noise Problem Set B " ,
[
{
" prompt " : " Why are extra two-qubit layers worth stress-testing? " ,
" options " : [
" They often increase sensitivity to local noise substantially " ,
" They always reduce depth " ,
" They remove readout error " ,
] ,
" correct_index " : 0 ,
" explanation " : " Extra entangling structure is a natural robustness risk. " ,
} ,
{
" prompt " : " What is a useful three-way comparison in this module? " ,
" options " : [
" Ideal probabilities, sampled counts, and noisy counts " ,
" Notebook title, file path, and font size " ,
" Only low-shot and high-shot counts " ,
] ,
" correct_index " : 0 ,
" explanation " : " The three-way comparison separates different kinds of deviation. " ,
} ,
{
" prompt " : " What is the danger of calling every mismatch ' noise ' immediately? " ,
" options " : [
" You may ignore protocol mistakes or structural design choices that also explain the deviation " ,
" There is no danger if the circuit is small " ,
" Noise is always the deepest explanation " ,
] ,
" correct_index " : 0 ,
" explanation " : " Good debugging names ordinary causes before romantic ones. " ,
} ,
] ,
) ,
(
" Noise Problem Set C " ,
[
{
" prompt " : " When does a deviation become more credible as a structural noise effect? " ,
" options " : [
" When it tracks the parts of the circuit most exposed to the chosen error model and persists under repeated runs " ,
" When it appears once at low shot count " ,
" When the compiled circuit looks longer " ,
] ,
" correct_index " : 0 ,
" explanation " : " Persistent structure-aligned drift deserves a stronger claim. " ,
} ,
{
" prompt " : " Why compare a lean candidate and a stressed candidate under the same noise profile? " ,
" options " : [
" To isolate the effect of structural cost on robustness " ,
" Because two candidates are required in every notebook " ,
" Because the lean circuit has no statevector " ,
] ,
" correct_index " : 0 ,
" explanation " : " The comparison is about design consequences, not variety for its own sake. " ,
} ,
{
" prompt " : " What belongs in a short noise memo? " ,
" options " : [
" The ideal target, the observed distortion, and the structural reason you think the gap appeared " ,
" Only the backend name " ,
" Only the highest bar in the histogram " ,
] ,
" correct_index " : 0 ,
" explanation " : " A useful memo ties evidence back to a causal story. " ,
} ,
] ,
) ,
(
" Noise Problem Set D " ,
[
{
" prompt " : " What is the strongest sentence about noise maturity? " ,
" options " : [
" I can say which mismatch is probably sampling, which is probably protocol, and which is plausibly structural noise " ,
" I can plot a histogram " ,
" I know that all real hardware is noisy " ,
] ,
" correct_index " : 0 ,
" explanation " : " Maturity means discriminating between kinds of failure. " ,
} ,
{
" prompt " : " Why does this course keep the main noise path local? " ,
" options " : [
" Because disciplined interpretation can be trained without cloud dependence " ,
" Because local models are always perfectly realistic " ,
" Because noise only exists in notebooks " ,
] ,
" correct_index " : 0 ,
" explanation " : " The goal is clean pedagogy and reproducibility, not false realism claims. " ,
} ,
{
" prompt " : " What should happen after you identify a noise-sensitive circuit region? " ,
" options " : [
" Propose a leaner or better-structured alternative and compare it honestly " ,
" Stop using the circuit entirely " ,
" Increase the markdown count " ,
] ,
" correct_index " : 0 ,
" explanation " : " The engineering response is redesign, not resignation. " ,
} ,
] ,
) ,
]
NOISE_STUDIO_QUIZ = [
{
" prompt " : " What is the core job of the noise studio? " ,
" options " : [
" Compare candidate circuits under the same distortion model and defend a robustness judgment " ,
" Avoid ideal references " ,
" Treat every histogram difference as proof of hardware failure " ,
] ,
" correct_index " : 0 ,
" explanation " : " The studio is about disciplined robustness comparison. " ,
} ,
{
" prompt " : " What makes a noise design memo convincing? " ,
" options " : [
" A stable protocol, explicit evidence, and a structural explanation for the observed gap " ,
" Only a large number of shots " ,
" Only the prettiest plot " ,
] ,
" correct_index " : 0 ,
" explanation " : " Good memos tie distortion back to design structure and evidence. " ,
} ,
]
def build_construction_lecture ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Circuit Construction and Analysis Lecture
The foundations band trained you to read circuits as arguments . This module trains you to build them as software artifacts . That shift matters . A professional circuit designer does not only understand a finished diagram . They create circuits that can be reviewed , extended , measured , compared , and reused without turning into a pile of duplicated gate fragments . That is why the first engineering module focuses on construction discipline rather than on new theory .
"""
) ,
markdown_cell (
"""
## Learning Objective
By the end of this lecture , you should be able to explain why named registers , role separation , reusable blocks , and circuit metrics are not software niceties bolted onto quantum work but part of quantum engineering itself . You should also be able to inspect a small circuit builder and say what the interface is , which substructure is worth encapsulating , and what metrics you would check before trusting the design .
"""
) ,
markdown_cell (
"""
## Why Construction Discipline Arrives Here
Many introductory Qiskit courses keep the learner in a one - cell , one - circuit mindset for too long . That is fine for first exposure but not for professional growth . Once you know what a circuit means , the next question is how to build that meaning repeatedly without drowning in fragile copy - paste code . This is where engineering starts . The quantum content has not vanished . It now lives inside better construction habits : named wires , stable subcircuits , explicit reporting layers , and comparison between candidate implementations .
The larger lesson is that software quality and quantum clarity should support each other . If a builder hides the important burden of the circuit , the code is too clever . If a circuit can only be understood by re - reading every line from scratch , the structure is too flat . Good construction creates reviewable shapes .
"""
) ,
markdown_cell (
"""
## Registers Are Interfaces, Not Storage Buckets
A register in Qiskit is more than a container for qubits or classical bits . In an engineering notebook it is often the first place where intent becomes explicit . If a circuit has data wires , a check wire , and a readout register , those names tell the next reader what role each part is supposed to play . That matters for review because many errors are really interface errors : a measurement landed in the wrong classical slot , an ancilla - like wire got reused as payload , or a builder silently changed the reporting contract .
Naming registers does not solve every problem , but it pushes the circuit toward role - bearing structure instead of anonymous positions . This is one of the earliest places where the field starts resembling real software architecture rather than one - off experiments .
"""
) ,
markdown_cell (
"""
## Blocks, Builders, And Abstraction Boundaries
The next leap is block thinking . A good builder takes a recurring substory and gives it a stable interface . That might be a preparation block , a measurement block , or a parity - style check layer . The point is not to worship abstraction . The point is to decide what deserves to be isolated and what should remain visible . That decision is where engineering judgment begins .
There is a real risk here . If you abstract too aggressively , the circuit becomes shorter but less reviewable . If you never abstract , every change becomes brittle and repetitive . The right balance is to isolate stable substructure while keeping the causal story of the whole circuit easy to narrate . This lecture keeps returning to that tradeoff because it will remain important through algorithms , hardware - aware redesign , and capstone work .
"""
) ,
markdown_cell (
"""
## Metrics Are Evidence, Not Decorations
Once circuits become software artifacts , metrics matter . Depth , size , width , and gate counts are not the whole story , but they are part of the story . They tell you something about cost , review surface , compilation pressure , and later noise sensitivity . The mistake is not using metrics . The mistake is using them without linking them back to the design move that caused them .
In this course , a metric is useful only when you can pair it with a sentence such as " depth increased because I added a second entangling layer " or " size stayed stable after refactoring, which suggests the builder improved structure without altering behavior. " Metrics without explanation are trivia . Explanation without metrics is often too vague . Good engineering uses both .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Code-To-Diagram Anchor
The anchor circuit below is intentionally modest . The point is not algorithmic novelty . The point is to show how naming , role separation , and explicit reporting create a cleaner engineering object . Read the marker table first , then inspect the editable builder .
"""
) ,
code_cell ( f " step_reference_table( { CONSTRUCTION_STEP_REFS !r} ) " ) ,
editable_lab_code (
CONSTRUCTION_ANCHOR ,
title = " Construction Anchor: Named Registers And Roles " ,
instructions = " Change one role-bearing choice at a time: a register name, a parity path, or the reporting mapping. Explain what that change does to the circuit story and the reviewability. " ,
) ,
code_cell (
"""
data = QuantumRegister ( 2 , " data " )
syndrome = QuantumRegister ( 1 , " syndrome " )
readout = ClassicalRegister ( 3 , " readout " )
anchor = QuantumCircuit ( data , syndrome , readout )
anchor . h ( data [ 0 ] )
anchor . cx ( data [ 0 ] , data [ 1 ] )
anchor . cx ( data [ 0 ] , syndrome [ 0 ] )
anchor . cx ( data [ 1 ] , syndrome [ 0 ] )
anchor . measure ( data [ 0 ] , readout [ 0 ] )
anchor . measure ( data [ 1 ] , readout [ 1 ] )
anchor . measure ( syndrome [ 0 ] , readout [ 2 ] )
{
" depth " : anchor . depth ( ) ,
" size " : anchor . size ( ) ,
" width " : anchor . width ( ) ,
" ops " : dict ( anchor . count_ops ( ) ) ,
}
"""
) ,
quiz_code ( CONSTRUCTION_QUIZ_A , " Construction Checkpoint A " ) ,
markdown_cell (
"""
## What A Good Builder Tries To Protect
A good builder protects three things at once . First , it protects intent : another reader can still tell what the circuit is for . Second , it protects behavior : refactoring does not silently change the experiment . Third , it protects evidence : the readout and reporting contract remain clear . That three - part standard is useful because it prevents the common mistake of treating refactoring as purely a software cleanup exercise . In a notebook - first quantum project , refactoring is part of scientific and engineering clarity too .
"""
) ,
markdown_cell (
"""
## Construction Review Questions
When you look at a circuit builder , ask these questions . Which wires carry which roles ? What substructure repeats enough to deserve a helper ? What information would be lost if I hid this region behind a function call ? Which metric would move first if I added another layer here ? And how is the classical reporting path being protected ? Those are the kinds of questions that turn " I can write Qiskit code " into " I can review and evolve circuit software. "
"""
) ,
markdown_cell (
"""
## From Notebook Cell To Maintainable Asset
A useful mental shift in this module is to stop asking only whether a circuit cell is correct today and start asking whether the same circuit would still be clear next week , after one more feature , or in the hands of another engineer . That is what makes this an engineering module instead of only a syntax module . Code that merely works in the current cell can still fail as a maintainable artifact if it mixes roles , hides the reporting contract , or repeats the same structural idea in slightly different forms .
In practice , maintainability comes from a small number of disciplined habits . Name the wires by role when role matters . Separate stable preparation structure from experiment - specific reporting structure . Encapsulate repeated logic , but only where the encapsulation leaves the burden of the circuit intelligible . Keep at least one metric in view so the cost of a structural choice is not left to vague intuition . And , most importantly , write enough explanation around the builder that another reader could tell whether a refactor preserved the scientific intention or merely preserved that the cell still executes .
"""
) ,
markdown_cell (
"""
## Review Heuristics That Scale Later
The heuristics installed here will keep reappearing in later bands . If an algorithm notebook gets too tangled , you will still ask which substructure deserves its own builder . If a transpiled circuit looks expensive , you will still ask which abstract region created the burden . If a noisy result looks unstable , you will still ask whether the reporting layer is clear enough that the evidence is even being read correctly . This is why the current examples stay small . The aim is not to impress you with size . The aim is to make these review heuristics visible before later modules make them harder to see .
"""
) ,
quiz_code ( CONSTRUCTION_QUIZ_B , " Construction Checkpoint B " ) ,
reflection_code (
" Write a short paragraph defending one abstraction boundary in the anchor circuit and one region you would deliberately keep inline. "
) ,
reflection_code (
" Name one metric you would track while refactoring a circuit builder and explain what design move you think that metric is proxying for. "
) ,
markdown_cell (
"""
## Mastery Gate
You should leave this lecture able to build a small circuit with explicit roles , explain why a block boundary exists , and use a circuit metric as evidence in a design discussion instead of as isolated trivia .
"""
) ,
]
)
def build_construction_lab ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Circuit Construction and Analysis Lab
The lab converts engineering vocabulary into controlled edits . The question is not whether the code runs . The question is whether you can change interface , structure , and abstraction while keeping the intended behavior and the reporting contract legible .
"""
) ,
markdown_cell (
"""
## Lab Protocol
Predict what should stay stable before you edit anything . Then change one structural choice at a time . After each render , inspect the diagram , the preview counts , and the circuit metrics you care about . The discipline here is not only quantum . It is also software engineering discipline applied to a quantum artifact .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Lab 1: Role-Bearing Registers
Start with the named - register anchor . Change one interface - level choice and ask whether the change improved or degraded reviewability . This is the fastest way to stop treating register declarations as boilerplate .
"""
) ,
code_cell ( f " step_reference_table( { CONSTRUCTION_STEP_REFS !r} ) " ) ,
editable_lab_code (
CONSTRUCTION_ANCHOR ,
title = " Lab 1: Register Roles " ,
instructions = " Rename a register, alter the check wire, or change the reporting map. Then explain what became clearer or more fragile. " ,
) ,
quiz_code ( CONSTRUCTION_LAB_QUIZ_A , " Construction Lab Checkpoint A " ) ,
reflection_code (
" Which register-level edit most changed how readable the circuit felt, and why? "
) ,
markdown_cell (
"""
## Lab 2: Builder Refactor
Now compare inline construction with block composition . The purpose is not to prove that helpers are always better . The purpose is to decide whether a helper actually preserved the circuit story while removing fragile duplication .
"""
) ,
editable_lab_code (
CONSTRUCTION_BLOCK_EDITABLE ,
title = " Lab 2: Builder Refactor " ,
instructions = " Split or merge the helper blocks and explain whether the resulting abstraction boundary improved the design. " ,
) ,
code_cell (
"""
flat = QuantumCircuit ( 2 , 2 )
flat . h ( 0 )
flat . cx ( 0 , 1 )
flat . measure ( [ 0 , 1 ] , [ 0 , 1 ] )
def bell_block ( ) - > QuantumCircuit :
block = QuantumCircuit ( 2 , name = " bell_prep " )
block . h ( 0 )
block . cx ( 0 , 1 )
return block
structured = QuantumCircuit ( 2 , 2 )
structured . compose ( bell_block ( ) , inplace = True )
structured . measure ( [ 0 , 1 ] , [ 0 , 1 ] )
{
" flat_metrics " : { " depth " : flat . depth ( ) , " size " : flat . size ( ) , " ops " : dict ( flat . count_ops ( ) ) } ,
" structured_metrics " : { " depth " : structured . depth ( ) , " size " : structured . size ( ) , " ops " : dict ( structured . count_ops ( ) ) } ,
}
"""
) ,
markdown_cell (
"""
The important lesson in this lab is that a cleaner code shape is only valuable if the circuit story and interface remain visible . Refactoring is not a beauty contest . It is a reviewability contest .
"""
) ,
markdown_cell (
"""
## Lab 3: Metric-Aware Candidate Comparison
Use the next widget to compare two structural candidates for the same reporting task . Toggle the extra entangling layer and inspect what the metrics and preview counts say together .
"""
) ,
editable_lab_code (
CONSTRUCTION_METRICS_EDITABLE ,
title = " Lab 3: Candidate Comparison " ,
instructions = " Compare the lean and extra-layer candidates. Keep the reporting contract stable and explain which structural cost is being paid. " ,
) ,
code_cell (
"""
def candidate ( extra_layer : bool ) - > QuantumCircuit :
circuit = QuantumCircuit ( 3 , 3 )
circuit . h ( 0 )
circuit . cx ( 0 , 1 )
circuit . cx ( 1 , 2 )
if extra_layer :
circuit . cx ( 0 , 2 )
circuit . measure ( [ 0 , 1 , 2 ] , [ 0 , 1 , 2 ] )
return circuit
lean = candidate ( False )
stressed = candidate ( True )
{
" lean " : { " depth " : lean . depth ( ) , " size " : lean . size ( ) , " ops " : dict ( lean . count_ops ( ) ) } ,
" stressed " : { " depth " : stressed . depth ( ) , " size " : stressed . size ( ) , " ops " : dict ( stressed . count_ops ( ) ) } ,
}
"""
) ,
quiz_code ( CONSTRUCTION_LAB_QUIZ_B , " Construction Lab Checkpoint B " ) ,
markdown_cell (
"""
## Lab Debrief
The three labs in this module are rehearsing the same engineering claim from different angles : circuit quality is not only about correct output . It is also about whether the interface is legible , whether the repeated structure is reviewable , and whether the cost of a design choice is visible in the metrics . That is why the lab asks you to keep the reporting layer stable while changing the builders . Stable objective plus controlled structural edits is the only way to tell whether your engineering explanation is getting sharper .
If these exercises feel slower than ordinary tutorial work , that is appropriate . Tutorials often reward motion . Engineering education has to reward discrimination . The point is to notice which edits are merely cosmetic , which edits improve reviewability , and which edits quietly create future maintenance cost . Those distinctions become expensive later if they are not practiced now .
"""
) ,
reflection_code (
" Write a short note explaining which candidate you would keep and what evidence actually supports that choice. "
) ,
reflection_code (
" Describe one case where a helper function could make a circuit harder, not easier, to review. "
) ,
]
)
def build_construction_problems ( ) - > dict :
cells = [
markdown_cell (
"""
# Circuit Construction and Analysis Problems
This notebook checks whether construction vocabulary is becoming engineering judgment . The questions are not about syntax recall alone . They are about identifying interface clarity , abstraction quality , and metric use in short , review - like situations .
"""
) ,
markdown_cell (
"""
## How To Use This Notebook
Answer each quiz slowly enough that you can explain why the wrong options remain tempting . Many weak engineering habits survive because they sound efficient . This notebook is trying to make those weak habits explicit enough to reject .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
]
for heading , questions in CONSTRUCTION_PROBLEM_SETS :
cells . append (
markdown_cell (
f """
## {heading}
Treat these as miniature code - review prompts . Each answer should sharpen the sentence you would later use in a design memo or review comment .
"""
)
)
cells . append ( quiz_code ( questions , heading ) )
cells . extend (
[
markdown_cell (
"""
## Mini Case: Shorter Code, Worse Design
One of the easiest engineering traps to fall into is mistaking shorter code for better design . A helper that compresses six lines into two can still be a worse artifact if it hides the measurement contract , muddles wire roles , or forces the next reader to reverse engineer the meaning from scratch . This module pushes against that trap repeatedly because it is common in notebook - heavy projects . Notebook users often optimize for immediate convenience , but a learning platform that aims at professional skill has to optimize for reviewable structure instead .
Keep that case in mind while answering the quizzes above . Whenever an option sounds efficient , ask efficient for whom and efficient under what future change . That is a stronger engineering question than " is the current cell shorter. "
"""
) ,
markdown_cell (
"""
## Written Checks
Use the prompts below to rehearse complete engineering sentences rather than isolated labels .
"""
) ,
reflection_code (
" Explain why explicit register roles and explicit reporting layers belong in the same engineering conversation. "
) ,
reflection_code (
" Write a short design-review note critiquing a circuit builder that is shorter but less narratable than the inline version. "
) ,
markdown_cell (
"""
## Exit Condition
Move on when you can justify a builder shape , not only write one . This module is about deliberate construction , not just circuit - producing syntax .
"""
) ,
]
)
return notebook ( cells )
def build_construction_studio ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Circuit Construction and Analysis Studio
The studio asks you to design small , reviewable circuit software . The focus is not novelty . The focus is whether your builders expose role structure , preserve behavior , and support comparison between candidates .
"""
) ,
markdown_cell (
"""
## Studio Standard
Every design brief in this notebook should end with a short memo : what the builder is for , what the interface contract is , and what tradeoff you chose between flat visibility and reusable structure .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Brief 1: Small Reusable Preparation Block
Start from the block - based Bell example and redesign it so another engineer could reuse it safely . Your goal is to make the interface and role of the block obvious .
"""
) ,
editable_lab_code (
CONSTRUCTION_BLOCK_EDITABLE ,
title = " Studio Brief 1: Reusable Preparation Block " ,
instructions = " Refine the block boundary and defend why it is the right amount of abstraction for this task. " ,
) ,
reflection_code (
" What is the contract of your block, and what design burden did you intentionally leave outside the helper? "
) ,
markdown_cell (
"""
## Brief 2: Register-Structured Multiwire Design
Use the named - register anchor as a starting point and redesign the role structure if needed . The point is to express interface clearly , not to maximize the number of wires .
"""
) ,
editable_lab_code (
CONSTRUCTION_ANCHOR ,
title = " Studio Brief 2: Register Structure " ,
instructions = " Reassign or rename circuit roles and then defend why the new interface is more reviewable. " ,
) ,
reflection_code (
" Which register name or split carries the most explanatory value in your design? "
) ,
markdown_cell (
"""
## Brief 3: Candidate Comparison Memo
Use the metric - aware candidate constructor and decide which version you would keep in a real codebase . Your answer should cite both structural reasoning and evidence .
"""
) ,
editable_lab_code (
CONSTRUCTION_METRICS_EDITABLE ,
title = " Studio Brief 3: Candidate Comparison Memo " ,
instructions = " Toggle the extra layer, inspect the cost, and write the memo you would leave in a review. " ,
) ,
quiz_code ( CONSTRUCTION_STUDIO_QUIZ , " Construction Studio Check " ) ,
reflection_code (
" What is the biggest construction smell you can now recognize in your own notebook code? "
) ,
reflection_code (
" Which abstraction decision in this studio still feels uncertain, and what extra evidence would settle it? "
) ,
markdown_cell (
"""
## Studio Rubric
Judge your studio work with four questions . First , does the builder expose the roles of the wires clearly enough that another engineer could review the circuit without re - reading every line ? Second , is the abstraction boundary justified by stable structure rather than by a vague desire for shorter code ? Third , did you keep the reporting layer explicit enough that behavior can be checked after refactoring ? Fourth , did you use at least one metric as evidence for a tradeoff rather than as decorative data ?
That rubric matters because the studio is where circuit code stops being a private exercise and starts becoming something like a shared engineering artifact . A builder that survives this rubric on a tiny example is much more likely to survive the later algorithmic and hardware - aware bands .
"""
) ,
markdown_cell (
"""
## Studio Exit
A good outcome is a small circuit design that another engineer could extend without re - learning the whole artifact from scratch . That is the engineering standard this module is trying to install .
"""
) ,
]
)
def build_transpilation_lecture ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Transpilation and Visualization Lecture
This module is where the course stops pretending that the clean abstract circuit is the whole engineering object . It is not . Real implementations live under basis - gate restrictions , connectivity limits , and compilation heuristics . A professional circuit designer must be able to explain what the compiler changed , why it changed it , and what design decisions upstream made that rescue more or less painful .
"""
) ,
markdown_cell (
"""
## Learning Objective
By the end of this lecture , you should be able to read a compiled circuit as engineering evidence . That means naming the relevant constraint set , comparing pre - and post - transpile metrics , spotting where routing pressure entered , and proposing when a topology - aware redesign is better than simply accepting the compiler output .
"""
) ,
markdown_cell (
"""
## Why This Band Leaves The Ideal World
The foundations band deliberately protected conceptual clarity . Now we start adding the distortions that separate a notebook toy from a realistic implementation path . The clean abstract circuit still matters . It expresses intent in the clearest possible form . But if you stop there , you will mistake intent for implementation . Transpilation is the bridge between the two .
In a local - first course , we do not need live hardware access to learn this lesson . A basis - gate set and a coupling map are already enough to create honest engineering pressure . They force the learner to confront the difference between " what I want " and " what this target can host directly. "
"""
) ,
markdown_cell (
"""
## The Three Main Sources Of Compile-Time Cost
There are three big reasons a compiled circuit may grow . First , high - level operations may need to be decomposed into the basis - gate vocabulary . Second , non - local two - qubit interactions may require routing across the allowed coupling map . Third , optimization choices may restructure the circuit in ways that trade one cost for another . A useful compiled - circuit explanation names which of those mechanisms dominated .
This matters because beginners often see the compiled circuit as arbitrary clutter . It is not arbitrary . It is a record of the costs your design and your target jointly created .
"""
) ,
markdown_cell (
"""
## Visualization Is Part Of The Analysis
A compiled diagram is not just a prettier alternative to a metrics table . The picture helps you see where the compiler inserted work , where interactions moved , and how the logical story was rewritten into an implementable one . But the picture alone is not enough . The prose and metrics must explain what you are seeing . Good engineering combines the visual and the verbal .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Code-To-Diagram Anchor
The anchor example creates a small amount of non - local pressure on a four - qubit line . Read the marker table first , then compare the abstract and compiled views .
"""
) ,
code_cell ( f " step_reference_table( { TRANSPILATION_STEP_REFS !r} ) " ) ,
editable_lab_code (
TRANSPILATION_ABSTRACT_EDITABLE ,
title = " Transpilation Anchor: Abstract Circuit " ,
instructions = " Edit the abstract circuit first. Ask which line is likely to trigger routing pressure on a four-qubit line. " ,
context_source = """
defaults = load_experiment_defaults ( )
constrained_counts = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( circuit . num_qubits ) ,
)
""" ,
context_name = " constrained_counts " ,
) ,
code_cell (
"""
defaults = load_experiment_defaults ( )
abstract = QuantumCircuit ( 4 , 4 )
abstract . h ( 0 )
abstract . cx ( 0 , 3 )
abstract . cx ( 3 , 1 )
abstract . measure ( [ 0 , 1 , 2 , 3 ] , [ 0 , 1 , 2 , 3 ] )
summary = transpile_summary (
abstract ,
BasicSimulator ( ) ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( 4 ) ,
optimization_level = 0 ,
)
{
" depth_before " : summary [ " depth_before " ] ,
" depth_after " : summary [ " depth_after " ] ,
" size_before " : summary [ " size_before " ] ,
" size_after " : summary [ " size_after " ] ,
" ops_before " : summary [ " ops_before " ] ,
" ops_after " : summary [ " ops_after " ] ,
}
"""
) ,
code_cell ( " draw_circuit(summary[ ' compiled_circuit ' ]) " ) ,
quiz_code ( TRANSPILATION_QUIZ_A , " Transpilation Checkpoint A " ) ,
markdown_cell (
"""
## Reading The Rewrite
A useful transpilation explanation usually starts with the constraint set , not with the picture . State the basis gates . State the topology . Then explain which abstract feature was hostile to those constraints . Only after that should you interpret the compiled rewrite . This order prevents magical thinking . The compiler did not " decide to make the circuit ugly. " It paid the bills created by the design and the target .
"""
) ,
markdown_cell (
"""
## When Human Redesign Beats Compiler Rescue
The compiler is powerful , but it is not a substitute for circuit judgment . If the compiled rewrite reveals that your abstract circuit is constantly asking for long - range interactions on a line , that is not only the compiler ' s problem. It may be a design smell. A topology-aware alternative that carries the same intent more cooperatively can be the better engineering solution.
"""
) ,
markdown_cell (
"""
## A Practical Reading Order For Compiled Circuits
When you inspect a compiled circuit , use a fixed reading order . First , state the abstract objective in one sentence so the target remains visible . Second , name the active constraints : basis gates , coupling map , and any optimization - level choice . Third , look at the largest metric changes , because they tell you where to focus . Fourth , inspect the compiled diagram and ask which part of the change came from basis conversion and which part came from routing pressure . Finally , ask whether the abstract circuit itself is topology - hostile in a way that a human redesign could soften . That order keeps the analysis causal instead of aesthetic .
This reading order is valuable because compiled circuits are easy to misread emotionally . Beginners often see more gates and conclude that the compiler is doing arbitrary damage . The disciplined alternative is to treat every extra structure as a bill and then ask which design choice or constraint generated it .
"""
) ,
markdown_cell (
"""
## Why This Module Uses Local Constraints Instead Of Cloud Hardware
A local - first transpilation module is not a compromise . It is a teaching choice . Basis - gate sets and coupling maps already expose the core compile - time tensions without making the learner chase moving remote targets . That makes the reasoning cleaner . Once the learner can already describe routing pressure , depth inflation , and topology - aware redesign locally , later encounters with richer hardware data will make more sense rather than less .
"""
) ,
markdown_cell (
"""
## Three Common Compile-Time Failure Patterns
The first failure pattern is hidden non - locality : the abstract circuit looks innocent until you notice that its most important interaction skips over intermediate qubits that the target topology cannot ignore . The second failure pattern is basis blindness : the author uses a gate vocabulary that is convenient for explanation but never asks what decomposition cost will be paid in the target basis . The third failure pattern is compiler overtrust : the learner sees a much larger compiled circuit and treats the compiler as a black box instead of asking what abstract design choice created the expense . These three patterns are common enough that they are worth naming explicitly now .
Naming them matters because diagnosis becomes faster . When a compiled circuit suddenly grows , you no longer have to stare at it vaguely . You can ask : am I paying for hidden non - locality , basis mismatch , or both ? That is already a much stronger engineering starting point .
"""
) ,
markdown_cell (
"""
## How To Write A Useful Transpilation Memo
A useful transpilation memo is short but structured . Start with the abstract objective . Then state the target assumptions : basis gates , topology , and optimization setting . Report the main metric changes . After that , name the causal story of the rewrite in plain language : which interaction triggered routing , which operation needed decomposition , and whether the compiler mostly rearranged cost or mostly introduced new cost . Finally , state the design judgment . Should the original circuit stay as it is , or is there a topology - aware rewrite that better respects the target ?
This memo format is more important than it may look . Later , when circuits become algorithmic and hardware - aware at the same time , you will need a compact way to talk about compilation without collapsing into either hand - waving or giant changelogs . The discipline starts here .
"""
) ,
markdown_cell (
"""
## Case Study Thinking Instead Of Feature Spotting
A weak learner opens a compiled circuit and starts feature spotting : there is a SWAP - like pattern here , more CNOTs there , maybe a few extra single - qubit rotations at the edges . That is not useless , but it is not enough . A stronger learner treats the whole example as a case study . What was the abstract request ? What target assumptions made that request expensive ? Which part of the rewrite is unavoidable , and which part reflects a poor initial layout ? What would another abstract design have changed ? Those are the questions that turn isolated compile artifacts into a coherent engineering story .
This case - study style matters because the same visual feature can mean different things in different contexts . An extra block of single - qubit gates might be harmless basis conversion in one example and evidence of a poor abstraction choice in another . A cluster of two - qubit operations might represent inevitable routing on one topology and avoidable hostility on another . The compiled circuit only becomes legible when you keep asking what problem it is solving and what bill it is paying .
"""
) ,
markdown_cell (
"""
## Why Design Accountability Still Belongs To The Human
It is easy to slip into a passive relationship with the transpiler . After all , it can usually produce some valid compiled circuit . But validity is not the only engineering standard . You are still responsible for whether the abstract design invites needless routing , whether the measurement protocol stayed stable enough for fair comparison , and whether the chosen target assumptions were made explicit enough that another person could reproduce the analysis . In other words , compilation does not erase authorship . It only makes authorship more visible .
This is one reason the course keeps pairing compiled diagrams with redesign prompts . The learner should not leave this module thinking that transpilation is something that happens to circuits from the outside . It is part of the circuit - design conversation . The abstract circuit , the target constraints , and the compiler together create the final implementation path . Professional judgment means taking ownership of all three .
"""
) ,
quiz_code ( TRANSPILATION_QUIZ_B , " Transpilation Checkpoint B " ) ,
reflection_code (
" Write a short paragraph explaining the difference between an abstract circuit being logically clear and the same circuit being implementation-friendly. "
) ,
reflection_code (
" Name one sign in a compiled circuit that would make you consider an upstream redesign instead of only accepting the transpiler output. "
) ,
markdown_cell (
"""
## Mastery Gate
You are ready to leave this lecture only if you can state the constraint set , describe the compiled rewrite in plain engineering language , and propose one topology - aware alternative when the compiler had to rescue poor structure .
"""
) ,
]
)
def build_transpilation_lab ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Transpilation and Visualization Lab
The lab moves from reading compiled circuits to manipulating the design choices that create them . The main skill here is attribution : which abstract choice created which compile - time cost .
"""
) ,
markdown_cell (
"""
## Lab Protocol
Keep the objective fixed while you edit structure . Then compare abstract and compiled outcomes under the same basis - gate set and coupling map . The point is not to make the compiler happy at any cost . The point is to understand what the compiler had to do on your behalf .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Lab 1: Abstract Pressure
Start from the abstract circuit with a non - local interaction . Predict which line on the diagram is causing the main routing burden before you render anything .
"""
) ,
code_cell ( f " step_reference_table( { TRANSPILATION_STEP_REFS !r} ) " ) ,
editable_lab_code (
TRANSPILATION_ABSTRACT_EDITABLE ,
title = " Lab 1: Abstract Pressure " ,
instructions = " Move the long-range interaction or replace it with a local chain. Then explain how that should affect the compiled cost. " ,
context_source = """
defaults = load_experiment_defaults ( )
constrained_counts = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( circuit . num_qubits ) ,
)
""" ,
context_name = " constrained_counts " ,
) ,
quiz_code ( TRANSPILATION_LAB_QUIZ_A , " Transpilation Lab Checkpoint A " ) ,
reflection_code (
" Which abstract line in the circuit is carrying the main routing burden, and how do you know? "
) ,
markdown_cell (
"""
## Lab 2: Render The Compiled Form Directly
The next widget compiles inside the editable code and renders the compiled circuit itself . This is useful because it forces the diagram you see to reflect the constrained implementation rather than the abstract source .
"""
) ,
editable_lab_code (
TRANSPILATION_COMPILED_EDITABLE ,
title = " Lab 2: Compiled Circuit View " ,
instructions = " Edit the abstract source or the optimization level in the code and inspect how the compiled diagram and metrics change. " ,
context_source = """
defaults = load_experiment_defaults ( )
constrained_counts = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( circuit . num_qubits ) ,
)
""" ,
context_name = " constrained_counts " ,
) ,
code_cell (
"""
defaults = load_experiment_defaults ( )
abstract = QuantumCircuit ( 4 , 4 )
abstract . h ( 0 )
abstract . cx ( 0 , 3 )
abstract . cx ( 3 , 1 )
abstract . measure ( [ 0 , 1 , 2 , 3 ] , [ 0 , 1 , 2 , 3 ] )
opt0 = transpile_summary (
abstract ,
BasicSimulator ( ) ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( 4 ) ,
optimization_level = 0 ,
)
opt3 = transpile_summary (
abstract ,
BasicSimulator ( ) ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( 4 ) ,
optimization_level = 3 ,
)
{
" opt0_depth_after " : opt0 [ " depth_after " ] ,
" opt3_depth_after " : opt3 [ " depth_after " ] ,
" opt0_ops_after " : opt0 [ " ops_after " ] ,
" opt3_ops_after " : opt3 [ " ops_after " ] ,
}
"""
) ,
markdown_cell (
"""
## Lab 3: Topology-Aware Rewrite
Now rewrite the circuit so it cooperates with the line from the start . The point is not to erase every cost . The point is to compare compiler rescue with human design foresight .
"""
) ,
editable_lab_code (
TRANSPILATION_TOPOLOGY_AWARE_EDITABLE ,
title = " Lab 3: Topology-Aware Rewrite " ,
instructions = " Keep the measurement protocol stable while you compare the local-chain rewrite to the topology-hostile original. " ,
context_source = """
defaults = load_experiment_defaults ( )
constrained_counts = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( circuit . num_qubits ) ,
)
""" ,
context_name = " constrained_counts " ,
) ,
quiz_code ( TRANSPILATION_LAB_QUIZ_B , " Transpilation Lab Checkpoint B " ) ,
markdown_cell (
"""
## Lab Debrief
The lab sequence is designed to teach attribution . First you identify the abstract source of routing pressure . Then you inspect the compiler ' s response directly. Finally, you compare that response to a circuit that cooperates with the topology from the start. Those three views are enough to build the core engineering habit: do not treat the compiled circuit as mysterious, and do not treat the compiler as an excuse not to redesign anything upstream.
This matters later because compile - time cost and noise cost often interact . A circuit that forces heavy routing is not only visually uglier after transpilation . It may also become a worse experimental object once noise enters . So even though this module is about compilation first , the design judgment it trains has consequences beyond compilation .
"""
) ,
reflection_code (
" Write a short memo explaining when the topology-aware rewrite is genuinely better and when it might overfit to one target. "
) ,
reflection_code (
" Describe one compiled-circuit feature that you can now interpret causally instead of treating as arbitrary clutter. "
) ,
]
)
def build_transpilation_problems ( ) - > dict :
cells = [
markdown_cell (
"""
# Transpilation and Visualization Problems
This notebook checks whether compile - time thinking is becoming explicit . The questions focus on constraints , routing pressure , metric interpretation , and redesign judgment .
"""
) ,
markdown_cell (
"""
## How To Use This Notebook
Answer as if you were preparing short review comments for another engineer . The goal is not only to know facts about transpilation but to speak about compile - time consequences precisely .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
]
for heading , questions in TRANSPILATION_PROBLEM_SETS :
cells . append (
markdown_cell (
f """
## {heading}
Treat these quizzes as compact design - review drills . You are practicing the sentences that make compiled circuits intelligible .
"""
)
)
cells . append ( quiz_code ( questions , heading ) )
cells . extend (
[
markdown_cell (
"""
## Mini Case: Correct Output, Expensive Realization
One of the central lessons of this module is that functional correctness does not end the engineering discussion . Two circuits can implement the same logical objective and even produce the same sampled evidence while having very different compile - time cost . If you ignore that , you will think the transpiler is only a performance detail . It is not . It is part of the design story .
The quizzes above are therefore not only about definitions . They are practice in keeping implementation cost visible even when the logical story stayed stable . That distinction is one of the main differences between being able to run circuits and being able to engineer them .
"""
) ,
markdown_cell (
"""
## Mini Case: Same Intent, Better Topology Cooperation
A useful transpilation exercise is to imagine two teammates proposing circuits for the same local objective . One writes the conceptually shortest abstract circuit and leaves the routing burden to the compiler . The other writes a slightly more topology - aware version that is less elegant at first glance but compiles more gently . Which one is better ? The only serious answer is : compare them under the same constraints and state the tradeoff honestly .
This mini case is here to reinforce that transpilation reasoning is not about punishing abstraction . It is about deciding when abstract elegance and physical cooperation pull in different directions and writing down that tension clearly .
"""
) ,
markdown_cell (
"""
## Written Checks
Use the prompts below to rehearse the core explanatory loop of this module : state the constraints , describe the rewrite , and justify the redesign recommendation .
"""
) ,
reflection_code (
" Explain why the same logical circuit can have very different compiled forms under different topologies or optimization levels. "
) ,
reflection_code (
" Write a short review note on when accepting the transpiler output is good enough and when upstream redesign is the stronger choice. "
) ,
markdown_cell (
"""
## Exit Condition
Move on only when you can read a compiled circuit as a constrained implementation , not as unexplained visual clutter .
"""
) ,
]
)
return notebook ( cells )
def build_transpilation_studio ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Transpilation and Visualization Studio
The studio asks you to act like a hardware - aware reviewer . You will compare hostile and cooperative designs under explicit constraints and write the kind of redesign memo that later bands will depend on .
"""
) ,
markdown_cell (
"""
## Studio Standard
Every answer should state the abstract objective , the constraint set , and the evidence for why one implementation path is better than another . If any one of those is missing , the redesign claim is too soft .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Brief 1: Rescue Versus Redesign
Start from the topology - hostile abstract circuit and write the memo you would leave after seeing the compiled result .
"""
) ,
editable_lab_code (
TRANSPILATION_COMPILED_EDITABLE ,
title = " Studio Brief 1: Rescue Versus Redesign " ,
instructions = " Inspect the compiled form and decide whether you would accept the rescue or redesign the abstract circuit. " ,
context_source = """
defaults = load_experiment_defaults ( )
constrained_counts = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( circuit . num_qubits ) ,
)
""" ,
context_name = " constrained_counts " ,
) ,
reflection_code (
" What exactly did the compiler have to rescue, and what upstream change would reduce that burden? "
) ,
markdown_cell (
"""
## Brief 2: Cooperative Rewrite
Build the topology - aware version and compare it honestly to the compiler - rescued one .
"""
) ,
editable_lab_code (
TRANSPILATION_TOPOLOGY_AWARE_EDITABLE ,
title = " Studio Brief 2: Cooperative Rewrite " ,
instructions = " Tune the local-chain design and explain whether it preserves the objective while reducing compile-time pain. " ,
context_source = """
defaults = load_experiment_defaults ( )
constrained_counts = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( circuit . num_qubits ) ,
)
""" ,
context_name = " constrained_counts " ,
) ,
reflection_code (
" What did your redesign gain, and what did it potentially give up? "
) ,
markdown_cell (
"""
## Brief 3: Optimization-Level Judgment
Use the compiled - render widget again , but this time focus on optimization - level tradeoffs and the review language they require .
"""
) ,
editable_lab_code (
TRANSPILATION_COMPILED_EDITABLE ,
title = " Studio Brief 3: Optimization Judgment " ,
instructions = " Adjust the optimization level or the abstract structure and defend the compiled result you would ship for this lesson ' s local target. " ,
context_source = """
defaults = load_experiment_defaults ( )
constrained_counts = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
basis_gates = list ( defaults . transpile . basis_gates ) ,
coupling_map = line_coupling_map ( circuit . num_qubits ) ,
)
""" ,
context_name = " constrained_counts " ,
) ,
quiz_code ( TRANSPILATION_STUDIO_QUIZ , " Transpilation Studio Check " ) ,
reflection_code (
" What is the main transpilation smell you can now recognize in an abstract circuit before compiling it? "
) ,
reflection_code (
" Which redesign judgment in this module still feels tentative, and what extra comparison would strengthen it? "
) ,
markdown_cell (
"""
## Studio Rubric
Use a strict rubric here . A strong studio answer states the objective without ambiguity , states the constraint set explicitly , shows the relevant pre - and post - compile evidence , and gives a redesign recommendation that another engineer could actually test . A weak answer says only that one circuit " looks cleaner " or " seems more hardware aware. " The studio exists to eliminate that kind of soft language .
This rubric matters because later hardware - aware modules will assume you can already argue about compile - time tradeoffs in review language . The current studio is where that language gets installed .
"""
) ,
markdown_cell (
"""
## Studio Review Standard
Before you leave this notebook , ask whether your memo would still make sense to a reader who never saw your intermediate experiments . If the answer is no , then the memo is still too dependent on the notebook context . A good engineering memo should survive outside the cell stream . It should say enough about the objective , constraints , and cost story that another person could reproduce the comparison or challenge your conclusion intelligently .
That standard is intentionally high . The whole point of the studio is to move from personal experimentation toward shared engineering language .
"""
) ,
markdown_cell (
"""
## Studio Exit
A strong outcome is a short redesign memo that another engineer could act on : it states the target , the constraints , the cost , and the reason the chosen rewrite is preferable .
"""
) ,
]
)
def build_noise_lecture ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Simulation and Noise Models Lecture
This module teaches the second half of the ideal - versus - reality split . The previous module showed how compilation distorts clean intent into constrained implementation . This one shows how evidence itself changes once sampling variation and local error enter the picture . A professional circuit designer needs a disciplined way to compare ideal models , shot - based evidence , and noisy distortion without collapsing them into one blurry story .
"""
) ,
markdown_cell (
"""
## Learning Objective
By the end of this lecture , you should be able to choose an appropriate local simulator for the question being asked , explain why ideal probabilities and sampled counts differ in status , build a simple local noise profile , and state which mismatches are likely structural rather than mere shot noise .
"""
) ,
markdown_cell (
"""
## Why Simulator Choice Matters
A statevector is the right tool when you want the ideal pre - measurement description . Shot - based simulation is the right tool when you care about the evidence produced by repeated measurement under a fixed protocol . A local noise model is the right tool when you want to ask how a specific distortion pattern interacts with the circuit structure . Confusion begins when these lenses are used interchangeably . Good engineering begins when the lens matches the question .
"""
) ,
markdown_cell (
"""
## Ideal, Sampled, And Noisy Are Three Different Claims
The ideal probability model is a claim about what the circuit would do in the clean reference story . The shot - based histogram is a claim about what repeated sampling of that story produced in one finite run . The noisy histogram is a claim about what happens after a distortion model has been applied on top of the compiled circuit . Those are three different statements . A good notebook keeps them separate long enough to compare them honestly .
"""
) ,
markdown_cell (
"""
## Structural Vulnerability
Not every circuit pays the same price under noise . Extra two - qubit depth , wider entangling structure , and poorly motivated additional layers can all make the empirical distribution drift farther from the clean reference . This is one reason engineering quality matters upstream . A leaner circuit is often not only cleaner to read and easier to compile . It may also be more robust under the same local distortion profile .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Code-To-Diagram Anchor
The anchor keeps the circuit simple so the comparison between ideal , sampled , and noisy views remains easy to narrate . Read the marker table first , then inspect the editable version .
"""
) ,
code_cell ( f " step_reference_table( { NOISE_STEP_REFS !r} ) " ) ,
editable_lab_code (
NOISE_IDEAL_EDITABLE ,
title = " Noise Anchor: Ideal Reference Circuit " ,
instructions = " Keep the ideal story clear. Change only one structural choice at a time and compare how the ideal and sampled stories respond. " ,
) ,
code_cell (
"""
anchor = QuantumCircuit ( 2 , 2 )
anchor . h ( 0 )
anchor . cx ( 0 , 1 )
anchor . measure ( [ 0 , 1 ] , [ 0 , 1 ] )
ideal_probs = statevector_probabilities ( anchor )
sampled_counts = simulate_counts ( anchor , shots = 512 )
noisy_counts = simulate_counts (
anchor ,
shots = 512 ,
noise_model = build_demo_noise_model ( two_qubit_error = 0.08 , readout_error = 0.05 ) ,
)
{
" ideal_probabilities " : ideal_probs ,
" sampled_probabilities " : counts_to_probabilities ( sampled_counts ) ,
" noisy_probabilities " : counts_to_probabilities ( noisy_counts ) ,
}
"""
) ,
quiz_code ( NOISE_QUIZ_A , " Noise Checkpoint A " ) ,
markdown_cell (
"""
## What A Local Noise Model Is And Is Not
In this platform the local noise model is a teaching instrument . It is not a claim that we have reconstructed a specific piece of hardware in microscopic detail . That would be the wrong promise for a local - first course . The model is valuable because it lets you ask disciplined what - if questions locally : what if two - qubit operations are appreciably noisier than single - qubit ones , what if readout introduces a small but persistent bias , and how does a deeper circuit compare to a leaner one under the same assumptions ?
"""
) ,
markdown_cell (
"""
## From Drift To Diagnosis
A mismatch between ideal and empirical behavior is only useful if you can classify it . Is it ordinary finite - shot variation ? Is it a protocol mistake , such as a changed basis or reporting map ? Is it a structural sensitivity to the chosen noise profile ? This module is trying to build exactly that classification habit . Without it , noisy evidence becomes a swamp of vaguely disappointing histograms .
"""
) ,
markdown_cell (
"""
## A Clean Diagnostic Order
Use a stable diagnostic order when results drift . First , confirm the protocol : basis , wiring , and shot count . Second , inspect the ideal reference so you know what target you are actually comparing against . Third , ask whether the mismatch could be ordinary sampling variation . Only after those checks should you lean into structural noise explanations . This order matters because it prevents the all - purpose excuse of saying " hardware is noisy " before easier explanations have been ruled out .
The value of a local - first course is that you can rehearse this order without any cloud dependence . The notebook can generate clean ideal evidence , sampled evidence , and locally distorted evidence side by side . That makes the classification habit much easier to train than if every question had to start with a remote backend run .
"""
) ,
markdown_cell (
"""
## Why Robustness Is A Design Property
It is tempting to treat robustness as something that hardware either grants or withholds . That is not the whole story . Circuit structure helps determine how gracefully a design will degrade . Extra entangling depth , repeated two - qubit burden , and avoidable structural clutter can all make a circuit a worse experimental object under the same local assumptions . This is why robustness belongs in the design conversation , not only in the postmortem .
"""
) ,
markdown_cell (
"""
## The Difference Between Sampling Drift And Structural Drift
Sampling drift is ordinary statistical variation around the same underlying probability story . Structural drift is different . It means the observed distribution is being pulled away from the ideal reference in a way that tracks some aspect of the circuit design or the applied noise model . In practice , the distinction is visible through repetition and alignment . If the same kind of distortion persists at higher shot counts and appears strongest where the circuit is structurally heaviest , that is a clue that the drift is not just statistical noise .
This distinction matters because it changes the engineering response . Sampling drift calls for shot reasoning and restraint . Structural drift calls for design analysis and possibly redesign . A serious learning platform has to make that fork explicit early .
"""
) ,
markdown_cell (
"""
## Limits Of A Local Demo Noise Model
The local model in this course is intentionally simple . That simplicity is a feature for teaching , but it also creates limits that should be named honestly . The model cannot capture every temporal correlation , calibration detail , or device - specific quirk of a real backend . What it can do is expose the broad fact that some structures are more distortion - sensitive than others and that those sensitivities can be compared under controlled local assumptions .
This honesty matters pedagogically . If the learner mistakes the local model for perfect realism , they will draw the wrong lesson . The right lesson is subtler and more useful : even a simplified model is enough to train good comparison habits and to show that robustness is partly a property of circuit structure , not only of mysterious hardware fate .
"""
) ,
markdown_cell (
"""
## How To Write A Useful Noise Memo
A useful noise memo does not begin with disappointment . It begins with a clean comparison structure . State the ideal target first . State the measurement protocol second . State the local noise assumptions third . Only then describe the observed gap . After that , propose the most plausible explanation categories in order : sampling variation , protocol mistake , structural sensitivity , or some combination . Finally , suggest the next discriminating check . This memo format matters because it turns a noisy plot from a vague mood into an engineering document .
The reason to practice this memo style so early is that later modules will depend on it heavily . Verification work , hardware - aware debugging , and capstone review all need concise ways to say what changed , what stayed fixed , and what still remains uncertain . The noise memo is one of the first places where disciplined uncertainty becomes part of the craft .
"""
) ,
markdown_cell (
"""
## Why This Module Comes Before Real Hardware Dependence
Some learners assume that serious noise thinking has to wait until they are using live cloud hardware . That is backwards . What has to come first is the ability to compare a clean model , a sampled run , and a controlled distortion pattern without losing the explanatory thread . If that skill is missing , real hardware access mostly adds confusion . Local - first noisy simulation is therefore not a substitute for seriousness . It is the training ground that makes later seriousness possible .
This sequencing choice also protects the beginner from the wrong kind of complexity . The point right now is not to capture every calibration detail . The point is to learn how circuit structure , error assumptions , and measurement evidence interact . Once that triangle is clear , richer hardware data becomes a refinement instead of an avalanche .
"""
) ,
quiz_code ( NOISE_QUIZ_B , " Noise Checkpoint B " ) ,
reflection_code (
" Explain why the same circuit should usually be inspected through all three lenses: ideal model, sampled evidence, and noisy evidence. "
) ,
reflection_code (
" Name one structural reason a circuit might drift more under noise even when the logical objective stayed the same. "
) ,
markdown_cell (
"""
## Mastery Gate
You should leave this lecture able to say which simulator or view matches which question , and to explain a mismatch without immediately collapsing every deviation into the single word noise .
"""
) ,
]
)
def build_noise_lab ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Simulation and Noise Models Lab
The lab puts the three - view comparison into motion . You will keep the protocol stable , change the structural burden of the circuit , and compare ideal , sampled , and noisy evidence under a consistent local model .
"""
) ,
markdown_cell (
"""
## Lab Protocol
Predict before each run which differences should count as ordinary sampling variation and which should count as structural vulnerability . Then use the same measurement protocol for fair comparison . The lab is about disciplined attribution , not just plot collection .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Lab 1: Ideal And Sampled
Start with the clean Bell - style reference . This lab is only about separating the ideal model from finite - shot evidence before noise is added .
"""
) ,
code_cell ( f " step_reference_table( { NOISE_STEP_REFS !r} ) " ) ,
editable_lab_code (
NOISE_IDEAL_EDITABLE ,
title = " Lab 1: Ideal Versus Sampled " ,
instructions = " Keep the circuit shallow. Compare the ideal story to the sampled histogram and name which differences are only statistical. " ,
) ,
quiz_code ( NOISE_LAB_QUIZ_A , " Noise Lab Checkpoint A " ) ,
reflection_code (
" What does the ideal reference tell you that a single finite-shot histogram cannot? "
) ,
markdown_cell (
"""
## Lab 2: Same Circuit Under A Local Noise Profile
Keep the same circuit and protocol , but now inspect it under a demo noise model . This is where the three - view discipline becomes useful : the protocol did not change , but the evidence did .
"""
) ,
editable_lab_code (
NOISE_IDEAL_EDITABLE ,
title = " Lab 2: Local Noise Preview " ,
instructions = " Edit the circuit cautiously and compare the preview under a stable local noise profile. " ,
context_source = """
noisy_preview = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
noise_model = build_demo_noise_model ( two_qubit_error = 0.08 , readout_error = 0.05 ) ,
)
""" ,
context_name = " noisy_preview " ,
) ,
code_cell (
"""
ideal = QuantumCircuit ( 2 , 2 )
ideal . h ( 0 )
ideal . cx ( 0 , 1 )
ideal . measure ( [ 0 , 1 ] , [ 0 , 1 ] )
ideal_counts = simulate_counts ( ideal , shots = 1024 )
noisy_counts = simulate_counts (
ideal ,
shots = 1024 ,
noise_model = build_demo_noise_model ( two_qubit_error = 0.08 , readout_error = 0.05 ) ,
)
{
" ideal_counts " : ideal_counts ,
" noisy_counts " : noisy_counts ,
" ideal_probabilities " : counts_to_probabilities ( ideal_counts ) ,
" noisy_probabilities " : counts_to_probabilities ( noisy_counts ) ,
}
"""
) ,
markdown_cell (
"""
## Lab 3: Stress Test A Lean And A Stressed Candidate
The last lab compares two circuits under the same noise profile . The question is not which one is prettier . The question is which one carries a more robust structure for the same style of task .
"""
) ,
editable_lab_code (
NOISE_STRESSED_EDITABLE ,
title = " Lab 3: Stressed Candidate Under Noise " ,
instructions = " Edit the stressed candidate and compare it to a leaner alternative under the same noise assumptions. " ,
context_source = """
noisy_preview = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
noise_model = build_demo_noise_model ( two_qubit_error = 0.08 , readout_error = 0.05 ) ,
)
""" ,
context_name = " noisy_preview " ,
) ,
editable_lab_code (
NOISE_ROBUST_EDITABLE ,
title = " Lab 3B: Lean Candidate Under Noise " ,
instructions = " Use the same protocol as the stressed candidate and compare which structure survives the local model better. " ,
context_source = """
noisy_preview = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
noise_model = build_demo_noise_model ( two_qubit_error = 0.08 , readout_error = 0.05 ) ,
)
""" ,
context_name = " noisy_preview " ,
) ,
quiz_code ( NOISE_LAB_QUIZ_B , " Noise Lab Checkpoint B " ) ,
markdown_cell (
"""
## Lab Debrief
These labs are deliberately repetitive in one sense : they keep forcing the same circuit family through different explanatory lenses . That repetition is useful . It trains the distinction between model , evidence , and distortion until the distinction becomes natural . The ideal reference says what clean behavior should mean . The sampled histogram says what repeated measurement produced in finite shots . The noisy histogram says what happened after a controlled distortion profile was added . If you can keep those three statements separate while the circuit changes , you are learning the right habit .
The debrief also reinforces another point : robustness comparison only works when the protocol stays fixed . If the measurement basis or reporting map changes at the same time as the structure , you no longer know which difference you are explaining . That is why this module is so insistent about controlled comparison .
"""
) ,
reflection_code (
" Write a short note explaining which difference in the stressed-circuit result you think is structural rather than mere sampling. "
) ,
reflection_code (
" What would you check next if you were not yet sure whether the observed drift came from noise or from a protocol mistake? "
) ,
]
)
def build_noise_problems ( ) - > dict :
cells = [
markdown_cell (
"""
# Simulation and Noise Models Problems
This notebook checks whether you can keep ideal , sampled , and noisy claims distinct under pressure . The target is not only factual knowledge . It is diagnostic discipline .
"""
) ,
markdown_cell (
"""
## How To Use This Notebook
Treat each question as a miniature debugging scenario . Ask yourself what kind of mismatch is being described and what evidence would strengthen or weaken the explanation .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
]
for heading , questions in NOISE_PROBLEM_SETS :
cells . append (
markdown_cell (
f """
## {heading}
Use these quizzes to rehearse the distinctions that later verification and robustness work will depend on .
"""
)
)
cells . append ( quiz_code ( questions , heading ) )
cells . extend (
[
markdown_cell (
"""
## Mini Case: The Wrong Kind Of Noise Explanation
A weak explanation says , " the circuit got noisier because real quantum computers are noisy. " That sentence is not false , but it is nearly useless . A stronger explanation says , " under this local error profile, the extra two-qubit layer created more opportunities for distortion, and the observed drift stayed aligned with that structural change even when the measurement protocol remained fixed. " The second sentence is what this notebook is training .
Keep that contrast in mind while answering the quizzes above . The target is not to sound realistic . The target is to sound diagnostically precise .
"""
) ,
markdown_cell (
"""
## Mini Case: Low Shots, Big Confidence
Another common mistake is to overread a small - shot run . A learner sees one surprising histogram and immediately writes a structural story around it . Sometimes that story is right . Often it is just too early . This case is worth naming because robust engineering judgment is as much about restraint as it is about insight . A good diagnosis knows when the evidence is still thin .
Keep that in mind while answering the reflections below . The right goal is not aggressive certainty . The right goal is justified certainty .
"""
) ,
markdown_cell (
"""
## Written Checks
The reflections below are here to force complete diagnostic sentences rather than vague appeals to realism .
"""
) ,
reflection_code (
" Explain the difference between a circuit that is sampling-noisy and a circuit that is structurally vulnerable to the chosen local error model. "
) ,
reflection_code (
" Write a short memo on how you would compare two candidate circuits under the same noise model without overclaiming from the results. "
) ,
markdown_cell (
"""
## Exit Condition
Move on only when you can classify mismatches instead of calling all of them noise without further thought .
"""
) ,
]
)
return notebook ( cells )
def build_noise_studio ( ) - > dict :
return notebook (
[
markdown_cell (
"""
# Simulation and Noise Models Studio
The studio asks you to act like a local - first experimentalist . You will compare candidate circuits under the same distortion model and defend a robustness judgment with explicit evidence .
"""
) ,
markdown_cell (
"""
## Studio Standard
Every design note in this notebook should state the ideal objective , the noise assumptions , and the structural reason one candidate appears more robust than another .
"""
) ,
code_cell ( SETUP ) ,
code_cell ( COMMON_IMPORTS ) ,
markdown_cell (
"""
## Brief 1: Clean Reference Versus Noisy Reality
Start from the Bell - style reference and write the memo you would leave after seeing ideal and noisy evidence side by side .
"""
) ,
editable_lab_code (
NOISE_IDEAL_EDITABLE ,
title = " Studio Brief 1: Clean Versus Noisy " ,
instructions = " Keep the protocol fixed and write the explanation that separates ideal intent, sampled evidence, and noisy drift. " ,
context_source = """
noisy_preview = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
noise_model = build_demo_noise_model ( two_qubit_error = 0.08 , readout_error = 0.05 ) ,
)
""" ,
context_name = " noisy_preview " ,
) ,
reflection_code (
" What part of the observed drift do you think comes from the chosen noise model rather than from a changed question? "
) ,
markdown_cell (
"""
## Brief 2: Candidate Robustness Comparison
Compare the stressed and lean candidates under the same local model . Your judgment should be explicit about what stayed fixed and what changed .
"""
) ,
editable_lab_code (
NOISE_STRESSED_EDITABLE ,
title = " Studio Brief 2: Stressed Candidate " ,
instructions = " Inspect the heavier candidate under the local model and prepare the comparison memo. " ,
context_source = """
noisy_preview = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
noise_model = build_demo_noise_model ( two_qubit_error = 0.08 , readout_error = 0.05 ) ,
)
""" ,
context_name = " noisy_preview " ,
) ,
editable_lab_code (
NOISE_ROBUST_EDITABLE ,
title = " Studio Brief 2B: Lean Candidate " ,
instructions = " Compare the leaner alternative under the same protocol and distortion model. " ,
context_source = """
noisy_preview = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
noise_model = build_demo_noise_model ( two_qubit_error = 0.08 , readout_error = 0.05 ) ,
)
""" ,
context_name = " noisy_preview " ,
) ,
reflection_code (
" Which candidate would you ship as the local teaching example, and what evidence actually supports that choice? "
) ,
markdown_cell (
"""
## Brief 3: Change The Noise Assumptions Deliberately
Keep the circuit fixed and alter the local noise assumptions in the code . The goal is to see how much of your robustness claim depends on the chosen distortion profile .
"""
) ,
editable_lab_code (
NOISE_IDEAL_EDITABLE ,
title = " Studio Brief 3: Noise-Assumption Sensitivity " ,
instructions = " Adjust the local error rates and explain which parts of your robustness judgment remain stable. " ,
context_source = """
custom_profile = build_demo_noise_model ( single_qubit_error = 0.002 , two_qubit_error = 0.12 , readout_error = 0.06 )
noisy_preview = lambda circuit , shots = 256 : simulate_counts (
circuit ,
shots = shots ,
noise_model = custom_profile ,
)
""" ,
context_name = " noisy_preview " ,
) ,
quiz_code ( NOISE_STUDIO_QUIZ , " Noise Studio Check " ) ,
reflection_code (
" What is the main robustness smell you can now recognize in a circuit before simulating it under noise? "
) ,
reflection_code (
" Which part of your noise reasoning still feels too dependent on one chosen local model, and how would you test that weakness? "
) ,
markdown_cell (
"""
## Studio Rubric
Judge your studio memo with five questions . Did you state the ideal objective clearly ? Did you state the noise assumptions clearly ? Did you compare the candidates under the same protocol ? Did you tie the observed gap back to a plausible structural reason ? And did you admit where the conclusion still depends on the chosen local model ? A memo that cannot answer those questions is still too soft for engineering use .
This rubric is intentionally demanding because later verification and capstone work will need exactly this style of disciplined uncertainty . The point is not to eliminate doubt . The point is to express it in a useful , testable form .
"""
) ,
markdown_cell (
"""
## Studio Review Standard
The best test of your memo is whether another engineer could disagree with it productively . That requires enough detail to challenge the protocol , the local assumptions , or the structural explanation . If your memo only announces that one candidate " felt more robust, " it is still too private and intuitive . If it states the setup clearly enough that disagreement can become experimental , then it has crossed the line into useful engineering writing .
"""
) ,
markdown_cell (
"""
## Studio Exit
A strong outcome is a review memo that another engineer could trust : it states the local assumptions , compares the candidates fairly , and ties the observed gap back to circuit structure .
"""
) ,
]
)
def main ( ) - > None :
outputs = {
MODULE_01_DIR / " lecture.ipynb " : build_construction_lecture ( ) ,
MODULE_01_DIR / " lab.ipynb " : build_construction_lab ( ) ,
MODULE_01_DIR / " problems.ipynb " : build_construction_problems ( ) ,
MODULE_01_DIR / " studio.ipynb " : build_construction_studio ( ) ,
MODULE_02_DIR / " lecture.ipynb " : build_transpilation_lecture ( ) ,
MODULE_02_DIR / " lab.ipynb " : build_transpilation_lab ( ) ,
MODULE_02_DIR / " problems.ipynb " : build_transpilation_problems ( ) ,
MODULE_02_DIR / " studio.ipynb " : build_transpilation_studio ( ) ,
MODULE_03_DIR / " lecture.ipynb " : build_noise_lecture ( ) ,
MODULE_03_DIR / " lab.ipynb " : build_noise_lab ( ) ,
MODULE_03_DIR / " problems.ipynb " : build_noise_problems ( ) ,
MODULE_03_DIR / " studio.ipynb " : build_noise_studio ( ) ,
}
for path , payload in outputs . items ( ) :
write_notebook ( path , payload )
if __name__ == " __main__ " :
main ( )