wai-quantum: published architectures, re-estimated — the bicycle architecture, RSA-2048 and FeMoCo, each delta explained #665
13 changed files with 3446 additions and 1 deletions
25
.github/workflows/wai-quantum-estimate.yml
vendored
25
.github/workflows/wai-quantum-estimate.yml
vendored
|
|
@ -8,6 +8,13 @@ name: wai-quantum resource estimation
|
|||
# frontier, the seals, and the planar model and its receipts
|
||||
# (quantum_resource, quantum_resource_receipt) beside them.
|
||||
#
|
||||
# The published-architecture check (src/published_architectures.rs) feeds the
|
||||
# stated assumptions of published resource estimates into the estimators
|
||||
# (quantum_arch, quantum_bicycle and the estimate job), holds every row to its
|
||||
# published figure (tests/data/published_figures.tsv: the digits it is printed
|
||||
# to, or a guard on ours) and the page docs/published-architectures.md to what
|
||||
# they give. Its search over 4¹¹ Paulis runs in a release build only.
|
||||
#
|
||||
# In a release build the calibration test measures every point of the
|
||||
# decoders' table again (the rotated surface-code memory experiment, decoded
|
||||
# by exact matching and by union-find on the same shots), so the code model
|
||||
|
|
@ -87,6 +94,24 @@ jobs:
|
|||
quantum_resource_receipt::tests::a_counted_program_binds_its_digest_and_its_epsilon; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/estimate.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
- name: Published architectures, re-estimated, and the page that prints them
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --lib -- quantum_arch:: quantum_bicycle:: published_architectures:: 2>&1 | tee "$RUNNER_TEMP/published.log"
|
||||
grep -qE '^test result: ok\. [1-9][0-9]+ passed; 0 failed; 0 ignored' "$RUNNER_TEMP/published.log" || { echo "::error::the published-architecture tests did not all run and pass"; exit 1; }
|
||||
for t in published_architectures::tests::the_page_is_what_the_estimators_give \
|
||||
published_architectures::tests::every_row_holds_to_its_published_figure \
|
||||
published_architectures::tests::the_ours_column_holds_only_ours_and_the_text_says_what_the_sources_say \
|
||||
quantum_bicycle::tests::the_cost_tables_are_what_the_search_finds \
|
||||
quantum_bicycle::tests::the_source_s_mean_costs_come_from_taking_z_by_the_inverse \
|
||||
quantum_bicycle::tests::the_fits_give_the_printed_rates \
|
||||
quantum_arch::tests::the_2021_rsa_table_is_reproduced_to_its_printed_digits \
|
||||
quantum_arch::tests::the_chemistry_estimate_is_priced_by_the_same_clock; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/published.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
cargo run --locked --release --example published_architectures --features full
|
||||
- name: The engine without receipts still builds the estimate
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
|
|
|
|||
24
wai/changes/2026-11-06-published-architectures.md
Normal file
24
wai/changes/2026-11-06-published-architectures.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
### wai-quantum: published architectures, re-estimated
|
||||
|
||||
- `published_architectures` feeds the stated assumptions of published resource estimates into
|
||||
the crate's estimators and prints, for each quantity, the published figure, ours, the delta
|
||||
and why they differ: a different assumption, the source's model, the source's own figures,
|
||||
a limit of ours, or open. The targets are the bicycle architecture of arXiv:2506.03094;
|
||||
RSA-2048 on the surface code (arXiv:1905.09749); FeMoCo (arXiv:2011.03494); RSA-2048 on
|
||||
yoked surface codes (arXiv:2505.15917); and the planar model's own source
|
||||
(arXiv:2211.07629). The published figures are kept in `tests/data/published_figures.tsv`,
|
||||
each with where it is printed and the rule a row is held to: the digits the source prints,
|
||||
its rounding, the range its fits' printed parameters allow, or, for a row that does not
|
||||
agree, a guard on ours. `docs/published-architectures.md` holds the rows, and tests hold
|
||||
the rows to their figures and the page to the code; `--example published_architectures`
|
||||
prints them.
|
||||
- `quantum_bicycle` prices a machine of bivariate-bicycle code modules: the gross and two-gross
|
||||
codes from their printed polynomials and basis, the native measurements and a search for the
|
||||
in-module cost of every Pauli, the instruction rates from the source's failure-spectrum
|
||||
fits, and the capability of a machine of a given size.
|
||||
- `quantum_arch` prices the 2021 surface-code machine: a Toffoli whose fixups are teleported
|
||||
away runs at the reaction-limited tick, not the lattice-surgery beat
|
||||
(`Timing::tick_us`, `Timing::teleported_add_us`); lookups through two access hallways
|
||||
(`Timing::double_access_lookup_us`); the two-level 15-to-1 and 8T-to-CCZ factory
|
||||
(`DistilledCczFactory`); and the windowed factoring cost (`windowed_factoring_estimate`).
|
||||
- The resource-estimation workflow runs these in a release build and requires each by name.
|
||||
|
|
@ -409,6 +409,10 @@ required-features = ["quantum_ldpc"]
|
|||
name = "arch_factoring"
|
||||
required-features = ["quantum_arch"]
|
||||
|
||||
[[example]]
|
||||
name = "published_architectures"
|
||||
required-features = ["quantum_arch", "quantum_engine"]
|
||||
|
||||
[[example]]
|
||||
name = "estimate_calibration"
|
||||
required-features = ["quantum_engine", "quantum_uf"]
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ never creates information.
|
|||
| `quantum_nqs` | **neural quantum states**: spin models on any graph (Heisenberg, frustrated J₁–J₂, transverse-field Ising), a restricted Boltzmann machine with real parameters (and Marshall's sign on bipartite lattices) or complex ones that learn a sign structure nobody supplied, projected onto a momentum and spin-flip sector, variational Monte Carlo by Metropolis chains or exact enumeration, and stochastic reconfiguration solved in whichever of parameter or sample space is smaller. Held to exact diagonalisation and to DMRG on the same operator sum |
|
||||
| `quantum_noisy` | **noisy circuits**: quantum trajectories on the state vector (depolarizing, dephasing, amplitude damping, readout), an exact density-matrix referee up to 12 qubits that reuses the same kernels, linear cross-entropy fidelity (sampled, exact and the circuit's own), and the digital error model. Measures where that model is off: below the true fidelity by a margin that grows with the error rate, not with depth |
|
||||
| `quantum_ldpc` | **qLDPC memory at circuit level**: bivariate-bicycle codes from their two polynomials (`k` by rank, logical bases), the depth-8 syndrome cycle with circuit-level noise, its detector error model, and BP-OSD decoding (min-sum with adaptive scaling, ordered statistics with a combination sweep). The error model has the same columns as the source's own decoding matrices, and on identical syndromes the decoder makes the source's decisions shot for shot |
|
||||
| `quantum_arch` | **architecture-level estimation**: yoked surface-code storage (row and grid parity checks over patches, hot and cold), magic-state cultivation read off the published simulation curves, CCZ factories, and a clock set by whichever is slowest of lattice surgery, the magic-state supply and the control loop. Assembles whole-machine estimates; its storage search matches the source's footprint tool layout for layout |
|
||||
| `quantum_arch` | **architecture-level estimation**: yoked surface-code storage (row and grid parity checks over patches, hot and cold), magic-state cultivation read off the published simulation curves, CCZ factories, and a clock set by whichever is slowest of lattice surgery, the magic-state supply and the control loop. Assembles whole-machine estimates; its storage search matches the source's footprint tool layout for layout. Also the reaction-limited clock and two-level factory of the 2021 surface-code machine, and (`quantum_bicycle`) machines of bivariate-bicycle code modules |
|
||||
| `quantum_receipt` | signed, energy-accounted receipt over a reconstruction |
|
||||
| `quantum_ops` | the operations/attestation layer |
|
||||
| `quantum_cal`, `quantum_control`, `quantum_noise` | calibration, filter-function robust control, DD noise spectroscopy, Cycle-Benchmarking noise learning |
|
||||
|
|
@ -451,6 +451,14 @@ under a million noisy qubits (arXiv:2505.15917).
|
|||
printed runtime is 14% above its own tallies. With every correction applied,
|
||||
the machine needs 958,480 qubits and 4.3 days. The conclusion holds.
|
||||
|
||||
It prices two more machines. The 2021 surface-code machine of
|
||||
arXiv:1905.09749 teleports each Toffoli's fixups away and runs at the reaction
|
||||
time, with a two-level factory; every row of that paper's RSA table comes
|
||||
back. `quantum_bicycle` prices a line of bivariate-bicycle code modules, the
|
||||
architecture of arXiv:2506.03094, from its printed codes, instructions and
|
||||
rates. [Published architectures, re-estimated](docs/published-architectures.md)
|
||||
puts these papers' own figures through the estimators, with each delta and why.
|
||||
|
||||
## Error correction at circuit level
|
||||
|
||||
An error-correction experiment is a noisy Clifford circuit, its detectors and
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ run one says why.
|
|||
- [The compiler](compiler.md): the passes, the ε budget and the certificate.
|
||||
- [Resource estimates](estimate.md): every number of an estimate and what it
|
||||
assumes.
|
||||
- [Published architectures, re-estimated](published-architectures.md): published
|
||||
resource estimates through these estimators, each delta and why.
|
||||
- [The reader's diagnostics](qasm-diagnostics.md) and
|
||||
[what it does with each construct](qasm-feature-matrix.md).
|
||||
- [The job layer's refusal codes](job-refusals.md).
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
- [判定](verdicts.md):引擎对一个答案检查到了什么程度,意图,以及修复。
|
||||
- [编译器](compiler.md):各遍处理、ε 预算和证书。
|
||||
- [资源估算](estimate.md):估算中的每个数字及其假设。
|
||||
- [已发表架构的重新估算](published-architectures.md):用这些估算器重算已发表的资源估算,给出每处差异及其原因。
|
||||
- [读取器的诊断](qasm-diagnostics.md),以及[它如何处理每种构造](qasm-feature-matrix.md)。
|
||||
- [其他格式](formats.md):按配置文件读写的 QIR 和 jeff,每次转换都经过检查。
|
||||
- [作业层的拒绝代码](job-refusals.md)。
|
||||
|
|
|
|||
369
wai/wai-quantum/docs/published-architectures.md
Normal file
369
wai/wai-quantum/docs/published-architectures.md
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
# Published architectures, re-estimated
|
||||
|
||||
This page puts published fault-tolerant resource estimates through this crate's
|
||||
estimators. For each quantity it gives the published figure, ours, the delta
|
||||
between them, and why they differ. Each estimator gets the source's stated
|
||||
assumptions (its code, distances, error rates, cycle and reaction times,
|
||||
factories and logical counts). Nothing is fitted to the figures it is compared
|
||||
with, with one exception its row names: which end of the line the Ising
|
||||
program's T factory sits at, which the source does not print.
|
||||
|
||||
Every row has one of six classes:
|
||||
|
||||
- **agrees**: equal to the digits the source prints;
|
||||
- **assumption**: we were given, or chose, a different assumption, and the row
|
||||
states it;
|
||||
- **their model**: the source models it differently, and the row says how;
|
||||
- **their numbers**: the source's own figures disagree with each other or with
|
||||
the method it states, and the row says where;
|
||||
- **our limit**: our estimator does not model this, and the row says what it
|
||||
leaves out;
|
||||
- **open**: not resolved, and the row says what is known.
|
||||
|
||||
The published figures are kept apart from the code that computes ours, in
|
||||
`tests/data/published_figures.tsv`: each with where it is printed, as printed,
|
||||
its value and its rule. A row that agrees agrees to the digits the source
|
||||
prints: exactly, to the nearest printed unit, rounded up or down where the
|
||||
source rounds so, or, for a figure ours takes from the source's fits, within
|
||||
the range the fits' printed parameters allow. Every other row carries a guard,
|
||||
our figure to four digits. A test holds every row to its rule, and another holds
|
||||
the rows below to the example's output, so a change to an estimator that moves
|
||||
a figure fails until its guard, its reason and this page are updated together.
|
||||
The resource-estimation workflow runs them in a release build.
|
||||
|
||||
```text
|
||||
cargo run --release --example published_architectures --features full # columns
|
||||
cargo run --release --example published_architectures --features full -- --markdown # this page's rows
|
||||
cargo run --release --example published_architectures --features full -- --guards # ours, for the guards
|
||||
```
|
||||
|
||||
## The sources
|
||||
|
||||
A row's source names the section, table or figure where its published figure
|
||||
is printed. `source files` means the figure is quoted from the paper's arXiv
|
||||
source (its TeX tables and plot data), which keeps more digits than its PDF
|
||||
prints; every other figure is quoted with the digits the PDF prints.
|
||||
|
||||
- **The bicycle architecture**, arXiv:2506.03094 (2025): the gross `[[144,12,12]]`
|
||||
and two-gross `[[288,12,18]]` codes, its Tables 1–3, 5, 6, 9 and 10, §§1.2,
|
||||
3.2 and 4, Fig. 9, Fig. 10, Fig. 17 and Appendices A.1, A.2, A.7 and A.10.
|
||||
Our model of it is `quantum_bicycle`. Beside it, the same codes' memory
|
||||
figures in arXiv:2308.07915, Table 1. Its authors' compiler is released as
|
||||
`bicycle_compiler`, `bicycle_cliffords` and `bicycle_common` on crates.io
|
||||
(0.1.0 of 2025-07-31); one row below cites its source.
|
||||
- **RSA-2048 on the surface code**, arXiv:1905.09749 (Quantum 5, 433, 2021): its
|
||||
Tables 1 and 3, §§2.10–2.14, and the cost script in its ancillary files. Our
|
||||
model of it is `quantum_arch::windowed_factoring_estimate`, and its counts go
|
||||
through the estimate job as well.
|
||||
- **FeMoCo on the surface code**, arXiv:2011.03494 (PRX Quantum 2, 030305,
|
||||
2021): its Table III, §IV.C and Fig. 10, on the same factory and clock.
|
||||
- **RSA-2048 on yoked surface codes**, arXiv:2505.15917 (2025): §3.2, through
|
||||
`quantum_arch::factoring_estimate`.
|
||||
- **The planar model's own source**, arXiv:2211.07629 (2022): Appendix F,
|
||||
through `quantum_resource`.
|
||||
|
||||
## What it finds
|
||||
|
||||
**The bicycle architecture.** Our model reproduces the paper's physical- and
|
||||
logical-qubit counts exactly, the 24 fitted rates of its Table 10 (each
|
||||
within the range its fits' printed parameters allow), every failure probability
|
||||
of its Table 10 from its instruction counts, and its error-rate bounds for the
|
||||
Ising program. Its other differences are explained in their rows:
|
||||
|
||||
- Its four mean compile costs (Fig. 9) come out to every printed digit when a
|
||||
shift's action is taken as A on X̄ and A⁻¹ on Z̄, on both halves of a module.
|
||||
That is what its authors' released compiler did in `bicycle_cliffords` 0.1.0
|
||||
(`src/measurement.rs`). A CNOT circuit |x⟩ → |Ax⟩ takes Z̄ by A⁻ᵀ, which is
|
||||
how the operators move, and ours follows the operators; its version 0.2.1
|
||||
takes X̄ by A⁻¹ and Z̄ by Aᵀ, a consistent pair. (On the printed basis a shift
|
||||
acts as A on the first half and Aᵀ on the second, where the paper says A on
|
||||
both; taken as the paper says, with Z̄ by A⁻ᵀ, every cost comes out as ours.)
|
||||
- Its idle and shift rates are the simulated circuit's failure, undivided,
|
||||
where its text says they are divided by the circuit's C cycles. Ours divides,
|
||||
as the text says, and that choice is about a third of a point of the gross
|
||||
capability at 10⁻³ (its own row).
|
||||
- Its Ising program takes 15,542,400 T gates in its tables and 19,036,800 in
|
||||
its text and Fig. 1. pygridsynth 1.0.1, the version it cites, gives the
|
||||
15,542,400 exactly.
|
||||
- Its gross Ising machine of 4,817 qubits takes the adapter of the 10⁻³
|
||||
factory beside the 10⁻⁴ factory it names (4,801).
|
||||
- The Ising program's inter-module measurements match its 946,800 with the
|
||||
factory after the last module; before the first, 781,200. The paper prints
|
||||
neither: this is the one choice here made to fit a published figure.
|
||||
|
||||
Two differences are open. Its gross capabilities at 10⁻⁴ need a failure per
|
||||
rotation of 8.3·10⁻⁷ that does not depend on the machine's size, where its
|
||||
factory's printed error is 4·10⁻⁸; its released compiler's capability estimate
|
||||
at those machines would settle it, and this check does not run third-party
|
||||
code. And the earlier paper's memory rate for the same codes, arXiv:2308.07915,
|
||||
is about 1,250 times the later's fit at the same p: their decoders, circuits and
|
||||
fitting differ, and which accounts for it is not found here.
|
||||
|
||||
**RSA-2048 (2021).** The re-run of its cost script reproduces every row of its
|
||||
Table 3 to the digits it prints, which it takes up to two, and its Table 1's
|
||||
Toffoli count. Its title's 8 hours is the re-run's 7.31 hours expected across
|
||||
retries, taken up to one digit. Its hand-worked §2.14 (23 million qubits)
|
||||
rounds as it goes and says so. Its §2.12 reads a 6.4% distillation error from
|
||||
an earlier paper's spreadsheet where its own script's formula gives 0.6%. Our
|
||||
estimate job, given the same counts, finds the same code distance but takes 12
|
||||
times as long: it prices the planar architecture of arXiv:2211.07629, three
|
||||
logical steps of `d` cycles a Toffoli, and has no reaction-limited clock. That
|
||||
clock is in `quantum_arch` (**our limit** in the job).
|
||||
|
||||
**FeMoCo.** Its floorplan, factory, Toffoli rate and 3 days come back on the
|
||||
same clock; its §IV.C.5 says 3.5 days where §IV.C.4 says 3. The estimate job
|
||||
again runs at the beat.
|
||||
|
||||
**RSA-2048 (2025).** As `quantum_arch` documents: its stated durations give
|
||||
10.6 hours a shot where it prints 12.07, its hot-storage counts disagree with
|
||||
its own formula, and so on. Its Toffoli count comes back.
|
||||
|
||||
**The planar model's source** comes back whole.
|
||||
|
||||
## What this does not do
|
||||
|
||||
- **The estimate job has no reaction-limited clock.** It prices the planar
|
||||
architecture, and a laid-out machine that teleports its fixups takes about
|
||||
a tenth of the time the job gives. `quantum_arch` has that clock; the job
|
||||
does not offer it.
|
||||
- **The bicycle machine is not scheduled.** A rotation's time is the mean of
|
||||
its parts, a few percent under the paper's compiled critical path, and
|
||||
repeated in-module measurements are not removed.
|
||||
- **The bicycle rates are the paper's.** No decoder here has run its
|
||||
instructions; its fits extrapolate far below what any simulation reaches,
|
||||
and its two-gross measurement rates are assumed without data.
|
||||
- **No third-party code runs here.** The paper's released compiler would
|
||||
settle the open gross rows.
|
||||
|
||||
## The rows
|
||||
|
||||
<!-- the rows: written by `--example published_architectures --markdown`; a test holds them -->
|
||||
|
||||
### The bicycle machine: its parts
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| gross: code block `c`, by `2n` | arXiv:2506.03094 Table 1 | 288 | 288 | 0 | agrees | |
|
||||
| gross: processing unit `u`, as tallied | arXiv:2506.03094 Table 1 | 90 | 90 | 0 | agrees | |
|
||||
| gross: adapter `a`, by `2(d−1)` | arXiv:2506.03094 Table 1 | 22 | 22 | 0 | agrees | |
|
||||
| two-gross: code block `c`, by `2n` | arXiv:2506.03094 Table 1 | 576 | 576 | 0 | agrees | |
|
||||
| two-gross: processing unit `u`, as tallied | arXiv:2506.03094 Table 1 | 158 | 158 | 0 | agrees | |
|
||||
| two-gross: adapter `a`, by `2(d−1)` | arXiv:2506.03094 Table 1 | 34 | 34 | 0 | agrees | |
|
||||
| 10⁻³ gross factory: adapter `a′`, by `2d−1` | arXiv:2506.03094 Table 3 | 29 | 29 | 0 | agrees | |
|
||||
| 10⁻³ two-gross factory: adapter `a′`, by `2d−1` | arXiv:2506.03094 Table 3 | 29 | 29 | 0 | agrees | |
|
||||
| 10⁻⁴ gross factory: adapter `a′`, by `2d−1` | arXiv:2506.03094 Table 3 | 13 | 13 | 0 | agrees | |
|
||||
| 10⁻⁴ two-gross factory: adapter `a′`, by `2d−1` | arXiv:2506.03094 Table 3 | 49 | 49 | 0 | agrees | |
|
||||
| logical qubits in 5,000 physical qubits, gross, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a) | 121 | 121 | 0 | agrees | |
|
||||
| logical qubits in 50,000 physical qubits, two-gross, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a) | 704 | 704 | 0 | agrees | |
|
||||
| logical qubits in 5,000 physical qubits, gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a) | 110 | 110 | 0 | agrees | |
|
||||
| logical qubits in 50,000 physical qubits, gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a) | 1,342 | 1,342 | 0 | agrees | |
|
||||
| logical qubits in 50,000 physical qubits, two-gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a) | 440 | 440 | 0 | agrees | |
|
||||
| logical qubits in 500,000 physical qubits, two-gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a) | 6,886 | 6,886 | 0 | agrees | |
|
||||
|
||||
### The bicycle machine: logical error rates
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| gross `P_I` at p = 10⁻³ | arXiv:2506.03094 Table 10 | 1.6·10⁻⁹ | 1.61e-9 | +0.36% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_U` at p = 10⁻³ | arXiv:2506.03094 Table 10 | 4.0·10⁻⁷ | 4.01e-7 | +0.22% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_M` at p = 10⁻³ | arXiv:2506.03094 Table 10 | 1.1·10⁻⁵ | 1.11e-5 | +0.72% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_C` at p = 10⁻³ | arXiv:2506.03094 Table 10 | 2.0·10⁻³ | 2.01e-3 | +0.66% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_I` at p = 10⁻⁴ | arXiv:2506.03094 Table 10 | 1.4·10⁻¹⁵ | 1.44e-15 | +2.93% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_U` at p = 10⁻⁴ | arXiv:2506.03094 Table 10 | 6.1·10⁻¹³ | 6.07e-13 | -0.45% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_M` at p = 10⁻⁴ | arXiv:2506.03094 Table 10 | 1.0·10⁻⁹ | 1.01e-9 | +1.43% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_C` at p = 10⁻⁴ | arXiv:2506.03094 Table 10 | 4.8·10⁻⁸ | 4.81e-8 | +0.24% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_I` at p = 5·10⁻⁵ | arXiv:2506.03094 Table 10 | 4.5·10⁻¹⁷ | 4.46e-17 | -0.99% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_U` at p = 5·10⁻⁵ | arXiv:2506.03094 Table 10 | 2.2·10⁻¹⁴ | 2.16e-14 | -1.63% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_M` at p = 5·10⁻⁵ | arXiv:2506.03094 Table 10 | 5.7·10⁻¹¹ | 5.74e-11 | +0.70% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_C` at p = 5·10⁻⁵ | arXiv:2506.03094 Table 10 | 2.8·10⁻⁹ | 2.79e-9 | -0.41% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_I` at p = 3·10⁻⁵ | arXiv:2506.03094 Table 10 | 3.5·10⁻¹⁸ | 3.54e-18 | +1.02% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_U` at p = 3·10⁻⁵ | arXiv:2506.03094 Table 10 | 1.9·10⁻¹⁵ | 1.92e-15 | +0.92% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_M` at p = 3·10⁻⁵ | arXiv:2506.03094 Table 10 | 5.9·10⁻¹² | 5.90e-12 | +0.07% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_C` at p = 3·10⁻⁵ | arXiv:2506.03094 Table 10 | 3.2·10⁻¹⁰ | 3.18e-10 | -0.73% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_I` at p = 10⁻⁵ | arXiv:2506.03094 Table 10 | 1.5·10⁻²⁰ | 1.51e-20 | +0.62% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_U` at p = 10⁻⁵ | arXiv:2506.03094 Table 10 | 9.5·10⁻¹⁸ | 9.53e-18 | +0.29% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_M` at p = 10⁻⁵ | arXiv:2506.03094 Table 10 | 3.3·10⁻¹⁴ | 3.29e-14 | -0.28% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross `P_C` at p = 10⁻⁵ | arXiv:2506.03094 Table 10 | 2.1·10⁻¹² | 2.10e-12 | +0.03% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| two-gross `P_I` at p = 10⁻³ | arXiv:2506.03094 Table 10 | 8.2·10⁻²¹ | 8.13e-21 | -0.84% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| two-gross `P_U` at p = 10⁻³ | arXiv:2506.03094 Table 10 | 3.3·10⁻¹⁵ | 3.24e-15 | -1.71% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| two-gross `P_I` at p = 10⁻⁴ | arXiv:2506.03094 Table 10 | 5.4·10⁻³⁹ | 5.39e-39 | -0.23% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| two-gross `P_U` at p = 10⁻⁴ | arXiv:2506.03094 Table 10 | 1.3·10⁻³⁷ | 1.34e-37 | +3.07% | agrees | Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit. |
|
||||
| gross idle, one syndrome cycle, p = 10⁻³ | arXiv:2506.03094 §A.7 against Table 2 | 10^−8.8 | 1.61e-10 | ×0.101 | their numbers | §A.7 says an idle's or a shift's rate is the simulated circuit's failure divided by its C cycles. Table 2 and Table 10 print the circuit's failure undivided: Table 6's fits give them so. Ours divides, as the text says, and is lower by C (10 for gross, 18 for two-gross). |
|
||||
| two-gross idle, one syndrome cycle, p = 10⁻³ | arXiv:2506.03094 §A.7 against Table 2 | 10^−20.1 | 4.52e-22 | ×0.057 | their numbers | §A.7 says an idle's or a shift's rate is the simulated circuit's failure divided by its C cycles. Table 2 and Table 10 print the circuit's failure undivided: Table 6's fits give them so. Ours divides, as the text says, and is lower by C (10 for gross, 18 for two-gross). |
|
||||
| gross automorphism, p = 10⁻³ | arXiv:2506.03094 §A.7 against Table 2 | 10^−6.4 | 4.01e-8 | ×0.101 | their numbers | §A.7 says an idle's or a shift's rate is the simulated circuit's failure divided by its C cycles. Table 2 and Table 10 print the circuit's failure undivided: Table 6's fits give them so. Ours divides, as the text says, and is lower by C (10 for gross, 18 for two-gross). |
|
||||
| gross memory per cycle, p = 10⁻³ | arXiv:2308.07915 Table 1, against arXiv:2506.03094 §A.7 | 2·10⁻⁷ | 1.61e-10 | ×8.0e-4 | open | Two papers on the same code at the same p. The earlier (decoded by BP-OSD) measures 2·10⁻⁷ a syndrome cycle for the gross code at 10⁻³; the later's fits (Relay-BP) give a circuit of C idle cycles, divided by C as its text says, 1.61e-10: a factor of about 1,246 (about 125 undivided). Their decoders, circuits and fitting differ, and which accounts for the factor is not found here. Ours takes the later's fits. |
|
||||
| gross memory per cycle, p = 10⁻⁴ | arXiv:2308.07915 Table 1, against arXiv:2506.03094 §A.7 | 8·10⁻¹³ | 1.44e-16 | ×1.8e-4 | open | Two papers on the same code at the same p. The earlier (decoded by BP-OSD) measures 2·10⁻⁷ a syndrome cycle for the gross code at 10⁻³; the later's fits (Relay-BP) give a circuit of C idle cycles, divided by C as its text says, 1.61e-10: a factor of about 1,246 (about 125 undivided). Their decoders, circuits and fitting differ, and which accounts for the factor is not found here. Ours takes the later's fits. |
|
||||
| two-gross memory per cycle, p = 10⁻³ | arXiv:2308.07915 Table 1, against arXiv:2506.03094 §A.7 | 2·10⁻¹² | 4.52e-22 | ×2.3e-10 | open | Two papers on the same code at the same p. The earlier (decoded by BP-OSD) measures 2·10⁻⁷ a syndrome cycle for the gross code at 10⁻³; the later's fits (Relay-BP) give a circuit of C idle cycles, divided by C as its text says, 1.61e-10: a factor of about 1,246 (about 125 undivided). Their decoders, circuits and fitting differ, and which accounts for the factor is not found here. Ours takes the later's fits. |
|
||||
| two-gross memory per cycle, p = 10⁻⁴ | arXiv:2308.07915 Table 1, against arXiv:2506.03094 §A.7 | 1·10⁻²² | 2.99e-40 | ×3.0e-18 | open | Two papers on the same code at the same p. The earlier (decoded by BP-OSD) measures 2·10⁻⁷ a syndrome cycle for the gross code at 10⁻³; the later's fits (Relay-BP) give a circuit of C idle cycles, divided by C as its text says, 1.61e-10: a factor of about 1,246 (about 125 undivided). Their decoders, circuits and fitting differ, and which accounts for the factor is not found here. Ours takes the later's fits. |
|
||||
|
||||
### The bicycle machine: the compile
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| native measurements | arXiv:2506.03094 §3.2 | 540 | 540 | 0 | agrees | |
|
||||
| any shift, in generators, at most | arXiv:2506.03094 §1.2 | 2 | 2 | 0 | agrees | |
|
||||
| native rotations | arXiv:2506.03094 §3.2 | 510 | 245 | ×0.480 | their numbers | §3.2 defines a native rotation by a native measurement Q ⊗ R with Q one of X, Y, Z on the pivot: there are 245 such R. Over all the native measurements there are 510 distinct R ≠ I: 284 occur with Q = I, 19 of them also with Q ≠ I. That its 510 counts those is our inference from the matching count. Fig. 9's first bin holds 245. |
|
||||
| mean in-module measurements per Pauli, pivot basis chosen, gross | arXiv:2506.03094 Fig. 9 caption, right | 18.48 | 18.526 | +0.25% | their numbers | Our search runs from the printed polynomials, basis and native set, over the 4¹¹ − 1 Paulis (4¹² − 1 with the pivot fixed). The authors' released compiler, bicycle_cliffords 0.1.0 (crates.io, 2025-07-31), takes a shift's action in src/measurement.rs as A on X̄ and A⁻¹ on Z̄, on both halves of a module; taken so, our search gives the source's four means to every printed digit (a test in quantum_bicycle holds this). A CNOT circuit |x⟩ → |Ax⟩ takes Z̄ by A⁻ᵀ, which is how the operators move and what ours follows; its version 0.2.1 takes X̄ by A⁻¹ and Z̄ by Aᵀ, a consistent pair. The difference moves a capability here by under 0.6%. |
|
||||
| the same, two-gross | arXiv:2506.03094 Fig. 9 caption, right | 18.58 | 18.482 | -0.53% | their numbers | Our search runs from the printed polynomials, basis and native set, over the 4¹¹ − 1 Paulis (4¹² − 1 with the pivot fixed). The authors' released compiler, bicycle_cliffords 0.1.0 (crates.io, 2025-07-31), takes a shift's action in src/measurement.rs as A on X̄ and A⁻¹ on Z̄, on both halves of a module; taken so, our search gives the source's four means to every printed digit (a test in quantum_bicycle holds this). A CNOT circuit |x⟩ → |Ax⟩ takes Z̄ by A⁻ᵀ, which is how the operators move and what ours follows; its version 0.2.1 takes X̄ by A⁻¹ and Z̄ by Aᵀ, a consistent pair. The difference moves a capability here by under 0.6%. |
|
||||
| mean in-module measurements per Pauli, pivot basis fixed, gross | arXiv:2506.03094 Fig. 9 caption, left | 18.55 | 18.593 | +0.23% | their numbers | Our search runs from the printed polynomials, basis and native set, over the 4¹¹ − 1 Paulis (4¹² − 1 with the pivot fixed). The authors' released compiler, bicycle_cliffords 0.1.0 (crates.io, 2025-07-31), takes a shift's action in src/measurement.rs as A on X̄ and A⁻¹ on Z̄, on both halves of a module; taken so, our search gives the source's four means to every printed digit (a test in quantum_bicycle holds this). A CNOT circuit |x⟩ → |Ax⟩ takes Z̄ by A⁻ᵀ, which is how the operators move and what ours follows; its version 0.2.1 takes X̄ by A⁻¹ and Z̄ by Aᵀ, a consistent pair. The difference moves a capability here by under 0.6%. |
|
||||
| the same, two-gross | arXiv:2506.03094 Fig. 9 caption, left | 18.67 | 18.561 | -0.58% | their numbers | Our search runs from the printed polynomials, basis and native set, over the 4¹¹ − 1 Paulis (4¹² − 1 with the pivot fixed). The authors' released compiler, bicycle_cliffords 0.1.0 (crates.io, 2025-07-31), takes a shift's action in src/measurement.rs as A on X̄ and A⁻¹ on Z̄, on both halves of a module; taken so, our search gives the source's four means to every printed digit (a test in quantum_bicycle holds this). A CNOT circuit |x⟩ → |Ax⟩ takes Z̄ by A⁻ᵀ, which is how the operators move and what ours follows; its version 0.2.1 takes X̄ by A⁻¹ and Z̄ by Aᵀ, a consistent pair. The difference moves a capability here by under 0.6%. |
|
||||
|
||||
### The bicycle machine: what a machine of a given size can run
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| T count at failure ⅓, 5,000 physical qubits, gross, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), source files | 13.5958 | 1.365e1 | +0.42% | assumption | Ours divides P_I and P_U by C, as §A.7's text says (the rates section); with them undivided, as Table 10 prints them, ours is 1.361e1 (next row). That choice is +0.30% of the difference, and the sampling below +0.12%. |
|
||||
| the same, P_I and P_U undivided, as Table 10 prints them, 5,000 physical qubits, gross, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), source files | 13.5958 | 1.361e1 | +0.12% | their model | Theirs samples eight random circuits of up to 10⁵ rotations and extends a straight-line fit (Fig. 17); ours is the expected count, at the rates as the tables print them. |
|
||||
| timesteps per T, 5,000 physical qubits, gross, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), source files | 3367.15 | 3190.77 | -5.24% | our limit | Theirs is the critical path of a compiled schedule; ours adds the mean time of a rotation's parts, with no scheduling. Ours runs a few percent low, more where a compiler takes more shifts than the fewest. |
|
||||
| T count at failure ⅓, 50,000 physical qubits, two-gross, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), source files | 3.4712·10⁶ | 3.478e6 | +0.21% | their model | Theirs samples eight random circuits of up to 10⁵ rotations and extends a straight-line fit (Fig. 17); ours is the expected count, at the rates as the tables print them. Our division of P_I and P_U by C, as §A.7's text says, is +0.00% of it (next row: undivided). |
|
||||
| the same, P_I and P_U undivided, as Table 10 prints them, 50,000 physical qubits, two-gross, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), source files | 3.4712·10⁶ | 3.478e6 | +0.20% | their model | Theirs samples eight random circuits of up to 10⁵ rotations and extends a straight-line fit (Fig. 17); ours is the expected count, at the rates as the tables print them. |
|
||||
| timesteps per T, 50,000 physical qubits, two-gross, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), source files | 7057.34 | 7060.97 | +0.05% | our limit | Theirs is the critical path of a compiled schedule; ours adds the mean time of a rotation's parts, with no scheduling. Ours runs a few percent low, more where a compiler takes more shifts than the fewest. |
|
||||
| T count at failure ⅓, 5,000 physical qubits, gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 2.2209·10⁵ | 4.701e5 | ×2.117 | open | Its two gross rows at this p need a failure per rotation of 6.70·10⁻⁸ per module (ours: 6.69·10⁻⁸) plus 8.3·10⁻⁷ whatever the machine's size. Ours has 4·10⁻⁸ there: Table 3's factory, an injection's inter-module measurement and one link fewer. Nothing the paper prints accounts for the other 7.9·10⁻⁷. Its authors' compiler is released (bicycle_compiler 0.1.0 on crates.io): its capability estimate at these two machines would settle it; this check does not run it. |
|
||||
| the same, P_I and P_U undivided, as Table 10 prints them, 5,000 physical qubits, gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 2.2209·10⁵ | 4.700e5 | ×2.116 | open | Its two gross rows at this p need a failure per rotation of 6.70·10⁻⁸ per module (ours: 6.69·10⁻⁸) plus 8.3·10⁻⁷ whatever the machine's size. Ours has 4·10⁻⁸ there: Table 3's factory, an injection's inter-module measurement and one link fewer. Nothing the paper prints accounts for the other 7.9·10⁻⁷. Its authors' compiler is released (bicycle_compiler 0.1.0 on crates.io): its capability estimate at these two machines would settle it; this check does not run it. |
|
||||
| timesteps per T, 5,000 physical qubits, gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 3090.55 | 2912.77 | -5.75% | our limit | Theirs is the critical path of a compiled schedule; ours adds the mean time of a rotation's parts, with no scheduling. Ours runs a few percent low, more where a compiler takes more shifts than the fewest. |
|
||||
| T count at failure ⅓, 50,000 physical qubits, gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 3.7033·10⁴ | 4.064e4 | +9.73% | open | Its two gross rows at this p need a failure per rotation of 6.70·10⁻⁸ per module (ours: 6.69·10⁻⁸) plus 8.3·10⁻⁷ whatever the machine's size. Ours has 4·10⁻⁸ there: Table 3's factory, an injection's inter-module measurement and one link fewer. Nothing the paper prints accounts for the other 7.9·10⁻⁷. Its authors' compiler is released (bicycle_compiler 0.1.0 on crates.io): its capability estimate at these two machines would settle it; this check does not run it. |
|
||||
| the same, P_I and P_U undivided, as Table 10 prints them, 50,000 physical qubits, gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 3.7033·10⁴ | 4.063e4 | +9.71% | open | Its two gross rows at this p need a failure per rotation of 6.70·10⁻⁸ per module (ours: 6.69·10⁻⁸) plus 8.3·10⁻⁷ whatever the machine's size. Ours has 4·10⁻⁸ there: Table 3's factory, an injection's inter-module measurement and one link fewer. Nothing the paper prints accounts for the other 7.9·10⁻⁷. Its authors' compiler is released (bicycle_compiler 0.1.0 on crates.io): its capability estimate at these two machines would settle it; this check does not run it. |
|
||||
| timesteps per T, 50,000 physical qubits, gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 3135.16 | 2912.77 | -7.09% | our limit | Theirs is the critical path of a compiled schedule; ours adds the mean time of a rotation's parts, with no scheduling. Ours runs a few percent low, more where a compiler takes more shifts than the fewest. |
|
||||
| T count at failure ⅓, 50,000 physical qubits, two-gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 7.0154·10¹⁵ | 7.033e15 | +0.26% | their model | Theirs samples eight random circuits of up to 10⁵ rotations and extends a straight-line fit (Fig. 17); ours is the expected count, at the rates as the tables print them. Our division of P_I and P_U by C, as §A.7's text says, is +0.00% of it (next row: undivided). |
|
||||
| the same, P_I and P_U undivided, as Table 10 prints them, 50,000 physical qubits, two-gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 7.0154·10¹⁵ | 7.033e15 | +0.26% | their model | Theirs samples eight random circuits of up to 10⁵ rotations and extends a straight-line fit (Fig. 17); ours is the expected count, at the rates as the tables print them. |
|
||||
| timesteps per T, 50,000 physical qubits, two-gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 5435.87 | 5300.97 | -2.48% | our limit | Theirs is the critical path of a compiled schedule; ours adds the mean time of a rotation's parts, with no scheduling. Ours runs a few percent low, more where a compiler takes more shifts than the fewest. |
|
||||
| T count at failure ⅓, 500,000 physical qubits, two-gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 4.4830·10¹⁴ | 4.494e14 | +0.25% | their model | Theirs samples eight random circuits of up to 10⁵ rotations and extends a straight-line fit (Fig. 17); ours is the expected count, at the rates as the tables print them. Our division of P_I and P_U by C, as §A.7's text says, is +0.00% of it (next row: undivided). |
|
||||
| the same, P_I and P_U undivided, as Table 10 prints them, 500,000 physical qubits, two-gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 4.4830·10¹⁴ | 4.494e14 | +0.25% | their model | Theirs samples eight random circuits of up to 10⁵ rotations and extends a straight-line fit (Fig. 17); ours is the expected count, at the rates as the tables print them. |
|
||||
| timesteps per T, 500,000 physical qubits, two-gross, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), source files | 5436.91 | 5300.97 | -2.50% | our limit | Theirs is the critical path of a compiled schedule; ours adds the mean time of a rotation's parts, with no scheduling. Ours runs a few percent low, more where a compiler takes more shifts than the fewest. |
|
||||
| surface code: logical qubits, 5,000 qubits, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), §A.10 | 45 | 45 | 0 | agrees | |
|
||||
| surface code: T count, its formula, 5,000 qubits, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), §A.10 | 7 | 7 | 0 | agrees | §A.10's formula for the surface-code row, evaluated as it states it: the largest whole T count. |
|
||||
| surface code: T count, our code model, 5,000 qubits, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), §A.10 | 7 | 1.23e2 | ×17.637 | their model | Our planar model takes `0.03·(p/p*)^((d+1)/2)` per patch per `d` cycles, as arXiv:2211.07629 does. §A.10 takes `0.03·(p/p*)^(d/2)` per cycle, times `d` cycles: higher by `d·√(p*/p)`. |
|
||||
| surface code: timesteps per T, 5,000 qubits, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a) | 381 | 381 | 0 | agrees | §A.10: the factory's timesteps (Table 3) and the lattice surgery's 6d. |
|
||||
| surface code: logical qubits, 50,000 qubits, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), §A.10 | 42 | 42 | 0 | agrees | |
|
||||
| surface code: T count, its formula, 50,000 qubits, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), §A.10 | 2.5·10⁶ | 2.46e6 | -1.58% | agrees | §A.10's formula for the surface-code row, evaluated as it states it: the largest whole T count. |
|
||||
| surface code: T count, our code model, 50,000 qubits, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a), §A.10 | 2.5·10⁶ | 1.32e8 | ×52.910 | their model | Our planar model takes `0.03·(p/p*)^((d+1)/2)` per patch per `d` cycles, as arXiv:2211.07629 does. §A.10 takes `0.03·(p/p*)^(d/2)` per cycle, times `d` cycles: higher by `d·√(p*/p)`. |
|
||||
| surface code: timesteps per T, 50,000 qubits, p = 10⁻³ | arXiv:2506.03094 Fig. 10(a) | 2,269 | 2,269 | 0 | agrees | §A.10: the factory's timesteps (Table 3) and the lattice surgery's 6d. |
|
||||
| surface code: logical qubits, 5,000 qubits, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), §A.10 | 21 | 21 | 0 | agrees | |
|
||||
| surface code: T count, its formula, 5,000 qubits, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), §A.10 | 377,928 | 377,928 | 0 | agrees | §A.10's formula for the surface-code row, evaluated as it states it: the largest whole T count. |
|
||||
| surface code: T count, our code model, 5,000 qubits, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a), §A.10 | 377,928 | 2.65e7 | ×70.000 | their model | Our planar model takes `0.03·(p/p*)^((d+1)/2)` per patch per `d` cycles, as arXiv:2211.07629 does. §A.10 takes `0.03·(p/p*)^(d/2)` per cycle, times `d` cycles: higher by `d·√(p*/p)`. |
|
||||
| surface code: timesteps per T, 5,000 qubits, p = 10⁻⁴ | arXiv:2506.03094 Fig. 10(a) | 115 | 115 | 0 | agrees | §A.10: the factory's timesteps (Table 3) and the lattice surgery's 6d. |
|
||||
| surface code: logical qubits, 50,000 qubits, p = 10⁻⁴, d = 7 | arXiv:2506.03094 Fig. 10(a), §A.10 | 250 | 250 | 0 | agrees | |
|
||||
| surface code: T count, its formula, 50,000 qubits, p = 10⁻⁴, d = 7 | arXiv:2506.03094 Fig. 10(a), §A.10 | 31,746 | 31,746 | 0 | agrees | §A.10's formula for the surface-code row, evaluated as it states it: the largest whole T count. |
|
||||
| surface code: T count, our code model, 50,000 qubits, p = 10⁻⁴, d = 7 | arXiv:2506.03094 Fig. 10(a), §A.10 | 31,746 | 2.22e6 | ×70.000 | their model | Our planar model takes `0.03·(p/p*)^((d+1)/2)` per patch per `d` cycles, as arXiv:2211.07629 does. §A.10 takes `0.03·(p/p*)^(d/2)` per cycle, times `d` cycles: higher by `d·√(p*/p)`. |
|
||||
| surface code: timesteps per T, 50,000 qubits, p = 10⁻⁴, d = 7 | arXiv:2506.03094 Fig. 10(a) | 115 | 115 | 0 | agrees | §A.10: the factory's timesteps (Table 3) and the lattice surgery's 6d. |
|
||||
| surface code: logical qubits, 50,000 qubits, p = 10⁻⁴, d = 17 | arXiv:2506.03094 Fig. 10(a), §A.10 | 27 | 27 | 0 | agrees | |
|
||||
| surface code: T count, its formula, 50,000 qubits, p = 10⁻⁴, d = 17 | arXiv:2506.03094 Fig. 10(a), §A.10 | 1.2·10¹⁵ | 1.21e15 | +0.86% | agrees | §A.10's formula for the surface-code row, evaluated as it states it: the largest whole T count. |
|
||||
| surface code: T count, our code model, 50,000 qubits, p = 10⁻⁴, d = 17 | arXiv:2506.03094 Fig. 10(a), §A.10 | 1.2·10¹⁵ | 2.06e17 | ×1.7e2 | their model | Our planar model takes `0.03·(p/p*)^((d+1)/2)` per patch per `d` cycles, as arXiv:2211.07629 does. §A.10 takes `0.03·(p/p*)^(d/2)` per cycle, times `d` cycles: higher by `d·√(p*/p)`. |
|
||||
| surface code: timesteps per T, 50,000 qubits, p = 10⁻⁴, d = 17 | arXiv:2506.03094 Fig. 10(a) | 509 | 509 | 0 | agrees | §A.10: the factory's timesteps (Table 3) and the lattice surgery's 6d. |
|
||||
| surface code: logical qubits, 500,000 qubits, p = 10⁻⁴, d = 17 | arXiv:2506.03094 Fig. 10(a), §A.10 | 416 | 416 | 0 | agrees | |
|
||||
| surface code: T count, its formula, 500,000 qubits, p = 10⁻⁴, d = 17 | arXiv:2506.03094 Fig. 10(a), §A.10 | 7.9·10¹³ | 7.86e13 | -0.56% | agrees | §A.10's formula for the surface-code row, evaluated as it states it: the largest whole T count. |
|
||||
| surface code: T count, our code model, 500,000 qubits, p = 10⁻⁴, d = 17 | arXiv:2506.03094 Fig. 10(a), §A.10 | 7.9·10¹³ | 1.34e16 | ×1.7e2 | their model | Our planar model takes `0.03·(p/p*)^((d+1)/2)` per patch per `d` cycles, as arXiv:2211.07629 does. §A.10 takes `0.03·(p/p*)^(d/2)` per cycle, times `d` cycles: higher by `d·√(p*/p)`. |
|
||||
| surface code: timesteps per T, 500,000 qubits, p = 10⁻⁴, d = 17 | arXiv:2506.03094 Fig. 10(a) | 509 | 509 | 0 | agrees | §A.10: the factory's timesteps (Table 3) and the lattice surgery's 6d. |
|
||||
|
||||
### The bicycle machine: the 10 × 10 Ising model
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| physical qubits, two-gross | arXiv:2506.03094 §4 | 8,138 | 8,138 | 0 | agrees | |
|
||||
| physical qubits, gross | arXiv:2506.03094 §4 | 4,817 | 4,801 | -0.33% | their numbers | §4 names the 10⁻⁴ gross factory, whose adapter is 13 qubits (Table 3). 4,817 takes the 29 of the 10⁻³ factory. |
|
||||
| rotations | arXiv:2506.03094 §A.10 | 184,000 | 184,000 | 0 | agrees | |
|
||||
| inter-module measurements `N_C`, gross | arXiv:2506.03094 Table 9 | 9.4680·10⁵ | 946,800 | 0 | assumption | Sites in order and the factory after the last module give the paper's count; before the first module, 781,200. The paper prints neither, and this is the end chosen to match it: the one choice in this check made to fit a published figure. |
|
||||
| the same on two-gross | arXiv:2506.03094 Table 9 | 9.4680·10⁵ | 946,800 | 0 | assumption | Sites in order and the factory after the last module give the paper's count; before the first module, 781,200. The paper prints neither, and this is the end chosen to match it: the one choice in this check made to fit a published figure. |
|
||||
| in-module measurements `N_M`, gross | arXiv:2506.03094 Table 9, source files | 4,215,240 | 4,283,200 | +1.61% | our limit | Ours removes no repeated in-module measurement, which theirs does (§4), and takes sites in order, which it does not print. Its counts also carry the compile section's action of a shift on Z̄, which puts its gross below its two-gross; ours has them the other way round. |
|
||||
| in-module measurements `N_M`, two-gross | arXiv:2506.03094 Table 9, source files | 4,238,828 | 4,148,800 | -2.12% | our limit | Ours removes no repeated in-module measurement, which theirs does (§4), and takes sites in order, which it does not print. Its counts also carry the compile section's action of a shift on Z̄, which puts its gross below its two-gross; ours has them the other way round. |
|
||||
| automorphisms `N_U`, gross | arXiv:2506.03094 Table 9, source files | 2,270,400 | 2,728,800 | +20.19% | our limit | Ours takes the fewest shifts on a path of fewest measurements, and merges none; theirs is a compiler's. |
|
||||
| automorphisms `N_U`, two-gross | arXiv:2506.03094 Table 9, source files | 2,294,400 | 2,368,000 | +3.21% | our limit | Ours takes the fewest shifts on a path of fewest measurements, and merges none; theirs is a compiler's. |
|
||||
| T injections `N_T` | arXiv:2506.03094 Table 9, source files | 15,542,400 | 14,665,600 | -5.64% | their model | pygridsynth 1.0.1, the version the source cites, run on the program's four angles at ε = 5·10⁻⁹, gives 86, 80, 84 and 82 T gates, which make 15,542,400 exactly; it approximates the rotation itself. Ours, the same Ross–Selinger method, gives 79, 80, 81 and 84, and also searches the class one global phase e^(iπ/8) away, which a rotation of the pivot allows. |
|
||||
| T injections as §4 and Fig. 1(b) state | arXiv:2506.03094 §4; Fig. 1(b), source files | 1.9·10⁷ (Fig. 1(b): 19,036,800) | 14,665,600 | -22.96% | their numbers | §4 says N_T = 1.9·10⁷ and Fig. 1(b) plots 19,036,800. Table 9 and every failure probability of Table 10 take 15,542,400, which the row above compares ours with. |
|
||||
| idles `N_I`, two-gross, from its `N_T` | arXiv:2506.03094 Table 9, source files | 41,636,714,298 | 42,100,476,000 | +1.11% | our limit | Ours: every module idles while the factory works, and otherwise never. Theirs counts the idles of its schedule. |
|
||||
| failure probability, gross, p = 10⁻³, its counts | arXiv:2506.03094 Table 10 | 3.33·10⁴ | 3.331e4 | +0.03% | agrees | Table 9's counts at our evaluation of Table 6's fits (Eq. (26)); the band moves the fits' parameters by their last printed digit. |
|
||||
| failure probability, gross, p = 10⁻⁴, its counts | arXiv:2506.03094 Table 10 | 7.97·10⁻¹ | 7.977e-1 | +0.09% | agrees | Table 9's counts at our evaluation of Table 6's fits (Eq. (26)); the band moves the fits' parameters by their last printed digit. |
|
||||
| failure probability, gross, p = 5·10⁻⁵, its counts | arXiv:2506.03094 Table 10 | 4.62·10⁻² | 4.622e-2 | +0.05% | agrees | Table 9's counts at our evaluation of Table 6's fits (Eq. (26)); the band moves the fits' parameters by their last printed digit. |
|
||||
| failure probability, gross, p = 3·10⁻⁵, its counts | arXiv:2506.03094 Table 10 | 5.27·10⁻³ | 5.263e-3 | -0.14% | agrees | Table 9's counts at our evaluation of Table 6's fits (Eq. (26)); the band moves the fits' parameters by their last printed digit. |
|
||||
| failure probability, gross, p = 10⁻⁵, its counts | arXiv:2506.03094 Table 10 | 3.48·10⁻⁵ | 3.478e-5 | -0.07% | agrees | Table 9's counts at our evaluation of Table 6's fits (Eq. (26)); the band moves the fits' parameters by their last printed digit. |
|
||||
| failure probability, two-gross, p = 10⁻³, its counts | arXiv:2506.03094 Table 10 | 1.65·10⁻² | 1.653e-2 | +0.19% | agrees | Table 9's counts at our evaluation of Table 6's fits (Eq. (26)); the band moves the fits' parameters by their last printed digit. |
|
||||
| failure probability, two-gross, p = 10⁻⁴, its counts | arXiv:2506.03094 Table 10 | 1.65·10⁻¹¹ | 1.653e-11 | +0.19% | agrees | Table 9's counts at our evaluation of Table 6's fits (Eq. (26)); the band moves the fits' parameters by their last printed digit. |
|
||||
| failure probability, two-gross, p = 10⁻³, a T injection at its factory | arXiv:2506.03094 Table 10 | 1.65·10⁻² | 3.274e-1 | ×19.841 | their model | Table 10 sets `P_T = P_C` ("the T factory can be chosen to distill states of sufficient fidelity") and §4 neglects the factory. At the factory it allocates, Table 3's 2·10⁻⁸, the T injections alone fail with 0.31. |
|
||||
| physical error rate for failure 10⁻³, two-gross | arXiv:2506.03094 §A.10 | 7.32·10⁻⁴ | 7.322e-4 | +0.03% | agrees | Its power law through two of its points of Table 10, solved for a failure of 10⁻³; the band moves the fits' parameters by their last printed digit. |
|
||||
| physical error rate for failure 10⁻³, gross | arXiv:2506.03094 §A.10 | 2.09·10⁻⁵ | 2.086e-5 | -0.20% | agrees | Its power law through two of its points of Table 10, solved for a failure of 10⁻³; the band moves the fits' parameters by their last printed digit. |
|
||||
| surface code, d = 9: physical error rate, Eq. (96) | arXiv:2506.03094 §A.10, Eq. (96) | 5.48·10⁻⁵ | 5.476e-5 | -0.07% | agrees | With §4's N_T of 19,036,800. §4 prints it truncated to two digits. |
|
||||
| surface code, d = 9: physical error rate, our code model | arXiv:2506.03094 §A.10, Eq. (96) | 5.48·10⁻⁵ | 1.430e-4 | ×2.610 | their model | As in the capability section: a patch's error per `d` cycles, not a cycle's times `d`, and `(d+1)/2`. |
|
||||
| surface code, d = 9: physical qubits | arXiv:2506.03094 §4, Fig. 10(b) | 17,010 | 33,210 | +95.24% | their numbers | §4 and Fig. 10(b) count `2d²` a logical qubit. Eq. (96) puts `2n` patches in each rotation, and §A.10's capability comparison reserves half the patches for routing: `4d²`. Ours is `4d²`. |
|
||||
| surface code, d = 17: physical error rate, Eq. (96) | arXiv:2506.03094 §A.10, Eq. (96) | 5.89·10⁻⁴ | 5.892e-4 | +0.03% | agrees | With §4's N_T of 19,036,800. §4 prints it truncated to two digits. |
|
||||
| surface code, d = 17: physical error rate, our code model | arXiv:2506.03094 §A.10, Eq. (96) | 5.89·10⁻⁴ | 9.446e-4 | +60.38% | their model | As in the capability section: a patch's error per `d` cycles, not a cycle's times `d`, and `(d+1)/2`. |
|
||||
| surface code, d = 17: physical qubits | arXiv:2506.03094 §4, Fig. 10(b) | 58,263 | 116,063 | +99.21% | their numbers | §4 and Fig. 10(b) count `2d²` a logical qubit. Eq. (96) puts `2n` patches in each rotation, and §A.10's capability comparison reserves half the patches for routing: `4d²`. Ours is `4d²`. |
|
||||
| surface code, d = 19: physical error rate, Eq. (96) | arXiv:2506.03094 §A.10, Eq. (96) | 7.85·10⁻⁴ | 7.845e-4 | -0.06% | agrees | With §4's N_T of 19,036,800. §4 prints it truncated to two digits. |
|
||||
| surface code, d = 19: physical error rate, our code model | arXiv:2506.03094 §A.10, Eq. (96) | 7.85·10⁻⁴ | 1.196e-3 | +52.36% | their model | As in the capability section: a patch's error per `d` cycles, not a cycle's times `d`, and `(d+1)/2`. |
|
||||
| surface code, d = 19: physical qubits | arXiv:2506.03094 §4, Fig. 10(b) | 72,663 | 144,863 | +99.36% | their numbers | §4 and Fig. 10(b) count `2d²` a logical qubit. Eq. (96) puts `2n` patches in each rotation, and §A.10's capability comparison reserves half the patches for routing: `4d²`. Ours is `4d²`. |
|
||||
|
||||
### RSA-2048 on the surface code (arXiv:1905.09749, Quantum 5, 433, 2021)
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| physical qubits, re-run on its layout | arXiv:1905.09749 Table 3 | 20 (megaqubits) | 19,248,768 | -3.76% | agrees | Its script takes each figure up to two digits. |
|
||||
| hours per run, re-run | arXiv:1905.09749 Table 3 | 5.1 | 5.05 | -1.06% | agrees | Its script takes each figure up to two digits. |
|
||||
| retry risk, re-run | arXiv:1905.09749 Table 3 | 31% | 0.3098 | -0.08% | agrees | Its script takes it up to a whole percent. |
|
||||
| megaqubit-days per run, re-run | arXiv:1905.09749 Table 3 | 4.1 | 4.05 | -1.29% | agrees | Its script takes each figure up to two digits. |
|
||||
| Toffolis, re-run | arXiv:1905.09749 Table 1 | 2.7 (billions) | 2.698e9 | -0.06% | agrees | |
|
||||
| factories in each piece, re-run | arXiv:1905.09749 §2.10 | 14 | 14 | 0 | agrees | |
|
||||
| hours, expected across retries | arXiv:1905.09749 title | 8 hours | 7.31 | -8.62% | agrees | The re-run's 5.05 hours a run at its 30.98% retry risk is 7.31 hours expected; the title takes that up to one digit. |
|
||||
| physical qubits, its worked case, level-1 distance 17 | arXiv:1905.09749 §2.14 | "approximately 23 million" | 21,616,448 | -6.02% | their numbers | That section rounds as it goes, and says so: 226 × 63 patches, where the script's layout at these distances has 226 × 61. |
|
||||
| distillation error of 3·10⁹ CCZ states, distances 17 and 27 | arXiv:1905.09749 §2.12 | 6.4% | 0.0060 | ×0.094 | their numbers | That section reads a spreadsheet of an earlier paper. Its own script's formula, which produced its tables, gives 0.6%. |
|
||||
| code distance, job, assumed code model | arXiv:1905.09749 §2.13 (d = 27); its counts in the estimate job | 27 | 27 | 0 | agrees | |
|
||||
| code distance, job, code model fitted to our decoders | arXiv:1905.09749 §2.13 (d = 27); its counts in the estimate job | 27 | 27 | 0 | agrees | Our fit is `a = 0.0233, p* = 0.01004`, extrapolated from p = 0.002–0.005. |
|
||||
| physical qubits, job, assumed code model | arXiv:1905.09749 Table 3; its counts in the estimate job | 20 (megaqubits) | 18,906,836 | -5.47% | our limit | The job lays out `2N + √(8N) + 1` tiles of `2d²` qubits and T factories from 15-to-1; the source a board of `2(d+1)²`-qubit patches and CCZ factories, placed by hand. |
|
||||
| physical qubits, job, fitted code model | arXiv:1905.09749 Table 3; its counts in the estimate job | 20 (megaqubits) | 18,906,836 | -5.47% | our limit | The job lays out `2N + √(8N) + 1` tiles of `2d²` qubits and T factories from 15-to-1; the source a board of `2(d+1)²`-qubit patches and CCZ factories, placed by hand. |
|
||||
| physical qubits, the planar model on the source's patch and error rule | arXiv:1905.09749 Table 3; its counts in the estimate job | 20 (megaqubits) | 27,571,456 | +37.86% | our limit | The job lays out `2N + √(8N) + 1` tiles of `2d²` qubits and T factories from 15-to-1; the source a board of `2(d+1)²`-qubit patches and CCZ factories, placed by hand. |
|
||||
| hours per run, job, assumed code model | arXiv:1905.09749 Table 3; its counts in the estimate job | 5.1 | 60.71 | ×11.904 | our limit | The estimate job prices the planar architecture of arXiv:2211.07629: three logical steps of `d` cycles for each Toffoli. The source teleports a Toffoli's fixups away and runs an addition at one 10 µs tick a Toffoli. The job has no such clock; quantum_arch's (the re-run rows) does. |
|
||||
| hours per run, the planar model on the source's patch and error rule | arXiv:1905.09749 Table 3; its counts in the estimate job | 5.1 | 69.71 | ×13.668 | our limit | The estimate job prices the planar architecture of arXiv:2211.07629: three logical steps of `d` cycles for each Toffoli. The source teleports a Toffoli's fixups away and runs an addition at one 10 µs tick a Toffoli. The job has no such clock; quantum_arch's (the re-run rows) does. |
|
||||
| factories, job | arXiv:1905.09749 §2.10; its counts in the estimate job | 14 CCZ per piece, 28 in all | 16 T factories | — | our limit | A CCZ state costs four T states in the planar model. |
|
||||
| 1024 bits: megaqubits, re-run | arXiv:1905.09749 Table 3 | 9.7 | 9.62 | -0.78% | agrees | Its script takes each figure up to two digits. |
|
||||
| 1024 bits: hours per run, re-run | arXiv:1905.09749 Table 3 | 1.3 | 1.26 | -2.79% | agrees | Its script takes each figure up to two digits. |
|
||||
| 3072 bits: megaqubits, re-run | arXiv:1905.09749 Table 3 | 38 | 37.90 | -0.27% | agrees | Its script takes each figure up to two digits. |
|
||||
| 3072 bits: hours per run, re-run | arXiv:1905.09749 Table 3 | 12 | 11.61 | -3.28% | agrees | Its script takes each figure up to two digits. |
|
||||
| 4096 bits: megaqubits, re-run | arXiv:1905.09749 Table 3 | 55 | 54.62 | -0.70% | agrees | Its script takes each figure up to two digits. |
|
||||
| 4096 bits: hours per run, re-run | arXiv:1905.09749 Table 3 | 22 | 21.08 | -4.20% | agrees | Its script takes each figure up to two digits. |
|
||||
| 8192 bits: megaqubits, re-run | arXiv:1905.09749 Table 3 | 140 | 133.32 | -4.77% | agrees | Its script takes each figure up to two digits. |
|
||||
| 8192 bits: hours per run, re-run | arXiv:1905.09749 Table 3 | 86 | 85.54 | -0.53% | agrees | Its script takes each figure up to two digits. |
|
||||
| 12288 bits: megaqubits, re-run | arXiv:1905.09749 Table 3 | 200 | 199.98 | -0.01% | agrees | Its script takes each figure up to two digits. |
|
||||
| 12288 bits: hours per run, re-run | arXiv:1905.09749 Table 3 | 200 | 192.47 | -3.76% | agrees | Its script takes each figure up to two digits. |
|
||||
| 16384 bits: megaqubits, re-run | arXiv:1905.09749 Table 3 | 270 | 266.64 | -1.25% | agrees | Its script takes each figure up to two digits. |
|
||||
| 16384 bits: hours per run, re-run | arXiv:1905.09749 Table 3 | 350 | 342.54 | -2.13% | agrees | Its script takes each figure up to two digits. |
|
||||
|
||||
### FeMoCo on the surface code (arXiv:2011.03494, PRX Quantum 2, 030305, 2021)
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| physical qubits, p = 10⁻³, its floorplan | arXiv:2011.03494 Fig. 10 | ≈ 4·10⁶ | 3,907,584 | -2.31% | agrees | 53 × 36 = 1,908 patches of 2(d+1)², as its caption works out. |
|
||||
| days, p = 10⁻³, re-run on our clock | arXiv:2011.03494 §IV.C.4 | 3 | 3.01 | +0.22% | agrees | |
|
||||
| what sets the pace, p = 10⁻³ | arXiv:2011.03494 §IV.C.4 | the factories (a "tick" limit) | MagicStates | — | agrees | |
|
||||
| Toffoli rate, kHz | arXiv:2011.03494 §IV.C.4 | 25 | 25.81 | +3.23% | agrees | Four factories each finish a CCZ state every 5·31 cycles: 25.8 kHz, printed as 25. |
|
||||
| distillation failure over 10¹⁰ Toffolis | arXiv:2011.03494 §IV.C.4 | "roughly 0.1%" | 0.00103 | +2.85% | agrees | |
|
||||
| physical qubits, p = 10⁻⁴ | arXiv:2011.03494 §IV.C.5 | "one million" | 976,896 | -2.31% | agrees | |
|
||||
| days, p = 10⁻⁴, re-run on our clock | arXiv:2011.03494 §IV.C.5 | 1.5 | 1.45 | -3.01% | agrees | |
|
||||
| days at p = 10⁻³, as §IV.C.5 states | arXiv:2011.03494 §IV.C.5 | 3.5 | 3.01 | -14.09% | their numbers | §IV.C.4 says 3 days; §IV.C.5 scales "3.5 days" by 15/31 and gets 1.5, which is 3 days scaled. Its abstract says under four. |
|
||||
| Toffolis, Table III against its layout | arXiv:2011.03494 Table III against §IV.C.4 | 5.3·10⁹ (Table III); 6.7·10⁹ (§IV.C.4) | — | — | their numbers | The paper's own two figures: Table III costs the algorithm with its own QROM choices; the layout takes an output expansion factor of 1 for the select reads (§IV.C.2), which holds fewer qubits and takes more Toffolis. Ours takes each in turn below. |
|
||||
| logical qubits, Table III against its layout's data | arXiv:2011.03494 Table III against §IV.C.4 | 2,142 (Table III); under 700 data qubits (§IV.C.4) | — | — | their numbers | The paper's own two figures: Table III costs the algorithm with its own QROM choices; the layout takes an output expansion factor of 1 for the select reads (§IV.C.2), which holds fewer qubits and takes more Toffolis. Ours takes each in turn below. |
|
||||
| code distance, its layout's counts | arXiv:2011.03494 §IV.C.4; its counts in the estimate job | 31 | 29 | -6.45% | assumption | Its rule is `0.1·(100p)^((d+1)/2)` a cycle (§IV.C.5: "Λ of 10"); the planar model's `0.03·(p/0.01)^((d+1)/2)` a step of `d` cycles, lower by `d/0.3`, one step of distance at this size. |
|
||||
| physical qubits, job, Table III's counts | arXiv:2011.03494 §IV.C.4; its counts in the estimate job | ≈ 4·10⁶ | 8,419,152 | ×2.105 | our limit | The job lays out `2N + √(8N) + 1` tiles of `2d²` qubits and T factories from 15-to-1; the source a board of `2(d+1)²`-qubit patches and CCZ factories, placed by hand. |
|
||||
| physical qubits, job, its layout's counts | arXiv:2011.03494 §IV.C.4; its counts in the estimate job | ≈ 4·10⁶ | 3,529,152 | -11.77% | our limit | The job lays out `2N + √(8N) + 1` tiles of `2d²` qubits and T factories from 15-to-1; the source a board of `2(d+1)²`-qubit patches and CCZ factories, placed by hand. |
|
||||
| days, job, Table III's counts | arXiv:2011.03494 §IV.C.4; its counts in the estimate job | 3 | 5.34 | +77.89% | our limit | The estimate job prices the planar architecture of arXiv:2211.07629: three logical steps of `d` cycles for each Toffoli. The source teleports a Toffoli's fixups away and runs an addition at one 10 µs tick a Toffoli. The job has no such clock; quantum_arch's (the re-run rows) does. |
|
||||
| days, job, its layout's counts | arXiv:2011.03494 §IV.C.4; its counts in the estimate job | 3 | 6.75 | ×2.250 | our limit | The estimate job prices the planar architecture of arXiv:2211.07629: three logical steps of `d` cycles for each Toffoli. The source teleports a Toffoli's fixups away and runs an addition at one 10 µs tick a Toffoli. The job has no such clock; quantum_arch's (the re-run rows) does. |
|
||||
| physical qubits, job, p = 10⁻⁴ | arXiv:2011.03494 §IV.C.5; its counts in the estimate job | "one million" | 968,200 | -3.18% | our limit | The job lays out `2N + √(8N) + 1` tiles of `2d²` qubits and T factories from 15-to-1; the source a board of `2(d+1)²`-qubit patches and CCZ factories, placed by hand. |
|
||||
| days, job, p = 10⁻⁴ | arXiv:2011.03494 §IV.C.5; its counts in the estimate job | 1.5 | 3.49 | ×2.328 | our limit | The estimate job prices the planar architecture of arXiv:2211.07629: three logical steps of `d` cycles for each Toffoli. The source teleports a Toffoli's fixups away and runs an addition at one 10 µs tick a Toffoli. The job has no such clock; quantum_arch's (the re-run rows) does. |
|
||||
|
||||
### RSA-2048 on yoked surface codes (arXiv:2505.15917, 2025)
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| physical qubits | arXiv:2505.15917 §3.2 | 897,864 | 958,480 | +6.75% | their numbers | Ours keeps 152 logical qubits hot by its peak formula and buys whole grid blocks; its count keeps 131 and a fractional block. At its 131 and 430 qubits a logical qubit, our arithmetic gives its 897,864. |
|
||||
| hours per shot | arXiv:2505.15917 §3.2 | 12.07 | 10.58 | -12.36% | their numbers | Its tallies at its stated durations give 10.62 hours, and its clock at whole milliseconds 10.58. |
|
||||
| days per factoring | arXiv:2505.15917 §3.2 | 4.96 | 4.31 | -13.20% | their numbers | From the hours per shot above; it also multiplies by 9.1 shots where its table gives 9.2. It rounds 4.96 up to "less than a week". |
|
||||
| logical qubits | arXiv:2505.15917 §3.2 | 1,409 | 1,432 | +1.63% | their numbers | §3.2 prints 1,409 for its peak formula `m + 3f + 2ℓ + len m`, which evaluates to 1,432; its Table 4 gives 1,399. |
|
||||
| Toffolis per factoring, by its counting rule | arXiv:2505.15917 §3.2 | "6.5 billion" | 6.50e9 | -0.04% | agrees | |
|
||||
|
||||
### The planar model's own source (arXiv:2211.07629, 2022)
|
||||
|
||||
| Quantity | Source | Published | Ours | Delta | Class | Why |
|
||||
|---|---|---:|---:|---:|---|---|
|
||||
| code distance, RSA-2048, (ns, 10⁻⁴) | arXiv:2211.07629 Appendix F | 13 | 13 | 0 | agrees | |
|
||||
| factories | arXiv:2211.07629 Appendix F | 18 | 18 | 0 | agrees | |
|
||||
| physical qubits | arXiv:2211.07629 Appendix F | 8.72M | 8,716,258 | -0.04% | agrees | |
|
||||
| run time, hours | arXiv:2211.07629 Appendix F | 17 hours 43 mins | 17.723 | +0.04% | agrees | Table IV prints 18 hours. |
|
||||
|
||||
<!-- end of the rows -->
|
||||
28
wai/wai-quantum/examples/published_architectures.rs
Normal file
28
wai/wai-quantum/examples/published_architectures.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//! Our estimators against published architectures: for each quantity the
|
||||
//! published figure, ours, the delta and why they differ.
|
||||
//!
|
||||
//! ```text
|
||||
//! cargo run --release --example published_architectures --features full # columns
|
||||
//! cargo run --release --example published_architectures --features full -- --markdown # the page's rows
|
||||
//! cargo run --release --example published_architectures --features full -- --guards # ours, for the guards
|
||||
//! ```
|
||||
//!
|
||||
//! The page is `docs/published-architectures.md`, and a test in the crate holds
|
||||
//! its rows to this output. The published figures are in
|
||||
//! `tests/data/published_figures.tsv`; `--guards` prints ours, to four
|
||||
//! digits, for each row that does not agree, which is its line's guard there.
|
||||
use wai_quantum::published_architectures::{guards, markdown, report, tally, text};
|
||||
|
||||
fn main() -> Result<(), String> {
|
||||
let sections = report()?;
|
||||
if std::env::args().any(|a| a == "--markdown") {
|
||||
print!("{}", markdown(§ions));
|
||||
} else if std::env::args().any(|a| a == "--guards") {
|
||||
print!("{}", guards(§ions));
|
||||
} else {
|
||||
print!("{}", text(§ions));
|
||||
let counts: Vec<String> = tally(§ions).iter().map(|(c, n)| format!("{} {n}", c.name())).collect();
|
||||
println!("rows by class: {}", counts.join(", "));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -187,6 +187,13 @@ pub mod quantum_resource_receipt;
|
|||
#[cfg(feature = "quantum_arch")]
|
||||
pub mod quantum_arch;
|
||||
|
||||
#[cfg(feature = "quantum_arch")]
|
||||
pub mod quantum_bicycle;
|
||||
|
||||
// Our estimators beside the published figures.
|
||||
#[cfg(all(feature = "quantum_arch", feature = "quantum_engine"))]
|
||||
pub mod published_architectures;
|
||||
|
||||
#[cfg(feature = "quantum_frame")]
|
||||
pub mod quantum_frame;
|
||||
|
||||
|
|
|
|||
925
wai/wai-quantum/src/published_architectures.rs
Normal file
925
wai/wai-quantum/src/published_architectures.rs
Normal file
|
|
@ -0,0 +1,925 @@
|
|||
//! Our estimators against published architectures: the figure, ours and the
|
||||
//! delta, for each quantity, with why they differ.
|
||||
//!
|
||||
//! [`report`] feeds each source's stated assumptions into this crate's
|
||||
//! estimators. Nothing is fitted to the figures it is compared with, with one
|
||||
//! exception its row names: which end of the line the Ising program's T
|
||||
//! factory sits at, which the source does not print.
|
||||
//!
|
||||
//! The published figures are kept apart from this code, in
|
||||
//! `tests/data/published_figures.tsv`: each with where it is printed (a
|
||||
//! section, table or figure; `source files` when quoted from a paper's arXiv
|
||||
//! source with more digits than its PDF prints), as it is printed, its value,
|
||||
//! and its rule. The report reads them from there, so regenerating the page
|
||||
//! cannot move them, and a test holds every row to its rule:
|
||||
//!
|
||||
//! - a row that agrees, to the digits the source prints: `exact`; `nearest u`
|
||||
//! (within half its last printed unit `u`); `up u` or `down u` (where the
|
||||
//! source states or applies that rounding); or `band u`, where ours comes
|
||||
//! from a fit whose printed parameters are themselves rounded, and the range
|
||||
//! those parameters' last digit allows must meet the printed figure's;
|
||||
//! - every other numeric row, a `guard`: our figure to four digits, so a
|
||||
//! change to an estimator that moves it fails until the guard, the reason
|
||||
//! and the page are updated together.
|
||||
//!
|
||||
//! Each row has a class ([`Class`]): the two agree; we were given or chose a
|
||||
//! different assumption; the source models it differently; the source's own
|
||||
//! figures disagree with each other or with its stated method; our estimator
|
||||
//! has a limit there; or the difference is open, with what is known about it.
|
||||
//!
|
||||
//! ```text
|
||||
//! cargo run --release --example published_architectures --features full
|
||||
//! ```
|
||||
|
||||
use crate::engine::estimate;
|
||||
use crate::engine::synth::rz::rz;
|
||||
use crate::quantum_arch::{factoring_estimate, patch_qubits, windowed_factoring_estimate, Bound, DistilledCczFactory, FactoringParams, Machine as ArchMachine, PhaseupCount, Timing, WindowedFactoringParams};
|
||||
use crate::quantum_bicycle::{ising_layer, Code, Instruction, InstructionCounts, Machine, PauliCosts, PauliRotation, SpectrumFit, TFactory};
|
||||
use crate::quantum_resource::{estimate as planar, EstimateConfig, InstructionSet, LogicalCounts, PhysicalQubit, QecModel};
|
||||
use crate::repro::{exp, ln};
|
||||
use serde_json::{json, Value};
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
/// Why a row's two numbers differ.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Class {
|
||||
/// They agree to the digits the source prints.
|
||||
Agrees,
|
||||
/// We were given, or chose, a different assumption, stated in the row.
|
||||
Assumption,
|
||||
/// The source's model does this differently from ours, and the row says how.
|
||||
TheirModel,
|
||||
/// The source's own figures disagree with each other or with the method it
|
||||
/// states, and the row says where.
|
||||
TheirNumbers,
|
||||
/// Our estimator does not model this, and the row says what it leaves out.
|
||||
OurLimit,
|
||||
/// Not resolved: the row says what is known.
|
||||
Open,
|
||||
}
|
||||
|
||||
impl Class {
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
Class::Agrees => "agrees",
|
||||
Class::Assumption => "assumption",
|
||||
Class::TheirModel => "their model",
|
||||
Class::TheirNumbers => "their numbers",
|
||||
Class::OurLimit => "our limit",
|
||||
Class::Open => "open",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// How a row's figure is held.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Rule {
|
||||
Exact,
|
||||
/// Within half the last printed unit.
|
||||
Nearest(f64),
|
||||
/// Printed rounded up to the unit: `value − unit < ours ≤ value`.
|
||||
Up(f64),
|
||||
/// Printed rounded down to the unit: `value ≤ ours < value + unit`.
|
||||
Down(f64),
|
||||
/// Ours from a fit with rounded parameters: the band they allow meets
|
||||
/// the printed figure's half-unit interval.
|
||||
Band(f64),
|
||||
/// Not agreeing: ours, to four significant digits.
|
||||
Guard(f64),
|
||||
/// No number on the published side.
|
||||
Text,
|
||||
}
|
||||
|
||||
/// A published figure: where it is printed, as printed, its value and rule.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Pin {
|
||||
pub source: String,
|
||||
pub printed: String,
|
||||
pub value: Option<f64>,
|
||||
pub rule: Rule,
|
||||
}
|
||||
|
||||
/// The published figures, from `tests/data/published_figures.tsv`.
|
||||
pub fn pins() -> &'static BTreeMap<String, Pin> {
|
||||
static PINS: OnceLock<BTreeMap<String, Pin>> = OnceLock::new();
|
||||
PINS.get_or_init(|| parse_pins(include_str!("../tests/data/published_figures.tsv")).expect("the published figures read"))
|
||||
}
|
||||
|
||||
fn parse_pins(text: &str) -> Result<BTreeMap<String, Pin>, String> {
|
||||
let mut out = BTreeMap::new();
|
||||
for (n, line) in text.lines().enumerate().skip(1) {
|
||||
if line.trim().is_empty() || line.starts_with('#') {
|
||||
continue;
|
||||
}
|
||||
let f: Vec<&str> = line.split('\t').collect();
|
||||
let [id, source, printed, value, rule] = f.as_slice() else { return Err(format!("line {}: five tab-separated fields", n + 1)) };
|
||||
let num = |s: &str| s.parse::<f64>().map_err(|_| format!("line {}: {s} is not a number", n + 1));
|
||||
let value = if value.is_empty() { None } else { Some(num(value)?) };
|
||||
let mut words = rule.split_whitespace();
|
||||
let rule = match (words.next(), words.next()) {
|
||||
(Some("exact"), None) => Rule::Exact,
|
||||
(Some("text"), None) => Rule::Text,
|
||||
(Some("nearest"), Some(u)) => Rule::Nearest(num(u)?),
|
||||
(Some("up"), Some(u)) => Rule::Up(num(u)?),
|
||||
(Some("down"), Some(u)) => Rule::Down(num(u)?),
|
||||
(Some("band"), Some(u)) => Rule::Band(num(u)?),
|
||||
(Some("guard"), Some(g)) => Rule::Guard(num(g)?),
|
||||
_ => return Err(format!("line {}: no rule {rule}", n + 1)),
|
||||
};
|
||||
if out.insert(id.to_string(), Pin { source: source.to_string(), printed: printed.to_string(), value, rule }).is_some() {
|
||||
return Err(format!("line {}: {id} twice", n + 1));
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Whether `ours` (and its band, for a fitted figure) holds to `rule` at
|
||||
/// `value`.
|
||||
pub fn holds(rule: Rule, value: f64, ours: f64, band: Option<(f64, f64)>) -> bool {
|
||||
let slack = 1e-12 * value.abs().max(ours.abs());
|
||||
match rule {
|
||||
Rule::Exact => ours == value,
|
||||
Rule::Nearest(u) => (ours - value).abs() <= u / 2.0 + slack,
|
||||
Rule::Up(u) => value - u < ours && ours <= value + slack,
|
||||
Rule::Down(u) => value - slack <= ours && ours < value + u,
|
||||
Rule::Band(u) => band.is_some_and(|(lo, hi)| lo <= value + u / 2.0 + slack && hi >= value - u / 2.0 - slack),
|
||||
Rule::Guard(g) => {
|
||||
// Half a unit in the guard's fourth significant digit.
|
||||
let unit = exp(ln(10.0) * (g.abs().log10().floor() - 3.0));
|
||||
(ours - g).abs() <= unit / 2.0 + slack
|
||||
}
|
||||
Rule::Text => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// One published quantity beside ours.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Row {
|
||||
/// Its line in the published figures.
|
||||
pub id: String,
|
||||
pub quantity: String,
|
||||
pub source: String,
|
||||
pub published: String,
|
||||
pub ours: String,
|
||||
pub delta: String,
|
||||
pub class: Class,
|
||||
pub why: String,
|
||||
/// The published value and ours, when both are numbers.
|
||||
pub values: Option<(f64, f64)>,
|
||||
/// For a fitted figure, ours with the fit's parameters at the ends of
|
||||
/// their last printed digit.
|
||||
pub band: Option<(f64, f64)>,
|
||||
pub rule: Rule,
|
||||
}
|
||||
|
||||
/// A target: the rows of one published estimate.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Section {
|
||||
pub title: String,
|
||||
pub rows: Vec<Row>,
|
||||
}
|
||||
|
||||
/// How a number is printed.
|
||||
#[derive(Clone, Copy)]
|
||||
enum F {
|
||||
/// Whole, with thousands separated.
|
||||
I,
|
||||
/// `d` digits after the point, scientific.
|
||||
E(usize),
|
||||
/// `d` digits after the point.
|
||||
D(usize),
|
||||
}
|
||||
|
||||
fn print(x: f64, f: F) -> String {
|
||||
match f {
|
||||
F::I => {
|
||||
let s = format!("{:.0}", x.abs());
|
||||
let mut out = String::new();
|
||||
for (i, c) in s.chars().enumerate() {
|
||||
if i > 0 && (s.len() - i).is_multiple_of(3) {
|
||||
out.push(',');
|
||||
}
|
||||
out.push(c);
|
||||
}
|
||||
if x < 0.0 {
|
||||
out.insert(0, '-');
|
||||
}
|
||||
out
|
||||
}
|
||||
F::E(d) => format!("{x:.d$e}"),
|
||||
F::D(d) => format!("{x:.d$}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn delta(published: f64, ours: f64) -> String {
|
||||
if published == ours {
|
||||
return "0".into();
|
||||
}
|
||||
let ratio = ours / published;
|
||||
if !(0.5..=2.0).contains(&ratio) {
|
||||
return if ratio >= 100.0 || ratio < 0.01 { format!("×{ratio:.1e}") } else { format!("×{ratio:.3}") };
|
||||
}
|
||||
format!("{:+.2}%", 100.0 * (ratio - 1.0))
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Rows {
|
||||
rows: Vec<Row>,
|
||||
}
|
||||
|
||||
impl Rows {
|
||||
fn pin(id: &str) -> Pin {
|
||||
pins().get(id).cloned().unwrap_or_else(|| panic!("no published figure {id} in tests/data/published_figures.tsv"))
|
||||
}
|
||||
|
||||
fn push(&mut self, id: &str, quantity: String, ours: String, values: Option<(f64, f64)>, band: Option<(f64, f64)>, class: Class, why: String) {
|
||||
let p = Rows::pin(id);
|
||||
let delta = values.map_or("—".to_string(), |(v, o)| delta(v, o));
|
||||
self.rows.push(Row { id: id.into(), quantity, source: p.source, published: p.printed, ours, delta, class, why, values, band, rule: p.rule });
|
||||
}
|
||||
|
||||
/// A number beside its published figure.
|
||||
fn num(&mut self, id: &str, quantity: impl Into<String>, ours: f64, f: F, class: Class, why: impl Into<String>) {
|
||||
let value = Rows::pin(id).value.unwrap_or_else(|| panic!("{id} has no value"));
|
||||
self.push(id, quantity.into(), print(ours, f), Some((value, ours)), None, class, why.into());
|
||||
}
|
||||
|
||||
/// A number from a fit, with the band its parameters' last digit allows.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn band(&mut self, id: &str, quantity: impl Into<String>, ours: f64, band: (f64, f64), f: F, class: Class, why: impl Into<String>) {
|
||||
let value = Rows::pin(id).value.unwrap_or_else(|| panic!("{id} has no value"));
|
||||
self.push(id, quantity.into(), print(ours, f), Some((value, ours)), Some(band), class, why.into());
|
||||
}
|
||||
|
||||
/// A row with no number to compare on one side.
|
||||
fn text(&mut self, id: &str, quantity: impl Into<String>, ours: impl Into<String>, class: Class, why: impl Into<String>) {
|
||||
self.push(id, quantity.into(), ours.into(), None, None, class, why.into());
|
||||
}
|
||||
}
|
||||
|
||||
fn section(title: &str, rows: Rows) -> Section {
|
||||
Section { title: title.into(), rows: rows.rows }
|
||||
}
|
||||
|
||||
const MACHINES: [(&str, u64, &str, Code, fn() -> TFactory, f64); 6] = [
|
||||
("gross_e3_5k", 5_000, "gross, p = 10⁻³", Code::Gross, TFactory::gross_e3, 1e-3),
|
||||
("two_e3_50k", 50_000, "two-gross, p = 10⁻³", Code::TwoGross, TFactory::two_gross_e3, 1e-3),
|
||||
("gross_e4_5k", 5_000, "gross, p = 10⁻⁴", Code::Gross, TFactory::gross_e4, 1e-4),
|
||||
("gross_e4_50k", 50_000, "gross, p = 10⁻⁴", Code::Gross, TFactory::gross_e4, 1e-4),
|
||||
("two_e4_50k", 50_000, "two-gross, p = 10⁻⁴", Code::TwoGross, TFactory::two_gross_e4, 1e-4),
|
||||
("two_e4_500k", 500_000, "two-gross, p = 10⁻⁴", Code::TwoGross, TFactory::two_gross_e4, 1e-4),
|
||||
];
|
||||
|
||||
fn machines() -> Section {
|
||||
let mut r = Rows::default();
|
||||
for (tag, name, code) in [("gross", "gross", Code::Gross), ("two", "two-gross", Code::TwoGross)] {
|
||||
r.num(&format!("table1.{tag}.c"), format!("{name}: code block `c`, by `2n`"), code.code_qubits() as f64, F::I, Class::Agrees, "");
|
||||
r.num(&format!("table1.{tag}.u"), format!("{name}: processing unit `u`, as tallied"), code.lpu_qubits() as f64, F::I, Class::Agrees, "");
|
||||
r.num(&format!("table1.{tag}.a"), format!("{name}: adapter `a`, by `2(d−1)`"), code.adapter_qubits() as f64, F::I, Class::Agrees, "");
|
||||
}
|
||||
for (tag, name, factory) in [("gross_e3", "10⁻³ gross factory", TFactory::gross_e3()), ("two_e3", "10⁻³ two-gross factory", TFactory::two_gross_e3()), ("gross_e4", "10⁻⁴ gross factory", TFactory::gross_e4()), ("two_e4", "10⁻⁴ two-gross factory", TFactory::two_gross_e4())] {
|
||||
r.num(&format!("table3.{tag}.adapter"), format!("{name}: adapter `a′`, by `2d−1`"), factory.adapter_qubits() as f64, F::I, Class::Agrees, "");
|
||||
}
|
||||
for (tag, q, name, code, factory, _) in MACHINES {
|
||||
let m = Machine::largest(code, factory(), q).expect("a module fits");
|
||||
r.num(&format!("fig10a.{tag}.n"), format!("logical qubits in {} physical qubits, {name}", print(q as f64, F::I)), m.logical_qubits() as f64, F::I, Class::Agrees, "");
|
||||
}
|
||||
section("The bicycle machine: its parts", r)
|
||||
}
|
||||
|
||||
/// The last printed digit of the failure-spectrum fits' parameters (Table 6
|
||||
/// prints `ln f₀` and `γ` to two decimals): half of it.
|
||||
const FIT_DIGIT: f64 = 0.005;
|
||||
|
||||
/// A rate as the source's tables print it, from a fit whose `ln f₀` and `γ`
|
||||
/// are moved by `d`. The rate grows with both, as every failing weight is at
|
||||
/// least `w₀`.
|
||||
fn fitted(code: Code, i: Instruction, p: f64, d: f64) -> f64 {
|
||||
match code.fit(i) {
|
||||
Some(f) => SpectrumFit { ln_f0: f.ln_f0 + d, gamma: f.gamma + d, ..f }.circuit_failure(p),
|
||||
None => code.tabulated_rate(i, p),
|
||||
}
|
||||
}
|
||||
|
||||
fn fitted_band(code: Code, i: Instruction, p: f64) -> (f64, f64) {
|
||||
(fitted(code, i, p, -FIT_DIGIT), fitted(code, i, p, FIT_DIGIT))
|
||||
}
|
||||
|
||||
/// Eq. (26) at the rates as the tables print them, a T injection at an
|
||||
/// inter-module measurement's rate, the fits moved by `d`.
|
||||
fn tabulated_sum(n: &InstructionCounts, code: Code, p: f64, d: f64) -> f64 {
|
||||
let r = |i| fitted(code, i, p, d);
|
||||
n.idle * r(Instruction::Idle) + n.automorphism * r(Instruction::Automorphism) + n.in_module * r(Instruction::InModule) + (n.inter_module + n.t_injection) * r(Instruction::InterModule)
|
||||
}
|
||||
|
||||
fn rates() -> Section {
|
||||
let mut r = Rows::default();
|
||||
let names = [(Instruction::Idle, "I", "P_I"), (Instruction::Automorphism, "U", "P_U"), (Instruction::InModule, "M", "P_M"), (Instruction::InterModule, "C", "P_C")];
|
||||
let fmt = F::E(2);
|
||||
let why = "Ours evaluates Table 6's fits by Eq. (83); the band is ours with their parameters at the ends of their last printed digit.";
|
||||
for (p, tag, label) in [(1e-3, "1e-3", "10⁻³"), (1e-4, "1e-4", "10⁻⁴"), (5e-5, "5e-5", "5·10⁻⁵"), (3e-5, "3e-5", "3·10⁻⁵"), (1e-5, "1e-5", "10⁻⁵")] {
|
||||
for (i, short, name) in names {
|
||||
r.band(&format!("table10.gross.{short}.{tag}"), format!("gross `{name}` at p = {label}"), Code::Gross.tabulated_rate(i, p), fitted_band(Code::Gross, i, p), fmt, Class::Agrees, why);
|
||||
}
|
||||
}
|
||||
for (p, tag, label) in [(1e-3, "1e-3", "10⁻³"), (1e-4, "1e-4", "10⁻⁴")] {
|
||||
for (i, short, name) in &names[..2] {
|
||||
r.band(&format!("table10.two.{short}.{tag}"), format!("two-gross `{name}` at p = {label}"), Code::TwoGross.tabulated_rate(*i, p), fitted_band(Code::TwoGross, *i, p), fmt, Class::Agrees, why);
|
||||
}
|
||||
}
|
||||
let per = "§A.7 says an idle's or a shift's rate is the simulated circuit's failure divided by its C cycles. Table 2 and Table 10 print the circuit's failure undivided: Table 6's fits give them so. Ours divides, as the text says, and is lower by C (10 for gross, 18 for two-gross).";
|
||||
r.num("a7.gross.idle", "gross idle, one syndrome cycle, p = 10⁻³", Code::Gross.rate(Instruction::Idle, 1e-3).value, fmt, Class::TheirNumbers, per);
|
||||
r.num("a7.two.idle", "two-gross idle, one syndrome cycle, p = 10⁻³", Code::TwoGross.rate(Instruction::Idle, 1e-3).value, fmt, Class::TheirNumbers, per);
|
||||
r.num("a7.gross.shift", "gross automorphism, p = 10⁻³", Code::Gross.rate(Instruction::Automorphism, 1e-3).value, fmt, Class::TheirNumbers, per);
|
||||
let gross_gap = 2e-7 / Code::Gross.rate(Instruction::Idle, 1e-3).value;
|
||||
let two = format!(
|
||||
"Two papers on the same code at the same p. The earlier (decoded by BP-OSD) measures 2·10⁻⁷ a syndrome cycle for the gross code at 10⁻³; the later's fits (Relay-BP) give a circuit of C idle cycles, divided by C as its text says, {}: a factor of about {} (about {} undivided). Their decoders, circuits and fitting differ, and which accounts for the factor is not found here. Ours takes the later's fits.",
|
||||
print(Code::Gross.rate(Instruction::Idle, 1e-3).value, F::E(2)),
|
||||
print(gross_gap, F::I),
|
||||
print(gross_gap / 10.0, F::I)
|
||||
);
|
||||
for (code, tag, name, p, label) in [(Code::Gross, "gross.1e-3", "gross", 1e-3, "10⁻³"), (Code::Gross, "gross.1e-4", "gross", 1e-4, "10⁻⁴"), (Code::TwoGross, "two.1e-3", "two-gross", 1e-3, "10⁻³"), (Code::TwoGross, "two.1e-4", "two-gross", 1e-4, "10⁻⁴")] {
|
||||
r.num(&format!("2308.table1.{tag}"), format!("{name} memory per cycle, p = {label}"), code.rate(Instruction::Idle, p).value, fmt, Class::Open, two.as_str());
|
||||
}
|
||||
section("The bicycle machine: logical error rates", r)
|
||||
}
|
||||
|
||||
/// The compile section needs the search: pass its results in.
|
||||
fn compile(gross: &PauliCosts, two: &PauliCosts) -> Section {
|
||||
use crate::quantum_bicycle::{fixed_pivot_histogram, histogram_mean, native_measurements, native_rotation_census, native_rotations, shift_word_lengths, ShiftAction};
|
||||
let mut r = Rows::default();
|
||||
r.num("s3.2.natives", "native measurements", native_measurements(Code::Gross).len() as f64, F::I, Class::Agrees, "");
|
||||
r.num("s3.2.shifts", "any shift, in generators, at most", f64::from(*shift_word_lengths().iter().flatten().max().unwrap_or(&0)), F::I, Class::Agrees, "");
|
||||
let (with, without, both) = native_rotation_census(Code::Gross);
|
||||
r.num(
|
||||
"s3.2.rotations",
|
||||
"native rotations",
|
||||
native_rotations(Code::Gross).len() as f64,
|
||||
F::I,
|
||||
Class::TheirNumbers,
|
||||
format!(
|
||||
"§3.2 defines a native rotation by a native measurement Q ⊗ R with Q one of X, Y, Z on the pivot: there are {with} such R. Over all the native measurements there are {} distinct R ≠ I: {without} occur with Q = I, {both} of them also with Q ≠ I. That its 510 counts those is our inference from the matching count. Fig. 9's first bin holds {with}.",
|
||||
with + without - both
|
||||
),
|
||||
);
|
||||
let why = "Our search runs from the printed polynomials, basis and native set, over the 4¹¹ − 1 Paulis (4¹² − 1 with the pivot fixed). The authors' released compiler, bicycle_cliffords 0.1.0 (crates.io, 2025-07-31), takes a shift's action in src/measurement.rs as A on X̄ and A⁻¹ on Z̄, on both halves of a module; taken so, our search gives the source's four means to every printed digit (a test in quantum_bicycle holds this). A CNOT circuit |x⟩ → |Ax⟩ takes Z̄ by A⁻ᵀ, which is how the operators move and what ours follows; its version 0.2.1 takes X̄ by A⁻¹ and Z̄ by Aᵀ, a consistent pair. The difference moves a capability here by under 0.6%.";
|
||||
let (gross_fixed, two_fixed) = (histogram_mean(&fixed_pivot_histogram(Code::Gross, ShiftAction::Operators)), histogram_mean(&fixed_pivot_histogram(Code::TwoGross, ShiftAction::Operators)));
|
||||
r.num("fig9.chosen.gross", "mean in-module measurements per Pauli, pivot basis chosen, gross", gross.mean_measurements(), F::D(3), Class::TheirNumbers, why);
|
||||
r.num("fig9.chosen.two", "the same, two-gross", two.mean_measurements(), F::D(3), Class::TheirNumbers, why);
|
||||
r.num("fig9.fixed.gross", "mean in-module measurements per Pauli, pivot basis fixed, gross", gross_fixed, F::D(3), Class::TheirNumbers, why);
|
||||
r.num("fig9.fixed.two", "the same, two-gross", two_fixed, F::D(3), Class::TheirNumbers, why);
|
||||
section("The bicycle machine: the compile", r)
|
||||
}
|
||||
|
||||
/// The source's surface-code row, as its §A.10 states it: `n = ⌊(q − f)/4d²⌋`,
|
||||
/// `P₁ = 0.03·(p/0.01)^(d/2)` per cycle, and the largest whole `N_T` with
|
||||
/// `2·N_T·n·P₁·d ≤ ⅓`. With our code model's `0.03·(p/0.01)^((d+1)/2)` per `d`
|
||||
/// cycles in its place, the same budget.
|
||||
fn surface_source_row(q: u64, f: u64, d: u32, p: f64) -> (u64, f64, f64) {
|
||||
let dd = u64::from(d) * u64::from(d);
|
||||
let n = (q - f) / (4 * dd);
|
||||
let p1 = 0.03 * exp(0.5 * f64::from(d) * ln(p / 0.01));
|
||||
let budget = 1.0 / 3.0;
|
||||
(n, (budget / (2.0 * n as f64 * p1 * f64::from(d))).floor(), budget / (2.0 * n as f64 * QecModel::surface_gate().logical_error(p, d)))
|
||||
}
|
||||
|
||||
fn capability() -> Section {
|
||||
let mut r = Rows::default();
|
||||
let budget = 1.0 / 3.0;
|
||||
let sampled = "Theirs samples eight random circuits of up to 10⁵ rotations and extends a straight-line fit (Fig. 17); ours is the expected count, at the rates as the tables print them.";
|
||||
let e4 = "Its two gross rows at this p need a failure per rotation of 6.70·10⁻⁸ per module (ours: 6.69·10⁻⁸) plus 8.3·10⁻⁷ whatever the machine's size. Ours has 4·10⁻⁸ there: Table 3's factory, an injection's inter-module measurement and one link fewer. Nothing the paper prints accounts for the other 7.9·10⁻⁷. Its authors' compiler is released (bicycle_compiler 0.1.0 on crates.io): its capability estimate at these two machines would settle it; this check does not run it.";
|
||||
let schedule = "Theirs is the critical path of a compiled schedule; ours adds the mean time of a rotation's parts, with no scheduling. Ours runs a few percent low, more where a compiler takes more shifts than the fewest.";
|
||||
for (tag, q, name, code, factory, p) in MACHINES {
|
||||
let m = Machine::largest(code, factory(), q).expect("a module fits");
|
||||
let label = format!("{} physical qubits, {name}", print(q as f64, F::I));
|
||||
let (ours, undivided) = (m.capability(p, budget), m.capability_undivided(p, budget));
|
||||
let published = Rows::pin(&format!("fig10a.{tag}.nt")).value.expect("a figure");
|
||||
let open = code == Code::Gross && p == 1e-4;
|
||||
let ours_share = ours / undivided - 1.0;
|
||||
let theirs_share = undivided / published - 1.0;
|
||||
let (class, why) = if open {
|
||||
(Class::Open, e4.to_string())
|
||||
} else if ours_share.abs() >= theirs_share.abs() {
|
||||
(Class::Assumption, format!("Ours divides P_I and P_U by C, as §A.7's text says (the rates section); with them undivided, as Table 10 prints them, ours is {} (next row). That choice is {:+.2}% of the difference, and the sampling below {:+.2}%.", print(undivided, F::E(3)), 100.0 * ours_share, 100.0 * theirs_share))
|
||||
} else {
|
||||
(Class::TheirModel, format!("{sampled} Our division of P_I and P_U by C, as §A.7's text says, is {:+.2}% of it (next row: undivided).", 100.0 * ours_share))
|
||||
};
|
||||
r.num(&format!("fig10a.{tag}.nt"), format!("T count at failure ⅓, {label}"), ours, F::E(3), class, why);
|
||||
r.num(&format!("fig10a.{tag}.nt_undivided"), format!("the same, P_I and P_U undivided, as Table 10 prints them, {label}"), undivided, F::E(3), if open { Class::Open } else { Class::TheirModel }, if open { e4 } else { sampled });
|
||||
r.num(&format!("fig10a.{tag}.steps"), format!("timesteps per T, {label}"), m.rotation_timesteps(), F::D(2), Class::OurLimit, schedule);
|
||||
}
|
||||
let as_printed = "§A.10's formula for the surface-code row, evaluated as it states it: the largest whole T count.";
|
||||
let ours = "Our planar model takes `0.03·(p/p*)^((d+1)/2)` per patch per `d` cycles, as arXiv:2211.07629 does. §A.10 takes `0.03·(p/p*)^(d/2)` per cycle, times `d` cycles: higher by `d·√(p*/p)`.";
|
||||
for (tag, q, f, d, p, label, steps_factory) in [
|
||||
("gross_e3_5k", 5_000, 454, 5, 1e-3, "5,000 qubits, p = 10⁻³", 351.0),
|
||||
("two_e3_50k", 50_000, 463, 17, 1e-3, "50,000 qubits, p = 10⁻³", 2167.0),
|
||||
("gross_e4_5k", 5_000, 810, 7, 1e-4, "5,000 qubits, p = 10⁻⁴", 73.0),
|
||||
("gross_e4_50k", 50_000, 810, 7, 1e-4, "50,000 qubits, p = 10⁻⁴, d = 7", 73.0),
|
||||
("two_e4_50k", 50_000, 18_600, 17, 1e-4, "50,000 qubits, p = 10⁻⁴, d = 17", 407.0),
|
||||
("two_e4_500k", 500_000, 18_600, 17, 1e-4, "500,000 qubits, p = 10⁻⁴, d = 17", 407.0),
|
||||
] {
|
||||
let (have_n, source_nt, our_nt) = surface_source_row(q, f, d, p);
|
||||
r.num(&format!("fig10a.surface.{tag}.n"), format!("surface code: logical qubits, {label}"), have_n as f64, F::I, Class::Agrees, "");
|
||||
let digits = if source_nt < 1e6 { F::I } else { F::E(2) };
|
||||
r.num(&format!("fig10a.surface.{tag}.nt"), format!("surface code: T count, its formula, {label}"), source_nt, digits, Class::Agrees, as_printed);
|
||||
r.num(&format!("fig10a.surface.{tag}.nt_ours"), format!("surface code: T count, our code model, {label}"), our_nt, F::E(2), Class::TheirModel, ours);
|
||||
r.num(
|
||||
&format!("fig10a.surface.{tag}.steps"),
|
||||
format!("surface code: timesteps per T, {label}"),
|
||||
steps_factory + 6.0 * f64::from(d),
|
||||
F::I,
|
||||
Class::Agrees,
|
||||
"§A.10: the factory's timesteps (Table 3) and the lattice surgery's 6d.",
|
||||
);
|
||||
}
|
||||
section("The bicycle machine: what a machine of a given size can run", r)
|
||||
}
|
||||
|
||||
/// The T gates of each of the Ising program's four rotation angles at
|
||||
/// `epsilon`, in this crate's synthesiser: `(ZZ, X)` in the four outer
|
||||
/// second-order formulas of a step, then in the middle one.
|
||||
pub fn ising_t_counts(epsilon: f64) -> Result<[u64; 4], String> {
|
||||
let gamma = 1.0 / (4.0 - exp(ln(4.0) / 3.0));
|
||||
let delta = 0.25;
|
||||
let t = |angle: f64| rz(angle, epsilon).map(|w| w.t_count as u64);
|
||||
let mid = (1.0 - 4.0 * gamma) * delta;
|
||||
Ok([t(gamma * delta)?, t(2.0 * gamma * delta)?, t(mid)?, t(2.0 * mid)?])
|
||||
}
|
||||
|
||||
/// The program's T gates: 80 steps of 5 second-order formulas, 360 `ZZ` and
|
||||
/// 100 `X` rotations each, the middle formula at its own angles.
|
||||
pub fn ising_t_count(epsilon: f64) -> Result<u64, String> {
|
||||
let [zz, x, zz_mid, x_mid] = ising_t_counts(epsilon)?;
|
||||
Ok(80 * (4 * (360 * zz + 100 * x) + 360 * zz_mid + 100 * x_mid))
|
||||
}
|
||||
|
||||
/// The physical error rate at which `a·pᵇ` through two points reaches `target`.
|
||||
fn power_law_bound(p1: f64, f1: f64, p2: f64, f2: f64, target: f64) -> f64 {
|
||||
let slope = ln(f1 / f2) / ln(p1 / p2);
|
||||
p2 * exp(ln(target / f2) / slope)
|
||||
}
|
||||
|
||||
/// The rotations of one second-order formula with the sites numbered from the
|
||||
/// other end of the line: the factory before the first module, not after the
|
||||
/// last.
|
||||
fn mirrored(layer: &[PauliRotation], slots: u64) -> Vec<PauliRotation> {
|
||||
let flip = |s: &u64| slots - 1 - s;
|
||||
layer.iter().map(|r| PauliRotation { xs: r.xs.iter().map(flip).collect(), zs: r.zs.iter().map(flip).collect() }).collect()
|
||||
}
|
||||
|
||||
fn ising(gross: &PauliCosts, two: &PauliCosts) -> Result<Section, String> {
|
||||
let mut r = Rows::default();
|
||||
let two_machine = Machine::for_logical(Code::TwoGross, TFactory::two_gross_e3(), 100);
|
||||
let gross_machine = Machine::for_logical(Code::Gross, TFactory::gross_e4(), 100);
|
||||
r.num("s4.ising.two.q", "physical qubits, two-gross", two_machine.physical_qubits() as f64, F::I, Class::Agrees, "");
|
||||
r.num("s4.ising.gross.q", "physical qubits, gross", gross_machine.physical_qubits() as f64, F::I, Class::TheirNumbers, "§4 names the 10⁻⁴ gross factory, whose adapter is 13 qubits (Table 3). 4,817 takes the 29 of the 10⁻³ factory.");
|
||||
let layer = ising_layer(10);
|
||||
r.num("a10.rotations", "rotations", (400 * layer.len()) as f64, F::I, Class::Agrees, "");
|
||||
let tally = |m: &Machine, c: &PauliCosts| {
|
||||
let mut t = InstructionCounts::default();
|
||||
for rot in &layer {
|
||||
let e = m.compile_rotation(c, rot);
|
||||
t.inter_module += 400.0 * e.inter_module;
|
||||
t.in_module += 400.0 * e.in_module;
|
||||
t.automorphism += 400.0 * e.automorphism;
|
||||
}
|
||||
t
|
||||
};
|
||||
let (g, t) = (tally(&gross_machine, gross), tally(&two_machine, two));
|
||||
let near: u64 = 400 * mirrored(&layer, gross_machine.logical_qubits()).iter().map(|x| gross_machine.links(x, true)).sum::<u64>();
|
||||
let placement = format!("Sites in order and the factory after the last module give the paper's count; before the first module, {}. The paper prints neither, and this is the end chosen to match it: the one choice in this check made to fit a published figure.", print(near as f64, F::I));
|
||||
r.num("table9.gross.nc", "inter-module measurements `N_C`, gross", g.inter_module, F::I, Class::Assumption, placement.as_str());
|
||||
r.num("table9.two.nc", "the same on two-gross", t.inter_module, F::I, Class::Assumption, placement.as_str());
|
||||
let peep = "Ours removes no repeated in-module measurement, which theirs does (§4), and takes sites in order, which it does not print. Its counts also carry the compile section's action of a shift on Z̄, which puts its gross below its two-gross; ours has them the other way round.";
|
||||
r.num("table9.gross.nm", "in-module measurements `N_M`, gross", g.in_module, F::I, Class::OurLimit, peep);
|
||||
r.num("table9.two.nm", "in-module measurements `N_M`, two-gross", t.in_module, F::I, Class::OurLimit, peep);
|
||||
let autos = "Ours takes the fewest shifts on a path of fewest measurements, and merges none; theirs is a compiler's.";
|
||||
r.num("table9.gross.nu", "automorphisms `N_U`, gross", g.automorphism, F::I, Class::OurLimit, autos);
|
||||
r.num("table9.two.nu", "automorphisms `N_U`, two-gross", t.automorphism, F::I, Class::OurLimit, autos);
|
||||
let counts = ising_t_counts(5e-9)?;
|
||||
let synthesised = ising_t_count(5e-9)? as f64;
|
||||
r.num(
|
||||
"table9.nt",
|
||||
"T injections `N_T`",
|
||||
synthesised,
|
||||
F::I,
|
||||
Class::TheirModel,
|
||||
format!(
|
||||
"pygridsynth 1.0.1, the version the source cites, run on the program's four angles at ε = 5·10⁻⁹, gives 86, 80, 84 and 82 T gates, which make 15,542,400 exactly; it approximates the rotation itself. Ours, the same Ross–Selinger method, gives {}, {}, {} and {}, and also searches the class one global phase e^(iπ/8) away, which a rotation of the pivot allows.",
|
||||
counts[0], counts[1], counts[2], counts[3]
|
||||
),
|
||||
);
|
||||
r.num("s4.nt", "T injections as §4 and Fig. 1(b) state", synthesised, F::I, Class::TheirNumbers, "§4 says N_T = 1.9·10⁷ and Fig. 1(b) plots 19,036,800. Table 9 and every failure probability of Table 10 take 15,542,400, which the row above compares ours with.");
|
||||
let idle = |nt: f64, m: &Machine| nt * m.modules as f64 * m.factory.timesteps / 8.0;
|
||||
r.num("table9.two.ni", "idles `N_I`, two-gross, from its `N_T`", idle(15_542_400.0, &two_machine), F::I, Class::OurLimit, "Ours: every module idles while the factory works, and otherwise never. Theirs counts the idles of its schedule.");
|
||||
|
||||
// Table 9's counts, as the source files hold them: Table 10's inputs.
|
||||
let gross_counts = InstructionCounts { idle: 41_634_378_765.0, automorphism: 2_270_400.0, in_module: 4_215_240.0, inter_module: 946_800.0, t_injection: 15_542_400.0 };
|
||||
let two_counts = InstructionCounts { idle: 41_636_714_298.0, automorphism: 2_294_400.0, in_module: 4_238_828.0, inter_module: 946_800.0, t_injection: 15_542_400.0 };
|
||||
let fmt = F::E(3);
|
||||
let banded = "Table 9's counts at our evaluation of Table 6's fits (Eq. (26)); the band moves the fits' parameters by their last printed digit.";
|
||||
for (code, counts, tag, name, ps) in [(Code::Gross, &gross_counts, "gross", "gross", &[(1e-3, "1e-3", "10⁻³"), (1e-4, "1e-4", "10⁻⁴"), (5e-5, "5e-5", "5·10⁻⁵"), (3e-5, "3e-5", "3·10⁻⁵"), (1e-5, "1e-5", "10⁻⁵")][..]), (Code::TwoGross, &two_counts, "two", "two-gross", &[(1e-3, "1e-3", "10⁻³"), (1e-4, "1e-4", "10⁻⁴")][..])] {
|
||||
for (p, ptag, label) in ps {
|
||||
let band = (tabulated_sum(counts, code, *p, -FIT_DIGIT), tabulated_sum(counts, code, *p, FIT_DIGIT));
|
||||
r.band(&format!("table10.fail.{tag}.{ptag}"), format!("failure probability, {name}, p = {label}, its counts"), counts.failure_as_tabulated(code, *p), band, fmt, Class::Agrees, banded);
|
||||
}
|
||||
}
|
||||
r.num(
|
||||
"table10.fail.two.factory",
|
||||
"failure probability, two-gross, p = 10⁻³, a T injection at its factory",
|
||||
two_counts.failure(Code::TwoGross, TFactory::two_gross_e3().error, 1e-3),
|
||||
fmt,
|
||||
Class::TheirModel,
|
||||
"Table 10 sets `P_T = P_C` (\"the T factory can be chosen to distill states of sufficient fidelity\") and §4 neglects the factory. At the factory it allocates, Table 3's 2·10⁻⁸, the T injections alone fail with 0.31.",
|
||||
);
|
||||
let bound = |code: Code, n: &InstructionCounts, (p1, p2): (f64, f64), d: f64| power_law_bound(p1, tabulated_sum(n, code, p1, d), p2, tabulated_sum(n, code, p2, d), 1e-3);
|
||||
let bounded = "Its power law through two of its points of Table 10, solved for a failure of 10⁻³; the band moves the fits' parameters by their last printed digit.";
|
||||
for (code, counts, tag, name, ps) in [(Code::TwoGross, &two_counts, "two", "two-gross", (1e-4, 1e-3)), (Code::Gross, &gross_counts, "gross", "gross", (1e-5, 3e-5))] {
|
||||
let (a, b) = (bound(code, counts, ps, -FIT_DIGIT), bound(code, counts, ps, FIT_DIGIT));
|
||||
r.band(&format!("a10.bound.{tag}"), format!("physical error rate for failure 10⁻³, {name}"), bound(code, counts, ps, 0.0), (a.min(b), a.max(b)), fmt, Class::Agrees, bounded);
|
||||
}
|
||||
|
||||
// Eq. (96) with §4's N_T, which reproduces §A.10's figures.
|
||||
let volume = 2.0 * 184_000.0 * 100.0 + 19_036_800.0 - 184_000.0;
|
||||
let their_surface = |d: f64| 0.01 * exp(ln(1e-3 / (0.03 * d * volume)) * 2.0 / d);
|
||||
let our_surface = |d: f64| 0.01 * exp(ln(1e-3 / (0.03 * volume)) * 2.0 / (d + 1.0));
|
||||
for (d, f) in [(9.0, 810.0), (17.0, 463.0), (19.0, 463.0)] {
|
||||
let tag = format!("d{d}");
|
||||
r.num(&format!("a10.surface.{tag}.p"), format!("surface code, d = {d}: physical error rate, Eq. (96)"), their_surface(d), fmt, Class::Agrees, "With §4's N_T of 19,036,800. §4 prints it truncated to two digits.");
|
||||
r.num(&format!("a10.surface.{tag}.p_ours"), format!("surface code, d = {d}: physical error rate, our code model"), our_surface(d), fmt, Class::TheirModel, "As in the capability section: a patch's error per `d` cycles, not a cycle's times `d`, and `(d+1)/2`.");
|
||||
r.num(&format!("s4.surface.{tag}.qubits"), format!("surface code, d = {d}: physical qubits"), 4.0 * 100.0 * d * d + f, F::I, Class::TheirNumbers, "§4 and Fig. 10(b) count `2d²` a logical qubit. Eq. (96) puts `2n` patches in each rotation, and §A.10's capability comparison reserves half the patches for routing: `4d²`. Ours is `4d²`.");
|
||||
}
|
||||
Ok(section("The bicycle machine: the 10 × 10 Ising model", r))
|
||||
}
|
||||
|
||||
/// The planar job, through the job's own door.
|
||||
struct Planar {
|
||||
distance: u64,
|
||||
physical: f64,
|
||||
factories: u64,
|
||||
runtime_h: f64,
|
||||
}
|
||||
|
||||
fn job(counts: Value, budget: f64, p: f64, calibration: &str) -> Result<Planar, String> {
|
||||
let request = json!({
|
||||
"counts": counts,
|
||||
"budget": budget,
|
||||
"qubit": { "name": "1 µs cycle", "instruction_set": "gate", "gate_ns": 1000.0 / 6.0, "meas_ns": 1000.0 / 6.0, "clifford_error": p, "t_error": p },
|
||||
"calibration": calibration,
|
||||
"max_slowdown": 1,
|
||||
});
|
||||
let answer = estimate::call(&request)?;
|
||||
let e = &answer["estimate"];
|
||||
Ok(Planar {
|
||||
distance: e["distance"].as_u64().unwrap_or(0),
|
||||
physical: e["physical_qubits"].as_f64().unwrap_or(0.0),
|
||||
factories: e["factories"].as_u64().unwrap_or(0),
|
||||
runtime_h: e["runtime_s"].as_f64().unwrap_or(0.0) / 3600.0,
|
||||
})
|
||||
}
|
||||
|
||||
/// The planar model on the source's own assumptions: `2(d+1)²` qubits a patch,
|
||||
/// and `0.1·(100p)^((d+1)/2)` per cycle, at the distance the source uses.
|
||||
fn their_noise(at_distance: f64) -> QecModel {
|
||||
QecModel { name: "surface code, as the source prices it".into(), instruction_set: InstructionSet::GateBased, prefactor: 0.1 * at_distance, threshold: 0.01, qubits: (2, 4, 2), cycle: (4.0, 2.0) }
|
||||
}
|
||||
|
||||
fn one_us(p: f64) -> PhysicalQubit {
|
||||
PhysicalQubit { name: "1 µs cycle".into(), instruction_set: InstructionSet::GateBased, gate_ns: 1000.0 / 6.0, meas_ns: 1000.0 / 6.0, clifford_error: p, t_error: p }
|
||||
}
|
||||
|
||||
/// What the estimate job leaves out against a laid-out surface-code machine.
|
||||
const JOB_TIME: &str = "The estimate job prices the planar architecture of arXiv:2211.07629: three logical steps of `d` cycles for each Toffoli. The source teleports a Toffoli's fixups away and runs an addition at one 10 µs tick a Toffoli. The job has no such clock; quantum_arch's (the re-run rows) does.";
|
||||
const JOB_SPACE: &str = "The job lays out `2N + √(8N) + 1` tiles of `2d²` qubits and T factories from 15-to-1; the source a board of `2(d+1)²`-qubit patches and CCZ factories, placed by hand.";
|
||||
|
||||
fn rsa_2021() -> Result<Section, String> {
|
||||
let params = WindowedFactoringParams::published(2048).expect("a published row");
|
||||
let e = windowed_factoring_estimate(¶ms, 1e-3, 1.0, 10.0);
|
||||
let toffolis = e.toffolis.round() as u64;
|
||||
let counts = json!({ "numQubits": 6189, "cczCount": toffolis });
|
||||
let assumed = job(counts.clone(), 0.31, 1e-3, "assumed")?;
|
||||
let fitted = job(counts, 0.31, 1e-3, "exact_matching")?;
|
||||
let source_noise = planar(&LogicalCounts { qubits: 6189, ccz: toffolis, ..Default::default() }, &one_us(1e-3), &their_noise(27.0), &EstimateConfig::new(0.31)).map_err(|x| format!("{x:?}"))?;
|
||||
|
||||
let mut r = Rows::default();
|
||||
let fmt = F::E(3);
|
||||
let up = "Its script takes each figure up to two digits.";
|
||||
r.num("r21.table3.qubits", "physical qubits, re-run on its layout", e.physical_qubits as f64, F::I, Class::Agrees, up);
|
||||
r.num("r21.table3.hours", "hours per run, re-run", e.hours, F::D(2), Class::Agrees, up);
|
||||
r.num("r21.table3.risk", "retry risk, re-run", e.retry_risk, F::D(4), Class::Agrees, "Its script takes it up to a whole percent.");
|
||||
r.num("r21.table3.mqd", "megaqubit-days per run, re-run", e.megaqubit_days(), F::D(2), Class::Agrees, up);
|
||||
r.num("r21.table1.toffolis", "Toffolis, re-run", e.toffolis, fmt, Class::Agrees, "");
|
||||
r.num("r21.s2.10.factories", "factories in each piece, re-run", (e.factories / e.pieces) as f64, F::I, Class::Agrees, "");
|
||||
r.num(
|
||||
"r21.title.hours",
|
||||
"hours, expected across retries",
|
||||
e.expected_hours(),
|
||||
F::D(2),
|
||||
Class::Agrees,
|
||||
format!("The re-run's {} hours a run at its {}% retry risk is {} hours expected; the title takes that up to one digit.", print(e.hours, F::D(2)), print(100.0 * e.retry_risk, F::D(2)), print(e.expected_hours(), F::D(2))),
|
||||
);
|
||||
let hand = windowed_factoring_estimate(&WindowedFactoringParams { factory: DistilledCczFactory { l1_distance: 17, l2_distance: 27 }, ..params }, 1e-3, 1.0, 10.0);
|
||||
r.num("r21.s2.14.qubits", "physical qubits, its worked case, level-1 distance 17", hand.physical_qubits as f64, F::I, Class::TheirNumbers, "That section rounds as it goes, and says so: 226 × 63 patches, where the script's layout at these distances has 226 × 61.");
|
||||
r.num("r21.s2.12.distillation", "distillation error of 3·10⁹ CCZ states, distances 17 and 27", 3e9 * DistilledCczFactory { l1_distance: 17, l2_distance: 27 }.error(1e-3), F::D(4), Class::TheirNumbers, "That section reads a spreadsheet of an earlier paper. Its own script's formula, which produced its tables, gives 0.6%.");
|
||||
|
||||
r.num("r21.job.distance.assumed", "code distance, job, assumed code model", assumed.distance as f64, F::I, Class::Agrees, "");
|
||||
r.num("r21.job.distance.fitted", "code distance, job, code model fitted to our decoders", fitted.distance as f64, F::I, Class::Agrees, "Our fit is `a = 0.0233, p* = 0.01004`, extrapolated from p = 0.002–0.005.");
|
||||
r.num("r21.job.qubits.assumed", "physical qubits, job, assumed code model", assumed.physical, F::I, Class::OurLimit, JOB_SPACE);
|
||||
r.num("r21.job.qubits.fitted", "physical qubits, job, fitted code model", fitted.physical, F::I, Class::OurLimit, JOB_SPACE);
|
||||
r.num("r21.job.qubits.source_rule", "physical qubits, the planar model on the source's patch and error rule", source_noise.physical_qubits as f64, F::I, Class::OurLimit, JOB_SPACE);
|
||||
r.num("r21.job.hours.assumed", "hours per run, job, assumed code model", assumed.runtime_h, F::D(2), Class::OurLimit, JOB_TIME);
|
||||
r.num("r21.job.hours.source_rule", "hours per run, the planar model on the source's patch and error rule", source_noise.runtime_ns / 3.6e12, F::D(2), Class::OurLimit, JOB_TIME);
|
||||
r.text("r21.job.factories", "factories, job", format!("{} T factories", assumed.factories), Class::OurLimit, "A CCZ state costs four T states in the planar model.");
|
||||
|
||||
for n in [1024, 3072, 4096, 8192, 12288, 16384] {
|
||||
let row = windowed_factoring_estimate(&WindowedFactoringParams::published(n).expect("a published row"), 1e-3, 1.0, 10.0);
|
||||
r.num(&format!("r21.table3.{n}.megaqubits"), format!("{n} bits: megaqubits, re-run"), row.physical_qubits as f64 / 1e6, F::D(2), Class::Agrees, up);
|
||||
r.num(&format!("r21.table3.{n}.hours"), format!("{n} bits: hours per run, re-run"), row.hours, F::D(2), Class::Agrees, up);
|
||||
}
|
||||
Ok(section("RSA-2048 on the surface code (arXiv:1905.09749, Quantum 5, 433, 2021)", r))
|
||||
}
|
||||
|
||||
fn femoco() -> Result<Section, String> {
|
||||
let toffolis = 483_000.0 * 13_880.0;
|
||||
let factory = DistilledCczFactory { l1_distance: 19, l2_distance: 31 };
|
||||
let clock = Timing { cycle_us: 1.0, reaction_us: 10.0, distance: 31, ccz_rounds: factory.rounds_per_ccz(), factories: 4 };
|
||||
let cheap = DistilledCczFactory { l1_distance: 9, l2_distance: 15 };
|
||||
let cheap_clock = Timing { distance: 15, ccz_rounds: cheap.rounds_per_ccz(), ..clock };
|
||||
let days = |t: &Timing| toffolis * t.tick_us() / 86.4e9;
|
||||
let table = json!({ "numQubits": 2142, "cczCount": 5_300_000_000u64 });
|
||||
let layout = json!({ "numQubits": 700, "cczCount": toffolis as u64 });
|
||||
let (a, b) = (job(table, 0.01, 1e-3, "assumed")?, job(layout.clone(), 0.01, 1e-3, "assumed")?);
|
||||
let low = job(layout, 0.01, 1e-4, "assumed")?;
|
||||
|
||||
let mut r = Rows::default();
|
||||
r.num("femoco.fig10.qubits", "physical qubits, p = 10⁻³, its floorplan", (53 * 36 * patch_qubits(31)) as f64, F::I, Class::Agrees, "53 × 36 = 1,908 patches of 2(d+1)², as its caption works out.");
|
||||
r.num("femoco.s4c4.days", "days, p = 10⁻³, re-run on our clock", days(&clock), F::D(2), Class::Agrees, "");
|
||||
r.text("femoco.s4c4.pace", "what sets the pace, p = 10⁻³", format!("{:?}", clock.bound()), if clock.bound() == Bound::MagicStates { Class::Agrees } else { Class::Open }, "");
|
||||
r.num("femoco.s4c4.rate", "Toffoli rate, kHz", 1e3 / clock.tick_us(), F::D(2), Class::Agrees, "Four factories each finish a CCZ state every 5·31 cycles: 25.8 kHz, printed as 25.");
|
||||
r.num("femoco.s4c4.distillation", "distillation failure over 10¹⁰ Toffolis", 1e10 * factory.error(1e-3), F::D(5), Class::Agrees, "");
|
||||
r.num("femoco.s4c5.qubits", "physical qubits, p = 10⁻⁴", (53 * 36 * patch_qubits(15)) as f64, F::I, Class::Agrees, "");
|
||||
r.num("femoco.s4c5.days", "days, p = 10⁻⁴, re-run on our clock", days(&cheap_clock), F::D(2), Class::Agrees, "");
|
||||
r.num("femoco.s4c5.days3", "days at p = 10⁻³, as §IV.C.5 states", days(&clock), F::D(2), Class::TheirNumbers, "§IV.C.4 says 3 days; §IV.C.5 scales \"3.5 days\" by 15/31 and gets 1.5, which is 3 days scaled. Its abstract says under four.");
|
||||
let qrom = "The paper's own two figures: Table III costs the algorithm with its own QROM choices; the layout takes an output expansion factor of 1 for the select reads (§IV.C.2), which holds fewer qubits and takes more Toffolis. Ours takes each in turn below.";
|
||||
r.text("femoco.table3.toffolis", "Toffolis, Table III against its layout", "—", Class::TheirNumbers, qrom);
|
||||
r.text("femoco.table3.qubits", "logical qubits, Table III against its layout's data", "—", Class::TheirNumbers, qrom);
|
||||
r.num("femoco.job.distance", "code distance, its layout's counts", b.distance as f64, F::I, Class::Assumption, "Its rule is `0.1·(100p)^((d+1)/2)` a cycle (§IV.C.5: \"Λ of 10\"); the planar model's `0.03·(p/0.01)^((d+1)/2)` a step of `d` cycles, lower by `d/0.3`, one step of distance at this size.");
|
||||
r.num("femoco.job.qubits.table", "physical qubits, job, Table III's counts", a.physical, F::I, Class::OurLimit, JOB_SPACE);
|
||||
r.num("femoco.job.qubits.layout", "physical qubits, job, its layout's counts", b.physical, F::I, Class::OurLimit, JOB_SPACE);
|
||||
r.num("femoco.job.days.table", "days, job, Table III's counts", a.runtime_h / 24.0, F::D(2), Class::OurLimit, JOB_TIME);
|
||||
r.num("femoco.job.days.layout", "days, job, its layout's counts", b.runtime_h / 24.0, F::D(2), Class::OurLimit, JOB_TIME);
|
||||
r.num("femoco.job.qubits.e4", "physical qubits, job, p = 10⁻⁴", low.physical, F::I, Class::OurLimit, JOB_SPACE);
|
||||
r.num("femoco.job.days.e4", "days, job, p = 10⁻⁴", low.runtime_h / 24.0, F::D(2), Class::OurLimit, JOB_TIME);
|
||||
Ok(section("FeMoCo on the surface code (arXiv:2011.03494, PRX Quantum 2, 030305, 2021)", r))
|
||||
}
|
||||
|
||||
fn rsa_2025() -> Result<Section, String> {
|
||||
let p = FactoringParams::published(2048).expect("a published row");
|
||||
let e = factoring_estimate(&p, &ArchMachine::published()).map_err(|x| x.to_string())?;
|
||||
let mut r = Rows::default();
|
||||
r.num("r25.qubits", "physical qubits", e.physical_qubits() as f64, F::I, Class::TheirNumbers, "Ours keeps 152 logical qubits hot by its peak formula and buys whole grid blocks; its count keeps 131 and a fractional block. At its 131 and 430 qubits a logical qubit, our arithmetic gives its 897,864.");
|
||||
r.num("r25.hours", "hours per shot", e.hours_per_shot_rounded, F::D(2), Class::TheirNumbers, "Its tallies at its stated durations give 10.62 hours, and its clock at whole milliseconds 10.58.");
|
||||
r.num("r25.days", "days per factoring", e.days, F::D(2), Class::TheirNumbers, "From the hours per shot above; it also multiplies by 9.1 shots where its table gives 9.2. It rounds 4.96 up to \"less than a week\".");
|
||||
r.num("r25.logical", "logical qubits", p.peak_logical_qubits() as f64, F::I, Class::TheirNumbers, "§3.2 prints 1,409 for its peak formula `m + 3f + 2ℓ + len m`, which evaluates to 1,432; its Table 4 gives 1,399.");
|
||||
let published_toffolis = p.toffolis_per_shot_source_rule(PhaseupCount::AsCoded) * f64::from(p.s + 1) / (1.0 - p.deviant);
|
||||
r.num("r25.toffolis", "Toffolis per factoring, by its counting rule", published_toffolis, F::E(2), Class::Agrees, "");
|
||||
Ok(section("RSA-2048 on yoked surface codes (arXiv:2505.15917, 2025)", r))
|
||||
}
|
||||
|
||||
fn planar_reference() -> Result<Section, String> {
|
||||
let counts = LogicalCounts { qubits: 12_581, measurements: 1_080_000_000, rotations: 12, rotation_depth: 12, t_gates: 12, ccz: 3_730_000_000 };
|
||||
let e = planar(&counts, &PhysicalQubit::ns_e4(), &QecModel::surface_gate(), &EstimateConfig::new(1.0 / 3.0)).map_err(|x| format!("{x:?}"))?;
|
||||
let mut r = Rows::default();
|
||||
r.num("planar.distance", "code distance, RSA-2048, (ns, 10⁻⁴)", f64::from(e.distance), F::I, Class::Agrees, "");
|
||||
r.num("planar.factories", "factories", e.factories as f64, F::I, Class::Agrees, "");
|
||||
r.num("planar.qubits", "physical qubits", e.physical_qubits as f64, F::I, Class::Agrees, "");
|
||||
r.num("planar.hours", "run time, hours", e.runtime_ns / 3.6e12, F::D(3), Class::Agrees, "Table IV prints 18 hours.");
|
||||
Ok(section("The planar model's own source (arXiv:2211.07629, 2022)", r))
|
||||
}
|
||||
|
||||
/// Every section, with the search run once per code.
|
||||
pub fn report() -> Result<Vec<Section>, String> {
|
||||
let gross = PauliCosts::search(Code::Gross);
|
||||
let two = PauliCosts::search(Code::TwoGross);
|
||||
Ok(vec![machines(), rates(), compile(&gross, &two), capability(), ising(&gross, &two)?, rsa_2021()?, femoco()?, rsa_2025()?, planar_reference()?])
|
||||
}
|
||||
|
||||
/// The rows as Markdown tables, one per section.
|
||||
pub fn markdown(sections: &[Section]) -> String {
|
||||
let mut out = String::new();
|
||||
for s in sections {
|
||||
out.push_str(&format!("### {}\n\n", s.title));
|
||||
out.push_str("| Quantity | Source | Published | Ours | Delta | Class | Why |\n|---|---|---:|---:|---:|---|---|\n");
|
||||
for r in &s.rows {
|
||||
out.push_str(&format!("| {} | {} | {} | {} | {} | {} | {} |\n", r.quantity, r.source, r.published, r.ours, r.delta, r.class.name(), r.why));
|
||||
}
|
||||
out.push('\n');
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// The rows as plain columns.
|
||||
pub fn text(sections: &[Section]) -> String {
|
||||
let mut out = String::new();
|
||||
for s in sections {
|
||||
out.push_str(&format!("== {}\n", s.title));
|
||||
for r in &s.rows {
|
||||
out.push_str(&format!("{:<76} published {:>24} ours {:>18} delta {:>9} {}\n", r.quantity, r.published, r.ours, r.delta, r.class.name()));
|
||||
}
|
||||
out.push('\n');
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// For each numeric row that does not agree: its id and ours to four
|
||||
/// significant digits, the guard its line in the published figures takes.
|
||||
pub fn guards(sections: &[Section]) -> String {
|
||||
let mut out = String::new();
|
||||
for r in sections.iter().flat_map(|s| &s.rows) {
|
||||
if let (Some((_, ours)), false) = (r.values, r.class == Class::Agrees) {
|
||||
out.push_str(&format!("{}\t{:.3e}\n", r.id, ours));
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Whether a row holds to its published figure's rule, and why not.
|
||||
pub fn check(r: &Row) -> Result<(), String> {
|
||||
let pin = pins().get(&r.id).ok_or(format!("{}: no published figure", r.id))?;
|
||||
match (r.values, r.class, pin.rule) {
|
||||
(None, _, Rule::Text) => Ok(()),
|
||||
(None, _, rule) => Err(format!("{}: a row with no number, its figure's rule {rule:?}", r.id)),
|
||||
(Some(_), _, Rule::Text) => Err(format!("{}: a number against a text figure", r.id)),
|
||||
(Some((value, ours)), Class::Agrees, rule) => {
|
||||
if matches!(rule, Rule::Guard(_)) {
|
||||
return Err(format!("{}: an agreeing row needs the rule its figure is printed to, not a guard", r.id));
|
||||
}
|
||||
if holds(rule, value, ours, r.band) { Ok(()) } else { Err(format!("{}: {ours} against {value} by {rule:?} (band {:?})", r.id, r.band)) }
|
||||
}
|
||||
(Some((_, ours)), _, Rule::Guard(g)) => {
|
||||
if holds(Rule::Guard(g), 0.0, ours, None) { Ok(()) } else { Err(format!("{}: ours is {ours:.3e}, its guard {g:e}: update the guard, the reason and the page together", r.id)) }
|
||||
}
|
||||
(Some(_), class, rule) => Err(format!("{}: a {} row needs a guard, not {rule:?}", r.id, class.name())),
|
||||
}
|
||||
}
|
||||
|
||||
/// How many rows of each class, in [`Class`] order.
|
||||
pub fn tally(sections: &[Section]) -> [(Class, usize); 6] {
|
||||
let classes = [Class::Agrees, Class::Assumption, Class::TheirModel, Class::TheirNumbers, Class::OurLimit, Class::Open];
|
||||
classes.map(|c| (c, sections.iter().flat_map(|s| &s.rows).filter(|r| r.class == c).count()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn the_deltas_are_what_they_say() {
|
||||
assert_eq!(delta(10.0, 10.0), "0");
|
||||
assert_eq!(delta(10.0, 11.0), "+10.00%");
|
||||
assert_eq!(delta(10.0, 9.0), "-10.00%");
|
||||
assert_eq!(delta(10.0, 30.0), "×3.000");
|
||||
assert_eq!(delta(1.0, 300.0), "×3.0e2");
|
||||
assert_eq!(print(1_234_567.0, F::I), "1,234,567");
|
||||
assert_eq!(print(999.0, F::I), "999");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_rule_holds_to_the_printed_digits_and_no_further() {
|
||||
// 8.72M printed to its last unit: 8,716,258 holds, 9.00M would not.
|
||||
assert!(holds(Rule::Nearest(0.01e6), 8.72e6, 8_716_258.0, None));
|
||||
assert!(!holds(Rule::Nearest(0.01e6), 9.00e6, 8_716_258.0, None));
|
||||
// Six percent was the old tolerance; the printed digit is tighter.
|
||||
assert!(!holds(Rule::Nearest(0.01e6), 8.72e6, 8.72e6 * 1.05, None));
|
||||
// Rounded up: 19.25 M is "20 M", 20.3 M is not, nor is 18.9 M.
|
||||
assert!(holds(Rule::Up(1e6), 20e6, 19.25e6, None));
|
||||
assert!(!holds(Rule::Up(1e6), 20e6, 20.3e6, None));
|
||||
assert!(!holds(Rule::Up(1e6), 20e6, 18.9e6, None));
|
||||
assert!(holds(Rule::Down(1.0), 25.0, 25.81, None));
|
||||
assert!(!holds(Rule::Down(1.0), 25.0, 26.1, None));
|
||||
// A band meets the printed figure's interval, or does not.
|
||||
assert!(holds(Rule::Band(0.1e-21), 8.2e-21, 8.13e-21, Some((8.06e-21, 8.24e-21))));
|
||||
assert!(!holds(Rule::Band(0.1e-21), 8.2e-21, 8.13e-21, Some((8.06e-21, 8.14e-21))));
|
||||
assert!(holds(Rule::Guard(1.467e7), 0.0, 14_665_600.0, None));
|
||||
assert!(!holds(Rule::Guard(1.467e7), 0.0, 14_592_000.0, None));
|
||||
assert!(holds(Rule::Exact, 381.0, 381.0, None) && !holds(Rule::Exact, 381.0, 380.0, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_published_figures_read_and_each_says_where_it_is_printed() {
|
||||
let p = pins();
|
||||
assert!(p.len() > 150, "{}", p.len());
|
||||
for (id, pin) in p {
|
||||
assert!(pin.source.starts_with("arXiv:"), "{id}: {}", pin.source);
|
||||
assert!(!pin.printed.is_empty(), "{id}");
|
||||
assert_eq!(pin.value.is_none(), pin.rule == Rule::Text, "{id}");
|
||||
}
|
||||
// Fig. 10(a)'s surface-code timesteps are its printed figures, not a
|
||||
// formula compared with itself.
|
||||
let steps: Vec<f64> = ["gross_e3_5k", "two_e3_50k", "gross_e4_5k", "gross_e4_50k", "two_e4_50k", "two_e4_500k"].iter().map(|t| p[&format!("fig10a.surface.{t}.steps")].value.unwrap()).collect();
|
||||
assert_eq!(steps, [381.0, 2269.0, 115.0, 115.0, 509.0, 509.0]);
|
||||
// As the PDF prints them, or from the source files and said so.
|
||||
assert_eq!(p["a10.bound.two"].printed, "7.32·10⁻⁴");
|
||||
assert_eq!(p["a10.bound.gross"].printed, "2.09·10⁻⁵");
|
||||
assert_eq!(p["table10.two.I.1e-3"].printed, "8.2·10⁻²¹");
|
||||
for (id, pin) in p.iter().filter(|(id, _)| id.starts_with("fig10a.") && id.ends_with(".nt")) {
|
||||
assert!(pin.source.ends_with("source files") || id.contains("surface"), "{id}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(debug_assertions, ignore = "the search over 4¹¹ Paulis takes minutes in a debug build")]
|
||||
fn the_page_is_what_the_estimators_give() {
|
||||
let page = include_str!("../docs/published-architectures.md");
|
||||
let (begin, end) = ("<!-- the rows: written by `--example published_architectures --markdown`; a test holds them -->\n\n", "<!-- end of the rows -->");
|
||||
let start = page.find(begin).expect("the page's first marker") + begin.len();
|
||||
let stop = page.find(end).expect("the page's second marker");
|
||||
let want = markdown(&report().unwrap());
|
||||
assert!(page[start..stop] == want, "the page differs from the estimators: run the example and read the difference");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(debug_assertions, ignore = "the search over 4¹¹ Paulis takes minutes in a debug build")]
|
||||
fn every_row_holds_to_its_published_figure() {
|
||||
let sections = report().unwrap();
|
||||
let mut used = std::collections::BTreeSet::new();
|
||||
let mut bad = Vec::new();
|
||||
for r in sections.iter().flat_map(|s| &s.rows) {
|
||||
if r.class != Class::Agrees {
|
||||
assert!(!r.why.is_empty(), "{}: a {} row with no reason", r.id, r.class.name());
|
||||
}
|
||||
assert!(used.insert(r.id.clone()), "{}: two rows", r.id);
|
||||
if let Err(e) = check(r) {
|
||||
bad.push(e);
|
||||
}
|
||||
}
|
||||
assert!(bad.is_empty(), "{bad:#?}");
|
||||
let unused: Vec<_> = pins().keys().filter(|k| !used.contains(*k)).collect();
|
||||
assert!(unused.is_empty(), "published figures no row takes: {unused:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(debug_assertions, ignore = "the search over 4¹¹ Paulis takes minutes in a debug build")]
|
||||
fn the_ours_column_holds_only_ours_and_the_text_says_what_the_sources_say() {
|
||||
let sections = report().unwrap();
|
||||
let rows: BTreeMap<&str, &Row> = sections.iter().flat_map(|s| &s.rows).map(|r| (r.id.as_str(), r)).collect();
|
||||
let synthesised = ising_t_count(5e-9).unwrap() as f64;
|
||||
// The Ising program's T gates as the text states them, beside ours.
|
||||
assert_eq!(rows["s4.nt"].values.unwrap().1, synthesised);
|
||||
// The FeMoCo paper's two figures are both the paper's: no "ours".
|
||||
assert_eq!(rows["femoco.table3.toffolis"].ours, "—");
|
||||
assert_eq!(rows["femoco.table3.qubits"].ours, "—");
|
||||
// The released compiler is cited, and nothing says it is not released.
|
||||
assert!(rows["fig9.chosen.gross"].why.contains("bicycle_cliffords 0.1.0"));
|
||||
assert!(rows["fig10a.gross_e4_5k.nt"].why.contains("bicycle_compiler 0.1.0"));
|
||||
let all: String = sections.iter().flat_map(|s| &s.rows).map(|r| format!("{} {} {}\n", r.quantity, r.source, r.why)).collect();
|
||||
for gone in ["not released", "Fig. 16", "shortfall", "press release", "announced", "every R ≠ I"] {
|
||||
assert!(!all.contains(gone), "{gone}");
|
||||
}
|
||||
assert!(rows["fig10a.gross_e3_5k.nt"].why.contains("Fig. 17") || rows["fig10a.gross_e3_5k.nt_undivided"].why.contains("Fig. 17"));
|
||||
// The arXiv:2308.07915 rows are open, the gap unexplained.
|
||||
for t in ["gross.1e-3", "gross.1e-4", "two.1e-3", "two.1e-4"] {
|
||||
assert_eq!(rows[format!("2308.table1.{t}").as_str()].class, Class::Open);
|
||||
}
|
||||
// The placement of the Ising factory is a stated choice, not a match.
|
||||
assert_eq!(rows["table9.gross.nc"].class, Class::Assumption);
|
||||
assert!(rows["table9.gross.nc"].why.contains("781,200"));
|
||||
// One computation for the expected hours, in the row and its text.
|
||||
let e = windowed_factoring_estimate(&WindowedFactoringParams::published(2048).unwrap(), 1e-3, 1.0, 10.0);
|
||||
assert_eq!(rows["r21.title.hours"].values.unwrap().1, e.expected_hours());
|
||||
assert!(rows["r21.title.hours"].why.contains(&print(e.expected_hours(), F::D(2))));
|
||||
// The division by C is ours, and the capability row says how much of
|
||||
// the gap it is.
|
||||
assert_eq!(rows["fig10a.gross_e3_5k.nt"].class, Class::Assumption);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_division_by_c_is_a_third_of_a_point_of_the_gross_capability() {
|
||||
let m = Machine::largest(Code::Gross, TFactory::gross_e3(), 5_000).unwrap();
|
||||
let (ours, undivided) = (m.capability(1e-3, 1.0 / 3.0), m.capability_undivided(1e-3, 1.0 / 3.0));
|
||||
let share = ours / undivided - 1.0;
|
||||
assert!((0.002..0.004).contains(&share), "{share}");
|
||||
// Undivided, ours is within 0.15% of the source's 13.5958.
|
||||
assert!((undivided / 13.595_802_668_072_07 - 1.0).abs() < 0.0015, "{undivided}");
|
||||
}
|
||||
|
||||
/// The Ising row's text names these.
|
||||
#[test]
|
||||
fn the_ising_angles_take_these_t_counts() {
|
||||
assert_eq!(ising_t_counts(5e-9).unwrap(), [79, 80, 81, 84]);
|
||||
assert_eq!(ising_t_count(5e-9).unwrap(), 14_665_600);
|
||||
// pygridsynth 1.0.1's counts on the same angles give the source's total.
|
||||
assert_eq!(80 * (4 * (360 * 86 + 100 * 80) + 360 * 84 + 100 * 82), 15_542_400);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_surface_rows_take_the_largest_whole_t_count() {
|
||||
// §A.10: "We find the maximum k ∈ N". Its formula gives 7.8 at 5,000
|
||||
// qubits and p = 10⁻³; the table prints 7.
|
||||
let (n, nt, _) = surface_source_row(5_000, 454, 5, 1e-3);
|
||||
assert_eq!((n, nt), (45, 7.0));
|
||||
assert_eq!(surface_source_row(5_000, 810, 7, 1e-4).1, 377_928.0);
|
||||
assert_eq!(surface_source_row(50_000, 810, 7, 1e-4).1, 31_746.0);
|
||||
}
|
||||
}
|
||||
|
|
@ -144,6 +144,42 @@
|
|||
//! takes 10.58 h. A factoring takes 4.3 days, shots lost to logical errors
|
||||
//! included.
|
||||
//!
|
||||
//! # The 2021 factoring estimate, re-run
|
||||
//!
|
||||
//! arXiv:1905.09749 (Quantum 5, 433) factors 2048 bits on 20 million qubits in
|
||||
//! hours, under the same physical assumptions as above, with a different
|
||||
//! machine:
|
||||
//! - plain patches with no yoked storage;
|
||||
//! - a two-level factory, 15-to-1 at a smaller distance feeding 8T-to-CCZ
|
||||
//! ([`DistilledCczFactory`]);
|
||||
//! - Toffolis whose Clifford fixups are teleported away from the data, so an
|
||||
//! addition runs at one *tick* per Toffoli, the slower of the reaction time
|
||||
//! and the CCZ supply, and does not wait a lattice-surgery *beat* of `d`
|
||||
//! cycles ([`Timing::tick_us`], [`Timing::teleported_add_us`]);
|
||||
//! - lookups through access hallways on both sides of each row, at half a beat
|
||||
//! per entry ([`Timing::double_access_lookup_us`]).
|
||||
//!
|
||||
//! [`WindowedFactoringParams`] carries its parameters and
|
||||
//! [`windowed_factoring_estimate`] re-runs its cost script. Every row of its
|
||||
//! RSA table is reproduced to the printed precision, by the script's own
|
||||
//! rounding, which takes each figure up to two significant digits. So the
|
||||
//! "20 million" is 19.25 million and the 5.1 hours per run is 5.05.
|
||||
//!
|
||||
//! Its title's 8 hours is the expected time across retries
|
||||
//! ([`WindowedEstimate::expected_hours`]): the re-run's 5.05 hours a run at its
|
||||
//! 30.98% retry risk is 7.31, taken up to one digit.
|
||||
//!
|
||||
//! **Where the source disagrees with itself.**
|
||||
//! - Its layout section works one case by hand at level-1 distance 17, a
|
||||
//! 226 × 63 board and 23 million qubits, and says so. The title and the table
|
||||
//! take level-1 distance 15, a 198 × 62 board and 19.25 million.
|
||||
//! - That section reads a distillation error of 6.4% off a spreadsheet. Its cost
|
||||
//! script's formula gives 0.6% at the same distances.
|
||||
//!
|
||||
//! The same factory and clock price the chemistry estimate of
|
||||
//! arXiv:2011.03494 (PRX Quantum 2, 030305): four factories at distances 19 and
|
||||
//! 31 tick at 38.75 µs, and 6.7·10⁹ Toffolis take 3 days.
|
||||
//!
|
||||
//! # Honest boundaries
|
||||
//!
|
||||
//! - **Fits are fits.** The storage formulas are path-counting extrapolations
|
||||
|
|
@ -757,6 +793,75 @@ impl Timing {
|
|||
pub fn phaseup_us(&self, w: u32) -> f64 {
|
||||
self.lookup_us(w) / 2.0
|
||||
}
|
||||
/// One tick: the slower of the CCZ supply and the reaction time. A Toffoli
|
||||
/// whose Clifford fixups are teleported away from the data takes one tick
|
||||
/// and no lattice-surgery beat, unlike a [`Timing::step_us`].
|
||||
pub fn tick_us(&self) -> f64 {
|
||||
self.ccz_period_us().max(self.reaction_us)
|
||||
}
|
||||
/// A ripple-carry addition over `n` qubits, its Toffolis at one tick each:
|
||||
/// `2n − 1` ticks, a sweep and its return.
|
||||
pub fn teleported_add_us(&self, n: u32) -> f64 {
|
||||
f64::from((2 * n).saturating_sub(1)) * self.tick_us()
|
||||
}
|
||||
/// A table lookup over `w` address bits through access hallways on both
|
||||
/// sides of each row: `2ʷ − 1` entries at half a beat each.
|
||||
pub fn double_access_lookup_us(&self, w: u32) -> f64 {
|
||||
((1u64 << w) - 1) as f64 * self.surgery_us() / 2.0
|
||||
}
|
||||
/// The measurement-based uncomputation of that lookup: `2·√(2ʷ − 1)`
|
||||
/// entries at half a beat each.
|
||||
pub fn double_access_unlookup_us(&self, w: u32) -> f64 {
|
||||
2.0 * (((1u64 << w) - 1) as f64).sqrt() * self.surgery_us() / 2.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Logical error of one plain patch per surface-code cycle:
|
||||
/// `0.1·(100·p)^((d+1)/2)`, so at `p = 10⁻³` each two of distance give a factor
|
||||
/// of ten. The rule of arXiv:1905.09749, its "Topological error" section and
|
||||
/// its cost script.
|
||||
pub fn patch_cycle_error(d: u32, p: f64) -> f64 {
|
||||
0.1 * exp(0.5 * f64::from(d + 1) * ln(100.0 * p))
|
||||
}
|
||||
|
||||
/// A two-level magic-state factory: 15-to-1 at distance `l1_distance` feeding
|
||||
/// 8T-to-CCZ at `l2_distance` (arXiv:1812.01238, with the footprint rule of the
|
||||
/// cost script of arXiv:1905.09749).
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct DistilledCczFactory {
|
||||
pub l1_distance: u32,
|
||||
pub l2_distance: u32,
|
||||
}
|
||||
|
||||
impl DistilledCczFactory {
|
||||
/// `(width, height, depth)`, in patches of the level-2 distance and beats:
|
||||
/// the six level-1 factories that feed one CCZ state beside the 3 × 6 CCZ
|
||||
/// block. `(15, 8, 5)` at distances 19 and 31, `(14, 8, 5)` at 9 and 15.
|
||||
pub fn footprint(&self) -> (u32, u32, f64) {
|
||||
let scale = f64::from(self.l1_distance) / f64::from(self.l2_distance);
|
||||
let (t1_height, t1_width, t1_depth) = (4.0 * scale, 8.0 * scale, 5.75 * scale);
|
||||
let (ccz_depth, ccz_height, ccz_width) = (5.0_f64, 6.0_f64, 3.0);
|
||||
let storage_width = 2.0 * scale;
|
||||
let t1_factories = ((1.0 / ccz_depth * 8.0) / (1.0 / t1_depth)).ceil();
|
||||
let column = t1_height * (t1_factories / 2.0).ceil();
|
||||
let width = (t1_width * 2.0 + ccz_width + storage_width).ceil();
|
||||
let height = ccz_height.max(column).ceil();
|
||||
(width as u32, height as u32, ccz_depth.max(t1_depth))
|
||||
}
|
||||
|
||||
/// Cycles per CCZ state: the depth in beats, times the level-2 distance.
|
||||
pub fn rounds_per_ccz(&self) -> f64 {
|
||||
self.footprint().2 * f64::from(self.l2_distance)
|
||||
}
|
||||
|
||||
/// Error of one CCZ state at physical error `p`. Physical T states at level
|
||||
/// 0 err by `p` plus 100 cells at half the level-1 distance; level 1 gives
|
||||
/// `35·p₀³` plus 1100 cells; level 2 gives `28·p₁²` plus 1000 cells.
|
||||
pub fn error(&self, p: f64) -> f64 {
|
||||
let l0 = p + 100.0 * patch_cycle_error(self.l1_distance / 2, p);
|
||||
let l1 = 35.0 * l0 * l0 * l0 + 1100.0 * patch_cycle_error(self.l1_distance, p);
|
||||
28.0 * l1 * l1 + 1000.0 * patch_cycle_error(self.l2_distance, p)
|
||||
}
|
||||
}
|
||||
|
||||
/// The parameters of the approximate-residue factoring algorithm of
|
||||
|
|
@ -1146,6 +1251,159 @@ pub fn factoring_estimate(params: &FactoringParams, machine: &Machine) -> Result
|
|||
})
|
||||
}
|
||||
|
||||
/// The parameters of the windowed factoring construction of arXiv:1905.09749.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct WindowedFactoringParams {
|
||||
/// Bits in the modulus.
|
||||
pub n: u32,
|
||||
/// Exponent qubits, `3(n/2 − 1) − 40` for an RSA modulus in one run.
|
||||
pub exponent_qubits: u32,
|
||||
pub exp_window: u32,
|
||||
pub mul_window: u32,
|
||||
/// Bits between the oblivious carry runways.
|
||||
pub runway_sep: u32,
|
||||
/// Runway and coset padding beyond `⌈log₂(n²·nₑ)⌉`.
|
||||
pub padding_offset: u32,
|
||||
pub factory: DistilledCczFactory,
|
||||
}
|
||||
|
||||
impl WindowedFactoringParams {
|
||||
/// A row of the source's RSA table (its table of implications for RSA), for
|
||||
/// `n` ∈ {1024, 2048, 3072, 4096, 8192, 12288, 16384}.
|
||||
pub fn published(n: u32) -> Option<WindowedFactoringParams> {
|
||||
let (l1_distance, l2_distance, padding_offset, mul_window) = match n {
|
||||
1024 => (15, 27, 5, 5),
|
||||
2048 => (15, 27, 4, 5),
|
||||
3072 => (17, 29, 6, 4),
|
||||
4096 => (17, 31, 9, 4),
|
||||
8192 => (19, 33, 4, 4),
|
||||
12288 => (19, 33, 3, 4),
|
||||
16384 => (19, 33, 4, 4),
|
||||
_ => return None,
|
||||
};
|
||||
Some(WindowedFactoringParams {
|
||||
n,
|
||||
exponent_qubits: 3 * (n / 2 - 1) - 40,
|
||||
exp_window: 5,
|
||||
mul_window,
|
||||
runway_sep: 1024,
|
||||
padding_offset,
|
||||
factory: DistilledCczFactory { l1_distance, l2_distance },
|
||||
})
|
||||
}
|
||||
|
||||
/// The carry runway and coset padding: `⌈log₂(n²·nₑ)⌉` plus the offset,
|
||||
/// as the source's cost script takes it (38 at `n = 2048`). Its text
|
||||
/// approximates it as `3·lg n + 10`.
|
||||
pub fn padding(&self) -> u64 {
|
||||
let n = u64::from(self.n);
|
||||
let square = n * n * u64::from(self.exponent_qubits);
|
||||
u64::from(64 - (square - 1).leading_zeros()) + u64::from(self.padding_offset)
|
||||
}
|
||||
|
||||
/// Qubits in one runway-separated piece of the register: the separation
|
||||
/// and the padding.
|
||||
pub fn piece_qubits(&self) -> u64 {
|
||||
u64::from(self.runway_sep) + self.padding()
|
||||
}
|
||||
}
|
||||
|
||||
/// What the windowed construction costs, per run.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct WindowedEstimate {
|
||||
/// Runway-separated pieces of the register, and each piece's board.
|
||||
pub pieces: u64,
|
||||
pub piece_width: u64,
|
||||
pub piece_height: u64,
|
||||
/// CCZ factories over all pieces.
|
||||
pub factories: u64,
|
||||
/// Patches on the board, and the physical qubits they cover.
|
||||
pub logical_qubits: u64,
|
||||
pub physical_qubits: u64,
|
||||
pub toffolis: f64,
|
||||
pub timing: Timing,
|
||||
/// One lookup addition, µs.
|
||||
pub inner_loop_us: f64,
|
||||
pub hours: f64,
|
||||
pub distillation_error: f64,
|
||||
pub topological_error: f64,
|
||||
pub deviation_error: f64,
|
||||
/// The chance a run must be retried: the union of the three above and a
|
||||
/// 1% post-processing allowance.
|
||||
pub retry_risk: f64,
|
||||
}
|
||||
|
||||
impl WindowedEstimate {
|
||||
/// Physical qubits × hours, in megaqubit-days.
|
||||
/// Hours expected across retries: a run's hours over the chance it needs
|
||||
/// no retry.
|
||||
pub fn expected_hours(&self) -> f64 {
|
||||
self.hours / (1.0 - self.retry_risk)
|
||||
}
|
||||
|
||||
pub fn megaqubit_days(&self) -> f64 {
|
||||
self.physical_qubits as f64 / 1e6 * self.hours / 24.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-run the cost script of arXiv:1905.09749 at physical error `p`, cycle time
|
||||
/// and reaction time in µs. Factory pairs are added until the CCZ supply keeps
|
||||
/// up with the reaction time, and each runway-separated piece gets its own.
|
||||
pub fn windowed_factoring_estimate(params: &WindowedFactoringParams, p: f64, cycle_us: f64, reaction_us: f64) -> WindowedEstimate {
|
||||
let n = u64::from(params.n);
|
||||
let n_e = u64::from(params.exponent_qubits);
|
||||
let sep = u64::from(params.runway_sep);
|
||||
let pieces = n.div_ceil(sep);
|
||||
let padding = params.padding();
|
||||
let piece_len = params.piece_qubits();
|
||||
let mul_in_bits = n + padding + 2;
|
||||
let inner_loops = (n_e * 2 * mul_in_bits).div_ceil(u64::from(params.exp_window * params.mul_window));
|
||||
let classical = inner_loops as f64 * pieces as f64 / pow2(padding as i32);
|
||||
let deviation_error = 4.0 * classical.sqrt();
|
||||
|
||||
let w = params.exp_window + params.mul_window;
|
||||
let d = params.factory.l2_distance;
|
||||
let (fw, fh, depth) = params.factory.footprint();
|
||||
let (fw, fh) = (u64::from(fw), u64::from(fh));
|
||||
let ccz_rounds = depth * f64::from(d);
|
||||
let pairs = (ccz_rounds * cycle_us / reaction_us / 2.0).ceil() as u64;
|
||||
let width = (fw + 1) * pairs + 1;
|
||||
let register_rows = piece_len.div_ceil(width - 2);
|
||||
let height = fh * 2 + 3 * 2 + 3 + 6 + register_rows * 3;
|
||||
let logical_qubits = width * height * pieces;
|
||||
let distillation_area = fh * fw * pairs * 2 * pieces;
|
||||
|
||||
let timing = Timing { cycle_us, reaction_us, distance: d, ccz_rounds, factories: (2 * pairs) as u32 };
|
||||
let adder_depth = (piece_len * 2 - 1) as f64;
|
||||
let lookup_depth = ((1u64 << w) - 1) as f64;
|
||||
let unlookup_depth = 2.0 * lookup_depth.sqrt();
|
||||
let toffolis = (adder_depth * pieces as f64 + lookup_depth + unlookup_depth) * inner_loops as f64;
|
||||
let inner_loop_us = timing.teleported_add_us(piece_len as u32) + timing.double_access_lookup_us(w) + timing.double_access_unlookup_us(w);
|
||||
let micros = inner_loop_us * inner_loops as f64;
|
||||
|
||||
let cells = (logical_qubits - distillation_area) as f64 * (micros / cycle_us);
|
||||
let topological_error = cells * patch_cycle_error(d, p);
|
||||
let distillation_error = toffolis * params.factory.error(p);
|
||||
let survive = [topological_error, distillation_error, deviation_error, 1e-2].iter().fold(1.0, |t, e: &f64| if *e >= 1.0 { 0.0 } else { t * (1.0 - e) });
|
||||
|
||||
WindowedEstimate {
|
||||
pieces,
|
||||
piece_width: width,
|
||||
piece_height: height,
|
||||
factories: 2 * pairs * pieces,
|
||||
logical_qubits,
|
||||
physical_qubits: logical_qubits * patch_qubits(d),
|
||||
toffolis,
|
||||
timing,
|
||||
inner_loop_us,
|
||||
hours: micros / 3.6e9,
|
||||
distillation_error,
|
||||
topological_error,
|
||||
deviation_error,
|
||||
retry_risk: 1.0 - survive,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
@ -1354,4 +1612,124 @@ mod tests {
|
|||
let m = StorageModel { flat: f, ..StorageModel::uniform_refit() };
|
||||
assert_eq!(flat_distance(&m, 1e-15), Some(26));
|
||||
}
|
||||
|
||||
/// The source's rounding: up, to two significant digits.
|
||||
fn printed(q: f64) -> f64 {
|
||||
let n = q.log10().floor();
|
||||
let r = (q / 10f64.powf(n - 1.0)).ceil() * 10f64.powf(n - 1.0);
|
||||
if r < 0.1 {
|
||||
(r * 100.0).round() / 100.0
|
||||
} else if r < 10.0 {
|
||||
(r * 10.0).round() / 10.0
|
||||
} else {
|
||||
r.round()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_title_s_hours_are_the_expected_hours_the_module_states() {
|
||||
// The module's text: "5.05 hours a run at its 30.98% retry risk is
|
||||
// 7.31", which the title's 8 hours takes up to one digit.
|
||||
let e = windowed_factoring_estimate(&WindowedFactoringParams::published(2048).unwrap(), 1e-3, 1.0, 10.0);
|
||||
assert_eq!(e.expected_hours(), e.hours / (1.0 - e.retry_risk));
|
||||
assert_eq!(format!("{:.2} {:.2} {:.2}", e.hours, 100.0 * e.retry_risk, e.expected_hours()), "5.05 30.98 7.31");
|
||||
assert!(e.expected_hours().ceil() == 8.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_teleported_addition_runs_at_the_tick_and_not_the_beat() {
|
||||
// arXiv:1905.09749, its Runtime section (§2.11) at n = 2048: 14
|
||||
// factories at distance 27 keep up with a 10 µs reaction time. An
|
||||
// addition over a piece of c_sep + c_pad qubits takes "≈ 22
|
||||
// milliseconds", a lookup over 10 address bits "≈ 14 milliseconds".
|
||||
// Its cost script's padding is 38 (its text's 3·lg n + 10 is 43): a
|
||||
// piece of 1,062 qubits.
|
||||
let piece = WindowedFactoringParams::published(2048).unwrap().piece_qubits();
|
||||
assert_eq!(piece, 1024 + 38);
|
||||
let t = Timing { cycle_us: 1.0, reaction_us: 10.0, distance: 27, ccz_rounds: 135.0, factories: 14 };
|
||||
assert_eq!(t.tick_us(), 10.0);
|
||||
assert!((t.teleported_add_us(piece as u32) / 1000.0 - 21.23).abs() < 1e-9);
|
||||
// At its text's padding, 2n − 1 ticks are 21.33 ms; its text counts
|
||||
// 2(c_sep + c_pad) ticks, 21.34 ms, and prints "≈ 22".
|
||||
assert!((t.teleported_add_us(1024 + 43) / 1000.0 - 21.33).abs() < 1e-9);
|
||||
assert!((t.double_access_lookup_us(10) / 1000.0 - 13.81).abs() < 0.01);
|
||||
// The step clock waits a beat at every Toffoli: 57.3 ms.
|
||||
assert!((t.add_us(piece as u32) / 1000.0 - 57.294).abs() < 1e-9);
|
||||
assert!(t.add_us(piece as u32) > 2.5 * t.teleported_add_us(piece as u32));
|
||||
// Too few factories: the supply sets the tick.
|
||||
let starved = Timing { factories: 4, ..t };
|
||||
assert_eq!(starved.tick_us(), 33.75);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_two_level_factory_has_the_published_footprints_and_errors() {
|
||||
// arXiv:1905.09749, the layout section: 15 × 8 at distances 17 and 27.
|
||||
assert_eq!(DistilledCczFactory { l1_distance: 17, l2_distance: 27 }.footprint().0, 15);
|
||||
assert_eq!(DistilledCczFactory { l1_distance: 17, l2_distance: 27 }.footprint().1, 8);
|
||||
// arXiv:2011.03494: "15d × 8d and a depth of 5d" at 19 and 31.
|
||||
let f = DistilledCczFactory { l1_distance: 19, l2_distance: 31 };
|
||||
assert_eq!(f.footprint(), (15, 8, 5.0));
|
||||
// ... and "14d × 8d" at 9 and 15.
|
||||
assert_eq!(DistilledCczFactory { l1_distance: 9, l2_distance: 15 }.footprint().0, 14);
|
||||
// "a roughly 0.1% chance of any distillation failure occurring when
|
||||
// executing ten billion Toffolis".
|
||||
let chance = 1e10 * f.error(1e-3);
|
||||
assert!((0.0009..0.0011).contains(&chance), "{chance}");
|
||||
// Its text reads "a total distillation error of 6.4%" for 3 billion at 17
|
||||
// and 27 off another paper's spreadsheet. Its own cost script's formula,
|
||||
// which produces its tables, gives 0.6%.
|
||||
let chance = 3e9 * DistilledCczFactory { l1_distance: 17, l2_distance: 27 }.error(1e-3);
|
||||
assert!((0.0055..0.0065).contains(&chance), "{chance}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_2021_rsa_table_is_reproduced_to_its_printed_digits() {
|
||||
// (n, retry risk %, volume per run, volume expected, megaqubits, hours)
|
||||
for (n, risk, volume, expected, mq, hours) in [
|
||||
(1024, 6.0, 0.5, 0.5, 9.7, 1.3),
|
||||
(2048, 31.0, 4.1, 5.9, 20.0, 5.1),
|
||||
(3072, 9.0, 19.0, 21.0, 38.0, 12.0),
|
||||
(4096, 5.0, 48.0, 51.0, 55.0, 22.0),
|
||||
(8192, 5.0, 480.0, 510.0, 140.0, 86.0),
|
||||
(12288, 12.0, 1700.0, 1900.0, 200.0, 200.0),
|
||||
(16384, 24.0, 3900.0, 5100.0, 270.0, 350.0),
|
||||
] {
|
||||
let e = windowed_factoring_estimate(&WindowedFactoringParams::published(n).unwrap(), 1e-3, 1.0, 10.0);
|
||||
assert_eq!((100.0 * e.retry_risk).ceil(), risk, "n={n}: {}", e.retry_risk);
|
||||
let at_published_risk = 1.0 - (100.0 * e.retry_risk).ceil() / 100.0;
|
||||
assert_eq!(printed(e.megaqubit_days()), volume, "n={n}");
|
||||
assert_eq!(printed(e.megaqubit_days() / at_published_risk), expected, "n={n}");
|
||||
assert_eq!(printed(e.physical_qubits as f64 / 1e6), mq, "n={n}");
|
||||
assert_eq!(printed(e.hours), hours, "n={n}");
|
||||
}
|
||||
let e = windowed_factoring_estimate(&WindowedFactoringParams::published(2048).unwrap(), 1e-3, 1.0, 10.0);
|
||||
assert_eq!((e.piece_width * e.pieces, e.piece_height), (198, 62));
|
||||
assert_eq!(e.physical_qubits, 198 * 62 * 1568);
|
||||
// Its layout section: 14 factories in each of the two pieces.
|
||||
assert_eq!(e.factories, 28);
|
||||
assert!((e.toffolis / 2.698e9 - 1.0).abs() < 1e-3, "{}", e.toffolis);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_chemistry_estimate_is_priced_by_the_same_clock() {
|
||||
// arXiv:2011.03494, its surface-code section. Four factories at
|
||||
// distances 19 and 31, "a Toffoli production rate of 25 kHz"; 483,000
|
||||
// inner loops of 13,880 Toffolis, "3 days"; 53 × 36 patches, "about four
|
||||
// million" qubits.
|
||||
let f = DistilledCczFactory { l1_distance: 19, l2_distance: 31 };
|
||||
let t = Timing { cycle_us: 1.0, reaction_us: 10.0, distance: 31, ccz_rounds: f.rounds_per_ccz(), factories: 4 };
|
||||
assert_eq!(t.tick_us(), 38.75);
|
||||
assert_eq!(t.bound(), Bound::MagicStates);
|
||||
let toffolis = 483_000.0 * 13_880.0;
|
||||
let days = toffolis * t.tick_us() / 86.4e9;
|
||||
assert!((3.0..3.01).contains(&days), "{days}");
|
||||
assert_eq!(53 * 36 * patch_qubits(31), 3_907_584);
|
||||
// At p = 10⁻⁴, distances 9 and 15 and the same floorplan: "about one
|
||||
// million" and "1.5 days".
|
||||
assert_eq!(53 * 36 * patch_qubits(15), 976_896);
|
||||
let g = DistilledCczFactory { l1_distance: 9, l2_distance: 15 };
|
||||
let t = Timing { distance: 15, ccz_rounds: g.rounds_per_ccz(), ..t };
|
||||
let days = toffolis * t.tick_us() / 86.4e9;
|
||||
assert!((1.45..1.46).contains(&days), "{days}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1491
wai/wai-quantum/src/quantum_bicycle.rs
Normal file
1491
wai/wai-quantum/src/quantum_bicycle.rs
Normal file
File diff suppressed because it is too large
Load diff
183
wai/wai-quantum/tests/data/published_figures.tsv
Normal file
183
wai/wai-quantum/tests/data/published_figures.tsv
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
id source printed value rule
|
||||
table1.gross.c arXiv:2506.03094 Table 1 288 288 exact
|
||||
table1.gross.u arXiv:2506.03094 Table 1 90 90 exact
|
||||
table1.gross.a arXiv:2506.03094 Table 1 22 22 exact
|
||||
table1.two.c arXiv:2506.03094 Table 1 576 576 exact
|
||||
table1.two.u arXiv:2506.03094 Table 1 158 158 exact
|
||||
table1.two.a arXiv:2506.03094 Table 1 34 34 exact
|
||||
table3.gross_e3.adapter arXiv:2506.03094 Table 3 29 29 exact
|
||||
table3.two_e3.adapter arXiv:2506.03094 Table 3 29 29 exact
|
||||
table3.gross_e4.adapter arXiv:2506.03094 Table 3 13 13 exact
|
||||
table3.two_e4.adapter arXiv:2506.03094 Table 3 49 49 exact
|
||||
fig10a.gross_e3_5k.n arXiv:2506.03094 Fig. 10(a) 121 121 exact
|
||||
fig10a.two_e3_50k.n arXiv:2506.03094 Fig. 10(a) 704 704 exact
|
||||
fig10a.gross_e4_5k.n arXiv:2506.03094 Fig. 10(a) 110 110 exact
|
||||
fig10a.gross_e4_50k.n arXiv:2506.03094 Fig. 10(a) 1,342 1342 exact
|
||||
fig10a.two_e4_50k.n arXiv:2506.03094 Fig. 10(a) 440 440 exact
|
||||
fig10a.two_e4_500k.n arXiv:2506.03094 Fig. 10(a) 6,886 6886 exact
|
||||
fig10a.gross_e3_5k.nt arXiv:2506.03094 Fig. 10(a), source files 13.5958 13.59580266807207 guard 1.365e1
|
||||
fig10a.gross_e3_5k.nt_undivided arXiv:2506.03094 Fig. 10(a), source files 13.5958 13.59580266807207 guard 1.361e1
|
||||
fig10a.gross_e3_5k.steps arXiv:2506.03094 Fig. 10(a), source files 3367.15 3367.153846 guard 3.191e3
|
||||
fig10a.two_e3_50k.nt arXiv:2506.03094 Fig. 10(a), source files 3.4712·10⁶ 3471247.948411036 guard 3.478e6
|
||||
fig10a.two_e3_50k.nt_undivided arXiv:2506.03094 Fig. 10(a), source files 3.4712·10⁶ 3471247.948411036 guard 3.478e6
|
||||
fig10a.two_e3_50k.steps arXiv:2506.03094 Fig. 10(a), source files 7057.34 7057.33765 guard 7.061e3
|
||||
fig10a.gross_e4_5k.nt arXiv:2506.03094 Fig. 10(a), source files 2.2209·10⁵ 222089.62968351436 guard 4.701e5
|
||||
fig10a.gross_e4_5k.nt_undivided arXiv:2506.03094 Fig. 10(a), source files 2.2209·10⁵ 222089.62968351436 guard 4.700e5
|
||||
fig10a.gross_e4_5k.steps arXiv:2506.03094 Fig. 10(a), source files 3090.55 3090.55115 guard 2.913e3
|
||||
fig10a.gross_e4_50k.nt arXiv:2506.03094 Fig. 10(a), source files 3.7033·10⁴ 37033.2338363515 guard 4.064e4
|
||||
fig10a.gross_e4_50k.nt_undivided arXiv:2506.03094 Fig. 10(a), source files 3.7033·10⁴ 37033.2338363515 guard 4.063e4
|
||||
fig10a.gross_e4_50k.steps arXiv:2506.03094 Fig. 10(a), source files 3135.16 3135.156775 guard 2.913e3
|
||||
fig10a.two_e4_50k.nt arXiv:2506.03094 Fig. 10(a), source files 7.0154·10¹⁵ 7015434087082015.0 guard 7.033e15
|
||||
fig10a.two_e4_50k.nt_undivided arXiv:2506.03094 Fig. 10(a), source files 7.0154·10¹⁵ 7015434087082015.0 guard 7.033e15
|
||||
fig10a.two_e4_50k.steps arXiv:2506.03094 Fig. 10(a), source files 5435.87 5435.87301 guard 5.301e3
|
||||
fig10a.two_e4_500k.nt arXiv:2506.03094 Fig. 10(a), source files 4.4830·10¹⁴ 448297625597020.8 guard 4.494e14
|
||||
fig10a.two_e4_500k.nt_undivided arXiv:2506.03094 Fig. 10(a), source files 4.4830·10¹⁴ 448297625597020.8 guard 4.494e14
|
||||
fig10a.two_e4_500k.steps arXiv:2506.03094 Fig. 10(a), source files 5436.91 5436.91476 guard 5.301e3
|
||||
table10.gross.I.1e-3 arXiv:2506.03094 Table 10 1.6·10⁻⁹ 1.6e-09 band 1.0000000000000002e-10
|
||||
table10.gross.U.1e-3 arXiv:2506.03094 Table 10 4.0·10⁻⁷ 4e-07 band 1e-08
|
||||
table10.gross.M.1e-3 arXiv:2506.03094 Table 10 1.1·10⁻⁵ 1.1e-05 band 1.0000000000000002e-06
|
||||
table10.gross.C.1e-3 arXiv:2506.03094 Table 10 2.0·10⁻³ 0.002 band 0.0001
|
||||
table10.gross.I.1e-4 arXiv:2506.03094 Table 10 1.4·10⁻¹⁵ 1.4e-15 band 1.0000000000000001e-16
|
||||
table10.gross.U.1e-4 arXiv:2506.03094 Table 10 6.1·10⁻¹³ 6.1e-13 band 1.0000000000000002e-14
|
||||
table10.gross.M.1e-4 arXiv:2506.03094 Table 10 1.0·10⁻⁹ 1e-09 band 1.0000000000000002e-10
|
||||
table10.gross.C.1e-4 arXiv:2506.03094 Table 10 4.8·10⁻⁸ 4.8e-08 band 1e-09
|
||||
table10.gross.I.5e-5 arXiv:2506.03094 Table 10 4.5·10⁻¹⁷ 4.5e-17 band 1e-18
|
||||
table10.gross.U.5e-5 arXiv:2506.03094 Table 10 2.2·10⁻¹⁴ 2.2e-14 band 1e-15
|
||||
table10.gross.M.5e-5 arXiv:2506.03094 Table 10 5.7·10⁻¹¹ 5.7e-11 band 1e-12
|
||||
table10.gross.C.5e-5 arXiv:2506.03094 Table 10 2.8·10⁻⁹ 2.8e-09 band 1.0000000000000002e-10
|
||||
table10.gross.I.3e-5 arXiv:2506.03094 Table 10 3.5·10⁻¹⁸ 3.5e-18 band 1.0000000000000001e-19
|
||||
table10.gross.U.3e-5 arXiv:2506.03094 Table 10 1.9·10⁻¹⁵ 1.9e-15 band 1.0000000000000001e-16
|
||||
table10.gross.M.3e-5 arXiv:2506.03094 Table 10 5.9·10⁻¹² 5.9e-12 band 1e-13
|
||||
table10.gross.C.3e-5 arXiv:2506.03094 Table 10 3.2·10⁻¹⁰ 3.2e-10 band 1.0000000000000001e-11
|
||||
table10.gross.I.1e-5 arXiv:2506.03094 Table 10 1.5·10⁻²⁰ 1.5e-20 band 1e-21
|
||||
table10.gross.U.1e-5 arXiv:2506.03094 Table 10 9.5·10⁻¹⁸ 9.5e-18 band 1.0000000000000001e-19
|
||||
table10.gross.M.1e-5 arXiv:2506.03094 Table 10 3.3·10⁻¹⁴ 3.3e-14 band 1e-15
|
||||
table10.gross.C.1e-5 arXiv:2506.03094 Table 10 2.1·10⁻¹² 2.1e-12 band 1e-13
|
||||
table10.two.I.1e-3 arXiv:2506.03094 Table 10 8.2·10⁻²¹ 8.2e-21 band 9.999999999999999e-23
|
||||
table10.two.U.1e-3 arXiv:2506.03094 Table 10 3.3·10⁻¹⁵ 3.3e-15 band 1.0000000000000001e-16
|
||||
table10.two.I.1e-4 arXiv:2506.03094 Table 10 5.4·10⁻³⁹ 5.4e-39 band 1e-40
|
||||
table10.two.U.1e-4 arXiv:2506.03094 Table 10 1.3·10⁻³⁷ 1.3e-37 band 1.0000000000000001e-38
|
||||
a7.gross.idle arXiv:2506.03094 §A.7 against Table 2 10^−8.8 1.584893192461111e-09 guard 1.606e-10
|
||||
a7.two.idle arXiv:2506.03094 §A.7 against Table 2 10^−20.1 7.943282347242789e-21 guard 4.517e-22
|
||||
a7.gross.shift arXiv:2506.03094 §A.7 against Table 2 10^−6.4 3.981071705534969e-07 guard 4.009e-8
|
||||
2308.table1.gross.1e-3 arXiv:2308.07915 Table 1, against arXiv:2506.03094 §A.7 2·10⁻⁷ 2e-07 guard 1.606e-10
|
||||
2308.table1.gross.1e-4 arXiv:2308.07915 Table 1, against arXiv:2506.03094 §A.7 8·10⁻¹³ 8e-13 guard 1.441e-16
|
||||
2308.table1.two.1e-3 arXiv:2308.07915 Table 1, against arXiv:2506.03094 §A.7 2·10⁻¹² 2e-12 guard 4.517e-22
|
||||
2308.table1.two.1e-4 arXiv:2308.07915 Table 1, against arXiv:2506.03094 §A.7 1·10⁻²² 1e-22 guard 2.993e-40
|
||||
s3.2.natives arXiv:2506.03094 §3.2 540 540 exact
|
||||
s3.2.shifts arXiv:2506.03094 §1.2 2 2 exact
|
||||
s3.2.rotations arXiv:2506.03094 §3.2 510 510 guard 2.450e2
|
||||
fig9.chosen.gross arXiv:2506.03094 Fig. 9 caption, right 18.48 18.48 guard 1.853e1
|
||||
fig9.chosen.two arXiv:2506.03094 Fig. 9 caption, right 18.58 18.58 guard 1.848e1
|
||||
fig9.fixed.gross arXiv:2506.03094 Fig. 9 caption, left 18.55 18.55 guard 1.859e1
|
||||
fig9.fixed.two arXiv:2506.03094 Fig. 9 caption, left 18.67 18.67 guard 1.856e1
|
||||
fig10a.surface.gross_e3_5k.n arXiv:2506.03094 Fig. 10(a), §A.10 45 45 exact
|
||||
fig10a.surface.gross_e3_5k.nt arXiv:2506.03094 Fig. 10(a), §A.10 7 7 exact
|
||||
fig10a.surface.gross_e3_5k.nt_ours arXiv:2506.03094 Fig. 10(a), §A.10 7 7 guard 1.235e2
|
||||
fig10a.surface.gross_e3_5k.steps arXiv:2506.03094 Fig. 10(a) 381 381 exact
|
||||
fig10a.surface.two_e3_50k.n arXiv:2506.03094 Fig. 10(a), §A.10 42 42 exact
|
||||
fig10a.surface.two_e3_50k.nt arXiv:2506.03094 Fig. 10(a), §A.10 2.5·10⁶ 2500000.0 nearest 100000.0
|
||||
fig10a.surface.two_e3_50k.nt_ours arXiv:2506.03094 Fig. 10(a), §A.10 2.5·10⁶ 2500000.0 guard 1.323e8
|
||||
fig10a.surface.two_e3_50k.steps arXiv:2506.03094 Fig. 10(a) 2,269 2269 exact
|
||||
fig10a.surface.gross_e4_5k.n arXiv:2506.03094 Fig. 10(a), §A.10 21 21 exact
|
||||
fig10a.surface.gross_e4_5k.nt arXiv:2506.03094 Fig. 10(a), §A.10 377,928 377928 exact
|
||||
fig10a.surface.gross_e4_5k.nt_ours arXiv:2506.03094 Fig. 10(a), §A.10 377,928 377928 guard 2.646e7
|
||||
fig10a.surface.gross_e4_5k.steps arXiv:2506.03094 Fig. 10(a) 115 115 exact
|
||||
fig10a.surface.gross_e4_50k.n arXiv:2506.03094 Fig. 10(a), §A.10 250 250 exact
|
||||
fig10a.surface.gross_e4_50k.nt arXiv:2506.03094 Fig. 10(a), §A.10 31,746 31746 exact
|
||||
fig10a.surface.gross_e4_50k.nt_ours arXiv:2506.03094 Fig. 10(a), §A.10 31,746 31746 guard 2.222e6
|
||||
fig10a.surface.gross_e4_50k.steps arXiv:2506.03094 Fig. 10(a) 115 115 exact
|
||||
fig10a.surface.two_e4_50k.n arXiv:2506.03094 Fig. 10(a), §A.10 27 27 exact
|
||||
fig10a.surface.two_e4_50k.nt arXiv:2506.03094 Fig. 10(a), §A.10 1.2·10¹⁵ 1200000000000000.0 nearest 1e14
|
||||
fig10a.surface.two_e4_50k.nt_ours arXiv:2506.03094 Fig. 10(a), §A.10 1.2·10¹⁵ 1200000000000000.0 guard 2.058e17
|
||||
fig10a.surface.two_e4_50k.steps arXiv:2506.03094 Fig. 10(a) 509 509 exact
|
||||
fig10a.surface.two_e4_500k.n arXiv:2506.03094 Fig. 10(a), §A.10 416 416 exact
|
||||
fig10a.surface.two_e4_500k.nt arXiv:2506.03094 Fig. 10(a), §A.10 7.9·10¹³ 79000000000000.0 nearest 1e12
|
||||
fig10a.surface.two_e4_500k.nt_ours arXiv:2506.03094 Fig. 10(a), §A.10 7.9·10¹³ 79000000000000.0 guard 1.335e16
|
||||
fig10a.surface.two_e4_500k.steps arXiv:2506.03094 Fig. 10(a) 509 509 exact
|
||||
s4.ising.two.q arXiv:2506.03094 §4 8,138 8138 exact
|
||||
s4.ising.gross.q arXiv:2506.03094 §4 4,817 4817 guard 4.801e3
|
||||
a10.rotations arXiv:2506.03094 §A.10 184,000 184000 exact
|
||||
table9.gross.nc arXiv:2506.03094 Table 9 9.4680·10⁵ 946800 guard 9.468e5
|
||||
table9.two.nc arXiv:2506.03094 Table 9 9.4680·10⁵ 946800 guard 9.468e5
|
||||
table9.gross.nm arXiv:2506.03094 Table 9, source files 4,215,240 4215240 guard 4.283e6
|
||||
table9.two.nm arXiv:2506.03094 Table 9, source files 4,238,828 4238828 guard 4.149e6
|
||||
table9.gross.nu arXiv:2506.03094 Table 9, source files 2,270,400 2270400 guard 2.729e6
|
||||
table9.two.nu arXiv:2506.03094 Table 9, source files 2,294,400 2294400 guard 2.368e6
|
||||
table9.nt arXiv:2506.03094 Table 9, source files 15,542,400 15542400 guard 1.467e7
|
||||
s4.nt arXiv:2506.03094 §4; Fig. 1(b), source files 1.9·10⁷ (Fig. 1(b): 19,036,800) 19036800 guard 1.467e7
|
||||
table9.two.ni arXiv:2506.03094 Table 9, source files 41,636,714,298 41636714298 guard 4.210e10
|
||||
table10.fail.gross.1e-3 arXiv:2506.03094 Table 10 3.33·10⁴ 33300.0 band 100.0
|
||||
table10.fail.gross.1e-4 arXiv:2506.03094 Table 10 7.97·10⁻¹ 0.797 band 0.001
|
||||
table10.fail.gross.5e-5 arXiv:2506.03094 Table 10 4.62·10⁻² 0.0462 band 0.0001
|
||||
table10.fail.gross.3e-5 arXiv:2506.03094 Table 10 5.27·10⁻³ 0.00527 band 1e-05
|
||||
table10.fail.gross.1e-5 arXiv:2506.03094 Table 10 3.48·10⁻⁵ 3.48e-05 band 1e-07
|
||||
table10.fail.two.1e-3 arXiv:2506.03094 Table 10 1.65·10⁻² 0.0165 band 0.0001
|
||||
table10.fail.two.1e-4 arXiv:2506.03094 Table 10 1.65·10⁻¹¹ 1.65e-11 band 1e-13
|
||||
table10.fail.two.factory arXiv:2506.03094 Table 10 1.65·10⁻² 0.0165 guard 3.274e-1
|
||||
a10.bound.two arXiv:2506.03094 §A.10 7.32·10⁻⁴ 0.000732 band 1e-06
|
||||
a10.bound.gross arXiv:2506.03094 §A.10 2.09·10⁻⁵ 2.09e-05 band 1e-07
|
||||
a10.surface.d9.p arXiv:2506.03094 §A.10, Eq. (96) 5.48·10⁻⁵ 5.48e-05 nearest 1e-07
|
||||
a10.surface.d9.p_ours arXiv:2506.03094 §A.10, Eq. (96) 5.48·10⁻⁵ 5.48e-05 guard 1.430e-4
|
||||
s4.surface.d9.qubits arXiv:2506.03094 §4, Fig. 10(b) 17,010 17010 guard 3.321e4
|
||||
a10.surface.d17.p arXiv:2506.03094 §A.10, Eq. (96) 5.89·10⁻⁴ 0.000589 nearest 1e-06
|
||||
a10.surface.d17.p_ours arXiv:2506.03094 §A.10, Eq. (96) 5.89·10⁻⁴ 0.000589 guard 9.446e-4
|
||||
s4.surface.d17.qubits arXiv:2506.03094 §4, Fig. 10(b) 58,263 58263 guard 1.161e5
|
||||
a10.surface.d19.p arXiv:2506.03094 §A.10, Eq. (96) 7.85·10⁻⁴ 0.000785 nearest 1e-06
|
||||
a10.surface.d19.p_ours arXiv:2506.03094 §A.10, Eq. (96) 7.85·10⁻⁴ 0.000785 guard 1.196e-3
|
||||
s4.surface.d19.qubits arXiv:2506.03094 §4, Fig. 10(b) 72,663 72663 guard 1.449e5
|
||||
r21.table3.qubits arXiv:1905.09749 Table 3 20 (megaqubits) 20000000.0 up 1000000.0
|
||||
r21.table3.hours arXiv:1905.09749 Table 3 5.1 5.1 up 0.1
|
||||
r21.table3.risk arXiv:1905.09749 Table 3 31% 0.31 up 0.01
|
||||
r21.table3.mqd arXiv:1905.09749 Table 3 4.1 4.1 up 0.1
|
||||
r21.table1.toffolis arXiv:1905.09749 Table 1 2.7 (billions) 2700000000.0 nearest 100000000.0
|
||||
r21.s2.10.factories arXiv:1905.09749 §2.10 14 14 exact
|
||||
r21.title.hours arXiv:1905.09749 title 8 hours 8.0 up 1.0
|
||||
r21.s2.14.qubits arXiv:1905.09749 §2.14 "approximately 23 million" 23000000.0 guard 2.162e7
|
||||
r21.s2.12.distillation arXiv:1905.09749 §2.12 6.4% 0.064 guard 6.026e-3
|
||||
r21.job.distance.assumed arXiv:1905.09749 §2.13 (d = 27); its counts in the estimate job 27 27 exact
|
||||
r21.job.distance.fitted arXiv:1905.09749 §2.13 (d = 27); its counts in the estimate job 27 27 exact
|
||||
r21.job.qubits.assumed arXiv:1905.09749 Table 3; its counts in the estimate job 20 (megaqubits) 20000000.0 guard 1.891e7
|
||||
r21.job.qubits.fitted arXiv:1905.09749 Table 3; its counts in the estimate job 20 (megaqubits) 20000000.0 guard 1.891e7
|
||||
r21.job.qubits.source_rule arXiv:1905.09749 Table 3; its counts in the estimate job 20 (megaqubits) 20000000.0 guard 2.757e7
|
||||
r21.job.hours.assumed arXiv:1905.09749 Table 3; its counts in the estimate job 5.1 5.1 guard 6.071e1
|
||||
r21.job.hours.source_rule arXiv:1905.09749 Table 3; its counts in the estimate job 5.1 5.1 guard 6.971e1
|
||||
r21.job.factories arXiv:1905.09749 §2.10; its counts in the estimate job 14 CCZ per piece, 28 in all text
|
||||
r21.table3.1024.megaqubits arXiv:1905.09749 Table 3 9.7 9.7 up 0.1
|
||||
r21.table3.1024.hours arXiv:1905.09749 Table 3 1.3 1.3 up 0.1
|
||||
r21.table3.3072.megaqubits arXiv:1905.09749 Table 3 38 38.0 up 1.0
|
||||
r21.table3.3072.hours arXiv:1905.09749 Table 3 12 12.0 up 1.0
|
||||
r21.table3.4096.megaqubits arXiv:1905.09749 Table 3 55 55.0 up 1.0
|
||||
r21.table3.4096.hours arXiv:1905.09749 Table 3 22 22.0 up 1.0
|
||||
r21.table3.8192.megaqubits arXiv:1905.09749 Table 3 140 140.0 up 10.0
|
||||
r21.table3.8192.hours arXiv:1905.09749 Table 3 86 86.0 up 1.0
|
||||
r21.table3.12288.megaqubits arXiv:1905.09749 Table 3 200 200.0 up 10.0
|
||||
r21.table3.12288.hours arXiv:1905.09749 Table 3 200 200.0 up 10.0
|
||||
r21.table3.16384.megaqubits arXiv:1905.09749 Table 3 270 270.0 up 10.0
|
||||
r21.table3.16384.hours arXiv:1905.09749 Table 3 350 350.0 up 10.0
|
||||
femoco.fig10.qubits arXiv:2011.03494 Fig. 10 ≈ 4·10⁶ 4000000.0 nearest 1000000.0
|
||||
femoco.s4c4.days arXiv:2011.03494 §IV.C.4 3 3.0 nearest 1.0
|
||||
femoco.s4c4.pace arXiv:2011.03494 §IV.C.4 the factories (a "tick" limit) text
|
||||
femoco.s4c4.rate arXiv:2011.03494 §IV.C.4 25 25.0 down 1.0
|
||||
femoco.s4c4.distillation arXiv:2011.03494 §IV.C.4 "roughly 0.1%" 0.001 nearest 0.001
|
||||
femoco.s4c5.qubits arXiv:2011.03494 §IV.C.5 "one million" 1000000.0 nearest 1000000.0
|
||||
femoco.s4c5.days arXiv:2011.03494 §IV.C.5 1.5 1.5 nearest 0.1
|
||||
femoco.s4c5.days3 arXiv:2011.03494 §IV.C.5 3.5 3.5 guard 3.007e0
|
||||
femoco.table3.toffolis arXiv:2011.03494 Table III against §IV.C.4 5.3·10⁹ (Table III); 6.7·10⁹ (§IV.C.4) text
|
||||
femoco.table3.qubits arXiv:2011.03494 Table III against §IV.C.4 2,142 (Table III); under 700 data qubits (§IV.C.4) text
|
||||
femoco.job.distance arXiv:2011.03494 §IV.C.4; its counts in the estimate job 31 31 guard 2.900e1
|
||||
femoco.job.qubits.table arXiv:2011.03494 §IV.C.4; its counts in the estimate job ≈ 4·10⁶ 4000000.0 guard 8.419e6
|
||||
femoco.job.qubits.layout arXiv:2011.03494 §IV.C.4; its counts in the estimate job ≈ 4·10⁶ 4000000.0 guard 3.529e6
|
||||
femoco.job.days.table arXiv:2011.03494 §IV.C.4; its counts in the estimate job 3 3.0 guard 5.337e0
|
||||
femoco.job.days.layout arXiv:2011.03494 §IV.C.4; its counts in the estimate job 3 3.0 guard 6.751e0
|
||||
femoco.job.qubits.e4 arXiv:2011.03494 §IV.C.5; its counts in the estimate job "one million" 1000000.0 guard 9.682e5
|
||||
femoco.job.days.e4 arXiv:2011.03494 §IV.C.5; its counts in the estimate job 1.5 1.5 guard 3.492e0
|
||||
r25.qubits arXiv:2505.15917 §3.2 897,864 897864 guard 9.585e5
|
||||
r25.hours arXiv:2505.15917 §3.2 12.07 12.07 guard 1.058e1
|
||||
r25.days arXiv:2505.15917 §3.2 4.96 4.96 guard 4.305e0
|
||||
r25.logical arXiv:2505.15917 §3.2 1,409 1409 guard 1.432e3
|
||||
r25.toffolis arXiv:2505.15917 §3.2 "6.5 billion" 6500000000.0 nearest 100000000.0
|
||||
planar.distance arXiv:2211.07629 Appendix F 13 13 exact
|
||||
planar.factories arXiv:2211.07629 Appendix F 18 18 exact
|
||||
planar.qubits arXiv:2211.07629 Appendix F 8.72M 8720000.0 nearest 10000.0
|
||||
planar.hours arXiv:2211.07629 Appendix F 17 hours 43 mins 17.716666666666665 nearest 0.016666666666666666
|
||||
|
Can't render this file because it contains an unexpected character in line 160 and column 61.
|
Loading…
Reference in a new issue