# Run notes: square qubit on IBM hardware (Kickoff 03)

This is step 2 of the hardware path: a demonstration on real, noisy hardware, not a test of anything anyone doubts. The ideal outcome is already fixed by the self-check and the statevector run. The hardware run shows the same shape surviving real device noise and measures how big that noise is.

## Run record

| Field | Value |
|---|---|
| Date and time (submitted) | 2026-09-23 16:59:26 EDT (20:59:26 UTC) |
| Backend | ibm_kingston (chosen by `least_busy`, no `--backend` given) |
| Job id | `daq3rdeekp0c73aq6aig` |
| Job status | DONE, first attempt, no retry |
| Shots | 4000 per circuit, 28 circuits (27 sweep points + 1 transfer check) |
| Wall-clock | 47 s end to end for the script; 40 s from submit to result; IBM job timestamps: created 20:59:33Z, running 20:59:34Z, finished 21:00:13Z |
| QPU time charged | 32 s (IBM `usage`), out of the 10-minute monthly Open plan budget |
| Hardware runs used | 1 of the 2 allowed |
| Transpiler | `generate_preset_pass_manager(optimization_level=3)`, as written in the script |
| Python | 3.14.7 (venv in this folder) |
| qiskit | 2.5.2 |
| qiskit-ibm-runtime | 0.49.0 |
| numpy / matplotlib | 2.5.3 / 3.11.2 |

## API calls changed

None. `StatevectorSampler`, `result[i].data.c.get_counts()`, `generate_preset_pass_manager`, `SamplerV2(mode=backend)` and `least_busy` all worked as written in the installed versions. The script is byte-identical to the one in the kickoff zip.

## Preliminary checks

- `--selfcheck`: max |numpy - prediction| = 4.44e-16; PST probability at t = π/2 = 1.000000.
- `--ideal` (statevector simulator, 4000 shots): transfer 1.0000; 0° peak 1.0000 at t = 0.785; 90° peak 0.5082 at t = 0.785; 180° row 0.0000 at every point. Saved as `square_qubit_results_ideal.json` and `square_qubit_plot_ideal.png`.

## The three numbers (hardware, ibm_kingston)

1. **Perfect state transfer, P(bead 55) at t = π/2: 0.9815** (3926 of 4000 shots on `11`; 42 on `01`, 32 on `10`). Expected range 0.90 to 0.98; the result is at the top of it.
2. **Peak of the 0° curve: 0.9890 at t = 0.785** (π/4), which is the sweep point where the peak is expected.
3. **Mean of the 180° row: 0.0126** (nine points, from 0.0085 to 0.0180). Small and positive, not zero. That gap is device noise and is the honest content of the result.

Supporting figures, for reading rather than headlining:

- 90° curve peak: 0.5240 at t = 0.785 (prediction 0.5000).
- Across all 27 sweep points, |measured - predicted| averages 0.012 and reaches at most 0.027 (90°, t = 0.589: 0.4535 against 0.4268).
- Binomial shot noise at 4000 shots is about 0.008 near p = 0.5 and about 0.002 near p = 0.01. The largest deviations are therefore bigger than shot noise alone. They are device error (gate, phase and readout), which is what "within device noise" refers to below, and not sampling scatter.

## Interpretation (one sentence, as scoped by the kickoff)

On ibm_kingston, the transfer reached 0.9815; the 180° dark state stayed at 0.0126; the shape of the curves matches cos²(φ/2)·sin²(2t) within device noise.

## Files

- `square_qubit_results.json`, `square_qubit_plot.png`: hardware run.
- `square_qubit_results_ideal.json`, `square_qubit_plot_ideal.png`: ideal run, renamed after it finished (the script writes both runs to the same filename).
- `hardware-run-1.log`: console output of the hardware run.
- `.venv/`: the virtual environment; not part of the hand-back.

## Note for the website kickoff

In both PNGs the "perfect state transfer check" label sits at the bottom left, where it slightly overlaps the 180° row near t = 0. This is cosmetic and was left alone, since the script was not to be modified beyond API fixes. If the website panel re-renders the chart from the JSON, the label can move there.
