QuantumLearning/notebooks/professional/module_02_hardware_aware_redesign/lab.ipynb

357 lines
16 KiB
Text

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Hardware-Aware Redesign Studio Lab\n"
],
"id": "81e0eae1"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<!-- COURSE_NAV_TOP -->\n",
"## Mainline Navigation\n",
"\n",
"Step 48 of 59. Follow the mainline in order and do not skip ahead.\n",
"\n",
"Previous notebook: [Hardware-Aware Redesign Studio Lecture](lecture.ipynb)\n",
"\n",
"Next notebook: [Hardware-Aware Redesign Studio Problems](problems.ipynb)\n",
"\n",
"Rule: finish this notebook top-to-bottom before you open the next one.\n"
],
"id": "a25c336b"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The lab turns topology pressure into something concrete. You will stress an abstract circuit, inspect the cost, and then edit alternative layouts that try to preserve the same objective more intelligently.\n"
],
"id": "86acaa35"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab Protocol\n",
"\n",
"\n",
" Keep the constraints fixed while you compare candidates. Use the same basis-gate set, the same coupling map, and the same reporting contract. Only then do the structural differences mean what you think they mean.\n"
],
"id": "d43795d9"
},
{
"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": "50c7b992"
},
{
"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": "933f1ed0"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab 1: Topology Stress Test\n",
"\n",
"\n",
" Start with the naive abstract circuit and let the line-topology preview expose its pressure. The purpose is not to shame the ideal circuit. The purpose is to learn how the mismatch shows up.\n"
],
"id": "db5bc5b6"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"step_reference_table([{'marker': '[1]', 'code_focus': 'Write the abstract target circuit clearly before worrying about rescue by the transpiler.', 'diagram_effect': 'The first diagram states the ideal intent with no attempt to hide topology pressure.', 'why_it_matters': 'Human redesign starts by knowing what the unpressured circuit was trying to express.'}, {'marker': '[2]', 'code_focus': 'Expose basis-gate and coupling-map assumptions explicitly.', 'diagram_effect': 'The device pressure becomes a visible part of the experiment rather than a hidden environment fact.', 'why_it_matters': 'You cannot reason about hardware cost if the constraints remain implicit.'}, {'marker': '[3]', 'code_focus': 'Inspect the compiled rewrite and decide which costs were caused by your abstract layout.', 'diagram_effect': 'The compiled version shows extra structure, depth, or routing burden.', 'why_it_matters': 'Professional redesign begins where default compilation becomes expensive.'}, {'marker': '[4]', 'code_focus': 'Create and compare a human-aware alternative instead of treating the compiler as the final word.', 'diagram_effect': 'A second circuit appears whose structure anticipates the topology rather than suffering under it.', 'why_it_matters': 'Hardware awareness is redesign, not passive observation of transpiler output.'}])\n"
],
"id": "6f2f2734"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"LOCAL_BASIS = [\"rz\", \"sx\", \"x\", \"cx\"]\n",
"\n",
"def simulate_line_counts(circuit, shots=256):\n",
" return simulate_counts(\n",
" circuit,\n",
" shots=shots,\n",
" basis_gates=LOCAL_BASIS,\n",
" coupling_map=line_coupling_map(circuit.num_qubits),\n",
" optimization_level=1,\n",
" )\n",
"\n",
"editable_code = '\\nfrom qiskit import QuantumCircuit\\n\\ndef naive_star_ghz() -> QuantumCircuit:\\n circuit = QuantumCircuit(4, 4)\\n # [1] Express the ideal entangling target directly.\\n circuit.h(0)\\n circuit.cx(0, 1)\\n circuit.cx(0, 2)\\n circuit.cx(0, 3)\\n # [2] Keep the evidence path stable while topology pressure is studied elsewhere.\\n circuit.measure([0, 1, 2, 3], [0, 1, 2, 3])\\n return circuit\\n\\ncircuit = naive_star_ghz()\\n'\n",
"editable_circuit_lab(\n",
" initial_code=editable_code,\n",
" context={\"QuantumCircuit\": QuantumCircuit, \"simulate_counts\": simulate_line_counts},\n",
" title='Lab 1: Topology Stress',\n",
" instructions='Edit the abstract entangling pattern and watch how the line-constrained preview reacts. Explain which interaction is creating the pressure.',\n",
" shots=256,\n",
")\n"
],
"id": "16d88880"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"quiz_block([{'prompt': 'What should you inspect first when a compiled circuit gets much deeper?', 'options': ['Which abstract interactions violated the declared topology', 'The notebook font', 'Whether the simulator seed changed'], 'correct_index': 0, 'explanation': 'Depth inflation is usually tracing back to topology or basis pressure.'}, {'prompt': 'Why compare a naive star GHZ to a middle-root or chain version?', 'options': ['To see whether human-aware structure can reduce routing cost before compilation', 'Because only one can be entangling', 'Because the transpiler refuses to compile chain circuits'], 'correct_index': 0, 'explanation': 'The comparison reveals which costs were self-inflicted by the abstract layout.'}], heading='Lab Checkpoint A')\n"
],
"id": "811b78ee"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"reflection_box('Which candidate in the lab most clearly demonstrated self-inflicted compile cost, and why?')\n"
],
"id": "c583cb58"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab 2: Manual Redesign\n",
"\n",
"\n",
" Now try a line-friendlier candidate whose abstract structure already anticipates the coupling map. The lesson is not that one circuit shape always wins. The lesson is that you should be able to propose a plausible alternative and explain why it fits the hardware story better.\n"
],
"id": "83f08c3d"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"LOCAL_BASIS = [\"rz\", \"sx\", \"x\", \"cx\"]\n",
"\n",
"def simulate_line_counts(circuit, shots=256):\n",
" return simulate_counts(\n",
" circuit,\n",
" shots=shots,\n",
" basis_gates=LOCAL_BASIS,\n",
" coupling_map=line_coupling_map(circuit.num_qubits),\n",
" optimization_level=1,\n",
" )\n",
"\n",
"editable_code = '\\nfrom qiskit import QuantumCircuit\\n\\ndef line_friendly_ghz() -> QuantumCircuit:\\n circuit = QuantumCircuit(4, 4)\\n circuit.h(1)\\n circuit.cx(1, 0)\\n circuit.cx(1, 2)\\n circuit.cx(2, 3)\\n circuit.measure([0, 1, 2, 3], [0, 1, 2, 3])\\n return circuit\\n\\ncircuit = line_friendly_ghz()\\n'\n",
"editable_circuit_lab(\n",
" initial_code=editable_code,\n",
" context={\"QuantumCircuit\": QuantumCircuit, \"simulate_counts\": simulate_line_counts},\n",
" title='Lab 2: Manual Redesign',\n",
" instructions='Refine the line-aware candidate while keeping the objective and readout stable. Explain why the new layout should ask less of the compiler.',\n",
" shots=256,\n",
")\n"
],
"id": "19fb4524"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab 3: Candidate Comparison\n",
"\n",
"\n",
" Compare several candidate families under the same local constraints. This is the closest the module gets to real redesign practice: more than one plausible answer, one fixed constraint model, and a need for explicit judgement.\n"
],
"id": "dfb3169b"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"LOCAL_BASIS = [\"rz\", \"sx\", \"x\", \"cx\"]\n",
"\n",
"def simulate_line_counts(circuit, shots=256):\n",
" return simulate_counts(\n",
" circuit,\n",
" shots=shots,\n",
" basis_gates=LOCAL_BASIS,\n",
" coupling_map=line_coupling_map(circuit.num_qubits),\n",
" optimization_level=1,\n",
" )\n",
"\n",
"editable_code = '\\nfrom qiskit import QuantumCircuit\\n\\ndef candidate(style: str = \"middle_root\") -> QuantumCircuit:\\n circuit = QuantumCircuit(4, 4)\\n if style == \"naive\":\\n circuit.h(0)\\n circuit.cx(0, 1)\\n circuit.cx(0, 2)\\n circuit.cx(0, 3)\\n elif style == \"chain\":\\n circuit.h(0)\\n circuit.cx(0, 1)\\n circuit.cx(1, 2)\\n circuit.cx(2, 3)\\n elif style == \"middle_root\":\\n circuit.h(1)\\n circuit.cx(1, 0)\\n circuit.cx(1, 2)\\n circuit.cx(2, 3)\\n else:\\n raise ValueError(\"style must be naive, chain, or middle_root\")\\n circuit.measure([0, 1, 2, 3], [0, 1, 2, 3])\\n return circuit\\n\\ncircuit = candidate(style=\"middle_root\")\\n'\n",
"editable_circuit_lab(\n",
" initial_code=editable_code,\n",
" context={\"QuantumCircuit\": QuantumCircuit, \"simulate_counts\": simulate_line_counts},\n",
" title='Lab 3: Candidate Comparison',\n",
" instructions='Switch among naive, chain, and middle_root candidates. Say which topology pressure you expect each one to create before trusting the counts or metrics.',\n",
" shots=256,\n",
")\n"
],
"id": "854bd838"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"quiz_block([{'prompt': 'What is a strong redesign note?', 'options': ['I moved the root to the middle because the line topology can host those interactions more directly', 'I changed the circuit because it looked simpler', 'I let the compiler decide and stopped reading'], 'correct_index': 0, 'explanation': 'Good redesign language ties structure to topology-aware intent.'}, {'prompt': 'Why is it useful to keep basis gates fixed during candidate comparison?', 'options': ['So differences in cost are more attributable to circuit design than to a moving target backend model', 'Because basis gates never matter', 'Because fixed basis gates guarantee identical counts'], 'correct_index': 0, 'explanation': 'Stable constraints make comparison more interpretable.'}], heading='Lab Checkpoint B')\n"
],
"id": "86eac93e"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lab Debrief\n",
"\n",
"\n",
" The key change after this lab should be that topology no longer feels like an external annoyance. It should feel like part of the circuit-design problem itself. Once that shift happens, the difference between observing transpilation and redesigning for it becomes much clearer.\n"
],
"id": "fa2f99d0"
},
{
"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": "c5e6fa79"
},
{
"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": "a68e347a"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"reflection_box('Write a short redesign note defending one manual alternative under the fixed line-topology assumptions.')\n"
],
"id": "0afa5593"
},
{
"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": "cb17c0f5"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"feedback_iteration_panel(title='Hardware-Aware Redesign Studio 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": "b0763e65"
},
{
"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='Hardware-Aware Redesign Studio Lab Self-Grading',\n",
")\n"
],
"id": "f47c6bd1"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<!-- COURSE_NAV_BOTTOM -->\n",
"## What To Open Next\n",
"\n",
"Next notebook: [Hardware-Aware Redesign Studio Problems](problems.ipynb)\n",
"\n",
"When you finish this notebook, open the next notebook shown above. Stay on the guarded mainline route.\n"
],
"id": "d818996c"
}
],
"metadata": {
"kernelspec": {
"display_name": "QuantumLearning (.venv)",
"language": "python",
"name": "quantum-learning"
},
"language_info": {
"name": "python",
"version": "3.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}