QuantumLearning/notebooks/professional/module_03_noise_aware_verification/lab.ipynb

312 lines
14 KiB
Text

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Noise-Aware Verification and Mitigation Lab\n"
],
"id": "566b6a08"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The lab turns diagnosis into a series of controlled comparisons: correct versus buggy, ideal versus noisy, and raw versus filtered evidence.\n"
],
"id": "5c685a89"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab Protocol\n",
"\n",
"\n",
" Keep the reporting contract fixed while you compare cases. The point is to isolate why the outcome changed, not to change the whole experiment and call the result insight.\n"
],
"id": "83ad3645"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"import sys\n",
"\n",
"project_root = Path.cwd().resolve()\n",
"while not (project_root / \"pyproject.toml\").exists():\n",
" if project_root.parent == project_root:\n",
" raise RuntimeError(\"Could not locate the project root from this notebook.\")\n",
" project_root = project_root.parent\n",
"\n",
"src_path = project_root / \"src\"\n",
"if str(src_path) not in sys.path:\n",
" sys.path.insert(0, str(src_path))\n"
],
"id": "3e7046de"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from quantum_learning import (\n",
" build_demo_noise_model,\n",
" counts_to_probabilities,\n",
" draw_circuit,\n",
" editable_circuit_lab,\n",
" evidence_checklist,\n",
" feedback_iteration_panel,\n",
" line_coupling_map,\n",
" load_assessment_blueprint,\n",
" plot_counts,\n",
" plot_probabilities,\n",
" quiz_block,\n",
" reflection_box,\n",
" rubric_scorecard,\n",
" simulate_counts,\n",
" statevector_probabilities,\n",
" step_reference_table,\n",
" transpile_summary,\n",
")\n",
"from qiskit import QuantumCircuit\n",
"from qiskit.providers.basic_provider import BasicSimulator\n"
],
"id": "2e8f1586"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab 1: Ideal And Noisy Baselines\n",
"\n",
"\n",
" Start by comparing the same correct circuit in ideal and noisy form. This establishes what the expected distortion looks like when the underlying mechanism is intact.\n"
],
"id": "ef099a4f"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"step_reference_table([{'marker': '[1]', 'code_focus': 'State an invariant or expected signature before you look at noisy data.', 'diagram_effect': 'The circuit is linked to a claim, not only to a plot.', 'why_it_matters': 'Verification begins with a falsifiable expectation, not with vibes about whether the histogram looks plausible.'}, {'marker': '[2]', 'code_focus': 'Create an ideal reference case with a clear evidence path.', 'diagram_effect': 'The clean diagram becomes the baseline against which distortion is interpreted.', 'why_it_matters': 'Without an ideal baseline, noise and design bugs get mixed together.'}, {'marker': '[3]', 'code_focus': 'Inject or study noise while preserving the same reporting contract.', 'diagram_effect': 'The circuit body stays recognizably the same while the output distribution degrades.', 'why_it_matters': 'Good diagnosis compares like with like.'}, {'marker': '[4]', 'code_focus': 'Use invariants, filters, or postselection to separate structural failure from expected physical distortion.', 'diagram_effect': 'The notebook now includes verification logic alongside execution.', 'why_it_matters': 'Mitigation thinking starts with diagnosis, not magical hope.'}])\n"
],
"id": "f1ea489d"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"demo_noise = build_demo_noise_model(\n",
" single_qubit_error=0.01,\n",
" two_qubit_error=0.05,\n",
" readout_error=0.03,\n",
")\n",
"\n",
"def simulate_noisy_counts(circuit, shots=256):\n",
" return simulate_counts(circuit, shots=shots, noise_model=demo_noise)\n",
"\n",
"editable_code = '\\nfrom qiskit import QuantumCircuit\\n\\ndef bell_candidate(bug: bool = False) -> QuantumCircuit:\\n circuit = QuantumCircuit(2, 2)\\n # [1] Toggle only one potential design defect at a time.\\n if not bug:\\n circuit.h(0)\\n # [2] Correlate the second wire so the intended support is {00, 11}.\\n circuit.cx(0, 1)\\n # [3] Keep the reporting layer explicit and stable.\\n circuit.barrier()\\n # [4] Measure both outputs so invariants can inspect the evidence.\\n circuit.measure([0, 1], [0, 1])\\n return circuit\\n\\ncircuit = bell_candidate(bug=False)\\n'\n",
"editable_circuit_lab(\n",
" initial_code=editable_code,\n",
" context={\"QuantumCircuit\": QuantumCircuit, \"simulate_counts\": simulate_noisy_counts},\n",
" title='Lab 1: Ideal Versus Noisy Baseline',\n",
" instructions='Keep the correct Bell-style mechanism intact and compare how the same evidence path behaves under local noise.',\n",
" shots=256,\n",
")\n"
],
"id": "0f17ebc6"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"quiz_block([{'prompt': 'What is the best use of a noisy preview in this lab?', 'options': ['To compare it directly to the ideal baseline while keeping the same measurement contract', 'To replace ideal simulation completely', 'To prove the circuit is wrong whenever the counts change'], 'correct_index': 0, 'explanation': 'Noise is informative only relative to a stable baseline.'}, {'prompt': 'What distinguishes a missing-H bug from mild noise in the Bell example?', 'options': ['The bug destroys the intended 00/11 balance mechanism itself', 'The bug only changes the transpiler seed', 'Nothing, they are equivalent'], 'correct_index': 0, 'explanation': 'The design defect changes the causal story, not just the output quality.'}], heading='Lab Checkpoint A')\n"
],
"id": "ca23c704"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"reflection_box('Which comparison in the lab most clarified the difference between a defect and a distortion?')\n"
],
"id": "f9147f16"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab 2: Bug Versus Noise\n",
"\n",
"\n",
" Now introduce a deliberate design defect and compare that story to mere noisy degradation. The goal is to make the difference between broken mechanism and distorted mechanism feel concrete.\n"
],
"id": "fb8eeda0"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"editable_code = '\\nfrom qiskit import QuantumCircuit\\n\\ndef bell_candidate(bug: bool = True) -> QuantumCircuit:\\n circuit = QuantumCircuit(2, 2)\\n if not bug:\\n circuit.h(0)\\n circuit.cx(0, 1)\\n circuit.measure([0, 1], [0, 1])\\n return circuit\\n\\ncircuit = bell_candidate(bug=True)\\n'\n",
"editable_circuit_lab(\n",
" initial_code=editable_code,\n",
" context={\"QuantumCircuit\": QuantumCircuit, \"simulate_counts\": simulate_counts},\n",
" title='Lab 2: Design Bug Stress Test',\n",
" instructions='Toggle the bug switch and explain why the resulting failure mode is not the same as mild noise on a correct design.',\n",
" shots=256,\n",
")\n"
],
"id": "a60a31bf"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab 3: Bounded Filtering And Mitigation\n",
"\n",
"\n",
" Finally, use a simple filtering idea to see what can and cannot be improved after the fact. This is not a miracle stage. It is a disciplined diagnostic stage.\n"
],
"id": "c7b66456"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"demo_noise = build_demo_noise_model(\n",
" single_qubit_error=0.01,\n",
" two_qubit_error=0.05,\n",
" readout_error=0.03,\n",
")\n",
"\n",
"def simulate_noisy_counts(circuit, shots=256):\n",
" return simulate_counts(circuit, shots=shots, noise_model=demo_noise)\n",
"\n",
"editable_code = '\\nfrom qiskit import QuantumCircuit\\n\\ndef bell_candidate() -> QuantumCircuit:\\n circuit = QuantumCircuit(2, 2)\\n circuit.h(0)\\n circuit.cx(0, 1)\\n circuit.measure([0, 1], [0, 1])\\n return circuit\\n\\ncircuit = bell_candidate()\\n'\n",
"editable_circuit_lab(\n",
" initial_code=editable_code,\n",
" context={\"QuantumCircuit\": QuantumCircuit, \"simulate_counts\": simulate_noisy_counts},\n",
" title='Lab 3: Filtering And Mitigation',\n",
" instructions='Keep the circuit fixed and think about what a correlated-outcome filter would reveal, rather than promising that it fixes everything.',\n",
" shots=256,\n",
")\n"
],
"id": "851327fe"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"quiz_block([{'prompt': 'Why use a simple correlated-outcome filter or postselection step?', 'options': ['To inspect whether the main failure is leakage outside the intended support or a deeper design mismatch', 'To guarantee perfect reconstruction', 'To remove the need to state invariants'], 'correct_index': 0, 'explanation': 'Filtering is most useful when tied to a clear diagnostic question.'}, {'prompt': 'What would make a mitigation claim weak?', 'options': ['It never says what invariant improved or what error mode it targeted', 'It compares ideal and noisy counts side by side', 'It preserves the reporting contract during diagnosis'], 'correct_index': 0, 'explanation': 'Mitigation needs targeted evidence, not generic optimism.'}], heading='Lab Checkpoint B')\n"
],
"id": "e6218d99"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab Debrief\n",
"\n",
"\n",
" The lab should leave you less tolerant of vague debugging. You now have a cleaner language for saying whether a problem is already visible ideally, whether noise is merely degrading a correct mechanism, and whether a simple mitigation step is clarifying a specific failure mode or merely masking confusion.\n"
],
"id": "0842c507"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Why The Lab Is Slower Than A Demo\n",
"\n",
"These labs are built to slow down the moment where many learners usually rush. In professional work, the difference between a good decision and a weak one often depends on whether you changed one variable at a time, whether you kept the objective fixed, and whether you wrote down what result you expected before running the next cell. That is why the labs here are not just demonstrations. They are rehearsals for disciplined engineering comparison.\n"
],
"id": "2d6f5c42"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Prediction Ledger\n",
"\n",
"If the comparison starts to blur, return to a prediction ledger. Write down what should stay invariant, what metric or observation should move, and what conclusion would follow if it does. That simple habit will make your later capstone work far stronger because it converts trial-and-error into interpretable evidence.\n"
],
"id": "62d79224"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"reflection_box('Write a short mitigation note that improves one statistic without overstating what was fixed.')\n"
],
"id": "b23bdbb0"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"reflection_box('Write one prediction habit from this lab that you want to preserve in later professional work.')\n"
],
"id": "4e38c207"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"feedback_iteration_panel(title='Noise-Aware Verification and Mitigation Lab Feedback Loop', prompt='Turn the lab into a review note: state the current claim, cite the strongest evidence, name the main remaining risk, and write the next comparison you would run.')\n"
],
"id": "b6a3804e"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"assessment_blueprint = load_assessment_blueprint()\n",
"rubric_scorecard(\n",
" assessment_blueprint.get_rubric('module_self_review'),\n",
" title='Noise-Aware Verification and Mitigation Lab Self-Grading',\n",
")\n"
],
"id": "ffacf6bc"
}
],
"metadata": {
"kernelspec": {
"display_name": "QuantumLearning (.venv)",
"language": "python",
"name": "quantum-learning"
},
"language_info": {
"name": "python",
"version": "3.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}