mirror of
https://github.com/saymrwulf/autoresearch-quantum.git
synced 2026-09-06 19:10:32 +00:00
878 lines
34 KiB
Text
878 lines
34 KiB
Text
|
|
{
|
|||
|
|
"cells": [
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"# Notebook 2: How Do You Know If It Worked?\n",
|
|||
|
|
"\n",
|
|||
|
|
"**Plan A — Measuring Progress**\n",
|
|||
|
|
"\n",
|
|||
|
|
"In Notebook 1 you built an encoded magic state and verified it in an ideal simulator. But real quantum hardware is noisy. This notebook answers: *How do we quantify how good our preparation is, and how do we turn those measurements into a single score the ratchet can optimize?*\n",
|
|||
|
|
"\n",
|
|||
|
|
"**What you will learn:**\n",
|
|||
|
|
"1. What noise does to your encoded state\n",
|
|||
|
|
"2. How to measure logical operators and compute the magic witness\n",
|
|||
|
|
"3. The scoring formula: quality, acceptance, and cost\n",
|
|||
|
|
"4. How to identify dominant failure modes\n",
|
|||
|
|
"5. How parameter choices affect the score"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"%matplotlib inline\n",
|
|||
|
|
"import sys, warnings\n",
|
|||
|
|
"warnings.filterwarnings('ignore')\n",
|
|||
|
|
"\n",
|
|||
|
|
"import numpy as np\n",
|
|||
|
|
"import matplotlib.pyplot as plt\n",
|
|||
|
|
"from math import pi, sqrt\n",
|
|||
|
|
"\n",
|
|||
|
|
"from qiskit import QuantumCircuit\n",
|
|||
|
|
"from qiskit.quantum_info import Statevector, DensityMatrix, state_fidelity\n",
|
|||
|
|
"from qiskit.visualization import plot_histogram\n",
|
|||
|
|
"from qiskit_aer import AerSimulator\n",
|
|||
|
|
"from qiskit_aer.noise import NoiseModel\n",
|
|||
|
|
"\n",
|
|||
|
|
"from autoresearch_quantum.codes.four_two_two import (\n",
|
|||
|
|
" build_preparation_circuit, encoded_magic_statevector,\n",
|
|||
|
|
" STABILIZERS, MEASUREMENT_OPERATORS, DATA_QUBITS,\n",
|
|||
|
|
")\n",
|
|||
|
|
"from autoresearch_quantum.experiments.encoded_magic_state import build_circuit_bundle\n",
|
|||
|
|
"from autoresearch_quantum.models import (\n",
|
|||
|
|
" ExperimentSpec, RungConfig, EvaluationMetrics,\n",
|
|||
|
|
" QualityWeights, CostWeights, ScoreConfig, SearchSpaceConfig,\n",
|
|||
|
|
" TierPolicyConfig, HardwareConfig,\n",
|
|||
|
|
")\n",
|
|||
|
|
"from autoresearch_quantum.execution.local import LocalCheapExecutor\n",
|
|||
|
|
"from autoresearch_quantum.execution.analysis import (\n",
|
|||
|
|
" logical_magic_witness, stability_score, summarize_context,\n",
|
|||
|
|
" local_memory_records,\n",
|
|||
|
|
")\n",
|
|||
|
|
"from autoresearch_quantum.execution.backends import resolve_backend\n",
|
|||
|
|
"from autoresearch_quantum.execution.transpile import (\n",
|
|||
|
|
" transpile_circuits, count_two_qubit_gates, circuit_metadata, runtime_estimate,\n",
|
|||
|
|
")\n",
|
|||
|
|
"from autoresearch_quantum.scoring.score import (\n",
|
|||
|
|
" score_metrics, weighted_acceptance_cost, factory_throughput_score,\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"print(\"All imports successful.\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"from autoresearch_quantum.teaching import LearningTracker\n",
|
|||
|
|
"from autoresearch_quantum.teaching.assess import quiz, predict_choice, reflect, order, checkpoint_summary\n",
|
|||
|
|
"tracker = LearningTracker(\"plan_a_02\")\n",
|
|||
|
|
"print(\"Learning tracker active.\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"## 1. Recap: The Ideal Encoded Magic State\n",
|
|||
|
|
"\n",
|
|||
|
|
"Let us quickly rebuild the preparation circuit and its ideal statevector from Notebook 1."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"prep = build_preparation_circuit(\"h_p\", \"cx_chain\")\n",
|
|||
|
|
"ideal_state = Statevector.from_instruction(prep)\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Verify stabilizers\n",
|
|||
|
|
"for name, stab in STABILIZERS.items():\n",
|
|||
|
|
" exp_val = ideal_state.expectation_value(stab)\n",
|
|||
|
|
" print(f\"{name}: <{name}> = {exp_val.real:+.6f}\")\n",
|
|||
|
|
"\n",
|
|||
|
|
"print(f\"\\nIdeal self-fidelity: {state_fidelity(ideal_state, ideal_state):.6f}\")\n",
|
|||
|
|
"prep.draw('mpl', style='iqp')"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### Recap check\n",
|
|||
|
|
"\n",
|
|||
|
|
"Before we add noise, make sure the Notebook 1 concepts are solid."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"quiz(tracker, \"q1_stabilizer_eigenvalue\",\n",
|
|||
|
|
" question=\"What do the stabilizer eigenvalues tell us about a quantum state?\",\n",
|
|||
|
|
" options=[\n",
|
|||
|
|
" \"They measure the energy of the system\",\n",
|
|||
|
|
" \"Eigenvalue +1 means the state is in the codespace (no error detected)\",\n",
|
|||
|
|
" \"They tell us which logical qubit is |0\\u27E9 vs |1\\u27E9\",\n",
|
|||
|
|
" \"They count the number of entangled qubits\",\n",
|
|||
|
|
" ],\n",
|
|||
|
|
" correct=1,\n",
|
|||
|
|
" section=\"1. Recap\",\n",
|
|||
|
|
" bloom=\"remember\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"Stabilizer eigenvalue +1 means the state satisfies the code constraints. \"\n",
|
|||
|
|
" \"If any single-qubit error occurs, at least one stabilizer flips to \\u22121.\"\n",
|
|||
|
|
" ))"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"## 2. Adding Noise: The fake_brisbane Backend\n",
|
|||
|
|
"\n",
|
|||
|
|
"Real hardware introduces gate errors, readout errors, and decoherence. Qiskit provides **fake backends** that model the noise of real IBM devices without requiring API access."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"# Load the fake_brisbane backend and extract its noise model\n",
|
|||
|
|
"backend = resolve_backend(\"fake_brisbane\")\n",
|
|||
|
|
"noise_model = NoiseModel.from_backend(backend)\n",
|
|||
|
|
"\n",
|
|||
|
|
"print(f\"Backend: {backend.name}\")\n",
|
|||
|
|
"print(f\"Qubits: {backend.num_qubits}\")\n",
|
|||
|
|
"print(f\"Basis gates: {noise_model.basis_gates}\")\n",
|
|||
|
|
"print(f\"Noise instructions: {len(noise_model.to_dict()['errors'])} error channels\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### What does noise do?\n",
|
|||
|
|
"\n",
|
|||
|
|
"The fake_brisbane backend simulates realistic noise from IBM's 127-qubit Eagle processor. Gate errors, readout errors, and crosstalk all contribute."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"predict_choice(tracker, \"q2_noise_effect\",\n",
|
|||
|
|
" question=\"When we run the same circuit with noise, what happens to the syndrome distribution?\",\n",
|
|||
|
|
" options=[\n",
|
|||
|
|
" \"Syndrome is still always '00' \\u2014 noise is too small to matter\",\n",
|
|||
|
|
" \"Some shots will have non-zero syndrome \\u2014 noise causes detectable errors\",\n",
|
|||
|
|
" \"All shots will have non-zero syndrome \\u2014 noise is overwhelming\",\n",
|
|||
|
|
" ],\n",
|
|||
|
|
" correct=1,\n",
|
|||
|
|
" section=\"2. Adding noise\",\n",
|
|||
|
|
" bloom=\"understand\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"Realistic noise causes some fraction of shots to leave the codespace, \"\n",
|
|||
|
|
" \"producing non-zero syndromes. Typical acceptance rates are 40\\u201380% for current hardware.\"\n",
|
|||
|
|
" ))"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### Ideal vs Noisy Simulation\n",
|
|||
|
|
"\n",
|
|||
|
|
"Let us run the same preparation circuit twice: once ideal, once with the Brisbane noise model."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"spec = ExperimentSpec(\n",
|
|||
|
|
" rung=1, seed_style=\"h_p\", encoder_style=\"cx_chain\",\n",
|
|||
|
|
" verification=\"both\", postselection=\"all_measured\",\n",
|
|||
|
|
" target_backend=\"fake_brisbane\", noise_backend=\"fake_brisbane\",\n",
|
|||
|
|
" optimization_level=2, shots=512, repeats=1,\n",
|
|||
|
|
")\n",
|
|||
|
|
"bundle = build_circuit_bundle(spec)\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Transpile the acceptance circuit\n",
|
|||
|
|
"transpiled = transpile_circuits([bundle.acceptance], spec, backend)[0]\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Ideal simulation\n",
|
|||
|
|
"ideal_sim = AerSimulator()\n",
|
|||
|
|
"ideal_result = ideal_sim.run(transpiled, shots=512, memory=True, seed_simulator=42).result()\n",
|
|||
|
|
"ideal_counts = ideal_result.get_counts()\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Noisy simulation\n",
|
|||
|
|
"noisy_sim = AerSimulator(\n",
|
|||
|
|
" noise_model=noise_model,\n",
|
|||
|
|
" basis_gates=noise_model.basis_gates,\n",
|
|||
|
|
" coupling_map=backend.coupling_map,\n",
|
|||
|
|
")\n",
|
|||
|
|
"noisy_result = noisy_sim.run(transpiled, shots=512, memory=True, seed_simulator=42).result()\n",
|
|||
|
|
"noisy_counts = noisy_result.get_counts()\n",
|
|||
|
|
"\n",
|
|||
|
|
"fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 4))\n",
|
|||
|
|
"plot_histogram(ideal_counts, ax=ax1, title=\"Ideal Simulation\")\n",
|
|||
|
|
"plot_histogram(noisy_counts, ax=ax2, title=\"Noisy Simulation (fake_brisbane)\")\n",
|
|||
|
|
"plt.tight_layout()\n",
|
|||
|
|
"plt.show()"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"> **Observe:** The ideal histogram shows only a few bitstrings (those consistent with the codespace). The noisy histogram is spread across many more outcomes — noise is kicking the state out of the codespace.\n",
|
|||
|
|
"\n",
|
|||
|
|
"---\n",
|
|||
|
|
"## 3. Postselection: Filtering Bad Shots\n",
|
|||
|
|
"\n",
|
|||
|
|
"Each bitstring has two parts: **syndrome bits** (from stabilizer checks) and **data bits** (from qubit measurements). Postselection keeps only shots where the syndrome indicates \"no error detected.\""
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"# Parse raw shots into records\n",
|
|||
|
|
"memory = noisy_result.get_memory(transpiled)\n",
|
|||
|
|
"records = local_memory_records(memory, [creg.name for creg in transpiled.cregs])\n",
|
|||
|
|
"\n",
|
|||
|
|
"total = len(records)\n",
|
|||
|
|
"accepted = sum(\n",
|
|||
|
|
" 1 for r in records\n",
|
|||
|
|
" if all(b == '0' for b in r.get('syndrome', ''))\n",
|
|||
|
|
")\n",
|
|||
|
|
"rejected = total - accepted\n",
|
|||
|
|
"\n",
|
|||
|
|
"print(f\"Total shots: {total}\")\n",
|
|||
|
|
"print(f\"Accepted (syndrome=00): {accepted} ({accepted/total:.1%})\")\n",
|
|||
|
|
"print(f\"Rejected: {rejected} ({rejected/total:.1%})\")\n",
|
|||
|
|
"\n",
|
|||
|
|
"fig, ax = plt.subplots(figsize=(5, 4))\n",
|
|||
|
|
"ax.bar([\"Accepted\", \"Rejected\"], [accepted, rejected], color=[\"#2ecc71\", \"#e74c3c\"])\n",
|
|||
|
|
"ax.set_ylabel(\"Shots\")\n",
|
|||
|
|
"ax.set_title(\"Postselection Results\")\n",
|
|||
|
|
"plt.tight_layout()\n",
|
|||
|
|
"plt.show()"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"quiz(tracker, \"q3_acceptance_cost\",\n",
|
|||
|
|
" question=\"If the acceptance rate is 50%, what does that mean for the experiment?\",\n",
|
|||
|
|
" options=[\n",
|
|||
|
|
" \"Half the qubits failed\",\n",
|
|||
|
|
" \"Half the shots were discarded \\u2014 we need 2x shots for the same statistics\",\n",
|
|||
|
|
" \"The circuit has 50% fidelity\",\n",
|
|||
|
|
" \"The code corrected half the errors\",\n",
|
|||
|
|
" ],\n",
|
|||
|
|
" correct=1,\n",
|
|||
|
|
" section=\"3. Postselection\",\n",
|
|||
|
|
" bloom=\"understand\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"Acceptance rate = fraction of shots surviving postselection. \"\n",
|
|||
|
|
" \"At 50%, you need twice as many total shots. This is a direct cost.\"\n",
|
|||
|
|
" ))\n",
|
|||
|
|
"checkpoint_summary(tracker, \"3. Postselection\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"> **Key Insight:** The acceptance rate is the fraction of shots that survive postselection. Under noise it can drop significantly — this is the code *working* by detecting errors. But a low acceptance rate means you need more shots to get the same statistical precision, which increases cost.\n",
|
|||
|
|
"\n",
|
|||
|
|
"---\n",
|
|||
|
|
"## 4. Measuring Logical Operators\n",
|
|||
|
|
"\n",
|
|||
|
|
"To certify that we have an encoded *magic* state (not just any codespace state), we need to measure three logical operators:\n",
|
|||
|
|
"\n",
|
|||
|
|
"| Operator | Pauli String | Physical Meaning |\n",
|
|||
|
|
"|----------|-------------|------------------|\n",
|
|||
|
|
"| Logical X | X_2$ | X-component of logical qubit 0 |\n",
|
|||
|
|
"| Logical Y | Z_1 X_2$ | Y-component of logical qubit 0 |\n",
|
|||
|
|
"| Spectator Z | Z_2$ | Z-component of logical qubit 1 (should be +1 if undisturbed) |\n",
|
|||
|
|
"\n",
|
|||
|
|
"Each requires a separate circuit with basis rotations before measurement."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"# Run all witness circuits on the noisy simulator\n",
|
|||
|
|
"context_names = [\"acceptance\", \"logical_x\", \"logical_y\", \"spectator_z\"]\n",
|
|||
|
|
"raw_circuits = [bundle.acceptance] + [bundle.witness_circuits[k] for k in [\"logical_x\", \"logical_y\", \"spectator_z\"]]\n",
|
|||
|
|
"transpiled_circuits = transpile_circuits(raw_circuits, spec, backend)\n",
|
|||
|
|
"\n",
|
|||
|
|
"results = {}\n",
|
|||
|
|
"for name, circuit in zip(context_names, transpiled_circuits):\n",
|
|||
|
|
" result = noisy_sim.run(circuit, shots=512, memory=True, seed_simulator=42).result()\n",
|
|||
|
|
" mem = result.get_memory(circuit)\n",
|
|||
|
|
" recs = local_memory_records(mem, [creg.name for creg in circuit.cregs])\n",
|
|||
|
|
" summary = summarize_context(\n",
|
|||
|
|
" recs,\n",
|
|||
|
|
" syndrome_labels=list(circuit.metadata.get('syndrome_labels', [])),\n",
|
|||
|
|
" postselection=str(circuit.metadata.get('postselection', 'none')),\n",
|
|||
|
|
" operator=MEASUREMENT_OPERATORS.get(name),\n",
|
|||
|
|
" )\n",
|
|||
|
|
" results[name] = summary\n",
|
|||
|
|
" print(f\"{name:15s} acceptance_rate={summary['acceptance_rate']:.3f} expectation={summary['expectation']:+.4f}\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"quiz(tracker, \"q4_three_circuits\",\n",
|
|||
|
|
" question=\"Why does the experiment use 3 separate circuits instead of measuring all operators at once?\",\n",
|
|||
|
|
" options=[\n",
|
|||
|
|
" \"The operators don't commute, so measuring one disturbs the others\",\n",
|
|||
|
|
" \"It's a software limitation\",\n",
|
|||
|
|
" \"Each operator requires different ancilla qubits\",\n",
|
|||
|
|
" ],\n",
|
|||
|
|
" correct=0,\n",
|
|||
|
|
" section=\"4. Logical operators\",\n",
|
|||
|
|
" bloom=\"analyze\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"Logical X and Logical Y do not commute. Measuring one collapses the state \"\n",
|
|||
|
|
" \"into an eigenstate that invalidates the other measurement.\"\n",
|
|||
|
|
" ))"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"## 5. The Magic Witness Formula\n",
|
|||
|
|
"\n",
|
|||
|
|
"The **logical magic witness** combines the three operator expectations into a single number between 0 and 1:\n",
|
|||
|
|
"\n",
|
|||
|
|
"9951W = \frac{1 + \frac{\\langle X_L \rangle + \\langle Y_L \rangle}{\\sqrt{2}}}{2} \times \frac{1 + \\langle Z_{\text{spectator}} \rangle}{2}9951\n",
|
|||
|
|
"\n",
|
|||
|
|
"- The first factor checks the \"magic\" — a perfect T-state has $\\langle X_L \rangle = \\langle Y_L \rangle = 1/\\sqrt{2}$, giving 1.0.\n",
|
|||
|
|
"- The second factor checks spectator integrity — the second logical qubit should be in $|0_L\rangle$, giving $\\langle Z_{\text{spectator}} \rangle = +1$.\n",
|
|||
|
|
"- For a perfect encoded T-state: = 1.0$.\n",
|
|||
|
|
"- For a maximally mixed state: \u0007pprox 0.25$."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"lx = results[\"logical_x\"][\"expectation\"]\n",
|
|||
|
|
"ly = results[\"logical_y\"][\"expectation\"]\n",
|
|||
|
|
"sz = results[\"spectator_z\"][\"expectation\"]\n",
|
|||
|
|
"\n",
|
|||
|
|
"magic_factor = (1.0 + (lx + ly) / sqrt(2.0)) / 2.0\n",
|
|||
|
|
"spectator_factor = (1.0 + sz) / 2.0\n",
|
|||
|
|
"witness = magic_factor * spectator_factor\n",
|
|||
|
|
"\n",
|
|||
|
|
"print(f\"Logical X expectation: {lx:+.4f}\")\n",
|
|||
|
|
"print(f\"Logical Y expectation: {ly:+.4f}\")\n",
|
|||
|
|
"print(f\"Spectator Z expectation: {sz:+.4f}\")\n",
|
|||
|
|
"print(f\"\")\n",
|
|||
|
|
"print(f\"Magic factor: {magic_factor:.4f}\")\n",
|
|||
|
|
"print(f\"Spectator factor: {spectator_factor:.4f}\")\n",
|
|||
|
|
"print(f\"Witness W: {witness:.4f}\")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Verify against the library function\n",
|
|||
|
|
"lib_witness = logical_magic_witness(lx, ly, sz)\n",
|
|||
|
|
"print(f\"Library witness: {lib_witness:.4f} (should match)\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### The magic witness formula\n",
|
|||
|
|
"\n",
|
|||
|
|
"$$W = \\frac{1 + (\\langle X_L \\rangle + \\langle Y_L \\rangle)/\\sqrt{2}}{2} \\times \\frac{1 + \\langle Z_{\\text{spectator}} \\rangle}{2}$$\n",
|
|||
|
|
"\n",
|
|||
|
|
"For a perfect T-state: $\\langle X_L \\rangle = \\langle Y_L \\rangle = 1/\\sqrt{2}$ and $\\langle Z_{\\text{spec}} \\rangle = 1$, giving $W = 1.0$."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"quiz(tracker, \"q5_ideal_witness\",\n",
|
|||
|
|
" question=\"For a perfect (noiseless) T-state, what is the magic witness value?\",\n",
|
|||
|
|
" options=[\"0.0\", \"0.5\", \"1/\\u221A2 \\u2248 0.707\", \"1.0\"],\n",
|
|||
|
|
" correct=3,\n",
|
|||
|
|
" section=\"5. Witness formula\",\n",
|
|||
|
|
" bloom=\"apply\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"magic_factor = (1 + (1/\\u221A2 + 1/\\u221A2)/\\u221A2) / 2 = (1+1)/2 = 1. \"\n",
|
|||
|
|
" \"spectator_factor = (1+1)/2 = 1. Product = 1.0.\"\n",
|
|||
|
|
" ))\n",
|
|||
|
|
"checkpoint_summary(tracker, \"5. Witness formula\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"## 6. Noisy Fidelity via Density Matrix\n",
|
|||
|
|
"\n",
|
|||
|
|
"An alternative quality metric is the **state fidelity** — how close the noisy output is to the ideal encoded T-state."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"# Noisy fidelity via density matrix on the LOGICAL (untranspiled) 4-qubit circuit.\n",
|
|||
|
|
"# Note: density matrix simulation on the transpiled 127-qubit circuit would require\n",
|
|||
|
|
"# 2^127 x 2^127 matrix entries — impossible on any current machine!\n",
|
|||
|
|
"# Instead, we apply the noise model to the compact 4-qubit prep circuit.\n",
|
|||
|
|
"\n",
|
|||
|
|
"target = encoded_magic_statevector()\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Build a small noise model for just the gates we use\n",
|
|||
|
|
"from qiskit_aer.noise import NoiseModel, depolarizing_error\n",
|
|||
|
|
"simple_noise = NoiseModel()\n",
|
|||
|
|
"simple_noise.add_all_qubit_quantum_error(depolarizing_error(0.001, 1), ['h', 'p', 'rz', 'ry', 'sx', 'x', 'u'])\n",
|
|||
|
|
"simple_noise.add_all_qubit_quantum_error(depolarizing_error(0.01, 2), ['cx'])\n",
|
|||
|
|
"\n",
|
|||
|
|
"dm_circuit = build_preparation_circuit(\"h_p\", \"cx_chain\")\n",
|
|||
|
|
"dm_circuit.save_density_matrix()\n",
|
|||
|
|
"\n",
|
|||
|
|
"density_sim = AerSimulator(method=\"density_matrix\", noise_model=simple_noise)\n",
|
|||
|
|
"dm_result = density_sim.run(dm_circuit).result()\n",
|
|||
|
|
"noisy_dm = dm_result.data(0)[\"density_matrix\"]\n",
|
|||
|
|
"noisy_fidelity = state_fidelity(noisy_dm, target)\n",
|
|||
|
|
"\n",
|
|||
|
|
"ideal_fidelity = state_fidelity(Statevector.from_instruction(bundle.prep), target)\n",
|
|||
|
|
"\n",
|
|||
|
|
"print(f\"Ideal fidelity (circuit vs target): {ideal_fidelity:.6f}\")\n",
|
|||
|
|
"print(f\"Noisy fidelity (density matrix): {noisy_fidelity:.6f}\")\n",
|
|||
|
|
"print(f\"Fidelity loss from noise: {ideal_fidelity - noisy_fidelity:.6f}\")\n",
|
|||
|
|
"print(f\"\\nNote: This uses a simplified depolarizing noise model on the 4-qubit\")\n",
|
|||
|
|
"print(f\"logical circuit. The full LocalCheapExecutor uses the backend-specific\")\n",
|
|||
|
|
"print(f\"noise model on the transpiled circuit via shot-based simulation.\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"quiz(tracker, \"q6_witness_vs_fidelity\",\n",
|
|||
|
|
" question=\"The witness and fidelity both measure quality. How do they differ?\",\n",
|
|||
|
|
" options=[\n",
|
|||
|
|
" \"They are the same thing\",\n",
|
|||
|
|
" \"Fidelity measures overlap with the ideal state; the witness tests magic-state properties specifically\",\n",
|
|||
|
|
" \"Fidelity is always higher than the witness\",\n",
|
|||
|
|
" ],\n",
|
|||
|
|
" correct=1,\n",
|
|||
|
|
" section=\"6. Fidelity\",\n",
|
|||
|
|
" bloom=\"analyze\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"Fidelity captures total overlap with the ideal state. \"\n",
|
|||
|
|
" \"The witness specifically tests the T-state signature. \"\n",
|
|||
|
|
" \"A state can have moderate fidelity but low witness if the noise corrupts the magic structure.\"\n",
|
|||
|
|
" ))"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"> **Key Insight:** The witness ($) and fidelity ($) measure different things. Fidelity captures *all* deviations from ideal. The witness specifically tests the \"magic\" property. Both are useful: fidelity is more complete, the witness is more targeted.\n",
|
|||
|
|
"\n",
|
|||
|
|
"---\n",
|
|||
|
|
"## 7. The Scoring Formula\n",
|
|||
|
|
"\n",
|
|||
|
|
"The autoresearch harness combines quality, acceptance rate, and cost into a single **score**:\n",
|
|||
|
|
"\n",
|
|||
|
|
"9951\text{score} = \frac{\text{quality} \times \text{acceptance\\_rate}}{\text{cost}}9951\n",
|
|||
|
|
"\n",
|
|||
|
|
"where:\n",
|
|||
|
|
"\n",
|
|||
|
|
"9951\text{quality} = \frac{\\sum_i w_i \\cdot q_i}{\\sum_i w_i}9951\n",
|
|||
|
|
"\n",
|
|||
|
|
"with quality components \\in$ {ideal_fidelity, noisy_fidelity, logical_witness, codespace_rate, stability_score, spectator_alignment}, each weighted by $, and:\n",
|
|||
|
|
"\n",
|
|||
|
|
"9951\text{cost} = \text{base} + w_{\text{2q}} \\cdot n_{\text{2q}} + w_d \\cdot d + w_s \\cdot s + w_r \\cdot r + w_q \\cdot q_{\text{proxy}}9951"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"# Build metrics by hand\n",
|
|||
|
|
"acceptance_rate = results[\"acceptance\"][\"acceptance_rate\"]\n",
|
|||
|
|
"\n",
|
|||
|
|
"metrics = EvaluationMetrics(\n",
|
|||
|
|
" ideal_encoded_fidelity=ideal_fidelity,\n",
|
|||
|
|
" noisy_encoded_fidelity=noisy_fidelity,\n",
|
|||
|
|
" logical_magic_witness=lib_witness,\n",
|
|||
|
|
" acceptance_rate=acceptance_rate,\n",
|
|||
|
|
" codespace_rate=np.mean([results[k][\"acceptance_rate\"] for k in context_names]),\n",
|
|||
|
|
" spectator_logical_z=sz,\n",
|
|||
|
|
" logical_x=lx,\n",
|
|||
|
|
" logical_y=ly,\n",
|
|||
|
|
" two_qubit_count=sum(count_two_qubit_gates(c) for c in transpiled_circuits),\n",
|
|||
|
|
" depth=max(c.depth() for c in transpiled_circuits),\n",
|
|||
|
|
" shot_count=512 * 1 * 4,\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Define weights (from rung1.yaml cheap_quality)\n",
|
|||
|
|
"score_config = ScoreConfig(\n",
|
|||
|
|
" name=\"weighted_acceptance_cost\",\n",
|
|||
|
|
" cheap_quality=QualityWeights(\n",
|
|||
|
|
" ideal_fidelity=0.10, noisy_fidelity=0.40, logical_witness=0.25,\n",
|
|||
|
|
" codespace_rate=0.15, stability_score=0.05, spectator_alignment=0.05,\n",
|
|||
|
|
" ),\n",
|
|||
|
|
" cost_weights=CostWeights(\n",
|
|||
|
|
" two_qubit_count=0.08, depth=0.01, shot_count=0.00020,\n",
|
|||
|
|
" runtime_estimate=0.015, queue_cost_proxy=0.30,\n",
|
|||
|
|
" ),\n",
|
|||
|
|
" base_cost=1.0,\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"score, quality, cost = score_metrics(metrics, \"cheap\", score_config)\n",
|
|||
|
|
"print(f\"Quality: {quality:.4f}\")\n",
|
|||
|
|
"print(f\"Acceptance:{acceptance_rate:.4f}\")\n",
|
|||
|
|
"print(f\"Cost: {cost:.4f}\")\n",
|
|||
|
|
"print(f\"Score: {score:.6f}\")\n",
|
|||
|
|
"print(f\"\\nFormula check: {quality:.4f} * {acceptance_rate:.4f} / {cost:.4f} = {quality * acceptance_rate / cost:.6f}\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### The scoring formula\n",
|
|||
|
|
"\n",
|
|||
|
|
"$$\\text{score} = \\frac{\\text{quality} \\times \\text{acceptance\\_rate}}{\\text{cost}}$$"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"predict_choice(tracker, \"q7_score_tension\",\n",
|
|||
|
|
" question=\"If you add stricter verification, what happens to the score?\",\n",
|
|||
|
|
" options=[\n",
|
|||
|
|
" \"Score always increases \\u2014 more checks = better quality\",\n",
|
|||
|
|
" \"Score always decreases \\u2014 more checks = lower acceptance\",\n",
|
|||
|
|
" \"It depends \\u2014 quality improves but acceptance drops; the net effect depends on noise\",\n",
|
|||
|
|
" ],\n",
|
|||
|
|
" correct=2,\n",
|
|||
|
|
" section=\"7. Scoring\",\n",
|
|||
|
|
" bloom=\"evaluate\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"Stricter verification filters more errors (higher quality) but rejects more shots (lower acceptance). \"\n",
|
|||
|
|
" \"At low noise, quality gain dominates. At high noise, acceptance crashes.\"\n",
|
|||
|
|
" ))\n",
|
|||
|
|
"checkpoint_summary(tracker, \"7. Scoring\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"> **Key Insight:** The score balances three tensions: (1) Higher quality is better, but requires expensive circuits. (2) Strict postselection improves quality but lowers acceptance rate. (3) More shots improve statistics but increase cost. The weights in the config determine the tradeoff.\n",
|
|||
|
|
"\n",
|
|||
|
|
"---\n",
|
|||
|
|
"## 8. Parameter Sweep: Optimization Level\n",
|
|||
|
|
"\n",
|
|||
|
|
"Let us see how affects the score. Higher levels produce more compact circuits but take longer to transpile."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"from autoresearch_quantum.config import load_rung_config\n",
|
|||
|
|
"\n",
|
|||
|
|
"rung_config = load_rung_config(\"../../configs/rungs/rung1.yaml\")\n",
|
|||
|
|
"opt_levels = [1, 2, 3]\n",
|
|||
|
|
"sweep_results = {}\n",
|
|||
|
|
"\n",
|
|||
|
|
"for opt in opt_levels:\n",
|
|||
|
|
" s = ExperimentSpec(\n",
|
|||
|
|
" rung=1, seed_style=\"h_p\", encoder_style=\"cx_chain\",\n",
|
|||
|
|
" verification=\"both\", postselection=\"all_measured\",\n",
|
|||
|
|
" target_backend=\"fake_brisbane\", noise_backend=\"fake_brisbane\",\n",
|
|||
|
|
" optimization_level=opt, shots=256, repeats=1,\n",
|
|||
|
|
" )\n",
|
|||
|
|
" executor = LocalCheapExecutor()\n",
|
|||
|
|
" tier_result = executor.evaluate(s, rung_config)\n",
|
|||
|
|
" sweep_results[opt] = tier_result\n",
|
|||
|
|
" m = tier_result.metrics\n",
|
|||
|
|
" print(f\"opt_level={opt}: score={tier_result.score:.4f} 2q_gates={m.two_qubit_count} depth={m.depth} accept={m.acceptance_rate:.3f} witness={m.logical_magic_witness:.3f}\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"fig, axes = plt.subplots(1, 3, figsize=(15, 4))\n",
|
|||
|
|
"\n",
|
|||
|
|
"labels = [f\"Level {o}\" for o in opt_levels]\n",
|
|||
|
|
"scores = [sweep_results[o].score for o in opt_levels]\n",
|
|||
|
|
"gates = [sweep_results[o].metrics.two_qubit_count for o in opt_levels]\n",
|
|||
|
|
"depths = [sweep_results[o].metrics.depth for o in opt_levels]\n",
|
|||
|
|
"accept = [sweep_results[o].metrics.acceptance_rate for o in opt_levels]\n",
|
|||
|
|
"witness_vals = [sweep_results[o].metrics.logical_magic_witness for o in opt_levels]\n",
|
|||
|
|
"\n",
|
|||
|
|
"axes[0].bar(labels, scores, color=[\"#3498db\", \"#2ecc71\", \"#e67e22\"])\n",
|
|||
|
|
"axes[0].set_title(\"Score\")\n",
|
|||
|
|
"axes[0].set_ylabel(\"Score\")\n",
|
|||
|
|
"\n",
|
|||
|
|
"x = np.arange(len(labels))\n",
|
|||
|
|
"w = 0.35\n",
|
|||
|
|
"axes[1].bar(x - w/2, gates, w, label=\"2Q Gates\", color=\"#e74c3c\")\n",
|
|||
|
|
"axes[1].bar(x + w/2, depths, w, label=\"Depth\", color=\"#9b59b6\")\n",
|
|||
|
|
"axes[1].set_xticks(x)\n",
|
|||
|
|
"axes[1].set_xticklabels(labels)\n",
|
|||
|
|
"axes[1].set_title(\"Circuit Cost\")\n",
|
|||
|
|
"axes[1].legend()\n",
|
|||
|
|
"\n",
|
|||
|
|
"axes[2].bar(x - w/2, accept, w, label=\"Acceptance\", color=\"#2ecc71\")\n",
|
|||
|
|
"axes[2].bar(x + w/2, witness_vals, w, label=\"Witness\", color=\"#3498db\")\n",
|
|||
|
|
"axes[2].set_xticks(x)\n",
|
|||
|
|
"axes[2].set_xticklabels(labels)\n",
|
|||
|
|
"axes[2].set_title(\"Quality Metrics\")\n",
|
|||
|
|
"axes[2].legend()\n",
|
|||
|
|
"\n",
|
|||
|
|
"plt.tight_layout()\n",
|
|||
|
|
"plt.show()"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"reflect(tracker, \"q8_sweep_insight\",\n",
|
|||
|
|
" question=\"Looking at the parameter sweep charts, which optimization level gives the best score and why?\",\n",
|
|||
|
|
" section=\"8. Parameter sweep\",\n",
|
|||
|
|
" bloom=\"evaluate\",\n",
|
|||
|
|
" model_answer=(\n",
|
|||
|
|
" \"The best optimization level balances gate count reduction against qubit routing overhead. \"\n",
|
|||
|
|
" \"Level 2 or 3 often wins because aggressive optimization reduces noisy 2-qubit gates. \"\n",
|
|||
|
|
" \"But the best choice depends on the specific backend topology.\"\n",
|
|||
|
|
" ))"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"> **Observe:** Higher optimization levels typically reduce gate count and depth, which lowers cost. But the effect on quality depends on how the transpiler remaps the circuit — sometimes a different layout performs better or worse under that backend's specific noise profile.\n",
|
|||
|
|
"\n",
|
|||
|
|
"---\n",
|
|||
|
|
"## 9. Dominant Failure Modes\n",
|
|||
|
|
"\n",
|
|||
|
|
"The harness classifies each experiment into a **dominant failure mode** — the biggest weakness:\n",
|
|||
|
|
"\n",
|
|||
|
|
"| Failure Mode | Trigger | Meaning |\n",
|
|||
|
|
"|---|---|---|\n",
|
|||
|
|
"| postselection collapse | acceptance_rate < 0.45 | Too many shots fail syndrome checks |\n",
|
|||
|
|
"| logical witness erosion | witness < 0.65 | Magic property is severely degraded |\n",
|
|||
|
|
"| noise sensitivity | stability_score < 0.75 | Results vary wildly between repeats |\n",
|
|||
|
|
"| transpile cost explosion | 2q_gates > 60 or depth > 120 | Circuit too expensive for the quality gained |"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"for opt, result in sweep_results.items():\n",
|
|||
|
|
" print(f\"opt_level={opt}: failure_mode = {result.metrics.dominant_failure_mode}\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"order(tracker, \"q9_failure_ordering\",\n",
|
|||
|
|
" instruction=\"Rank failure modes from least to most severe for magic state quality:\",\n",
|
|||
|
|
" items=[\"high_cost_low_throughput\", \"poor_acceptance_rate\", \"low_magic_witness\"],\n",
|
|||
|
|
" correct_order=[\"high_cost_low_throughput\", \"poor_acceptance_rate\", \"low_magic_witness\"],\n",
|
|||
|
|
" section=\"9. Failure modes\",\n",
|
|||
|
|
" bloom=\"analyze\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"High cost is fixable (fewer gates). Poor acceptance is concerning (too many errors). \"\n",
|
|||
|
|
" \"Low magic witness is worst \\u2014 the state has lost its T-state character.\"\n",
|
|||
|
|
" ))\n",
|
|||
|
|
"checkpoint_summary(tracker, \"9. Failure modes\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"## 10. Factory Throughput Score\n",
|
|||
|
|
"\n",
|
|||
|
|
"The default scorer optimizes . An alternative — **factory throughput** — optimizes for producing accepted magic states per unit cost, penalizing circuit resources more heavily:\n",
|
|||
|
|
"\n",
|
|||
|
|
"9951\text{throughput} = \frac{\text{acceptance\\_rate} \times W}{\text{cost}}9951\n",
|
|||
|
|
"\n",
|
|||
|
|
"This is useful when you care about *yield* in a magic state distillation factory."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"factory_config = ScoreConfig(\n",
|
|||
|
|
" name=\"factory_throughput\",\n",
|
|||
|
|
" cheap_quality=QualityWeights(\n",
|
|||
|
|
" noisy_fidelity=0.3, logical_witness=0.4,\n",
|
|||
|
|
" codespace_rate=0.2, stability_score=0.1,\n",
|
|||
|
|
" ),\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"print(f\"{'Metric':<25} {'Weighted Acceptance Cost':>25} {'Factory Throughput':>20}\")\n",
|
|||
|
|
"print(\"=\" * 72)\n",
|
|||
|
|
"for opt in opt_levels:\n",
|
|||
|
|
" m = sweep_results[opt].metrics\n",
|
|||
|
|
" # Reset extra dict for factory calc\n",
|
|||
|
|
" m.extra = {}\n",
|
|||
|
|
" s_wac, q_wac, c_wac = weighted_acceptance_cost(m, \"cheap\", score_config)\n",
|
|||
|
|
" s_ft, q_ft, c_ft = factory_throughput_score(m, \"cheap\", factory_config)\n",
|
|||
|
|
" print(f\"opt_level={opt:<15} {s_wac:>25.4f} {s_ft:>20.4f}\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"quiz(tracker, \"q10_factory_vs_wac\",\n",
|
|||
|
|
" question=\"When would factory throughput scoring beat default WAC scoring?\",\n",
|
|||
|
|
" options=[\n",
|
|||
|
|
" \"When raw quality matters most\",\n",
|
|||
|
|
" \"When producing many T-states in a pipeline and throughput matters more than per-state quality\",\n",
|
|||
|
|
" \"When running on hardware instead of a simulator\",\n",
|
|||
|
|
" ],\n",
|
|||
|
|
" correct=1,\n",
|
|||
|
|
" section=\"10. Factory throughput\",\n",
|
|||
|
|
" bloom=\"evaluate\",\n",
|
|||
|
|
" explanation=(\n",
|
|||
|
|
" \"Factory throughput penalizes cost more heavily because in a pipeline, \"\n",
|
|||
|
|
" \"the rate of producing usable T-states matters more than any individual one.\"\n",
|
|||
|
|
" ))\n",
|
|||
|
|
"checkpoint_summary(tracker, \"10. Factory throughput\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"> **Key Insight:** Different scoring functions rank experiments differently. The choice depends on your goal: maximizing state quality vs maximizing factory throughput. The ratchet is agnostic — it optimizes whichever score you configure.\n",
|
|||
|
|
"\n",
|
|||
|
|
"---\n",
|
|||
|
|
"## 11. Summary\n",
|
|||
|
|
"\n",
|
|||
|
|
"You now understand every number the harness produces:\n",
|
|||
|
|
"\n",
|
|||
|
|
"| Concept | What it measures |\n",
|
|||
|
|
"|---|---|\n",
|
|||
|
|
"| **Acceptance rate** | Fraction of shots surviving postselection |\n",
|
|||
|
|
"| **Logical witness** | Certification of magic property ( = 1.0$ for perfect T-state) |\n",
|
|||
|
|
"| **Noisy fidelity** | Overlap with ideal encoded state under noise |\n",
|
|||
|
|
"| **Score** | quality × acceptance / cost — the single number to optimize |\n",
|
|||
|
|
"| **Failure mode** | Biggest weakness of the current configuration |\n",
|
|||
|
|
"\n",
|
|||
|
|
"**Next:** Notebook 3 shows how the ratchet *automatically* explores parameter space to maximize this score."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"## Final Assessment"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"tracker.dashboard()\n",
|
|||
|
|
"path = tracker.save()\n",
|
|||
|
|
"print(f\"\\nProgress saved to: {path}\")"
|
|||
|
|
],
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"kernelspec": {
|
|||
|
|
"display_name": "Python 3",
|
|||
|
|
"language": "python",
|
|||
|
|
"name": "python3"
|
|||
|
|
},
|
|||
|
|
"language_info": {
|
|||
|
|
"name": "python",
|
|||
|
|
"version": "3.14.2"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"nbformat": 4,
|
|||
|
|
"nbformat_minor": 5
|
|||
|
|
}
|