mirror of
https://github.com/saymrwulf/QuantumLearning.git
synced 2026-07-25 19:48:28 +00:00
286 lines
18 KiB
Text
286 lines
18 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Bernstein-Vazirani and Structured Oracles Lecture\n"
|
|
],
|
|
"id": "02da69a2"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Bernstein-Vazirani is the next step because it takes the oracle language from the Deutsch family and gives it a richer internal structure. Instead of distinguishing a promise class like constant versus balanced, you now recover a hidden linear pattern. That shift matters pedagogically. The oracle is no longer just an example of query logic; it becomes a reusable way to encode structure. If you learn the module well, you stop seeing the circuit as a memorized diagram and start seeing it as a design pattern for extracting hidden linear information.\n"
|
|
],
|
|
"id": "aedb8d5c"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Learning Objective\n",
|
|
"\n",
|
|
"\n",
|
|
" By the end of this lecture you should be able to explain how the hidden string appears as actual connectivity inside the oracle, why the final Hadamards recover that structure, and why bit-order discipline is not a cosmetic issue but part of the external contract of the notebook. You should also be able to compare two candidate oracle builders and say which one is more reviewable.\n"
|
|
],
|
|
"id": "bd62637f"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The most important conceptual move in Bernstein-Vazirani is to stop treating the secret string as a mysterious label attached after the fact. In the circuit, the string is implemented. Each secret bit decides whether a query wire participates in the parity-like interaction with the ancilla. That means the secret is embodied in the oracle's shape. This is a professional-design lesson as much as an algorithm lesson. Good code should make that embodiment visible enough that another engineer can audit it without reverse engineering an opaque indexing trick.\n"
|
|
],
|
|
"id": "f9df162c"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The ancilla preparation and the final Hadamard layer still play the same broad roles they played in the Deutsch family, but the middle is now more structured. The circuit is asking a wider question in one shot. The phase-sensitive ancilla lets the oracle write a linear pattern across many query branches, and the closing Hadamards decode that pattern back into the computational basis. Once you see that arc, the algorithm stops being a curiosity and becomes a design motif: encode structured information into phase, then decode it coherently.\n"
|
|
],
|
|
"id": "53829277"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Bit order becomes central here because the target result is itself a string. It is possible to build a correct oracle and still present the result badly if the mapping between qubit indices, circuit drawing order, and classical readout order is muddy. That is why this lecture treats reporting as part of the algorithm. If the notebook says the secret is 101 but the measurement contract is really returning that pattern in the opposite direction, the notebook is not professionally finished. It may still be mathematically salvageable, but the engineering surface is weak.\n"
|
|
],
|
|
"id": "3a5208c7"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Another valuable feature of Bernstein-Vazirani is that it rewards family-level experimentation. Once you have a parameterized oracle helper, you can vary the secret string and watch what remains invariant. The preparation layer remains the same. The decoding layer remains the same. Only the internal routing pattern changes. This is precisely the kind of transfer you want in a serious lecture series. The learner should stop asking 'what is the BV circuit?' and start asking 'which parts of the BV family are stable, and which parts encode the task instance?'\n"
|
|
],
|
|
"id": "3ef1bbd6"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"That family perspective is also what keeps the module from becoming too toy-like. In real engineering work you rarely get to memorize one answer. You need a builder that scales across a class of inputs and still stays intelligible under review. Bernstein-Vazirani is a manageable place to practice that standard. The notebook can stay small while the design question becomes more serious: can you write a family builder that remains transparent about which structure is being encoded?\n"
|
|
],
|
|
"id": "28e1a7d1"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The module therefore sits at an important midpoint. It is still clean enough to live mostly in ideal mode, but it already behaves like real circuit engineering. There is a parameterized helper, a reporting contract, an auditable oracle body, and a clear difference between 'the circuit executed' and 'the circuit expressed the intended structured claim clearly.' That difference is exactly what the bundle is trying to teach.\n"
|
|
],
|
|
"id": "d27b718d"
|
|
},
|
|
{
|
|
"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": "d4700ff6"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from math import pi\n",
|
|
"\n",
|
|
"from quantum_learning import (\n",
|
|
" counts_to_probabilities,\n",
|
|
" draw_circuit,\n",
|
|
" editable_circuit_lab,\n",
|
|
" plot_counts,\n",
|
|
" plot_probabilities,\n",
|
|
" quiz_block,\n",
|
|
" reflection_box,\n",
|
|
" simulate_counts,\n",
|
|
" statevector_probabilities,\n",
|
|
" step_reference_table,\n",
|
|
")\n",
|
|
"from qiskit import QuantumCircuit\n",
|
|
"from qiskit.quantum_info import Statevector\n"
|
|
],
|
|
"id": "4c0cfb48"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Code-To-Diagram Anchor\n",
|
|
"\n",
|
|
"\n",
|
|
" The anchor implementation below makes the secret string visible as routing structure. Read the code-to-diagram reference table first. Then edit the secret and the measurement order carefully enough that you can still defend what the printed bitstring means.\n"
|
|
],
|
|
"id": "7859cad0"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"step_reference_table([{'marker': '[1]', 'code_focus': 'Prepare every query wire in superposition and the ancilla in |->.', 'diagram_effect': 'The diagram begins with a wide preparation fan-out instead of a single branch.', 'why_it_matters': 'Bernstein-Vazirani asks one structured question about several bits at once.'}, {'marker': '[2]', 'code_focus': 'Route only the secret-controlled query wires into the ancilla.', 'diagram_effect': 'The oracle body visually highlights which secret bits are active.', 'why_it_matters': 'The hidden string is not mystical. It is literally the connectivity pattern inside the oracle.'}, {'marker': '[3]', 'code_focus': 'Apply final Hadamards to decode the hidden pattern back onto the query register.', 'diagram_effect': 'The second Hadamard layer closes the algorithmic sandwich.', 'why_it_matters': 'This is the moment where phase-encoded structure becomes classical evidence.'}, {'marker': '[4]', 'code_focus': 'Measure the query register in a bit order you can defend.', 'diagram_effect': 'The readout layer makes the interface contract explicit.', 'why_it_matters': 'Bit-order confusion is one of the easiest ways to sabotage an otherwise correct circuit.'}])\n"
|
|
],
|
|
"id": "bcf3bc7d"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"editable_code = '\\nfrom qiskit import QuantumCircuit\\n\\ndef bv_oracle(secret: str = \"101\") -> QuantumCircuit:\\n oracle = QuantumCircuit(4, name=f\"bv_{secret}\")\\n ancilla = 3\\n for index, bit in enumerate(reversed(secret)):\\n if bit == \"1\":\\n oracle.cx(index, ancilla)\\n return oracle\\n\\ncircuit = QuantumCircuit(4, 3)\\n# [1] Prepare the query register and phase-sensitive ancilla.\\ncircuit.h([0, 1, 2])\\ncircuit.x(3)\\ncircuit.h(3)\\n# [2] Query the structured oracle.\\ncircuit.compose(bv_oracle(\"101\"), inplace=True)\\n# [3] Decode the hidden pattern.\\ncircuit.h([0, 1, 2])\\n# [4] Measure only the recovered string.\\ncircuit.measure([0, 1, 2], [0, 1, 2])\\n'\n",
|
|
"editable_circuit_lab(\n",
|
|
" initial_code=editable_code,\n",
|
|
" context={\"QuantumCircuit\": QuantumCircuit, \"simulate_counts\": simulate_counts},\n",
|
|
" title='Bernstein-Vazirani and Structured Oracles Anchor',\n",
|
|
" instructions='Edit one causal region at a time. Use the reference table to keep code changes tied to circuit meaning.',\n",
|
|
" shots=256,\n",
|
|
")\n"
|
|
],
|
|
"id": "031f2ec3"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def bv_counts(secret: str) -> dict[str, int]:\n",
|
|
" circuit = QuantumCircuit(4, 3)\n",
|
|
" circuit.h([0, 1, 2])\n",
|
|
" circuit.x(3)\n",
|
|
" circuit.h(3)\n",
|
|
" for index, bit in enumerate(reversed(secret)):\n",
|
|
" if bit == \"1\":\n",
|
|
" circuit.cx(index, 3)\n",
|
|
" circuit.h([0, 1, 2])\n",
|
|
" circuit.measure([0, 1, 2], [0, 1, 2])\n",
|
|
" return simulate_counts(circuit, shots=256)\n",
|
|
"\n",
|
|
"{secret: bv_counts(secret) for secret in [\"000\", \"101\", \"110\", \"111\"]}\n"
|
|
],
|
|
"id": "bb101c96"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"quiz_block([{'prompt': 'What is the hidden string in Bernstein-Vazirani, from a circuit-design point of view?', 'options': ['A pattern of oracle-controlled interactions from query wires into the ancilla', 'A random measurement artifact', 'A post-processing choice made after simulation'], 'correct_index': 0, 'explanation': 'The secret is implemented structurally inside the oracle.'}, {'prompt': 'Why is the final Hadamard layer still necessary in BV?', 'options': ['It decodes phase-encoded structure back onto the query register', 'It reduces the number of classical bits needed', 'It prepares the ancilla for measurement'], 'correct_index': 0, 'explanation': 'The last Hadamards convert the hidden linear pattern into a classical report.'}, {'prompt': 'Why is bit-order discipline a central engineering lesson in this module?', 'options': ['Because a correct oracle can still be misreported by a sloppy measurement mapping', 'Because Qiskit requires alphabetical register names', 'Because secret strings must always be palindromes'], 'correct_index': 0, 'explanation': 'The circuit and the reporting interface have to agree on which bit is which.'}], heading='Lecture Checkpoint A')\n"
|
|
],
|
|
"id": "ac99407a"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"A useful discipline in this module is to narrate the circuit from left to right in terms of burden. The preparation layer defines the question format. The oracle body encodes the secret structure. The final Hadamards decode that structure. The measurement layer reports the secret using a chosen ordering convention. If you can say that cleanly, the module is no longer just a set of gates. It is a compact engineering artifact.\n"
|
|
],
|
|
"id": "991fd6a4"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Another discipline is to treat any bit-order confusion as a serious bug even if the fix is small. This may sound strict, but the strictness is what turns a notebook into professional training. Many subtle failures in real quantum workflows are really interface failures. They arise because someone knew the mathematics but could not preserve the mapping between representation layers. This is the safest module in which to learn that lesson.\n"
|
|
],
|
|
"id": "bfb08593"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Reading Discipline For This Module\n",
|
|
"\n",
|
|
"A serious lecture notebook has to teach more than recognition. It has to teach what to look at, what to ask, and what kind of evidence would count as a meaningful check. That is why this module keeps repeating a small number of disciplined questions. Which region prepares the state or question format? Which region encodes the task-specific structure? Which region translates that hidden structure into evidence you can actually read? And which parts of the notebook are presentation choices rather than mechanism? Those questions may sound repetitive, but repetition is useful here because algorithmic circuits become opaque very quickly when the learner loses the habit of dividing them into roles.\n",
|
|
"\n",
|
|
"Another reason for this slower lecture style is that professional design does not tolerate admiration as a substitute for analysis. It is perfectly possible to feel impressed by an algorithm, reproduce the overall diagram, and still be unable to explain what would break if one line changed. This course is trying to build the opposite habit. A mature notebook reader should be able to look at a circuit region and say what burden it carries, what evidence would test it, and what kind of mistake would falsify the current explanation. If that standard feels demanding, that is appropriate. The goal is to create designers, not spectators.\n"
|
|
],
|
|
"id": "7a5f3223"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Forward Link\n",
|
|
"\n",
|
|
"One reason these notebooks are written so densely is that later professional-design modules will assume this vocabulary is stable. When you later compare transpiled candidates, argue about noise sensitivity, or defend a capstone recommendation, you will not have time to rediscover what an oracle contract, reporting convention, controlled phase, or iteration choice means. The language has to be ready. That is why this lecture insists on precision now. The details are not there to slow you down forever. They are there so later speed is built on something trustworthy.\n"
|
|
],
|
|
"id": "9bf07c99"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"quiz_block([{'prompt': 'What generalizable design idea does BV teach beyond the specific hidden-string problem?', 'options': ['How to encode a structured linear rule in an oracle and recover it in one coherent pass', 'How to avoid ancillas in all algorithms', 'How to replace measurement with transpilation'], 'correct_index': 0, 'explanation': 'BV is useful because it exposes a reusable structure, not just a party trick.'}, {'prompt': \"Why is a barrier sometimes acceptable in this module's lab work?\", 'options': ['It can make the logical regions visible without changing the algorithmic claim', 'It improves the mathematics of the oracle', 'It changes the secret string automatically'], 'correct_index': 0, 'explanation': 'Barriers are presentation tools here, not algorithmic ingredients.'}, {'prompt': 'What is the strongest argument for testing multiple secrets in the same notebook?', 'options': ['It checks whether your builder really expresses a family rather than one lucky example', 'It forces the simulator to randomize less', 'It removes the need for comments'], 'correct_index': 0, 'explanation': 'Family-level reasoning is the real target of the module.'}], heading='Lecture Checkpoint B')\n"
|
|
],
|
|
"id": "82f2b847"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"reflection_box('Explain why the hidden string in BV should be thought of as structure in the oracle rather than as a label added after execution.')\n"
|
|
],
|
|
"id": "06b63a63"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"reflection_box('Describe one way to make a BV builder more reviewable without changing its behavior.')\n"
|
|
],
|
|
"id": "9c22af39"
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Mastery Gate\n",
|
|
"\n",
|
|
"Leave this lecture only when you can explain the mechanism line by line, not just recognize the diagram.\n"
|
|
],
|
|
"id": "f3b127e3"
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "QuantumLearning (.venv)",
|
|
"language": "python",
|
|
"name": "quantum-learning"
|
|
},
|
|
"language_info": {
|
|
"name": "python",
|
|
"version": "3.12"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|