From cd7841d4f76859b0a570b0a4c2461aa6f565395c Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Fri, 6 Nov 2026 03:07:06 -0500 Subject: [PATCH 01/14] wai-quantum: a gate under many controls held as one op (first pass, before review) The state a first pass left uncommitted, recorded as it was so that the review and its fixes read as changes against it: - qasm::read_whole keeps a gate whose standard form doubles with its controls as one op; Program::lowered writes it in standard gates, one lowering (qasm/controls.rs) behind both forms. - StateVector::run_ops applies such a gate as one; the bit-exact simulator walks only the indices its controls leave on. - The bit-exact method reports the global phase its lowering drops and the angles below its table; a named mps job runs metered on the bond it reaches; the error-correction reader takes C_XYZ, E and PAULI_CHANNEL_1. Not yet built or tested as a whole; later commits review it. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/wai-quantum-lang.yml | 2 +- .github/workflows/wai-quantum-qec.yml | 5 + ...-11-05-many-controlled-gates-stay-whole.md | 12 + wai/quantum-cross-simulator/README.md | 54 +- .../corpus/manifest.json | 17 +- .../corpus/qasm/mps_qft_n30_bond256.qasm | 499 ++++++++++++++++++ .../corpus/qec-hand-written.json | 16 +- .../tools/before_after.py | 30 ++ wai/quantum-cross-simulator/tools/compare.py | 36 +- wai/quantum-cross-simulator/tools/corpus.py | 28 +- wai/quantum-cross-simulator/tools/perf.py | 4 +- wai/quantum-cross-simulator/tools/report.py | 12 + .../examples/cross_simulator.rs | 18 +- wai/wai-quantum/README.md | 2 +- wai/wai-quantum/docs/qasm-diagnostics.md | 2 +- wai/wai-quantum/docs/qasm-feature-matrix.md | 2 +- wai/wai-quantum/schemas/job-request.v1.json | 2 +- wai/wai-quantum/schemas/job-result.v1.json | 38 +- wai/wai-quantum/schemas/tools.v1.json | 8 +- wai/wai-quantum/src/engine/catalog.rs | 122 ++++- .../src/engine/catalog/whole_tests.rs | 376 +++++++++++++ wai/wai-quantum/src/engine/compile.rs | 2 + wai/wai-quantum/src/engine/dynamic.rs | 32 ++ wai/wai-quantum/src/engine/estimate/count.rs | 2 + wai/wai-quantum/src/engine/fabric.rs | 4 +- wai/wai-quantum/src/engine/formats/mod.rs | 2 + wai/wai-quantum/src/engine/job.rs | 9 +- .../src/engine/registry/builtin.rs | 6 +- wai/wai-quantum/src/engine/registry/mod.rs | 32 +- wai/wai-quantum/src/engine/run.rs | 76 ++- wai/wai-quantum/src/engine/schema.rs | 3 + wai/wai-quantum/src/qasm.rs | 361 ++++++++++++- wai/wai-quantum/src/qasm/controls.rs | 318 +++++++++++ wai/wai-quantum/src/qasm/diag.rs | 2 +- wai/wai-quantum/src/qasm/elab.rs | 277 ++-------- wai/wai-quantum/src/qasm/whole_tests.rs | 366 +++++++++++++ wai/wai-quantum/src/quantum.rs | 101 ++++ wai/wai-quantum/src/quantum_frame.rs | 265 +++++++++- wai/wai-quantum/src/quantum_mpsim.rs | 66 +++ wai/wai-quantum/src/quantum_sv.rs | 211 ++++++++ wai/wai-quantum/tests/data/color_d3.circuit | 79 +++ wai/wai-quantum/tests/data/color_d3.dem | 72 +++ 42 files changed, 3234 insertions(+), 337 deletions(-) create mode 100644 wai/changes/2026-11-05-many-controlled-gates-stay-whole.md create mode 100644 wai/quantum-cross-simulator/corpus/qasm/mps_qft_n30_bond256.qasm create mode 100644 wai/quantum-cross-simulator/tools/before_after.py create mode 100644 wai/wai-quantum/src/engine/catalog/whole_tests.rs create mode 100644 wai/wai-quantum/src/qasm/controls.rs create mode 100644 wai/wai-quantum/src/qasm/whole_tests.rs create mode 100644 wai/wai-quantum/tests/data/color_d3.circuit create mode 100644 wai/wai-quantum/tests/data/color_d3.dem diff --git a/.github/workflows/wai-quantum-lang.yml b/.github/workflows/wai-quantum-lang.yml index e098dda17..e0b7fbe4a 100644 --- a/.github/workflows/wai-quantum-lang.yml +++ b/.github/workflows/wai-quantum-lang.yml @@ -79,7 +79,7 @@ jobs: set -euo pipefail cargo test --locked --release --features full --lib qasm 2>&1 | tee "$RUNNER_TEMP/qasm.log" grep -qE '^test result: ok\. [1-9][0-9]+ passed; 0 failed' "$RUNNER_TEMP/qasm.log" || { echo "::error::the reader's tests did not pass"; exit 1; } - for m in qasm::diag qasm::lex qasm::parse qasm::value qasm::lang_tests qasm::tests quantum_toolchain::tests::qasm_round_trip; do + for m in qasm::diag qasm::lex qasm::parse qasm::value qasm::lang_tests qasm::whole_tests qasm::tests quantum_toolchain::tests::qasm_round_trip; do grep -q "^test $m.* \.\.\. ok$" "$RUNNER_TEMP/qasm.log" || { echo "::error::no test of $m ran"; exit 1; } done - name: The conformance corpus diff --git a/.github/workflows/wai-quantum-qec.yml b/.github/workflows/wai-quantum-qec.yml index 817525814..9a297a580 100644 --- a/.github/workflows/wai-quantum-qec.yml +++ b/.github/workflows/wai-quantum-qec.yml @@ -113,6 +113,11 @@ jobs: quantum_frame::tests::pauli_targets_agree_between_sampler_and_model \ quantum_frame::tests::tags_reach_the_model_and_its_text \ quantum_frame::tests::the_text_round_trips \ + quantum_frame::tests::a_pauli_channel_s_rates_have_its_law \ + quantum_frame::tests::a_pauli_channel_samples_its_law \ + quantum_frame::tests::the_cycling_gates_cycle_the_axes \ + quantum_frame::tests::a_correlated_error_flips_its_targets_together \ + quantum_frame::tests::the_reference_colour_code_has_the_reference_s_model \ engine::mitigate::tests::pauli_channels_round_trip_through_rates_and_fidelities \ engine::mitigate::tests::the_twirled_circuit_is_the_job_where_the_noise_is_pauli \ engine::mitigate::tests::the_exact_inverse_undoes_the_noise \ diff --git a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md new file mode 100644 index 000000000..277c46e0d --- /dev/null +++ b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md @@ -0,0 +1,12 @@ +### wai-quantum: a gate under many controls stays one operation, the bit-exact method says what its lowering did, and the error-correction reader takes `C_XYZ`, `E` and `PAULI_CHANNEL_1` + +**A request that changes what it gives.** A job on `exact` whose program holds a gate under controls that used to be written through a phase polynomial (`x`, `y`, `z` or `h` under three or more controls; `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` or `sxdg` under two or more) gives another `state_hash`, other integers and other seeded counts. The expansion's `P(±θ/2^{m−1})` round at each amplitude, and the gate held whole has no such steps, so the new integers are nearer the ideal state, by no more than the extension's published bound from the old ones; no two forms of such a gate can give one set of bits. `"options": {"controls": "standard"}` runs the expansion and gives the old hash, bit for bit. A result on `statevector` moves by double-precision rounding, within its bound. Every other program, every other method and every other request gives what it gave. + +- **The reader.** `qasm::read_whole` keeps a gate whose standard gates would double as one operation (`Op::is_whole`), under as many as 255 controls. `Program::lowered` writes it in standard gates: exactly what `qasm::read` gives of the same text, its steps, timing and records moved with it, one lowering behind both. `read` and `parse` give standard gates as they did, and refuse past 16 controls and past `MAX_OPS` as they did, saying what can run it. +- **The state vectors.** `StateVector::run_ops` applies such a gate as one (`Controlled`), visiting only the `2^(n − c)` amplitudes its controls leave on; a run without one is `run`, to the bit. The bit-exact simulator walks those indices too, with the scan's bits. Two Grover iterations on 14 qubits are 130 operations, not 131,186. +- **A job.** `exact` and `statevector` run such a gate as one, in programs that measure in the middle too. Their results' `gates` counts operations, and `standard_gates`, a new optional member, says what they are in standard gates. A job with `compile`, `noise`, `mitigate`, `target`, `provider` or a named `fabric` place runs standard gates as it did, as do the other methods, a registered method among them. Methods that need standard gates refuse what those cannot hold with `Q208` or `Q210`, and `auto` passes over them. `lint_qasm` counts as a job does. +- **What depended on the expansion** did not change, checked against this engine's output before the change on arm64 and x86_64: the reader's standard gates, compile, QIR and jeff export, the resource estimate's counts, the expected hashes of `quantum-conformance/` (they hold op-logs and no gate under more than one control). +- **The bit-exact method says what its lowering did** (`accuracy`, each only when there is something to say). `global_phase`: `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `u` become phase gates, so OpenQASM's state is `e^(i·radians)` times the amplitudes given; the phase is exact, in 2^33rds of a turn, whole turns counted. `below_table`: an angle of `2π/2^47` or less ran as no phase, as the table's arithmetic has it, and now says so here and in the plan's `why`. `moved_angles`: an angle within the reader's tolerance of a dyadic one, by more than a double's rounding of it. `Program::dyadic_with_report` gives all three. +- **The matrix-product job.** A job that names `mps` is no longer refused on an estimate at the bond it asks for: it runs under a meter of the bonds it holds (`Chain::run_within`, `Chain::work`), which changes no number, and stops with `J011`, saying where, if those pass one job's work. The 30-qubit QFT at `max_bond` 256 runs, and reaches far less. A job with `auto` is held to the estimate as it was, and told what naming the method does. +- **The error-correction text.** `C_XYZ` and `C_ZYX`; `E` (or `CORRELATED_ERROR`), a flip on a qubit of its own handed to its Pauli targets, so a circuit with one holds one qubit more than its text names; and `PAULI_CHANNEL_1`, as the independent flips with its law. A channel with no such flips (`PAULI_CHANNEL_1(0.1, 0.1, 0)`) is refused with its line. The reference generator's colour-code memory circuits run, their models equal to that tool's, mechanism for mechanism. +- **The corpus** ([quantum-cross-simulator/](quantum-cross-simulator/README.md)): rerun on both hosts, with the bit-exact method now held to OpenQASM's amplitudes with the phase its result states, nothing fitted, and before-and-after timings on one host. diff --git a/wai/quantum-cross-simulator/README.md b/wai/quantum-cross-simulator/README.md index 5ef01b037..fde8381b2 100644 --- a/wai/quantum-cross-simulator/README.md +++ b/wai/quantum-cross-simulator/README.md @@ -59,8 +59,8 @@ turn, a rational fraction of a turn, or a decimal number of radians. | measurement in the middle | teleportation, reset of an entangled qubit, measuring twice, feedback, a GHZ state by fusion, repeat-until-success: exact laws from every branch | | stabilizer circuits | GHZ and cluster states to 5000 qubits; random Clifford layers at 63, 64, 65, 127, 128 and 129 qubits (either side of a machine word) and to 2000; a Clifford circuit as a state vector and a tableau; outcomes at 40 qubits | | noise | depolarizing channels after X and cx chains, whose expectation values are closed forms | -| wide circuits | GHZ to 100 qubits and the QFT at 30 and 40 by matrix product states and contraction; a shallow brickwork at 26; a 40-qubit mirror | -| error correction | the rotated surface-code memory experiment in Z (d = 3 … 15) and X, the unrotated layout, repetition codes to d = 25, a noiseless run, a colour code, and hand-written circuits for inverted targets, tags, flip noise, merging, Pauli observables, and three instructions that must be refused | +| wide circuits | GHZ to 100 qubits and the QFT at 30 and 40 by matrix product states and contraction, and at 30 at a bond far above what it reaches; a shallow brickwork at 26; a 40-qubit mirror | +| error correction | the rotated surface-code memory experiment in Z (d = 3 … 15) and X, the unrotated layout, repetition codes to d = 25, a noiseless run, a colour code whose cycle turns the axes with `C_XYZ`, and hand-written circuits for inverted targets, tags, flip noise, merging, Pauli observables, correlated errors and Pauli channels, and two circuits that must be refused | ## How a result is judged @@ -94,7 +94,8 @@ result: the circuit; detection rates against the rates the model gives, by Bernstein's inequality. A state is held to its reference modulo a global phase, which no measurement sees; the -distance with the phase is recorded beside it (`strict`). The bounds are worst cases and so are +distance with the phase is recorded beside it (`strict`). The bit-exact method is held a second +time with the phase its results state, nothing fitted. The bounds are worst cases and so are loose: each result records how far inside its bound an engine is, and the table below gives the largest such ratio. @@ -149,15 +150,19 @@ figure the extension states. ### Conventions the corpus shows - **Global phase.** Every engine keeps OpenQASM 3's global phases except the bit-exact method, - which lowers `rz`, `rx`, `ry` and `U` through phase gates and so differs from the standard's - matrices by a global phase (a `strict` distance of up to 1.97 on a rotation by a whole turn). - No measurement sees it, and under a control the method is right (`controlled_rz_full_turn`, - `gate_crz`, `gate_cu`). The amplitudes a job answers with this method carry that phase, and the - result does not say so. + which lowers `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `U` through phase gates, and so differs + from the standard's matrices by a global phase (a `strict` distance of up to 1.97 on a rotation + by a whole turn). No measurement sees it, and under a control the method is right + (`controlled_rz_full_turn`, `gate_crz`, `gate_cu`). A result on this method now states the phase + (`accuracy.global_phase`, exactly, in 2^33rds of a turn), and with it the method's state meets + its bound against OpenQASM's on every circuit here. - **Angles below the table.** The bit-exact method reads an angle within 10^-14 of a turn of a dyadic one as that dyadic. A phase of 2π/2^k is therefore refused for k = 33 … 46 (`[Q500]`), - and for k ≥ 47 runs as no phase at all, labelled bit-exact; the state is then within 2.3·10^-14 - of the ideal one, far inside the method's resolution. Method `auto` sends k = 33 … 46 to double + and for k ≥ 47 runs as no phase, which is what the table's arithmetic gives for such an angle + from k = 34 on; the state is then within 2.3·10^-14 of the ideal one, far inside the method's + resolution. The result and the plan say so (`accuracy.below_table`, with how many and the + largest), and an angle moved to a dyadic neighbour other than zero by more than a double's + rounding is stated too (`accuracy.moved_angles`). Method `auto` sends k = 33 … 46 to double precision. - **Bit order.** Every engine's answers were brought to one convention (qubit 0 the lowest bit of an index, classical bit 0 the last character of an outcome) by its adapter, and the bit-order @@ -168,11 +173,13 @@ figure the extension states. The performance tables below are one shared host each; read the Limits before any figure. What they show, where it does not depend on the host's other work: -- **Gates under many controls are where the engine under test is slow.** Its reader lowers - `ctrl(k) @` to standard gates by a Gray-code construction whose length doubles with each - control. Two Grover iterations on 14 qubits (four Z gates under 13 controls) ran as 131,214 - gates on its state vector and 557,146 on the bit-exact method, and took seconds; the other - state-vector engines apply such a gate as one, and took milliseconds (`grover_n14`). +- **Gates under many controls.** The engine under test now runs one as one gate, on its state + vector and on the bit-exact method: `grover_n14` (four Z gates under 13 controls) is 130 + operations where it was 131,214 standard gates, and 557,146 on the bit-exact method. The last + table below has it before and after on one host. Other engines still lead this case by the + overhead of a job, a Python process excepted: see each row. A gate under controls + costs `2^(n − c)` amplitudes. Past 16 controls the standard form refuses (`[Q208]`), so `grover_n20` + has no "before". - **Dense state vectors, with every CPU.** At 26 and 28 qubits, on the QFT and on the rotation brickwork, the three state-vector engines are within three times of one another, and which is first changes with the circuit and the host. At 20 qubits both of the others took longer with @@ -467,12 +474,16 @@ Host: Apple M3 Ultra, macOS 27.2, 32 logical CPUs, 256 GiB, arm64. Each figure i - **Not compared at all:** the engine's Pauli propagation, cut-rank, stabilizer-rank, trajectory, pulse and mitigation methods; its GPU and other fabric members; single-precision GPU state vectors of any engine; decoders; noise beyond depolarizing channels in closed form. -- **What the engine under test refused.** Its frame simulator does not implement `C_XYZ`, - correlated errors (`E`) or general Pauli channels, so the reference generator's colour-code - memory circuits do not run on it; it refuses each with its line. Its matrix-product-state job - refuses the 30- and 40-qubit QFT at `max_bond` 256 as more work than one job may take - (`[J011]`): its estimate counts the bond asked for, not the bond the circuit reaches. The - corpus runs it at 64, where the bond it reaches is recorded in the results. +- **What the engine under test refuses.** A Pauli channel whose exclusive outcomes no independent + flips can give, such as `PAULI_CHANNEL_1(0.1, 0.1, 0)`, whose Z would need a rate below zero: a + detector error model of independent mechanisms cannot state it, and its frame simulator takes + every channel in that form, so it refuses such a channel with its line + (`qec_refused_channel_with_no_independent_form`). The other engine samples it, and gives no + model of it. For a channel with such flips (`qec_pauli_channel`) the other engine again gives + no model without an approximation it must be asked for, so its sampler holds the engine's model. + A job naming method `auto` on a matrix product state keeps to the estimate at the bond asked + for; a job naming `mps` runs under a meter of the bond it holds (`mps_qft_n30_bond256`) and stops + with `[J011]` if that passes one job's work. - **What the adapters do not drive.** The qsim adapter runs no measurement in the middle of a circuit, so those entries are `not run` for it; that is this adapter's limit. `aer.mps` is not run at 100 qubits: its target holds 63. An engine that has not answered a circuit within @@ -530,5 +541,6 @@ is the command above, run by hand. | `tools/compare.py` | the run: references, tolerances, injected faults, the results file | | `tools/perf.py` | run time and peak memory | | `tools/report.py` | this page's results section | +| `tools/before_after.py` | one host's timings of two builds side by side, from `tools/perf.py` run on each | | `provider/` | the provider template and its test | | `results/` | the committed runs | diff --git a/wai/quantum-cross-simulator/corpus/manifest.json b/wai/quantum-cross-simulator/corpus/manifest.json index 29e1ffa86..a3a89edae 100644 --- a/wai/quantum-cross-simulator/corpus/manifest.json +++ b/wai/quantum-cross-simulator/corpus/manifest.json @@ -1887,6 +1887,21 @@ "gates": 860, "sha256": "acd8a1a61d5131a006b2fba9a3fd5eef79fcb6d407323fb32080d8c117b09b86" }, + { + "id": "mps_qft_n30_bond256", + "family": "wide_mps", + "params": { + "n": 30, + "x": 715827883, + "max_bond": 256 + }, + "reason": "The 30-qubit QFT at a bond far above what it reaches: a job naming the method runs under a meter of the bond it holds, and stays exact.", + "expect": "amplitudes", + "tier": "full", + "qubits": 30, + "gates": 496, + "sha256": "a85588ba6e9133b1d19ff9cae05c2f1b599755e1738458a888eff79ec67079e1" + }, { "id": "tn_shallow_n26", "family": "wide_tn", @@ -2136,7 +2151,7 @@ "rounds": 3, "p": 0.002 }, - "reason": "A colour code with C_XYZ gates: an instruction the frame simulator does not implement must be refused with its line, never skipped.", + "reason": "A colour code, whose syndrome cycle turns the axes with C_XYZ gates: the model must match mechanism by mechanism, and every detector's rate must follow it.", "expect": "qec", "tier": "full", "sha256": "bcda6739a090378385999ac51a2a66e2cfcee038796f1e12e9b8efcd9c33f75c" diff --git a/wai/quantum-cross-simulator/corpus/qasm/mps_qft_n30_bond256.qasm b/wai/quantum-cross-simulator/corpus/qasm/mps_qft_n30_bond256.qasm new file mode 100644 index 000000000..64bb8e224 --- /dev/null +++ b/wai/quantum-cross-simulator/corpus/qasm/mps_qft_n30_bond256.qasm @@ -0,0 +1,499 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[30] q; +x q[0]; +x q[1]; +x q[3]; +x q[5]; +x q[7]; +x q[9]; +x q[11]; +x q[13]; +x q[15]; +x q[17]; +x q[19]; +x q[21]; +x q[23]; +x q[25]; +x q[27]; +x q[29]; +h q[29]; +cp(pi/2) q[28], q[29]; +cp(pi/4) q[27], q[29]; +cp(pi/8) q[26], q[29]; +cp(pi/16) q[25], q[29]; +cp(pi/32) q[24], q[29]; +cp(pi/64) q[23], q[29]; +cp(pi/128) q[22], q[29]; +cp(pi/256) q[21], q[29]; +cp(pi/512) q[20], q[29]; +cp(pi/1024) q[19], q[29]; +cp(pi/2048) q[18], q[29]; +cp(pi/4096) q[17], q[29]; +cp(pi/8192) q[16], q[29]; +cp(pi/16384) q[15], q[29]; +cp(pi/32768) q[14], q[29]; +cp(pi/65536) q[13], q[29]; +cp(pi/131072) q[12], q[29]; +cp(pi/262144) q[11], q[29]; +cp(pi/524288) q[10], q[29]; +cp(pi/1048576) q[9], q[29]; +cp(pi/2097152) q[8], q[29]; +cp(pi/4194304) q[7], q[29]; +cp(pi/8388608) q[6], q[29]; +cp(pi/16777216) q[5], q[29]; +cp(pi/33554432) q[4], q[29]; +cp(pi/67108864) q[3], q[29]; +cp(pi/134217728) q[2], q[29]; +cp(pi/268435456) q[1], q[29]; +cp(pi/536870912) q[0], q[29]; +h q[28]; +cp(pi/2) q[27], q[28]; +cp(pi/4) q[26], q[28]; +cp(pi/8) q[25], q[28]; +cp(pi/16) q[24], q[28]; +cp(pi/32) q[23], q[28]; +cp(pi/64) q[22], q[28]; +cp(pi/128) q[21], q[28]; +cp(pi/256) q[20], q[28]; +cp(pi/512) q[19], q[28]; +cp(pi/1024) q[18], q[28]; +cp(pi/2048) q[17], q[28]; +cp(pi/4096) q[16], q[28]; +cp(pi/8192) q[15], q[28]; +cp(pi/16384) q[14], q[28]; +cp(pi/32768) q[13], q[28]; +cp(pi/65536) q[12], q[28]; +cp(pi/131072) q[11], q[28]; +cp(pi/262144) q[10], q[28]; +cp(pi/524288) q[9], q[28]; +cp(pi/1048576) q[8], q[28]; +cp(pi/2097152) q[7], q[28]; +cp(pi/4194304) q[6], q[28]; +cp(pi/8388608) q[5], q[28]; +cp(pi/16777216) q[4], q[28]; +cp(pi/33554432) q[3], q[28]; +cp(pi/67108864) q[2], q[28]; +cp(pi/134217728) q[1], q[28]; +cp(pi/268435456) q[0], q[28]; +h q[27]; +cp(pi/2) q[26], q[27]; +cp(pi/4) q[25], q[27]; +cp(pi/8) q[24], q[27]; +cp(pi/16) q[23], q[27]; +cp(pi/32) q[22], q[27]; +cp(pi/64) q[21], q[27]; +cp(pi/128) q[20], q[27]; +cp(pi/256) q[19], q[27]; +cp(pi/512) q[18], q[27]; +cp(pi/1024) q[17], q[27]; +cp(pi/2048) q[16], q[27]; +cp(pi/4096) q[15], q[27]; +cp(pi/8192) q[14], q[27]; +cp(pi/16384) q[13], q[27]; +cp(pi/32768) q[12], q[27]; +cp(pi/65536) q[11], q[27]; +cp(pi/131072) q[10], q[27]; +cp(pi/262144) q[9], q[27]; +cp(pi/524288) q[8], q[27]; +cp(pi/1048576) q[7], q[27]; +cp(pi/2097152) q[6], q[27]; +cp(pi/4194304) q[5], q[27]; +cp(pi/8388608) q[4], q[27]; +cp(pi/16777216) q[3], q[27]; +cp(pi/33554432) q[2], q[27]; +cp(pi/67108864) q[1], q[27]; +cp(pi/134217728) q[0], q[27]; +h q[26]; +cp(pi/2) q[25], q[26]; +cp(pi/4) q[24], q[26]; +cp(pi/8) q[23], q[26]; +cp(pi/16) q[22], q[26]; +cp(pi/32) q[21], q[26]; +cp(pi/64) q[20], q[26]; +cp(pi/128) q[19], q[26]; +cp(pi/256) q[18], q[26]; +cp(pi/512) q[17], q[26]; +cp(pi/1024) q[16], q[26]; +cp(pi/2048) q[15], q[26]; +cp(pi/4096) q[14], q[26]; +cp(pi/8192) q[13], q[26]; +cp(pi/16384) q[12], q[26]; +cp(pi/32768) q[11], q[26]; +cp(pi/65536) q[10], q[26]; +cp(pi/131072) q[9], q[26]; +cp(pi/262144) q[8], q[26]; +cp(pi/524288) q[7], q[26]; +cp(pi/1048576) q[6], q[26]; +cp(pi/2097152) q[5], q[26]; +cp(pi/4194304) q[4], q[26]; +cp(pi/8388608) q[3], q[26]; +cp(pi/16777216) q[2], q[26]; +cp(pi/33554432) q[1], q[26]; +cp(pi/67108864) q[0], q[26]; +h q[25]; +cp(pi/2) q[24], q[25]; +cp(pi/4) q[23], q[25]; +cp(pi/8) q[22], q[25]; +cp(pi/16) q[21], q[25]; +cp(pi/32) q[20], q[25]; +cp(pi/64) q[19], q[25]; +cp(pi/128) q[18], q[25]; +cp(pi/256) q[17], q[25]; +cp(pi/512) q[16], q[25]; +cp(pi/1024) q[15], q[25]; +cp(pi/2048) q[14], q[25]; +cp(pi/4096) q[13], q[25]; +cp(pi/8192) q[12], q[25]; +cp(pi/16384) q[11], q[25]; +cp(pi/32768) q[10], q[25]; +cp(pi/65536) q[9], q[25]; +cp(pi/131072) q[8], q[25]; +cp(pi/262144) q[7], q[25]; +cp(pi/524288) q[6], q[25]; +cp(pi/1048576) q[5], q[25]; +cp(pi/2097152) q[4], q[25]; +cp(pi/4194304) q[3], q[25]; +cp(pi/8388608) q[2], q[25]; +cp(pi/16777216) q[1], q[25]; +cp(pi/33554432) q[0], q[25]; +h q[24]; +cp(pi/2) q[23], q[24]; +cp(pi/4) q[22], q[24]; +cp(pi/8) q[21], q[24]; +cp(pi/16) q[20], q[24]; +cp(pi/32) q[19], q[24]; +cp(pi/64) q[18], q[24]; +cp(pi/128) q[17], q[24]; +cp(pi/256) q[16], q[24]; +cp(pi/512) q[15], q[24]; +cp(pi/1024) q[14], q[24]; +cp(pi/2048) q[13], q[24]; +cp(pi/4096) q[12], q[24]; +cp(pi/8192) q[11], q[24]; +cp(pi/16384) q[10], q[24]; +cp(pi/32768) q[9], q[24]; +cp(pi/65536) q[8], q[24]; +cp(pi/131072) q[7], q[24]; +cp(pi/262144) q[6], q[24]; +cp(pi/524288) q[5], q[24]; +cp(pi/1048576) q[4], q[24]; +cp(pi/2097152) q[3], q[24]; +cp(pi/4194304) q[2], q[24]; +cp(pi/8388608) q[1], q[24]; +cp(pi/16777216) q[0], q[24]; +h q[23]; +cp(pi/2) q[22], q[23]; +cp(pi/4) q[21], q[23]; +cp(pi/8) q[20], q[23]; +cp(pi/16) q[19], q[23]; +cp(pi/32) q[18], q[23]; +cp(pi/64) q[17], q[23]; +cp(pi/128) q[16], q[23]; +cp(pi/256) q[15], q[23]; +cp(pi/512) q[14], q[23]; +cp(pi/1024) q[13], q[23]; +cp(pi/2048) q[12], q[23]; +cp(pi/4096) q[11], q[23]; +cp(pi/8192) q[10], q[23]; +cp(pi/16384) q[9], q[23]; +cp(pi/32768) q[8], q[23]; +cp(pi/65536) q[7], q[23]; +cp(pi/131072) q[6], q[23]; +cp(pi/262144) q[5], q[23]; +cp(pi/524288) q[4], q[23]; +cp(pi/1048576) q[3], q[23]; +cp(pi/2097152) q[2], q[23]; +cp(pi/4194304) q[1], q[23]; +cp(pi/8388608) q[0], q[23]; +h q[22]; +cp(pi/2) q[21], q[22]; +cp(pi/4) q[20], q[22]; +cp(pi/8) q[19], q[22]; +cp(pi/16) q[18], q[22]; +cp(pi/32) q[17], q[22]; +cp(pi/64) q[16], q[22]; +cp(pi/128) q[15], q[22]; +cp(pi/256) q[14], q[22]; +cp(pi/512) q[13], q[22]; +cp(pi/1024) q[12], q[22]; +cp(pi/2048) q[11], q[22]; +cp(pi/4096) q[10], q[22]; +cp(pi/8192) q[9], q[22]; +cp(pi/16384) q[8], q[22]; +cp(pi/32768) q[7], q[22]; +cp(pi/65536) q[6], q[22]; +cp(pi/131072) q[5], q[22]; +cp(pi/262144) q[4], q[22]; +cp(pi/524288) q[3], q[22]; +cp(pi/1048576) q[2], q[22]; +cp(pi/2097152) q[1], q[22]; +cp(pi/4194304) q[0], q[22]; +h q[21]; +cp(pi/2) q[20], q[21]; +cp(pi/4) q[19], q[21]; +cp(pi/8) q[18], q[21]; +cp(pi/16) q[17], q[21]; +cp(pi/32) q[16], q[21]; +cp(pi/64) q[15], q[21]; +cp(pi/128) q[14], q[21]; +cp(pi/256) q[13], q[21]; +cp(pi/512) q[12], q[21]; +cp(pi/1024) q[11], q[21]; +cp(pi/2048) q[10], q[21]; +cp(pi/4096) q[9], q[21]; +cp(pi/8192) q[8], q[21]; +cp(pi/16384) q[7], q[21]; +cp(pi/32768) q[6], q[21]; +cp(pi/65536) q[5], q[21]; +cp(pi/131072) q[4], q[21]; +cp(pi/262144) q[3], q[21]; +cp(pi/524288) q[2], q[21]; +cp(pi/1048576) q[1], q[21]; +cp(pi/2097152) q[0], q[21]; +h q[20]; +cp(pi/2) q[19], q[20]; +cp(pi/4) q[18], q[20]; +cp(pi/8) q[17], q[20]; +cp(pi/16) q[16], q[20]; +cp(pi/32) q[15], q[20]; +cp(pi/64) q[14], q[20]; +cp(pi/128) q[13], q[20]; +cp(pi/256) q[12], q[20]; +cp(pi/512) q[11], q[20]; +cp(pi/1024) q[10], q[20]; +cp(pi/2048) q[9], q[20]; +cp(pi/4096) q[8], q[20]; +cp(pi/8192) q[7], q[20]; +cp(pi/16384) q[6], q[20]; +cp(pi/32768) q[5], q[20]; +cp(pi/65536) q[4], q[20]; +cp(pi/131072) q[3], q[20]; +cp(pi/262144) q[2], q[20]; +cp(pi/524288) q[1], q[20]; +cp(pi/1048576) q[0], q[20]; +h q[19]; +cp(pi/2) q[18], q[19]; +cp(pi/4) q[17], q[19]; +cp(pi/8) q[16], q[19]; +cp(pi/16) q[15], q[19]; +cp(pi/32) q[14], q[19]; +cp(pi/64) q[13], q[19]; +cp(pi/128) q[12], q[19]; +cp(pi/256) q[11], q[19]; +cp(pi/512) q[10], q[19]; +cp(pi/1024) q[9], q[19]; +cp(pi/2048) q[8], q[19]; +cp(pi/4096) q[7], q[19]; +cp(pi/8192) q[6], q[19]; +cp(pi/16384) q[5], q[19]; +cp(pi/32768) q[4], q[19]; +cp(pi/65536) q[3], q[19]; +cp(pi/131072) q[2], q[19]; +cp(pi/262144) q[1], q[19]; +cp(pi/524288) q[0], q[19]; +h q[18]; +cp(pi/2) q[17], q[18]; +cp(pi/4) q[16], q[18]; +cp(pi/8) q[15], q[18]; +cp(pi/16) q[14], q[18]; +cp(pi/32) q[13], q[18]; +cp(pi/64) q[12], q[18]; +cp(pi/128) q[11], q[18]; +cp(pi/256) q[10], q[18]; +cp(pi/512) q[9], q[18]; +cp(pi/1024) q[8], q[18]; +cp(pi/2048) q[7], q[18]; +cp(pi/4096) q[6], q[18]; +cp(pi/8192) q[5], q[18]; +cp(pi/16384) q[4], q[18]; +cp(pi/32768) q[3], q[18]; +cp(pi/65536) q[2], q[18]; +cp(pi/131072) q[1], q[18]; +cp(pi/262144) q[0], q[18]; +h q[17]; +cp(pi/2) q[16], q[17]; +cp(pi/4) q[15], q[17]; +cp(pi/8) q[14], q[17]; +cp(pi/16) q[13], q[17]; +cp(pi/32) q[12], q[17]; +cp(pi/64) q[11], q[17]; +cp(pi/128) q[10], q[17]; +cp(pi/256) q[9], q[17]; +cp(pi/512) q[8], q[17]; +cp(pi/1024) q[7], q[17]; +cp(pi/2048) q[6], q[17]; +cp(pi/4096) q[5], q[17]; +cp(pi/8192) q[4], q[17]; +cp(pi/16384) q[3], q[17]; +cp(pi/32768) q[2], q[17]; +cp(pi/65536) q[1], q[17]; +cp(pi/131072) q[0], q[17]; +h q[16]; +cp(pi/2) q[15], q[16]; +cp(pi/4) q[14], q[16]; +cp(pi/8) q[13], q[16]; +cp(pi/16) q[12], q[16]; +cp(pi/32) q[11], q[16]; +cp(pi/64) q[10], q[16]; +cp(pi/128) q[9], q[16]; +cp(pi/256) q[8], q[16]; +cp(pi/512) q[7], q[16]; +cp(pi/1024) q[6], q[16]; +cp(pi/2048) q[5], q[16]; +cp(pi/4096) q[4], q[16]; +cp(pi/8192) q[3], q[16]; +cp(pi/16384) q[2], q[16]; +cp(pi/32768) q[1], q[16]; +cp(pi/65536) q[0], q[16]; +h q[15]; +cp(pi/2) q[14], q[15]; +cp(pi/4) q[13], q[15]; +cp(pi/8) q[12], q[15]; +cp(pi/16) q[11], q[15]; +cp(pi/32) q[10], q[15]; +cp(pi/64) q[9], q[15]; +cp(pi/128) q[8], q[15]; +cp(pi/256) q[7], q[15]; +cp(pi/512) q[6], q[15]; +cp(pi/1024) q[5], q[15]; +cp(pi/2048) q[4], q[15]; +cp(pi/4096) q[3], q[15]; +cp(pi/8192) q[2], q[15]; +cp(pi/16384) q[1], q[15]; +cp(pi/32768) q[0], q[15]; +h q[14]; +cp(pi/2) q[13], q[14]; +cp(pi/4) q[12], q[14]; +cp(pi/8) q[11], q[14]; +cp(pi/16) q[10], q[14]; +cp(pi/32) q[9], q[14]; +cp(pi/64) q[8], q[14]; +cp(pi/128) q[7], q[14]; +cp(pi/256) q[6], q[14]; +cp(pi/512) q[5], q[14]; +cp(pi/1024) q[4], q[14]; +cp(pi/2048) q[3], q[14]; +cp(pi/4096) q[2], q[14]; +cp(pi/8192) q[1], q[14]; +cp(pi/16384) q[0], q[14]; +h q[13]; +cp(pi/2) q[12], q[13]; +cp(pi/4) q[11], q[13]; +cp(pi/8) q[10], q[13]; +cp(pi/16) q[9], q[13]; +cp(pi/32) q[8], q[13]; +cp(pi/64) q[7], q[13]; +cp(pi/128) q[6], q[13]; +cp(pi/256) q[5], q[13]; +cp(pi/512) q[4], q[13]; +cp(pi/1024) q[3], q[13]; +cp(pi/2048) q[2], q[13]; +cp(pi/4096) q[1], q[13]; +cp(pi/8192) q[0], q[13]; +h q[12]; +cp(pi/2) q[11], q[12]; +cp(pi/4) q[10], q[12]; +cp(pi/8) q[9], q[12]; +cp(pi/16) q[8], q[12]; +cp(pi/32) q[7], q[12]; +cp(pi/64) q[6], q[12]; +cp(pi/128) q[5], q[12]; +cp(pi/256) q[4], q[12]; +cp(pi/512) q[3], q[12]; +cp(pi/1024) q[2], q[12]; +cp(pi/2048) q[1], q[12]; +cp(pi/4096) q[0], q[12]; +h q[11]; +cp(pi/2) q[10], q[11]; +cp(pi/4) q[9], q[11]; +cp(pi/8) q[8], q[11]; +cp(pi/16) q[7], q[11]; +cp(pi/32) q[6], q[11]; +cp(pi/64) q[5], q[11]; +cp(pi/128) q[4], q[11]; +cp(pi/256) q[3], q[11]; +cp(pi/512) q[2], q[11]; +cp(pi/1024) q[1], q[11]; +cp(pi/2048) q[0], q[11]; +h q[10]; +cp(pi/2) q[9], q[10]; +cp(pi/4) q[8], q[10]; +cp(pi/8) q[7], q[10]; +cp(pi/16) q[6], q[10]; +cp(pi/32) q[5], q[10]; +cp(pi/64) q[4], q[10]; +cp(pi/128) q[3], q[10]; +cp(pi/256) q[2], q[10]; +cp(pi/512) q[1], q[10]; +cp(pi/1024) q[0], q[10]; +h q[9]; +cp(pi/2) q[8], q[9]; +cp(pi/4) q[7], q[9]; +cp(pi/8) q[6], q[9]; +cp(pi/16) q[5], q[9]; +cp(pi/32) q[4], q[9]; +cp(pi/64) q[3], q[9]; +cp(pi/128) q[2], q[9]; +cp(pi/256) q[1], q[9]; +cp(pi/512) q[0], q[9]; +h q[8]; +cp(pi/2) q[7], q[8]; +cp(pi/4) q[6], q[8]; +cp(pi/8) q[5], q[8]; +cp(pi/16) q[4], q[8]; +cp(pi/32) q[3], q[8]; +cp(pi/64) q[2], q[8]; +cp(pi/128) q[1], q[8]; +cp(pi/256) q[0], q[8]; +h q[7]; +cp(pi/2) q[6], q[7]; +cp(pi/4) q[5], q[7]; +cp(pi/8) q[4], q[7]; +cp(pi/16) q[3], q[7]; +cp(pi/32) q[2], q[7]; +cp(pi/64) q[1], q[7]; +cp(pi/128) q[0], q[7]; +h q[6]; +cp(pi/2) q[5], q[6]; +cp(pi/4) q[4], q[6]; +cp(pi/8) q[3], q[6]; +cp(pi/16) q[2], q[6]; +cp(pi/32) q[1], q[6]; +cp(pi/64) q[0], q[6]; +h q[5]; +cp(pi/2) q[4], q[5]; +cp(pi/4) q[3], q[5]; +cp(pi/8) q[2], q[5]; +cp(pi/16) q[1], q[5]; +cp(pi/32) q[0], q[5]; +h q[4]; +cp(pi/2) q[3], q[4]; +cp(pi/4) q[2], q[4]; +cp(pi/8) q[1], q[4]; +cp(pi/16) q[0], q[4]; +h q[3]; +cp(pi/2) q[2], q[3]; +cp(pi/4) q[1], q[3]; +cp(pi/8) q[0], q[3]; +h q[2]; +cp(pi/2) q[1], q[2]; +cp(pi/4) q[0], q[2]; +h q[1]; +cp(pi/2) q[0], q[1]; +h q[0]; +swap q[0], q[29]; +swap q[1], q[28]; +swap q[2], q[27]; +swap q[3], q[26]; +swap q[4], q[25]; +swap q[5], q[24]; +swap q[6], q[23]; +swap q[7], q[22]; +swap q[8], q[21]; +swap q[9], q[20]; +swap q[10], q[19]; +swap q[11], q[18]; +swap q[12], q[17]; +swap q[13], q[16]; +swap q[14], q[15]; diff --git a/wai/quantum-cross-simulator/corpus/qec-hand-written.json b/wai/quantum-cross-simulator/corpus/qec-hand-written.json index bfb420cd1..3c928a2d6 100644 --- a/wai/quantum-cross-simulator/corpus/qec-hand-written.json +++ b/wai/quantum-cross-simulator/corpus/qec-hand-written.json @@ -15,13 +15,17 @@ "reason": "An observable on Pauli targets rather than measurement records.", "text": "R 0 1 2\nH 0\nCX 0 1 1 2\nZ_ERROR(0.01) 1\nOBSERVABLE_INCLUDE(0) X0 X1 X2\n" }, - "qec_refused_correlated": { - "reason": "A correlated error, which the frame simulator does not implement: it must be refused with its line.", - "text": "R 0 1\nE(0.01) X0 X1\nM 0 1\nDETECTOR rec[-1]\n" + "qec_correlated": { + "reason": "A correlated error, with a Y among its targets: one mechanism with every symptom, and the targets flipping together.", + "text": "R 0 1 2\nE(0.01) X0 Y1\nE(0.02) X2\nM 0 1 2\nDETECTOR rec[-3]\nDETECTOR rec[-2]\nDETECTOR rec[-1]\n" }, - "qec_refused_pauli_channel": { - "reason": "A general Pauli channel, which it does not implement either.", - "text": "R 0\nPAULI_CHANNEL_1(0.01, 0.02, 0.03) 0\nM 0\nDETECTOR rec[-1]\n" + "qec_pauli_channel": { + "reason": "A general Pauli channel: exclusive outcomes, whose independent mechanisms have rates that give the same law. The other engine gives no exact model of this channel, so its sampler holds the engine's.", + "text": "R 0\nRX 1\nPAULI_CHANNEL_1(0.01, 0.02, 0.03) 0 1\nM 0\nMX 1\nDETECTOR rec[-2]\nDETECTOR rec[-1]\n" + }, + "qec_refused_channel_with_no_independent_form": { + "reason": "A Pauli channel whose exclusive outcomes no independent flips can give (Z's rate would be below zero): it must be refused with its line, never approximated in silence.", + "text": "R 0\nPAULI_CHANNEL_1(0.1, 0.1, 0) 0\nM 0\nDETECTOR rec[-1]\n" }, "qec_refused_random_detector": { "reason": "A detector that is random without noise is no detector: it must be refused.", diff --git a/wai/quantum-cross-simulator/tools/before_after.py b/wai/quantum-cross-simulator/tools/before_after.py new file mode 100644 index 000000000..2b3beacb1 --- /dev/null +++ b/wai/quantum-cross-simulator/tools/before_after.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +"""One host's timings of two builds of the engine, side by side. + + before_after.py BEFORE.json AFTER.json OUT.json + +BEFORE and AFTER are tools/perf.py's output on one host with WAI_CROSS_SIMULATOR naming each +build's driver, run one straight after the other. Standard library only. +""" +import json +import sys + + +def main(): + before, after = (json.load(open(p)) for p in sys.argv[1:3]) + if before["host"] != after["host"] or before["repeat"] != after["repeat"]: + sys.exit("before_after.py: two hosts, or two repeat counts: these timings do not compare") + index = {(r["case"], r["engine"], r["threads"]): r for r in before["rows"]} + rows = [] + for r in after["rows"]: + was = index.get((r["case"], r["engine"], r["threads"])) + if was is not None: + rows.append({"case": r["case"], "what": r["what"], "engine": r["engine"], "threads": r["threads"], "before": {k: v for k, v in was.items() if k not in ("case", "what", "engine", "threads")}, "after": {k: v for k, v in r.items() if k not in ("case", "what", "engine", "threads")}}) + out = {"about": "One host's timings of two builds of the engine under test, one straight after the other: tools/perf.py run on each, tools/before_after.py putting them side by side.", "host": after["host"], "versions": after["versions"], "before": before["engine_under_test"], "after": after["engine_under_test"], "repeat": after["repeat"], "rows": rows} + with open(sys.argv[3], "w") as f: + json.dump(out, f, indent=1) + f.write("\n") + + +if __name__ == "__main__": + main() diff --git a/wai/quantum-cross-simulator/tools/compare.py b/wai/quantum-cross-simulator/tools/compare.py index 46c003202..1d25b1b7e 100644 --- a/wai/quantum-cross-simulator/tools/compare.py +++ b/wai/quantum-cross-simulator/tools/compare.py @@ -279,6 +279,13 @@ def check_state_entry(e, runner, rep, engines): c["strict"] = d c["global_phase"] = phase exact_ops, exact_phase = ans["ops"], phase + # The phase its results state: with it the state is OpenQASM's, nothing taken out. + turn = np.exp(1j * ans.get("global_phase", 0.0)) + rotated = vec * turn + stated, _, _ = exact_distance(ref, rotated) + # And a double's rounding of the turn, on a state of norm 1. + stated_bound = bound + 8 * tol.U_DOUBLE + rep.add(e["id"], eng, "distance from the exact state, with the global phase its results state", stated, stated_bound, stated <= stated_bound) if not dyadic: c["note"] = (c.get("note") or "") + "; read every angle as dyadic within the reader's tolerance" # Bit for bit: an independent integer implementation of section 3.0 reruns the op-log. @@ -302,15 +309,12 @@ def check_state_entry(e, runner, rep, engines): ans = runner.run("wai.auto", {"id": e["id"], "kind": "amplitudes", "n": n, "steps": e["steps"], "bitstrings": bits}) if ans.get("ok"): planned = ans.get("planned") - # The bit-exact method keeps no global phase (it lowers rz to a phase gate, and so on): - # its amplitudes are held up to one phase, the one that aligns the largest of them. + # The bit-exact method lowers rz to a phase gate, and so on; its result states the phase + # that drops, and its amplitudes are held to OpenQASM's with that phase, nothing fitted. turn = 1 if planned == "exact": - top = max(picks, key=lambda i: ref.re[i] ** 2 + ref.im[i] ** 2) - got = complex(*ans["amplitudes"][format(top, "0%db" % n)]) - want = complex(ref.re[top] / 2.0**exact.PREC, ref.im[top] / 2.0**exact.PREC) - if abs(got) > 0: - turn = (want / got) / abs(want / got) + stated = ((ans.get("accuracy") or {}).get("global_phase") or {}).get("radians", 0.0) + turn = complex(math.cos(stated), math.sin(stated)) worst = 0.0 for b in bits: a = complex(*ans["amplitudes"][b]) * turn @@ -323,7 +327,7 @@ def check_state_entry(e, runner, rep, engines): bound = tol.fixed_point_bound(n, exact_ops) + 4 * tol.U_DOUBLE else: bound = tol.double_state(tol.gate_count(e["steps"]), n, width=3) - rep.add(e["id"], "wai.auto", "chosen amplitudes through the job path, worst error" + (", modulo a global phase" if planned == "exact" else ""), worst, bound, worst <= bound, note="planned %s" % planned) + rep.add(e["id"], "wai.auto", "chosen amplitudes through the job path, worst error" + (", with the global phase the result states" if planned == "exact" else ""), worst, bound, worst <= bound, note="planned %s" % planned) else: rep.not_run(e["id"], "wai.auto", "chosen amplitudes through the job path", ans.get("refused") or ans.get("error")) @@ -547,7 +551,8 @@ def check_wide_entry(e, runner, rep): engines = ["wai.mps", "wai.tensor_network", "aer.mps", "quimb.mps", "quimb.tensor_network"] if n <= 26: engines += ["wai.statevector", "aer.statevector"] - jobs = {eng: {"id": e["id"], "kind": "amplitudes", "n": n, "steps": e["steps"], "bitstrings": bits, "memory_gb": 24} for eng in engines} + engines = e.get("only_engines") or engines + jobs = {eng: {"id": e["id"], "kind": "amplitudes", "n": n, "steps": e["steps"], "bitstrings": bits, "memory_gb": 24, "max_bond": e.get("max_bond")} for eng in engines} got = {} gates = tol.gate_count(e["steps"]) for eng, ans in run_all(runner, jobs).items(): @@ -640,11 +645,18 @@ def check_qec_entry(q, text, runner, rep, qec_plan): rb = b.get("error") or b.get("unsupported") if not a.get("ok") and not b.get("ok"): rep.add(q["id"], "wai.qec ~ stim.tableau", "both refuse the circuit", ra, rb, True, note="refused by both: %s | %s" % (str(ra)[:200], str(rb)[:200])) + return elif not a.get("ok"): line = "line" in str(ra) rep.add(q["id"], "wai.qec", "refuses an instruction it does not implement, naming its line", ra, None, line, status="limit" if line else "fail", note="the other engine runs it") + return else: - rep.add(q["id"], "stim.tableau", "detector error model", None, None, False, note="refused here, run by the engine under test: %s" % rb) + # A channel the other engine gives no exact model of: its sampler still holds the + # engine's model, by the rates below. + rep.not_run(q["id"], "stim.tableau", "detector error model", "gives no model of this circuit, which the engine under test models: %s" % str(rb)[:200]) + shots = 200000 if q["tier"] == "ci" else 1000000 + sj = {eng: {"id": q["id"], "kind": "qec_sample", "text": text, "shots": shots, "seed": 5} for eng in ("wai.qec", "stim.tableau")} + qec_plan.append((q, merged(a["mechanisms"]), a["detectors"], a["observables"], run_all(runner, sj), shots)) return rep.add(q["id"], "wai.qec ~ stim.tableau", "detectors and observables", [a["detectors"], a["observables"]], [b["detectors"], b["observables"]], [a["detectors"], a["observables"]] == [b["detectors"], b["observables"]]) ma, mb = merged(a["mechanisms"]), merged(b["mechanisms"]) @@ -682,7 +694,7 @@ def text_noise_sites(text): stack.pop() continue m = re.match(r"([A-Z_0-9]+)(\[[^\]]*\])?\(([^)]*)\)\s*(.*)", s) - if m and (m.group(1).endswith("ERROR") or m.group(1).startswith("DEPOLARIZE") or m.group(1) in ("M", "MX", "MR", "MRX", "MY")): + if m and (m.group(1).endswith("ERROR") or m.group(1).startswith(("DEPOLARIZE", "PAULI_CHANNEL")) or m.group(1) in ("E", "M", "MX", "MR", "MRX", "MY")): total += stack[-1] * max(len(m.group(4).split()), 1) return total @@ -864,7 +876,7 @@ def main(): rep.add(q["id"], "wai.qec", "the engine's own generator writes the same text, byte for byte", mine == text, True, mine == text) if a.tier == "full" or not only: for k, v in hand.items(): - if a.tier == "ci" and k not in ("qec_inverted_and_tagged", "qec_refused_correlated", "qec_refused_random_detector"): + if a.tier == "ci" and k not in ("qec_inverted_and_tagged", "qec_correlated", "qec_refused_random_detector"): continue check_qec_entry({"id": k, "tier": a.tier}, v["text"], runner, rep, qplan) judge_qec(qplan, rep) diff --git a/wai/quantum-cross-simulator/tools/corpus.py b/wai/quantum-cross-simulator/tools/corpus.py index be00800a5..3382f8194 100644 --- a/wai/quantum-cross-simulator/tools/corpus.py +++ b/wai/quantum-cross-simulator/tools/corpus.py @@ -397,6 +397,8 @@ def entries(): add("mps_ghz_n%d" % n, "wide_mps", {"n": n}, "Bond dimension 2 at any width: the amplitudes of the two outcomes, in closed form.", n, ghz_steps(n), "amplitudes", wide_kind="ghz", tier="ci" if n == 30 else "full") for n, x in ((30, 715827883), (40, 366503875925)): add("mps_qft_n%d" % n, "wide_mps", {"n": n, "x": x}, "The QFT of a basis state is a product state, reached through modest entanglement. Chosen amplitudes in closed form.", n, basis_prep(n, x) + qft_steps(n), "amplitudes", wide_kind="qft", qft_x=x) + # The bond asked for is not the bond reached: at 256, past what an estimate at that bond admits. + add("mps_qft_n30_bond256", "wide_mps", {"n": 30, "x": 715827883, "max_bond": 256}, "The 30-qubit QFT at a bond far above what it reaches: a job naming the method runs under a meter of the bond it holds, and stays exact.", 30, basis_prep(30, 715827883) + qft_steps(30), "amplitudes", wide_kind="qft", qft_x=715827883, max_bond=256, only_engines=["wai.mps"]) add("tn_shallow_n26", "wide_tn", {"n": 26, "depth": 5, "seed": 41}, "A shallow rotation brickwork: amplitudes by contraction, against matrix product states and a state vector.", 26, random_rotations(26, 5, 41), "wide_pairwise") add("tn_mirror_n40", "wide_tn", {"n": 40, "depth": 3, "seed": 42}, "A shallow mirror circuit, too wide for a state vector here: the amplitude of |0…0> is exactly 1.", 40, random_dyadic(40, 3, 42, 16) + inverse_steps(random_dyadic(40, 3, 42, 16)), "wide_mirror") @@ -430,7 +432,7 @@ def qec_entries(): for d in (3, 9, 25): add("repetition_d%d" % d, "repetition_code:memory", d, d, 0.005, "A line of data qubits: the simplest model, with long detector chains at d = 25.") add("surface_z_d5_noiseless", "surface_code:rotated_memory_z", 5, 5, 0.0, "No noise at all: every detector and the observable are silent on every shot, and the model is empty.", tier="ci") - add("color_d3", "color_code:memory_xyz", 3, 3, 0.002, "A colour code with C_XYZ gates: an instruction the frame simulator does not implement must be refused with its line, never skipped.") + add("color_d3", "color_code:memory_xyz", 3, 3, 0.002, "A colour code, whose syndrome cycle turns the axes with C_XYZ gates: the model must match mechanism by mechanism, and every detector's rate must follow it.") return out @@ -467,15 +469,27 @@ CX 0 1 1 2 Z_ERROR(0.01) 1 OBSERVABLE_INCLUDE(0) X0 X1 X2 """), - "qec_refused_correlated": ("A correlated error, which the frame simulator does not implement: it must be refused with its line.", """\ -R 0 1 -E(0.01) X0 X1 -M 0 1 + "qec_correlated": ("A correlated error, with a Y among its targets: one mechanism with every symptom, and the targets flipping together.", """\ +R 0 1 2 +E(0.01) X0 Y1 +E(0.02) X2 +M 0 1 2 +DETECTOR rec[-3] +DETECTOR rec[-2] DETECTOR rec[-1] """), - "qec_refused_pauli_channel": ("A general Pauli channel, which it does not implement either.", """\ + "qec_pauli_channel": ("A general Pauli channel: exclusive outcomes, whose independent mechanisms have rates that give the same law. The other engine gives no exact model of this channel, so its sampler holds the engine's.", """\ R 0 -PAULI_CHANNEL_1(0.01, 0.02, 0.03) 0 +RX 1 +PAULI_CHANNEL_1(0.01, 0.02, 0.03) 0 1 +M 0 +MX 1 +DETECTOR rec[-2] +DETECTOR rec[-1] +"""), + "qec_refused_channel_with_no_independent_form": ("A Pauli channel whose exclusive outcomes no independent flips can give (Z's rate would be below zero): it must be refused with its line, never approximated in silence.", """\ +R 0 +PAULI_CHANNEL_1(0.1, 0.1, 0) 0 M 0 DETECTOR rec[-1] """), diff --git a/wai/quantum-cross-simulator/tools/perf.py b/wai/quantum-cross-simulator/tools/perf.py index 8235b746f..dbfba2001 100644 --- a/wai/quantum-cross-simulator/tools/perf.py +++ b/wai/quantum-cross-simulator/tools/perf.py @@ -53,7 +53,9 @@ def cases(quick): if n <= 20: engines.append("quimb.dense") out.append({"id": "rotations_n%d" % n, "what": "20 layers of arbitrary U gates on a brickwork of cx, the whole state", "kind": "state", "n": n, "steps": steps, "engines": engines}) - for n in (10, 14): + # Past 16 the gates under n - 1 controls stand whole, or (at 17) past what a program may be + # in standard gates: a width only the state vectors that hold them whole reach. + for n in (10, 14, 16, 20): out.append({"id": "grover_n%d" % n, "what": "two Grover iterations on %d qubits: four Z gates under %d controls, the whole state" % (n, n - 1), "kind": "state", "n": n, "steps": corpus.grover_steps(n, (1 << n) // 3, 2), "engines": ["wai.statevector", "wai.exact", "aer.statevector", "qsim.statevector", "ddsim.statevector"]}) for n, depth in ((1000, 30), (5000, 10)): steps = corpus.random_clifford(n, depth, 200 + n) diff --git a/wai/quantum-cross-simulator/tools/report.py b/wai/quantum-cross-simulator/tools/report.py index b2524f020..de0f1b0c0 100644 --- a/wai/quantum-cross-simulator/tools/report.py +++ b/wai/quantum-cross-simulator/tools/report.py @@ -142,6 +142,18 @@ def results_section(): mem = "%s (%s)" % (fmt_mib(row["peak_rss_mib"]), fmt_mib(row.get("baseline_rss_mib"))) out.append("| %s | `%s` | %s | %s | %s | %s → %s |" % (row["case"], row["engine"], row["threads"], sec, mem, row["load_before"][0], row["load_after"][0])) out.append("") + for path in sorted(glob.glob(os.path.join(ROOT, "results", "before-after-*.json"))): + p = json.load(open(path)) + out.append("### `%s`" % os.path.basename(path)) + out.append("") + out.append("Host: %s. The same driver and circuits, with the engine before and after a gate under many controls stood whole: the engine's own call, the median of %d runs (the minimum in brackets), one build straight after the other." % (host_line(p), p["repeat"])) + out.append("") + out.append("| case | engine | threads | before: seconds, median (min) | after: seconds, median (min) | load average before → after |") + out.append("|---|---|---|---|---|---|") + for row in p["rows"]: + cell = lambda r: ("not run: %s" % r["not_run"][:90]) if r.get("not_run") else "%s (%s)" % (fmt_seconds(r["seconds_median"]), fmt_seconds(r["seconds_min"])) + out.append("| %s | `%s` | %s | %s | %s | %s → %s |" % (row["case"], row["engine"], row["threads"], cell(row["before"]), cell(row["after"]), row["before"]["load_before"][0], row["after"]["load_before"][0])) + out.append("") return "\n".join(out).rstrip() + "\n" diff --git a/wai/wai-quantum-cli/examples/cross_simulator.rs b/wai/wai-quantum-cli/examples/cross_simulator.rs index 49a569999..badb8fa47 100644 --- a/wai/wai-quantum-cli/examples/cross_simulator.rs +++ b/wai/wai-quantum-cli/examples/cross_simulator.rs @@ -11,9 +11,11 @@ //! its `kind`: //! //! - `state`: the program's whole state, written to `state_out` with qubit 0 as -//! the lowest bit of the index. `method` `exact` writes `i64` pairs at scale -//! `2^30` (with the state's hash and its op-log, which an independent reader -//! reruns); `statevector` writes `f64` pairs, at fusion width `fusion`. +//! the lowest bit of the index, each gate under many controls held as one, as +//! a job holds it. `method` `exact` writes `i64` pairs at scale `2^30` (with +//! the state's hash, its op-log, which an independent reader reruns, and the +//! global phase the job's result states); `statevector` writes `f64` pairs, at +//! fusion width `fusion`. //! - `job`: `request` through [`wai_quantum::engine::job::plan_and_run`], the //! engine's whole path: its plan, its run and its answers, unsealed. //! - `stabilizers`: the program on the tableau, and `⟨g⟩` of each Pauli string @@ -53,12 +55,12 @@ fn text<'a>(j: &'a Value, k: &str) -> Result<&'a str, String> { } fn state(j: &Value) -> Result { - let program = qasm::read(text(j, "qasm")?).map_err(|d| d.to_string())?.program; + let program = qasm::read_whole(text(j, "qasm")?).map_err(|d| d.to_string())?.program; let n = program.n_qubits; let out = j.get("state_out").and_then(Value::as_str); match text(j, "method")? { "exact" => { - let c = program.dyadic()?; + let (c, report) = program.dyadic_with_report()?; let t = Instant::now(); let sv = c.simulate().map_err(|e| e.to_string())?; let seconds = t.elapsed().as_secs_f64(); @@ -66,14 +68,14 @@ fn state(j: &Value) -> Result { write_pairs(path, sv.amps.iter().map(|a| (a.re, a.im)), i64::to_le_bytes)?; } let ops: Vec = c.ops.iter().map(|g| json!([g.base as u8, g.controls, g.target, g.param])).collect(); - Ok(json!({ "n": n, "seconds": seconds, "state_hash": hex(&sv.statevector_hash()), "ops": if j.get("ops").and_then(Value::as_bool).unwrap_or(true) { Value::Array(ops) } else { Value::Null }, "n_ops": c.ops.len() })) + Ok(json!({ "n": n, "seconds": seconds, "state_hash": hex(&sv.statevector_hash()), "ops": if j.get("ops").and_then(Value::as_bool).unwrap_or(true) { Value::Array(ops) } else { Value::Null }, "n_ops": c.ops.len(), "global_phase": report.global_phase_radians() })) } "statevector" => { - let gates = program.matrices(); + let gates = program.sv_ops(); let width = j.get("fusion").and_then(Value::as_u64).unwrap_or(3) as usize; let mut sv = StateVector::zero(n).map_err(|e| format!("{e:?}"))?; let t = Instant::now(); - sv.run(&gates, width).map_err(|e| format!("{e:?}"))?; + sv.run_ops(&gates, width).map_err(|e| format!("{e:?}"))?; let seconds = t.elapsed().as_secs_f64(); if let Some(path) = out { // Qubit 0 is the state vector's highest bit; the file has it lowest. diff --git a/wai/wai-quantum/README.md b/wai/wai-quantum/README.md index 542c44253..5eae4c54c 100644 --- a/wai/wai-quantum/README.md +++ b/wai/wai-quantum/README.md @@ -67,7 +67,7 @@ never creates information. |---|---| | `quantum` | byte-exact statevector simulation (dyadic Clifford+T+P(k)), as `wai.quantum.circuit2` by default or as the frozen `wai.quantum.circuit` | | `quantum_toolchain` | algorithm library, backend recommendation, **OpenQASM 2/3 import through the one reader** (`from_qasm`): everything the reader takes, under the bit-exact circuit's restriction, dyadic angles and measurements at the end, refused with the reader's codes otherwise (non-dyadic angles are refused, never rounded); a controlled gate the modifiers write is held whole, so `to_qasm`'s output reads back gate for gate; **device-ready OpenQASM 2/3** (`device::device_qasm`): every gate lowered exactly to its dialect's standard library, multi-controlled gates included, every qubit measured into `c[i]`, and the service's counts read back onto the crate's basis; **native programs** (`native::compile`): a processor's own basis (`rz`/`sx`/`x`/`cz`; `prx`/`cz`; or `gpi`/`gpi2`/`zz` with angles in turns, written exactly; the Z rotations carried in the phases of the last two) on its own qubits, routed over its coupling map, and checked against the circuit by simulation before it is sent — Bloch / entanglement / purity analysis | -| `quantum_lang` | **the OpenQASM reader, one grammar for every surface** (`qasm::read`, `qasm::parse`): the job service, the command line, both MCP servers, the Studio, the desktop app, the edge component and the in-browser IDE all read through it. OpenQASM 3.1 and the OpenQASM 2 forms in common use, read in three stages with the source position of everything: registers, aliases and slices; gate definitions; every modifier (`ctrl @`, `negctrl @`, `inv @`, `pow(k) @`, exact fractional powers) on any gate, lowered exactly; `def` subroutines, inlined, a returned measurement written into the caller's bit; classical types (`int`, `uint`, `float`, `angle[n]`, `complex`, `bool`, `bit`, arrays), their arithmetic, casts and built-in functions, computed on reading with the same bits on every platform; `for`, `while` (unrolled when known, or run at most `@wai.max_iterations N` times on measured bits), `switch`, `break`, `continue`, `end`; conditions on measured bits with comparisons, `&&`, `||` and `!`, compiled to steps that branch forward; `output` carried into the result; `delay`, `box`, `stretch` and `barrier` carried as timing and labelled when a method ignores durations; `defcal` and `cal` kept verbatim, never run. Generators: integer `input`s, so one program describes a family of circuits (`qasm::read_with`, `qasm::instantiate`). **Every refusal and warning carries a stable code** (`line 3: unknown gate foo [Q103]`, and as data with its line, column and length): [the table of codes](docs/qasm-diagnostics.md) (`qasm::diag::codes()`, `wai-quantum diagnostics`), and [what the reader does with each construct of OpenQASM 3.1](docs/qasm-feature-matrix.md). The [conformance corpus](../quantum-conformance/qasm3/) holds the specification's examples and a program for each construct, run natively, under wasm32-wasip2 and in the browser | +| `quantum_lang` | **the OpenQASM reader, one grammar for every surface** (`qasm::read`, `qasm::parse`): the job service, the command line, both MCP servers, the Studio, the desktop app, the edge component and the in-browser IDE all read through it. OpenQASM 3.1 and the OpenQASM 2 forms in common use, read in three stages with the source position of everything: registers, aliases and slices; gate definitions; every modifier (`ctrl @`, `negctrl @`, `inv @`, `pow(k) @`, exact fractional powers) on any gate, lowered exactly; `def` subroutines, inlined, a returned measurement written into the caller's bit; classical types (`int`, `uint`, `float`, `angle[n]`, `complex`, `bool`, `bit`, arrays), their arithmetic, casts and built-in functions, computed on reading with the same bits on every platform; `for`, `while` (unrolled when known, or run at most `@wai.max_iterations N` times on measured bits), `switch`, `break`, `continue`, `end`; conditions on measured bits with comparisons, `&&`, `||` and `!`, compiled to steps that branch forward; `output` carried into the result; `delay`, `box`, `stretch` and `barrier` carried as timing and labelled when a method ignores durations; `defcal` and `cal` kept verbatim, never run. Generators: integer `input`s, so one program describes a family of circuits (`qasm::read_with`, `qasm::instantiate`). **Every refusal and warning carries a stable code** (`line 3: unknown gate foo [Q103]`, and as data with its line, column and length): [the table of codes](docs/qasm-diagnostics.md) (`qasm::diag::codes()`, `wai-quantum diagnostics`), and [what the reader does with each construct of OpenQASM 3.1](docs/qasm-feature-matrix.md). The [conformance corpus](../quantum-conformance/qasm3/) holds the specification's examples and a program for each construct, run natively, under wasm32-wasip2 and in the browser. `qasm::read_whole` keeps a gate under many controls as one operation, for the methods that run it so, and `Program::lowered` writes it in standard gates | | `quantum_qasm` | the reader's program lowered to each method's input, exactly up to a global phase: dense matrices, two-qubit matrices for the matrix product state, Pauli rotations, Clifford gates, and the dyadic circuit (`Program::dyadic`); `qasm::dyadic_circuit` gives the exact state vector's circuit for a program whose measurements all come at the end, and refuses any other with its code | | `quantum_engine` | **the quantum job service's engine, for every host**: a job (an OpenQASM program and what is asked of it: shots, Pauli expectation values, amplitudes, noise) planned onto the strongest method it admits, with the reason and the memory and work it will take; run; answered in the service's JSON with its accuracy class; and sealed over the request and the result in their canonical JSON (`engine::job`, `engine::receipt`), so a result from the service, the command line or a browser tab checks the same way. Also a program's circuit drawn as text (`engine::draw`) and as a standalone SVG drawing, the Studio's picture with each gate marked by whose hand it is in (`engine::svg`, which the Python package draws in notebooks: `wai/wai-quantum-py`); the specification-and-evaluator workbench (`engine::discover`: a specification, the engine's verdict on a generator at every size, and an archive of the cheapest verified generator in every cell of two measures, sealed); a program's history, attributed (`engine::versions`: versions in a sealed chain, each with who made it and how, proposals reviewed change by change, and each line and gate in the hand that wrote it, which a job's receipt can bind); the person's rules for proposals (`engine::locks`: held blocks, the gates allowed, the qubit declarations, what to avoid and a region, checked change by change); what is new in a program (`engine::novelty`: its structural distance to the known constructions and to programs given, each known construction it is proved to be and whether by a different route, and the strengths a cost did not ask for; a workbench candidate that breaks only a rule is an aberration, with the cost it would have); a study (`engine::study`: a protocol sealed before any data, each participant's condition fixed by their key, their record sealed with it, the measures computed by the engine from what they made, and a cohort report with seeded bootstrap intervals and Cronbach's alpha); convergence (`engine::converge`: along a program's history, how far the person's versions are built from a model's proposals and the model's share of the gates, with the versions made on their own set beside the rest; and a cohort's diversity, its Vendi score, centroid and narrowing over time); rewrites that keep a circuit's meaning (`engine::rewrite`: cancellations, merges, Hadamard conjugations and gates carried past what they commute with, each checked on the qubits it touches, so a chain of them proves two programs equal at any width, explains an optimisation, and offers a person one rewrite at a time); a person's taste (`engine::taste`: a Bradley–Terry model of their own choices between programs the engine proves equal, part by part of a rubric, with typicality shown beside it and moved only by a dial, and how well it predicts them measured); what an agent is told (`engine::guide`: the language the reader takes, its diagnostics, each held to the reader by a test, the methods and their accuracy classes, worked examples each with its intent, and the rules an agent keeps, which both MCP servers serve as resources and prompts); the language service an editor needs (`engine::editor`: the reader's refusal and the critique's smells as diagnostics on their lines, completion by what the cursor's place takes, hover with each standard gate's matrix written exactly and held to the engine's own, a user gate's computed from its gates, and each gate's cost as the engine counts it, definitions, references, renames, an outline, folding, and a formatter with one layout that keeps every token, all pure and with no protocol in it); compilation with a certificate (`engine::compile`: checked passes, every rotation written in Clifford+T within an ε budget by `engine::synth`, one sealed record of each pass and the distance; see [docs/compiler.md](docs/compiler.md)); resource estimation from programs (`engine::estimate`: logical counts with each rotation at its synthesised `T` count, the physical estimate with the code model fitted to the crate's own decoders, the frontier, every estimate sealed; see [docs/estimate.md](docs/estimate.md)); the debugger (`engine::debug`: a program stepped forward and back one operation at a time on the bit-exact or double-precision state vector, or the density matrix under noise beside its noiseless state, stopped before a line, and probed anywhere for its amplitudes and phases, each qubit's Bloch vector and purity, the reduced density matrix of chosen qubits and the entanglement across a cut; every branch at its measurements in the middle with its weight, exact fractions by the tableau for a noiseless Clifford program; a recorded path replayed; a state seen twice the same bits, and the exact method's state after the last gate the exact run's, by its hash; refused past 16 qubits, or 8 under noise); the circuit as LaTeX in plain TikZ (`engine::latex`) and in words for a screen reader (`engine::describe`); the circuit edited by its drawing, a gate put on a wire, moved or deleted as an edit to the program's own text through its syntax tree (`engine::visual`); Pearson's chi-squared test and the G-test of sampled outcomes against a stated distribution, the p-value the same bits everywhere (`engine::stats`); sets and sweeps (`engine::sets`: a list of programs, or one program over a grid of its integer, float and angle inputs, run as plain jobs, each item sealed and one receipt over the head that holds the Merkle root of every item's leaf, with each item's path to it); a result's provenance under the categories provenance surveys use (`engine::run::run_with_provenance`: the program's digest, the method, each pass a compile ran with its check's verdict and the certificate's digest, the shots, seed and plan, the engine's version); and the energy a job spent (`engine::energy`: the CPU energy the kernel counts for one process on macOS, and on Linux the processor packages' counters over a window, read only when live and labelled with no attribution to the job).; and programs in other formats (`engine::formats`): QIR read under the base and adaptive profiles its entry point names (1.x and 2.x, what a profile forbids refused on its line, a rotation at any angle read at its exact double) and written as QIR 2.0, and jeff read and written through the crate's own Cap'n Proto reader and writer (loops over registers unrolled, a switch on a measured bit read as a condition, Pauli-product rotations lowered exactly), every construct a reader cannot hold refused with a code (`Q700` to `Q721`) and its place and each conversion checked by the equivalence ladder ([the formats page](docs/formats.md), [the conformance set](../quantum-conformance/formats/)). It builds for `wasm32-unknown-unknown`, where it runs on one thread and claims no time | | `quantum_stabilizer` | stabilizer (CHP) tableau — `O(n²)`, scales far past statevector | diff --git a/wai/wai-quantum/docs/qasm-diagnostics.md b/wai/wai-quantum/docs/qasm-diagnostics.md index 06322fd70..60a6153f3 100644 --- a/wai/wai-quantum/docs/qasm-diagnostics.md +++ b/wai/wai-quantum/docs/qasm-diagnostics.md @@ -87,7 +87,7 @@ engine. A test holds this page to the code's table. | `Q205` | refused | `pow(r) @` with a fractional `r` where no exact gate exists here: a user gate, `u`, `cu`, or a rotation by 2π or more. | | `Q206` | lowered | `gphase(θ)`: a global phase, which no measurement sees, dropped; under controls it is a phase on the controls. | | `Q207` | refused | A control modifier that adds no control: `ctrl(0) @`. | -| `Q208` | refused | Modifiers that add more controls than the reader lowers (16). | +| `Q208` | refused | Modifiers that add more controls than the reader lowers (16 written in standard gates, 255 on a gate a method holds whole). | | `Q209` | refused | Gate definitions or subroutine calls nested deeper than 32. | | `Q210` | refused | A program that expands to more gates than the reader holds (2 000 000). | | `Q211` | refused | A modifier on something that is not a gate. | diff --git a/wai/wai-quantum/docs/qasm-feature-matrix.md b/wai/wai-quantum/docs/qasm-feature-matrix.md index 6213d823b..3e02357cf 100644 --- a/wai/wai-quantum/docs/qasm-feature-matrix.md +++ b/wai/wai-quantum/docs/qasm-feature-matrix.md @@ -109,7 +109,7 @@ and in the browser build. | Construct | Status | Codes | |---|---|---| -| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls | Q201, Q207, Q208 | +| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` or `exact` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`) | Q201, Q207, Q208 | | `inv @` on any gate | lowered exactly: each gate's inverse, in reverse order | Q202 | | `pow(k) @`, `k` a whole number | lowered exactly: angles scaled or the gate repeated; negative `k` repeats the inverse | Q203 | | `pow(r) @`, `r` fractional | lowered where an exact principal root exists (`pow(1/2) @ x` is `sx`; rotations by less than 2π; phases; controlled forms); refused otherwise (`u`, `cu`, user gates) | Q204, Q205 | diff --git a/wai/wai-quantum/schemas/job-request.v1.json b/wai/wai-quantum/schemas/job-request.v1.json index 96c48c65a..8692009f0 100644 --- a/wai/wai-quantum/schemas/job-request.v1.json +++ b/wai/wai-quantum/schemas/job-request.v1.json @@ -137,7 +137,7 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: \"standard\" runs a gate under many controls in standard gates on exact and statevector too, which reproduces a result made that way, bit for bit." }, "compile": { "$ref": "compile-result.v1.json#/$defs/options" diff --git a/wai/wai-quantum/schemas/job-result.v1.json b/wai/wai-quantum/schemas/job-result.v1.json index d3bd353d4..a9f3172c7 100644 --- a/wai/wai-quantum/schemas/job-result.v1.json +++ b/wai/wai-quantum/schemas/job-result.v1.json @@ -49,7 +49,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The operations the method ran. On exact and statevector a gate under many controls is one." + }, + "standard_gates": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one: how many gates the program is in standard gates, at most 2^53 - 1." }, "accuracy": { "$ref": "#/$defs/accuracy" @@ -664,6 +670,36 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "required": ["turns_over_2_33", "radians", "note"], + "properties": { + "turns_over_2_33": { "type": "integer", "minimum": 0, "description": "The phase exactly, in 2^33rds of a turn." }, + "radians": { "type": "number", "description": "The same in radians, in (-pi, pi]." }, + "note": { "type": "string" } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "required": ["angles", "largest_radians", "note"], + "properties": { + "angles": { "type": "integer", "minimum": 1 }, + "largest_radians": { "type": "number" }, + "note": { "type": "string" } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "required": ["angles", "largest_radians", "note"], + "properties": { + "angles": { "type": "integer", "minimum": 1 }, + "largest_radians": { "type": "number" }, + "note": { "type": "string" } + } + }, "fusion": { "type": "integer" }, diff --git a/wai/wai-quantum/schemas/tools.v1.json b/wai/wai-quantum/schemas/tools.v1.json index b20c99dd1..f2972ebf1 100644 --- a/wai/wai-quantum/schemas/tools.v1.json +++ b/wai/wai-quantum/schemas/tools.v1.json @@ -62,7 +62,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "A gate under many controls counts one, as the state-vector methods run it." + }, + "standard_gates": { + "type": "integer", + "minimum": 0, + "description": "When a gate under many controls counted one: how many gates the program is in standard gates, at most 2^53 - 1." }, "bits": { "type": "integer", diff --git a/wai/wai-quantum/src/engine/catalog.rs b/wai/wai-quantum/src/engine/catalog.rs index cec85febf..b635ebfcc 100644 --- a/wai/wai-quantum/src/engine/catalog.rs +++ b/wai/wai-quantum/src/engine/catalog.rs @@ -291,7 +291,9 @@ pub fn statevector_max_qubits(job_bytes: u64) -> u32 { /// as `(qubit, 'X'|'Y'|'Z')`. pub type Observable = (String, f64, Vec<(u32, char)>); -/// A job as submitted, read and checked. +/// A job as submitted, read and checked. Its `program` is in standard gates, +/// except for a built-in method that runs a gate under many controls as one +/// ([`runs_whole`]). pub struct Request { pub program: Program, /// The reader's warnings and notes on the program, each with its code. @@ -318,6 +320,54 @@ pub struct Request { pub mitigate: Option, } +impl Request { + /// The request with its program in standard gates ([`Program::lowered`]); + /// refused where the standard form cannot hold it. + pub(crate) fn lowered(&self) -> Result { + Ok(Request { + program: self.program.lowered().map_err(String::from)?, + diagnostics: self.diagnostics.clone(), + method: self.method.clone(), + shots: self.shots, + seed: self.seed, + observables: self.observables.clone(), + amplitudes: self.amplitudes.clone(), + noise: self.noise, + options: self.options.clone(), + compiled: self.compiled.clone(), + compile_passes: self.compile_passes.clone(), + repaired: self.repaired.clone(), + mitigate: self.mitigate.clone(), + }) + } +} + +/// Whether a built-in method runs a gate under many controls as one: every +/// other takes the program in standard gates. +pub(crate) fn runs_whole(method: &str) -> bool { + matches!(method, "exact" | "statevector") +} + +/// Whether this job may hold a gate under many controls as one op +/// ([`qasm::read_whole`]). Not with a compile, which writes standard gates; not +/// with noise or mitigation, whose channels follow standard gates (a job with +/// noise reaches no method that runs whole in any case); not on a device +/// target or a provider, compiled to its gates; not when the job names a +/// place on the fabric, where every member runs the standard gates and the +/// state is the CPU's, bit for bit; and not when it asks for +/// `"options": {"controls": "standard"}`, which reproduces a result made in +/// standard gates, bit for bit. +pub(crate) fn may_run_whole(v: &Value) -> bool { + let absent = |k: &str| v.get(k).is_none_or(Value::is_null); + absent("compile") + && absent("noise") + && absent("mitigate") + && absent("target") + && absent("provider") + && matches!(super::fabric::asked(v), Ok(super::fabric::Ask::Auto)) + && v.pointer("/options/controls").and_then(Value::as_str) != Some("standard") +} + fn observable(v: &Value, n: u32) -> Result { let (text, coeff) = match v { Value::String(s) => (s.clone(), 1.0), @@ -474,7 +524,8 @@ pub fn bind_params(src: &str, params: Option<&Value>) -> Result qasm::bind(src, &values).map_err(|e| tag(refusal::PARAMS, e)) } -/// Reads a job's JSON. A refusal ends with its code ([`super::refusal`]). +/// Reads a job's JSON, its program in standard gates. A refusal ends with its +/// code ([`super::refusal`]). pub fn read(v: &Value) -> Result { read_in(Registry::builtins(), v).map(|(r, _)| r) } @@ -483,6 +534,12 @@ pub fn read(v: &Value) -> Result { /// channel its noise names with a value other than zero, by its place in /// the registry with its values. pub(crate) fn read_in(reg: &Registry, v: &Value) -> Result<(Request, Uses), String> { + read_form(reg, v, false) +} + +/// [`read_in`], with each gate under many controls held as one op when `whole` +/// (and the job may hold one, [`may_run_whole`]). +pub(crate) fn read_form(reg: &Registry, v: &Value, whole: bool) -> Result<(Request, Uses), String> { // A set runs as a set, item by item; read as one job it would run one // program in place of all of them. if is_set(v) { @@ -513,8 +570,12 @@ pub(crate) fn read_in(reg: &Registry, v: &Value) -> Result<(Request, Uses), Stri (qasm, Some(said)) } }; - let reading = qasm::read(&src)?; + let reading = if whole && may_run_whole(v) { qasm::read_whole(&src)? } else { qasm::read(&src)? }; let (program, diagnostics) = (reading.program, reading.diagnostics); + // A verdict reads the program in standard gates, whichever way it runs. + if program.has_whole() && super::verdict::asked(v) { + program.lowered()?; + } // "intent": what the program must do, checked with its result // (super::verdict); refused here when it does not read. if let Some(i) = v.get("intent").filter(|i| !i.is_null()) { @@ -626,12 +687,22 @@ pub fn mps_bond(r: &Request) -> usize { /// An `mps` job's work: its two-site updates (each two-qubit gate and the /// swaps that route it) at `(2χ)³` each, and its shots at `n·χ²` each. pub fn mps_work(r: &Request, chi: u64) -> u64 { - let updates: u64 = r.program.ops.iter().map(|o| match o.qubits.as_slice() { + mps_updates(r).saturating_mul((2 * chi).pow(3)).saturating_add(mps_shots_work(r, chi)) +} + +/// An `mps` job's shots, at bond `chi`, in [`mps_work`]'s unit. +pub(crate) fn mps_shots_work(r: &Request, chi: u64) -> u64 { + r.shots.saturating_mul(r.program.n_qubits as u64 * chi * chi * 2) +} + +/// An `mps` job's two-site updates: each two-qubit gate and the swaps that +/// route it. +fn mps_updates(r: &Request) -> u64 { + r.program.ops.iter().map(|o| match o.qubits.as_slice() { [a, b] => 2 * (a.abs_diff(*b) as u64).saturating_sub(1) + 1, [a, b, c] => 15 * (1 + 2 * (a.abs_diff(*b).max(b.abs_diff(*c)).max(a.abs_diff(*c)) as u64)), _ => 0, - }).sum(); - updates.saturating_mul((2 * chi).pow(3)).saturating_add(r.shots.saturating_mul(r.program.n_qubits as u64 * chi * chi * 2)) + }).sum() } /// A `cutrank` job's state: the program's Clifford part as a graph form with @@ -897,7 +968,13 @@ pub(crate) fn try_method(method: &str, r: &Request, dyadic: &Result 0 + { + why = format!("{why}; {} angle(s) below its table, the largest {:e} rad, run as no phase and the result says so", report.below_table, report.largest_below_table); + } + Ok(plan(bytes, gates << n, why)) } "statevector" => { let bytes = statevector_bytes(n); @@ -973,11 +1050,18 @@ pub(crate) fn try_method(method: &str, r: &Request, dyadic: &Result MPS_MAX_WORK { - return Err(format!("this circuit at bond dimension {chi} is more work than one job may take; ask for a smaller max_bond or fewer shots")); + // At the bond the job asks for, this bounds the work from above. A + // job that names the method runs under a meter of the bond its + // circuit reaches (run_mps); it is refused here only if even the + // smallest bond that entangles is too much. `auto` keeps to what + // the bound admits, and picks no job it may have to stop. + let named = r.method == "mps"; + if work > MPS_MAX_WORK && (!named || mps_work(r, 2) > MPS_MAX_WORK) { + return Err(format!("this circuit at bond dimension {chi} is more work than one job may take ({work} at that bond, at most {MPS_MAX_WORK}); ask for a smaller max_bond or fewer shots{}", if named { "" } else { ", or name method mps, which meters the bond the circuit reaches" })); } let memory = (n as u64) * chi * chi * 64 + (2 * chi) * (2 * chi) * 96 + 256 * MIB; - Ok(plan(memory, work, format!("matrix product state of {n} qubits at bond dimension {chi}"))) + let metered = if work > MPS_MAX_WORK { format!("; its work at that bond would pass one job's ({work}, at most {MPS_MAX_WORK}), so it runs metered on the bond it reaches and stops [{}] if that passes it", refusal::METHOD_REFUSES) } else { String::new() }; + Ok(plan(memory, work, format!("matrix product state of {n} qubits at bond dimension {chi}{metered}"))) } "cutrank" => { use crate::quantum_cutrank::Precision; @@ -1153,8 +1237,13 @@ pub(crate) fn plan_in(reg: &Registry, v: &Value, job_bytes: u64) -> Result Result) -> Result { use super::fabric::Ask; - let r = job.request()?; + let r = job.as_read()?; let ask = super::fabric::asked(job.json())?; if r.method != "auto" || matches!(ask, Ask::Auto | Ask::Cpu) { return choose(job); @@ -1189,7 +1278,7 @@ fn with_intent(reg: &Registry, v: &Value, r: &Request, mut p: Plan, job_bytes: u /// every channel the job names held to what the method takes (each refusal /// of a channel `J061`). pub(crate) fn plan_one(m: &dyn Method, job: &Job<'_>) -> Result { - let r = job.request()?; + let r = job.as_read()?; if r.noise.is_some() && !m.models_noise() { return Err(tag(refusal::CHANNEL_REFUSED, format!("{} does not model noise", m.name()))); } @@ -1206,7 +1295,7 @@ pub(crate) fn plan_one(m: &dyn Method, job: &Job<'_>) -> Result { /// The method for the job: the one it names, or the first `auto` finds, in /// the registry's order for what the job asks ([`Question`]). fn choose(job: &Job<'_>) -> Result { - let r = job.request()?; + let r = job.as_read()?; let reg = job.registry(); if r.method != "auto" { let Some(m) = reg.method(&r.method) else { @@ -1229,6 +1318,9 @@ fn choose(job: &Job<'_>) -> Result { Err(tag(refusal::NO_METHOD, format!("no method takes this job — {}", refusals.join("; ")))) } +#[cfg(all(test, feature = "quantum_receipt"))] +mod whole_tests; + #[cfg(test)] mod tests { use super::*; diff --git a/wai/wai-quantum/src/engine/catalog/whole_tests.rs b/wai/wai-quantum/src/engine/catalog/whole_tests.rs new file mode 100644 index 000000000..ef01435b8 --- /dev/null +++ b/wai/wai-quantum/src/engine/catalog/whole_tests.rs @@ -0,0 +1,376 @@ +//! A gate under many controls through a job: which methods hold it whole, what +//! stays as it was, and what a result says. + +use super::*; +use crate::engine::job::plan_and_run; +use crate::engine::{compile, estimate, formats}; + +const CAP: u64 = 16 << 30; + +fn hx(b: &[u8]) -> String { + blake3::hash(b).as_bytes()[..8].iter().map(|x| format!("{x:02x}")).collect() +} + +/// Each program with what the engine gave of it before a gate stood whole, on +/// arm64 and x86_64 alike (each row taken from that commit on both): its +/// standard gates and their digest, the bit-exact state hash, the compile's +/// output, the QIR and jeff exports and the resource estimate's counts. +#[rustfmt::skip] +const BEFORE: &[(&str, &str, usize, &str, &str, &str, &str, &str, &str)] = &[ + ("c3z", "qubit[5] q;\nh q;\nctrl(3) @ z q[0], q[1], q[2], q[3];\n", 34, "29718f9ab500304a", "181acaa4aad01230", "f23087907c80c69d", "c8c5157978bce0e3", "5483575a012810bb", "747ea02fde8aeaca"), + ("c3x", "qubit[5] q;\nh q;\nctrl(3) @ x q[0], q[1], q[2], q[3];\n", 36, "7a786cc271f2501b", "8a504be7fc0299e8", "19be6f5bfc085d84", "0c304a3bc21ab20d", "c35804da5d616eb1", "d7c18a0142c206a0"), + ("c3y", "qubit[5] q;\nh q;\nt q[1];\nctrl(3) @ y q[0], q[1], q[2], q[3];\n", 39, "83dfa98a747a790d", "fbc90dbfada344a4", "263ae5be1f8ed271", "3248786655ef4b22", "0c039f9aa8aaf730", "9fd8aa3d94545ea2"), + ("c3h", "qubit[5] q;\nh q;\nt q[1];\nctrl(3) @ h q[0], q[1], q[2], q[3];\n", 37, "d6da69225d63f4a2", "f9fd9fa5547c7200", "de15875954d42157", "b2d92db2f0938d25", "412b56a798ee15ad", "744da0841af0f928"), + ("c2p", "qubit[4] q;\nh q;\nctrl(2) @ p(pi / 8) q[0], q[1], q[2];\n", 17, "b076ca7327b88b22", "13346662e1739d87", "18407afca6242403", "82518b8435656332", "1ad0afc42fc8a458", "0da1476c3de0dffa"), + ("c2rz", "qubit[4] q;\nh q;\nctrl(2) @ rz(pi / 4) q[0], q[1], q[2];\n", 18, "ade98300c7a91bea", "ca049c0c8dd637ed", "a4f6414c00826c92", "0f6065ef438dadba", "74d61b41579349ab", "d2f07d8d123fa85a"), + ("c2rx", "qubit[4] q;\nh q;\nctrl(2) @ rx(pi / 2) q[0], q[1], q[2];\n", 20, "6ae6ae2309534fbb", "3eab347bbdb8b27c", "5a664df2c0c8b771", "4dc76727674b23fa", "c607efaafd1b104c", "d992c105de67f83c"), + ("c2ry", "qubit[4] q;\nh q;\nctrl(2) @ ry(pi / 2) q[0], q[1], q[2];\n", 22, "27369425f1ce33f2", "94f7f25bde25caef", "947dd07eb6275558", "27aeedd8797a64c3", "92bc2218593c67d2", "b75ea5448c736963"), + ("c2u", "qubit[4] q;\nh q;\nctrl(2) @ u(pi / 2, pi / 4, pi / 8) q[0], q[1], q[2];\n", 51, "0032cafc1cf71c51", "7c43ae072ebd46be", "e8f8bdd2fd064d70", "529d746a02266c75", "c4d07e54180ae52d", "94c720252c873ede"), + ("c2sx", "qubit[4] q;\nh q;\nctrl(2) @ sx q[0], q[1], q[2];\n", 21, "3011642a37dab1c8", "378d6c6c3635da01", "e65547fe84b0d8cf", "8a53373f168fcddd", "77db3f01554b29e4", "c3e8535f252e0170"), + ("neg", "qubit[4] q;\nh q;\nnegctrl(2) @ ctrl @ s q[0], q[1], q[2], q[3];\n", 37, "64475caf52138761", "77667386517f1f09", "1c755ad6249197a1", "e46c16636e80eebd", "901334ecfa216508", "e42f39af5237beca"), + ("ccu", "qubit[4] q;\nh q;\nctrl @ cu(pi / 2, pi / 4, pi / 8, pi / 16) q[0], q[1], q[2];\n", 52, "a9f7955f0864db33", "fa538ea89cfe5c9a", "0ba490c2dda2780c", "c40db1252b470677", "5d1f6d595cdfbe0d", "b27c6c0bb9082d58"), + ("c2swap", "qubit[4] q;\nh q;\nctrl(2) @ swap q[0], q[1], q[2], q[3];\n", 37, "90d28cfbf2beef6c", "7982dfa1bd563330", "76fee435a36b077d", "f1554f2143fd5485", "0ce2bc73b4fa722f", "fe16b8d3921fa66b"), + ("c2rzz", "qubit[4] q;\nh q;\nctrl(2) @ rzz(pi / 2) q[0], q[1], q[2], q[3];\n", 20, "169448464ac572eb", "b537afe5c235346c", "c0df4fdb5cb39f1a", "e7c473ac7aced773", "9486d505cc21b5a0", "d992c105de67f83c"), + ("c2gphase", "qubit[3] q;\nh q;\nctrl(2) @ gphase(pi / 4) q[0], q[1];\n", 4, "613a1f7f53c2c634", "0e065cabc1032cc6", "eb75b70b655bedca", "87c33623c70c4586", "e5c2502f696c5154", "709224f43ac6c30e"), + ("invc3t", "qubit[4] q;\nh q;\ninv @ ctrl(3) @ t q[0], q[1], q[2], q[3];\n", 33, "6d8735fa38b73015", "8ac349a04bd30ca8", "389140fbf3231c9f", "cfc33faa8c2f6e40", "ab64f2e385bb59da", "b0d2a886a160dcc2"), + ("grover6", "qubit[6] q;\nh q;\nctrl(5) @ z q[0], q[1], q[2], q[3], q[4], q[5];\nh q;\nx q;\nctrl(5) @ z q[0], q[1], q[2], q[3], q[4], q[5];\nx q;\nh q;\n", 280, "71390b8e8200400a", "9e5c239c034ba374", "9b7fb2311b984049", "384c13c05764b82d", "dcba716313b6ece1", "d164abfb32a62b0a"), + ("ccx", "qubit[4] q;\nh q;\nt q[0];\nctrl(2) @ x q[0], q[1], q[2];\n", 6, "542e1352d6cd7c2e", "bc16012d7e5c98a8", "99b450e817595855", "6645931b4b759afb", "b6b70437c04ac558", "d370a78cc7e92248"), + ("ccz", "qubit[4] q;\nh q;\nt q[0];\nctrl(2) @ z q[0], q[1], q[2];\n", 6, "32cc8ef799a35dc2", "b357eae18a404904", "f3b4c56a4b8d0c9d", "7a9c51e72904ac4a", "3b78a28be6428788", "d370a78cc7e92248"), + ("c2y", "qubit[4] q;\nh q;\nt q[0];\nctrl(2) @ y q[0], q[1], q[2];\n", 8, "2c326695e1bde126", "59d46a5019e4d87c", "dacf9a1398e3e043", "a9ff98ce426f905d", "281d8093937d891e", "551165238caa42d2"), + ("c2h", "qubit[4] q;\nh q;\nt q[0];\nctrl(2) @ h q[0], q[1], q[2];\n", 8, "ae920e55c106966c", "e61608a2117a83aa", "58443259e04d5f16", "7e9d2678d90ccadc", "ac5f279656d62dc7", "d76ade781f528b10"), + ("cp", "qubit[3] q;\nh q;\nctrl @ p(pi / 8) q[0], q[1];\n", 4, "48ca258d13245d56", "cddd783aad2071d2", "e062f8754960a2d9", "ed65712144049bea", "6db848b83c6a454c", "0e28272539b04b2a"), + ("cswap", "qubit[3] q;\nh q;\nctrl @ swap q[0], q[1], q[2];\n", 4, "2a5e8a545c769f54", "70fe25ec22008f86", "27282765b5abf030", "e85d174f9e4e97da", "87a240aab7d4fc0e", "694084d5478b13ed"), + ("plain", "qubit[3] q;\nh q;\ncx q[0], q[1];\nrz(pi / 4) q[2];\n", 5, "8103a71b8f08fb58", "92dbd1cf0f4ce0e1", "275c3c9040292ce0", "2bd714b375f08ed0", "368eeef29b7aa1f2", "68eebfa353685fb7"), +]; + +/// What needs standard gates gives what it gave, byte for byte: the reader's +/// `read`, a compile, the QIR and jeff exports, the resource estimate, and the +/// bit-exact method asked for standard gates, which reproduces a hash made +/// before gates stood whole. +#[test] +fn what_takes_standard_gates_gives_what_it_gave() { + for (name, src, ops, digest, state, compiled, qir, jeff, counts) in BEFORE { + let p = qasm::read(src).unwrap().program; + assert_eq!(p.ops.len(), *ops, "{name}"); + let mut t = String::new(); + for o in &p.ops { + t += &format!("{:?} {:?} {:?}\n", o.kind, o.qubits, o.params.iter().map(|x| x.to_bits()).collect::>()); + } + assert_eq!(hx(t.as_bytes()), *digest, "{name}: the standard gates"); + let job = json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": ["0".repeat(p.n_qubits as usize)], "options": { "controls": "standard" } }); + let (_, out) = plan_and_run(&job, CAP).unwrap(); + assert_eq!(&out["state_hash"].as_str().unwrap()[..16], *state, "{name}: the bit-exact hash"); + assert_eq!(out["gates"], json!(*ops), "{name}: {out}"); + assert!(out.get("standard_gates").is_none(), "{name}: {out}"); + assert_eq!(hx(compile::compile(&p, &compile::Options::default()).unwrap().qasm.as_bytes()), *compiled, "{name}: the compile"); + assert_eq!(hx(&formats::write(formats::Format::Qir, &p, None).unwrap().bytes), *qir, "{name}: QIR"); + assert_eq!(hx(&formats::write(formats::Format::Jeff, &p, None).unwrap().bytes), *jeff, "{name}: jeff"); + assert_eq!(hx(estimate::call(&json!({ "qasm": src })).unwrap()["counts"].to_string().as_bytes()), *counts, "{name}: the estimate"); + // Given a program holding gates whole, each writes its standard gates. + let w = qasm::read_whole(src).unwrap().program; + assert_eq!(hx(compile::compile(&w, &compile::Options::default()).unwrap().qasm.as_bytes()), *compiled, "{name}: the compile, from the whole form"); + assert_eq!(hx(&formats::write(formats::Format::Qir, &w, None).unwrap().bytes), *qir, "{name}: QIR, from the whole form"); + assert_eq!(estimate::count::lower_program(&w).unwrap(), estimate::count::lower_program(&p).unwrap(), "{name}: the estimate's circuit, from the whole form"); + } +} + +fn wide(n: usize) -> String { + (0..n).map(|i| format!("q[{i}]")).collect::>().join(", ") +} + +/// `iterations` Grover iterations on `n` qubits, every qubit marked by `x`. +fn grover(n: usize, iterations: usize) -> String { + let qs = wide(n); + let mut s = format!("qubit[{n}] q;\nh q;\n"); + for _ in 0..iterations { + s += &format!("ctrl({}) @ z {qs};\nh q;\nx q;\nctrl({}) @ z {qs};\nx q;\nh q;\n", n - 1, n - 1); + } + s +} + +/// Two Grover iterations on 14 qubits run as 130 gates, not 131,186, on both +/// state-vector methods, and say how many they are in standard gates. The +/// marked state's amplitude is the closed form's, within each method's bound. +#[test] +fn a_job_on_the_state_vectors_holds_the_gate_whole() { + let (n, k) = (14usize, 2usize); + let src = grover(n, k); + let marked = "1".repeat(n); + let theta = (2f64.powf(-(n as f64) / 2.0)).asin(); + let want = ((2 * k + 1) as f64 * theta).sin(); + for (method, gates, bound) in [("exact", 130, 1e-5), ("statevector", 130, 1e-12)] { + let job = json!({ "qasm": src, "method": method, "shots": 0, "amplitudes": [marked] }); + let (plan, out) = plan_and_run(&job, CAP).unwrap(); + assert_eq!((plan.method.as_str(), out["gates"].as_u64()), (method, Some(gates)), "{out}"); + assert_eq!(out["standard_gates"], 131_186, "{out}"); + let a = &out["amplitudes"][0]; + assert!((a["re"].as_f64().unwrap().hypot(a["im"].as_f64().unwrap()) - want.abs()).abs() < bound, "{method}: {a}, want {want}"); + } + // The bit-exact method's bits are the same on every host: this test holds them there. + let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": [marked] }), CAP).unwrap(); + assert_eq!(&out["state_hash"].as_str().unwrap()[..16], "454d8a59c85c788b", "{out}"); +} + +/// Asked for standard gates, or placed on the fabric, the job takes them all, +/// and its state is the old one's to the bit on the bit-exact method. +#[test] +fn a_job_can_ask_for_standard_gates() { + let src = grover(8, 1); + let run = |extra: Value| { + let mut job = json!({ "qasm": src, "shots": 0, "amplitudes": ["11111111"] }); + job.as_object_mut().unwrap().extend(extra.as_object().unwrap().clone()); + plan_and_run(&job, CAP).unwrap().1 + }; + let whole = run(json!({ "method": "statevector" })); + let standard = run(json!({ "method": "statevector", "options": { "controls": "standard" } })); + assert!(whole["gates"].as_u64().unwrap() < standard["gates"].as_u64().unwrap()); + assert_eq!(whole["standard_gates"], standard["gates"]); + let d = (whole["amplitudes"][0]["re"].as_f64().unwrap() - standard["amplitudes"][0]["re"].as_f64().unwrap()).abs(); + assert!(d < 1e-12, "{d}"); + let e = run(json!({ "method": "exact", "options": { "controls": "standard" } })); + let want = qasm::read(&src).unwrap().program.dyadic().unwrap().simulate().unwrap().statevector_hash(); + assert_eq!(e["state_hash"].as_str().unwrap(), want.iter().map(|b| format!("{b:02x}")).collect::()); + // A job that names a place on the fabric runs what every member runs. + #[cfg(feature = "quantum_fabric")] + { + let cpu = run(json!({ "method": "statevector", "fabric": "cpu" })); + assert_eq!(cpu["gates"], standard["gates"], "{cpu}"); + assert!(cpu.get("standard_gates").is_none(), "{cpu}"); + } +} + +/// A method that needs standard gates takes them, each answer the state +/// vector's within its own accuracy, and says how many it ran. +#[test] +fn every_other_method_takes_standard_gates() { + let src = "qubit[6] q;\nh q;\nctrl(3) @ p(0.7) q[0], q[1], q[2], q[3];\nctrl(4) @ x q[0], q[1], q[2], q[3], q[4];\n"; + let standard = qasm::read(src).unwrap().program.ops.len(); + let bits = "011111"; + let (_, sv) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "amplitudes": [bits] }), CAP).unwrap(); + assert_eq!((sv["gates"].as_u64(), sv["standard_gates"].as_u64()), (Some(8), Some(standard as u64))); + let a = |v: &Value, k: &str| v["amplitudes"][0][k].as_f64().unwrap(); + for method in ["mps", "tensor_network"] { + let (p, out) = plan_and_run(&json!({ "qasm": src, "method": method, "amplitudes": [bits] }), CAP).unwrap(); + assert_eq!(p.method, method); + assert_eq!(out["gates"].as_u64(), Some(standard as u64), "{method}: {out}"); + assert!(out.get("standard_gates").is_none(), "{method}: {out}"); + assert!((a(&out, "re") - a(&sv, "re")).abs() < 1e-9 && (a(&out, "im") - a(&sv, "im")).abs() < 1e-9, "{method}: {out}, {sv}"); + } + let (p, out) = plan_and_run(&json!({ "qasm": src, "noise": { "depolarizing_1q": 0.0001 }, "shots": 16 }), CAP).unwrap(); + assert_eq!((p.method.as_str(), out["gates"].as_u64()), ("density_matrix", Some(standard as u64)), "{out}"); + let (p, out) = plan_and_run(&json!({ "qasm": src, "method": "pauli", "observables": ["Z0"] }), CAP).unwrap(); + assert_eq!((p.method.as_str(), out["gates"].as_u64()), ("pauli", Some(standard as u64)), "{out}"); + // A compile writes standard gates: the job runs what it wrote. + let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 4, "compile": { "basis": "standard", "level": 0 } }), CAP).unwrap(); + assert!(out.get("standard_gates").is_none() && out["compiled"].is_object(), "{out}"); +} + +/// Past what standard gates can hold: 20 controls run whole on both state +/// vectors, and `auto` takes them there. Everything that needs standard gates +/// refuses, naming why, and a Clifford check takes one gate to say no. +#[test] +fn past_the_standard_form_only_the_state_vectors_take_it() { + let (n, marked) = (21, "1".repeat(21)); + let src = format!("qubit[{n}] q;\nx q;\nctrl(20) @ z {};\nctrl(20) @ x {};\n", wide(n), wide(n)); + for method in ["exact", "statevector", "auto"] { + let (p, out) = plan_and_run(&json!({ "qasm": src, "method": method, "shots": 0, "amplitudes": [marked] }), CAP).unwrap(); + assert!(runs_whole(&p.method), "{method}: {}", p.why); + assert_eq!(out["gates"], 23, "{out}"); + assert_eq!(out["standard_gates"].as_u64(), Some(qasm::read_whole(&src).unwrap().program.standard_gates() as u64), "{out}"); + } + for method in ["mps", "tensor_network", "stabilizer", "pauli"] { + let e = plan(&json!({ "qasm": src, "method": method, "amplitudes": [marked], "observables": if method == "pauli" { json!(["Z0"]) } else { json!([]) } }), CAP).unwrap_err(); + assert!(e.contains("J011") || e.contains("Q208") || e.contains("Clifford") || e.contains("expectation"), "{method}: {e}"); + } + let e = plan(&json!({ "qasm": src, "method": "mps", "amplitudes": [marked] }), CAP).unwrap_err(); + assert!(e.contains("Q208") && e.contains("at most 16 controls"), "{e}"); + let e = plan(&json!({ "qasm": src, "method": "statevector", "amplitudes": [marked], "options": { "controls": "standard" } }), CAP).unwrap_err(); + assert!(e.contains("Q208"), "{e}"); + let e = plan(&json!({ "qasm": src, "amplitudes": [marked], "noise": { "dephasing": 0.01 } }), CAP).unwrap_err(); + assert!(e.contains("Q208"), "{e}"); + // A verdict reads standard gates, so a job that asks for one is held to them. + let e = plan(&json!({ "qasm": src, "amplitudes": [marked], "verdict": true }), CAP).unwrap_err(); + assert!(e.contains("Q208"), "{e}"); + // lint says what a job takes. + let l = crate::engine::job::lint(&src); + assert_eq!((l["ok"].as_bool(), l["gates"].as_u64()), (Some(true), Some(23)), "{l}"); + assert!(l["standard_gates"].as_u64().unwrap() > 1 << 22, "{l}"); +} + +/// Between measurements too: a gate in a branch runs whole, each expectation +/// the standard form's within rounding, the branches' counts equal. +#[test] +fn a_gate_in_a_program_that_measures_runs_whole() { + let src = "qubit[5] q;\nbit[1] c;\nh q;\nc[0] = measure q[0];\nif (c[0] == 1) { ctrl(3) @ x q[1], q[2], q[3], q[4]; }\nctrl(3) @ z q[1], q[2], q[3], q[4];\nh q[4];\n"; + let job = |extra: Value| { + let mut j = json!({ "qasm": src, "method": "statevector", "observables": ["Z4", "X1 Z2"], "shots": 20000, "seed": 3 }); + j.as_object_mut().unwrap().extend(extra.as_object().unwrap().clone()); + j + }; + let (_, whole) = plan_and_run(&job(json!({})), CAP).unwrap(); + let (_, standard) = plan_and_run(&job(json!({ "options": { "controls": "standard" } })), CAP).unwrap(); + assert_eq!(whole["gates"].as_u64(), Some(8), "{whole}"); + assert_eq!(whole["standard_gates"], standard["gates"], "{whole}"); + assert!(whole["dynamic"].is_object(), "{whole}"); + for i in 0..2 { + let (a, b) = (whole["expectations"][i]["value"].as_f64().unwrap(), standard["expectations"][i]["value"].as_f64().unwrap()); + assert!((a - b).abs() < 1e-12, "{a} against {b}"); + } + assert_eq!(whole["counts"].as_object().unwrap().len(), standard["counts"].as_object().unwrap().len()); +} + +/// The intent's check reads standard gates, whatever the run took. +#[test] +fn a_verdict_holds_a_whole_run_to_its_intent() { + let n = 5; + let src = format!("qubit[{n}] q;\nx q;\nctrl({}) @ x {};\n", n - 1, wide(n)); + let want = json!({ "distribution": { "01111": 1.0 } }); + let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 8, "intent": want }), CAP).unwrap(); + assert_eq!(out["verdict"]["holds"], true, "{out}"); + assert!(out["standard_gates"].as_u64().unwrap() > out["gates"].as_u64().unwrap()); +} + +/// A registered method, which takes the program as the reader's standard +/// gates, never meets a gate held whole, and `auto` passes over it for the +/// methods that do not need them. +#[test] +fn a_registered_method_sees_standard_gates() { + use crate::engine::registry::{Component, Job, Method, Question, Registry}; + struct Looks; + impl Method for Looks { + fn name(&self) -> &str { + "looks" + } + fn version(&self) -> &str { + "1.0.0" + } + fn classes(&self) -> Vec { + vec!["exact".into()] + } + fn descriptor(&self) -> Value { + json!({}) + } + fn auto_rank(&self, _: Question) -> Option { + None + } + fn plan(&self, job: &Job<'_>) -> Result { + let r = job.request()?; + assert!(!r.program.has_whole()); + Ok(Plan { method: "looks".into(), why: format!("{} standard gates", r.program.ops.len()), memory_bytes: 1, work: 1, qubits: r.program.n_qubits, target: None }) + } + fn run(&self, job: &Job<'_>, _: &Plan, out: &mut Value) -> Result<(), String> { + let r = job.request()?; + assert!(!r.program.has_whole()); + out["accuracy"] = json!({ "class": "exact" }); + out["amplitudes"] = json!([]); + Ok(()) + } + } + let mut reg = Registry::with_builtins(); + reg.register(Component::method(Looks)).unwrap(); + let src = grover(6, 1); + let job = json!({ "qasm": src, "method": "looks", "amplitudes": ["111111"] }); + let p = reg.plan(&job, CAP).unwrap(); + assert!(p.why.starts_with(&format!("{} standard gates", qasm::read(&src).unwrap().program.ops.len())), "{}", p.why); + let out = reg.run(&job, &p).unwrap(); + assert!(out.get("standard_gates").is_none(), "{out}"); + assert_eq!(out["gates"].as_u64().unwrap() as usize, qasm::read(&src).unwrap().program.ops.len()); +} + +/// The phase by which the bit-exact method's amplitudes differ from +/// OpenQASM's is stated, exactly, and held to the state vector's amplitudes: +/// multiplied in, they agree within the method's resolution; left out, they +/// differ by the phase. A program with none has no such member. +#[test] +fn a_bit_exact_result_states_its_global_phase() { + for (body, phase) in [ + ("rz(2 * pi) q[0];\n", Some(std::f64::consts::PI)), + ("rz(pi / 4) q[0];\n", Some(-std::f64::consts::FRAC_PI_8)), + ("h q[0];\nrx(pi / 2) q[1];\nry(pi / 4) q[1];\nu(pi / 2, pi / 4, pi / 8) q[0];\nrzz(pi / 2) q[0], q[1];\nrxx(pi / 4) q[0], q[1];\nryy(pi / 8) q[0], q[1];\n", None), + ("h q[0];\nctrl @ rz(pi / 4) q[0], q[1];\nu(0, 0, 0) q[1];\ncp(pi / 2) q[0], q[1];\n", Some(0.0)), + ] { + let src = format!("qubit[2] q;\n{body}"); + let bits = ["00", "01", "10", "11"]; + let (_, exact) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": bits }), CAP).unwrap(); + let (_, sv) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 0, "amplitudes": bits }), CAP).unwrap(); + let stated = exact["accuracy"]["global_phase"]["radians"].as_f64(); + match phase { + Some(p) if p == 0.0 => assert!(exact["accuracy"].get("global_phase").is_none(), "{exact}"), + Some(p) => assert!((stated.unwrap() - p).abs() < 1e-14, "{exact}"), + None => assert!(stated.is_some(), "{exact}"), + } + let phi = stated.unwrap_or(0.0); + let (c, s) = (phi.cos(), phi.sin()); + for i in 0..4 { + let (ar, ai) = (exact["amplitudes"][i]["re"].as_f64().unwrap(), exact["amplitudes"][i]["im"].as_f64().unwrap()); + let (br, bi) = (sv["amplitudes"][i]["re"].as_f64().unwrap(), sv["amplitudes"][i]["im"].as_f64().unwrap()); + assert!((ar * c - ai * s - br).abs() < 1e-6 && (ar * s + ai * c - bi).abs() < 1e-6, "{body}: amplitude {i}: {exact} against {sv}"); + } + } + // Whole, the phase of a rotation under controls stays in the amplitudes. + let src = "qubit[3] q;\nx q[0];\nx q[1];\nh q[2];\nctrl(2) @ rz(pi / 2) q[0], q[1], q[2];\n"; + let bits = ["011", "111"]; + let (_, exact) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": bits }), CAP).unwrap(); + let (_, sv) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 0, "amplitudes": bits }), CAP).unwrap(); + assert!(exact["accuracy"].get("global_phase").is_none(), "{exact}"); + for i in 0..2 { + for k in ["re", "im"] { + assert!((exact["amplitudes"][i][k].as_f64().unwrap() - sv["amplitudes"][i][k].as_f64().unwrap()).abs() < 1e-6, "{exact} against {sv}"); + } + } +} + +/// An angle below the bit-exact table no longer runs as no phase in silence. +#[test] +fn an_angle_below_the_table_is_stated() { + let src = "qubit[1] q;\nh q[0];\np(2 * pi / 2**50) q[0];\n"; + let job = json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": ["1"] }); + let p = plan(&job, CAP).unwrap(); + assert!(p.why.contains("below its table") && p.why.contains("no phase"), "{}", p.why); + let (_, out) = plan_and_run(&job, CAP).unwrap(); + assert_eq!(out["accuracy"]["below_table"]["angles"], 1, "{out}"); + assert!(out["accuracy"]["below_table"]["note"].as_str().unwrap().contains("no phase")); + // A dyadic angle is not. + let (_, out) = plan_and_run(&json!({ "qasm": "qubit[1] q;\nh q[0];\np(2 * pi / 2**32) q[0];\n", "method": "exact", "shots": 0, "amplitudes": ["1"] }), CAP).unwrap(); + assert!(out["accuracy"].get("below_table").is_none(), "{out}"); + // An angle the table's reader cannot place is still refused. + let e = plan(&json!({ "qasm": "qubit[1] q;\np(2 * pi / 2**40) q[0];\n", "method": "exact", "shots": 16 }), CAP).unwrap_err(); + assert!(e.contains("Q500"), "{e}"); +} + +/// The 30-qubit QFT at `max_bond` 256, which the estimate of the bond asked for +/// refused: named, it runs, on the bond it reaches, and the plan says how. Under +/// `auto` nothing moves, and an estimate too large at the smallest bond that +/// entangles is refused still. +#[test] +fn a_named_matrix_product_job_is_held_to_the_bond_it_reaches() { + let n = 30usize; + let mut src = format!("qubit[{n}] q;\n"); + for q in 0..n { + src += &format!("h q[{q}];\n"); + for t in q + 1..n { + src += &format!("cp(pi / 2**{}) q[{t}], q[{q}];\n", t - q); + } + } + let zero = "0".repeat(n); + let job = json!({ "qasm": src, "method": "mps", "amplitudes": [zero], "options": { "max_bond": 256 } }); + let p = plan(&job, CAP).unwrap(); + assert!(p.work > MPS_MAX_WORK && p.why.contains("metered"), "{p:?}"); + let (_, out) = plan_and_run(&job, CAP).unwrap(); + assert_eq!(out["accuracy"]["max_bond"], 256, "{out}"); + let used = out["accuracy"]["max_bond_used"].as_u64().unwrap(); + assert!(used < 256, "reached {used}"); + let want = 2f64.powf(-(n as f64) / 2.0); + assert!((out["amplitudes"][0]["re"].as_f64().unwrap() - want).abs() < 1e-9, "{out}"); + // Below the budget the plan is what it was: nothing metered to say. + let small = plan(&json!({ "qasm": src, "method": "mps", "amplitudes": [zero], "options": { "max_bond": 32 } }), CAP).unwrap(); + assert!(small.work < MPS_MAX_WORK && !small.why.contains("metered"), "{small:?}"); + // Unnamed, a job is held to the bound, and told what naming the method does. + let r = read(&json!({ "qasm": src, "method": "auto", "amplitudes": [zero], "options": { "max_bond": 256 } })).unwrap(); + let e = try_method("mps", &r, &Err("".into()), &Err("".into()), CAP).unwrap_err(); + assert!(e.contains("name method mps"), "{e}"); + // More than a job may take at the smallest bond there is: refused now. + let far = format!("qubit[4096] q;\nfor uint i in [0:799999] {{ cx q[0], q[4095]; }}\n"); + let e = plan(&json!({ "qasm": far, "method": "mps", "shots": 1 }), CAP).unwrap_err(); + assert!(e.contains("[J011]") && e.contains("more work than one job may take"), "{e}"); +} diff --git a/wai/wai-quantum/src/engine/compile.rs b/wai/wai-quantum/src/engine/compile.rs index d63c9e1ce..43cf5079b 100644 --- a/wai/wai-quantum/src/engine/compile.rs +++ b/wai/wai-quantum/src/engine/compile.rs @@ -936,6 +936,8 @@ pub fn compile(p: &Program, o: &Options) -> Result { /// the level's own and before twirling and decoupling. A registered pass's /// record names it (`component`), and its check is the engine's. pub(crate) fn compile_in(reg: &Registry, p: &Program, o: &Options, extra: &[&str]) -> Result { + // A compile writes standard gates, whatever form the program came in. + let p = &*p.standard_form().map_err(String::from)?; if p.dynamic.is_some() { return Err("the program measures in the middle, resets after a gate or acts on what it measured; compiling takes programs whose measurements all come at the end".into()); } diff --git a/wai/wai-quantum/src/engine/dynamic.rs b/wai/wai-quantum/src/engine/dynamic.rs index 1b208714d..e03a4374a 100644 --- a/wai/wai-quantum/src/engine/dynamic.rs +++ b/wai/wai-quantum/src/engine/dynamic.rs @@ -72,6 +72,38 @@ impl Engine for Dense<'_> { } } +/// [`Dense`] with each gate under many controls held as one. +#[derive(Clone)] +pub struct DenseOps<'a> { + pub sv: StateVector, + pub ops: &'a [crate::quantum_sv::SvOp], +} + +impl Engine for DenseOps<'_> { + fn gate(&mut self, i: usize) -> Result<(), String> { + match &self.ops[i] { + crate::quantum_sv::SvOp::Gate(g) => self.sv.apply(g), + crate::quantum_sv::SvOp::Controlled(c) => self.sv.apply_controlled(c), + } + .map_err(|e| format!("{e:?}")) + } + fn prob_one(&mut self, q: u32) -> Result { + Ok(self.sv.probability_one(q).clamp(0.0, 1.0)) + } + fn collapse(&mut self, q: u32, outcome: bool) -> Result<(), String> { + match self.sv.collapse(q, outcome).map_err(|e| format!("{e:?}"))? { + p if p > 0.0 => Ok(()), + _ => Err(format!("qubit {q} cannot read {}", u8::from(outcome))), + } + } + fn flip(&mut self, q: u32) -> Result<(), String> { + self.sv.apply(&Matrix::x(q)).map_err(|e| format!("{e:?}")) + } + fn expectation(&self, string: &[(u32, char)]) -> Result { + Ok(self.sv.expectation(&[(1.0, string.to_vec())])) + } +} + /// The stabilizer tableau, each op as its Clifford gates. #[derive(Clone)] pub struct Stabilizer<'a> { diff --git a/wai/wai-quantum/src/engine/estimate/count.rs b/wai/wai-quantum/src/engine/estimate/count.rs index a37893b29..a23bdf927 100644 --- a/wai/wai-quantum/src/engine/estimate/count.rs +++ b/wai/wai-quantum/src/engine/estimate/count.rs @@ -180,6 +180,8 @@ fn lower_op(o: &Op, out: &mut Vec) { /// `p` in the estimate's gate set (see the module); refused for a program /// whose steps jump back, which no count bounds. pub fn lower_program(p: &Program) -> Result { + // Its ladders read the standard form's records. + let p = &*p.standard_form().map_err(String::from)?; let n = p.n_qubits; // Each op's ladder, by the index of the controlled gate it belongs to. let mut owner: Vec> = vec![None; p.ops.len()]; diff --git a/wai/wai-quantum/src/engine/fabric.rs b/wai/wai-quantum/src/engine/fabric.rs index d1de7a484..272314ef8 100644 --- a/wai/wai-quantum/src/engine/fabric.rs +++ b/wai/wai-quantum/src/engine/fabric.rs @@ -158,7 +158,9 @@ pub(crate) fn admit(v: &Value, r: &Request, plan: &mut Plan) -> Result<(), Strin } }; } - let placed_method = plan.method == "statevector" && r.program.dynamic.is_none(); + // A gate held whole runs on the CPU: a member takes standard gates. A job + // that names a place reads its program in them (catalog::may_run_whole). + let placed_method = plan.method == "statevector" && r.program.dynamic.is_none() && !r.program.has_whole(); if !placed_method { return match ask { Ask::Auto => Ok(()), diff --git a/wai/wai-quantum/src/engine/formats/mod.rs b/wai/wai-quantum/src/engine/formats/mod.rs index c7f54f7cb..70344022f 100644 --- a/wai/wai-quantum/src/engine/formats/mod.rs +++ b/wai/wai-quantum/src/engine/formats/mod.rs @@ -161,6 +161,8 @@ pub(crate) fn read_fe(fe: &dyn FrontEnd, input: &[u8]) -> Result) -> Result { + // Another format holds standard gates, whatever form the program came in. + let p = &*p.standard_form()?; match format { Format::Qasm => { if p.dynamic.is_some() { diff --git a/wai/wai-quantum/src/engine/job.rs b/wai/wai-quantum/src/engine/job.rs index 0b03eedd3..216a17315 100644 --- a/wai/wai-quantum/src/engine/job.rs +++ b/wai/wai-quantum/src/engine/job.rs @@ -74,7 +74,9 @@ pub fn did_of(key_hex: &str) -> Option { /// gates, bits and measurements (and its steps, when it is dynamic), or /// `{"ok": false}` with the problem, its line, and its diagnostic code, /// column and length (`qasm::diag`). The warnings and notes the reader gave -/// a program it read are under `diagnostics`, when there are any. +/// a program it read are under `diagnostics`, when there are any. A gate under +/// many controls is one gate, as a job on the state vectors runs it, and +/// `standard_gates` then says how many it is in standard gates. pub fn lint(src: &str) -> Value { lint_with(src, &crate::qasm::Inputs::new()) } @@ -82,7 +84,7 @@ pub fn lint(src: &str) -> Value { /// [`lint`] for a generator read at `inputs`: a problem keeps the generator's /// line. pub fn lint_with(src: &str, inputs: &crate::qasm::Inputs) -> Value { - match crate::qasm::read_with(src, inputs) { + match crate::qasm::read_whole_with(src, inputs) { Ok(r) => { let p = &r.program; let mut v = json!({ @@ -93,6 +95,9 @@ pub fn lint_with(src: &str, inputs: &crate::qasm::Inputs) -> Value { "measured": p.measured.len(), "dynamic_steps": p.dynamic.as_ref().map(Vec::len), }); + if p.has_whole() { + v["standard_gates"] = json!(p.standard_gates().min((1u128 << 53) - 1) as u64); + } if !r.diagnostics.is_empty() { v["diagnostics"] = Value::Array(r.diagnostics.iter().map(|d| d.to_json()).collect()); } diff --git a/wai/wai-quantum/src/engine/registry/builtin.rs b/wai/wai-quantum/src/engine/registry/builtin.rs index a40954a1a..d1ad8743c 100644 --- a/wai/wai-quantum/src/engine/registry/builtin.rs +++ b/wai/wai-quantum/src/engine/registry/builtin.rs @@ -98,7 +98,11 @@ impl Method for BuiltinMethod { self.ranks[question_index(question)] } fn plan(&self, job: &Job<'_>) -> Result { - catalog::try_method(self.name, job.request()?, job.dyadic(), job.clifford(), job.job_bytes()) + // A method that runs gates whole takes the program as read. A tableau + // needs standard gates only for a circuit that is Clifford, which the + // first gate that is not settles without writing the rest. + let request = if catalog::runs_whole(self.name) || (self.name == "stabilizer" && job.clifford().is_err()) { job.as_read()? } else { job.request()? }; + catalog::try_method(self.name, request, job.dyadic(), job.clifford(), job.job_bytes()) } fn run(&self, job: &Job<'_>, plan: &Plan, out: &mut Value) -> Result<(), String> { crate::engine::run::run_builtin(self.name, job, plan, out) diff --git a/wai/wai-quantum/src/engine/registry/mod.rs b/wai/wai-quantum/src/engine/registry/mod.rs index 6ff1ceb05..9d5763b15 100644 --- a/wai/wai-quantum/src/engine/registry/mod.rs +++ b/wai/wai-quantum/src/engine/registry/mod.rs @@ -542,6 +542,9 @@ pub struct Job<'a> { json: &'a Value, job_bytes: u64, request: Option<&'a Request>, + /// The request in standard gates, written when a method asks for it, where + /// `request` holds gates whole. + standard: Option<&'a OnceCell>>, channels: Vec>, dyadic: OnceCell>, clifford: OnceCell, String>>, @@ -550,7 +553,21 @@ pub struct Job<'a> { impl<'a> Job<'a> { pub(crate) fn new(registry: &'a Registry, json: &'a Value, job_bytes: u64, request: Option<&'a Request>, uses: &[(usize, Vec)]) -> Job<'a> { let channels = uses.iter().map(|(i, v)| ChannelUse { channel: &*registry.channels[*i].component, identity: ®istry.channels[*i].identity, values: v.clone() }).collect(); - Job { registry, json, job_bytes, request, channels, dyadic: OnceCell::new(), clifford: OnceCell::new() } + Job { registry, json, job_bytes, request, standard: None, channels, dyadic: OnceCell::new(), clifford: OnceCell::new() } + } + + /// The job with `request` holding gates whole: [`Job::request`] then gives + /// it in standard gates, written once, in `cell`. + pub(crate) fn with_standard(mut self, cell: &'a OnceCell>) -> Job<'a> { + self.standard = Some(cell); + self + } + + /// The request as it was read: what every method is asked about, whatever + /// form it runs in. For a built-in method that runs a gate under many + /// controls as one ([`super::catalog::runs_whole`]), the request it runs. + pub(crate) fn as_read(&self) -> Result<&'a Request, String> { + self.request.ok_or_else(|| "internal: this method reads its own program, and the job was not read".to_string()) } /// The registry the job runs in. @@ -568,10 +585,14 @@ impl<'a> Job<'a> { self.job_bytes } - /// The job as the engine's reader read it. A method that reads its - /// program itself is given none. + /// The job as the engine's reader read it, its program in standard gates. + /// A method that reads its program itself is given none. pub fn request(&self) -> Result<&'a Request, String> { - self.request.ok_or_else(|| "internal: this method reads its own program, and the job was not read".to_string()) + let r = self.as_read()?; + match self.standard { + Some(cell) => cell.get_or_init(|| r.lowered()).as_ref().map_err(Clone::clone), + None => Ok(r), + } } /// Every noise channel the job names with a value other than zero, in @@ -586,7 +607,8 @@ impl<'a> Job<'a> { self.channels.iter().filter(|c| !c.identity.is_builtin()) } - /// The program as the bit-exact simulator's circuit, or why not. + /// The program as the bit-exact simulator's circuit, or why not: a gate + /// held whole is one gate of it. pub fn dyadic(&self) -> &Result { self.dyadic.get_or_init(|| match self.request { Some(r) => r.program.dyadic(), diff --git a/wai/wai-quantum/src/engine/run.rs b/wai/wai-quantum/src/engine/run.rs index e450638eb..b091fc82e 100644 --- a/wai/wai-quantum/src/engine/run.rs +++ b/wai/wai-quantum/src/engine/run.rs @@ -45,6 +45,36 @@ fn index_of(bits: &str, n: u32, pos: impl Fn(u32) -> u32) -> usize { x } +/// What the bit-exact method promises of a result, and what the lowering to +/// its gates did to the program, so that neither is silent: the global phase +/// by which its amplitudes differ from OpenQASM's, and the angles below its +/// table that ran as no phase. +fn exact_accuracy(report: &crate::qasm::DyadicReport) -> Value { + let mut a = json!({ "class": "bit-exact" }); + if report.global_phase != 0 { + a["global_phase"] = json!({ + "turns_over_2_33": report.global_phase, + "radians": report.global_phase_radians(), + "note": "OpenQASM's state is e^(i·radians) times these amplitudes: this method lowers rz, rx, ry, rxx, ryy, rzz and u to phase gates, each without the standard's e^(−iθ/2). No measurement sees it; a gate under a control keeps its phase.", + }); + } + if report.below_table > 0 { + a["below_table"] = json!({ + "angles": report.below_table, + "largest_radians": report.largest_below_table, + "note": "angles this close to a whole turn are below every entry of the phase table and ran as no phase; this method's bound holds, and method statevector applies them", + }); + } + if report.moved > 0 { + a["moved_angles"] = json!({ + "angles": report.moved, + "largest_radians": report.largest_moved, + "note": "angles within the reader's tolerance of a dyadic one, by more than a double's rounding, ran as that dyadic angle", + }); + } + a +} + /// `⟨ψ|P|ψ⟩` on the bit-exact state, exactly: the fixed-point amplitudes /// multiplied and summed in 128-bit integers, then scaled once. fn expect_fixed(amps: &[crate::quantum::Amp], string: &[(u32, char)]) -> f64 { @@ -244,7 +274,8 @@ fn run_job(reg: &Registry, request: &Value, plan: &Plan, passes: &mut Option, plan: &Plan, out: &mut Va let n = r.program.n_qubits; match method { "exact" => { - let c = r.program.dyadic()?; + let (c, report) = r.program.dyadic_with_report()?; let sv = c.simulate().map_err(|e| e.to_string())?; - out["accuracy"] = json!({ "class": "bit-exact" }); + out["accuracy"] = exact_accuracy(&report); out["state_hash"] = json!(hex(&sv.statevector_hash())); if r.shots > 0 { let per_index = sv.sample_shots(r.seed, r.shots); @@ -380,11 +415,18 @@ pub(crate) fn run_builtin(method: &str, job: &Job<'_>, plan: &Plan, out: &mut Va } } "statevector" => { - let gates = r.program.matrices(); let width = r.options.get("fusion").and_then(Value::as_u64).unwrap_or(3).clamp(1, 5) as usize; // On the CPU, or on the fabric's member the job's placement - // names: the CPU's bits either way. - let (sv, placed) = crate::engine::fabric::statevector(request, n, &gates, width, crate::engine::fabric::widest_of(r))?; + // names: the CPU's bits either way. A gate held whole runs as one, + // on the CPU (catalog::may_run_whole). + let (sv, placed) = if r.program.has_whole() { + let mut sv = crate::quantum_sv::StateVector::zero(n).map_err(|e| format!("{e:?}"))?; + sv.run_ops(&r.program.sv_ops(), width).map_err(|e| format!("{e:?}"))?; + (sv, None) + } else { + let gates = r.program.matrices(); + crate::engine::fabric::statevector(request, n, &gates, width, crate::engine::fabric::widest_of(r))? + }; out["accuracy"] = json!({ "class": "exact", "fusion": width }); if let Some(f) = placed { out["fabric"] = f; @@ -556,8 +598,17 @@ pub(crate) fn run_builtin(method: &str, job: &Job<'_>, plan: &Plan, out: &mut Va use crate::quantum_mpsim::{Chain, MpsConfig}; let chi = catalog::mps_bond(r); let cutoff = r.options.get("cutoff").and_then(Value::as_f64).unwrap_or(1e-12).clamp(0.0, 1e-2); - let mut chain = Chain::run(n, &r.program.local_matrices(), MpsConfig { max_bond: chi, cutoff }).map_err(|e| e.to_string())?; + let gates = r.program.local_matrices(); + // The plan's work bounds this run from above at the bond asked for; + // the run is held to the bond it reaches. + let mut chain = Chain::run_within(n, &gates, MpsConfig { max_bond: chi, cutoff }, catalog::MPS_MAX_WORK.saturating_sub(catalog::mps_shots_work(r, 1))).map_err(|e| match e { + crate::quantum_mpsim::MpsRunError::Chain(e) => e.to_string(), + crate::quantum_mpsim::MpsRunError::OutOfWork { gate, gates, work, max_bond_used } => crate::engine::refusal::tag(crate::engine::refusal::METHOD_REFUSES, format!("stopped after {gate} of {gates} gates: {work} units of work at the bond the circuit has reached ({max_bond_used}), the most one job may take ({}); ask for a smaller max_bond", catalog::MPS_MAX_WORK)), + })?; let rep = chain.report(); + if chain.work().saturating_add(catalog::mps_shots_work(r, rep.max_bond_used as u64)) > catalog::MPS_MAX_WORK { + return Err(crate::engine::refusal::tag(crate::engine::refusal::METHOD_REFUSES, format!("{} shots at the bond the circuit reached ({}) are more work than one job has left; ask for fewer shots", r.shots, rep.max_bond_used))); + } out["accuracy"] = if rep.truncations == 0 { json!({ "class": "exact", "max_bond": chi, "max_bond_used": rep.max_bond_used, "note": "no truncation dropped weight beyond the cutoff's rounding" }) } else { @@ -854,10 +905,19 @@ fn carried(r: &Request, plan: &Plan, out: &mut Value) { /// ([`crate::engine::dynamic`]): counts by shot splitting, expectation values as the /// exact mixture over its branches. fn run_dynamic(r: &catalog::Request, plan: &Plan, steps: &[crate::qasm::Instr], out: &mut Value) -> Result<(), String> { - use crate::engine::dynamic::{self, Dense, Stabilizer}; + use crate::engine::dynamic::{self, Dense, DenseOps, Stabilizer}; let (n, nb) = (r.program.n_qubits, r.program.n_bits); let strings: Vec> = r.observables.iter().map(|(_, _, s)| s.clone()).collect(); let (sampled, exact) = match plan.method.as_str() { + // A gate held whole runs as one between the measurements too. + "statevector" if r.program.has_whole() => { + let gates = r.program.sv_ops(); + let states = (plan.memory_bytes.saturating_sub((256 << 20) + r.shots * 24) / catalog::amplitude_bytes(n)).max(1) as usize; + let start = DenseOps { sv: crate::quantum_sv::StateVector::zero(n).map_err(|e| format!("{e:?}"))?, ops: &gates }; + let s = if r.shots > 0 { Some(dynamic::sample(steps, nb, start.clone(), r.shots, r.seed, states)?) } else { None }; + let e = if strings.is_empty() { None } else { Some(dynamic::expectations(steps, &r.program.ops, nb, start, &strings, states)?) }; + (s, e) + } "statevector" => { let gates = r.program.matrices(); // The states the plan admitted: its memory less the job's margin and the counts. diff --git a/wai/wai-quantum/src/engine/schema.rs b/wai/wai-quantum/src/engine/schema.rs index 151578fe0..2dc5e7df6 100644 --- a/wai/wai-quantum/src/engine/schema.rs +++ b/wai/wai-quantum/src/engine/schema.rs @@ -696,6 +696,9 @@ mod tests { let mut methods = std::collections::BTreeSet::new(); for req in [ json!({ "qasm": bell, "method": "exact", "shots": 100, "observables": ["Z0 Z1", { "pauli": "X0 X1", "coeff": 0.5 }], "amplitudes": ["00", "11"] }), + // A gate held whole, the phase the method drops, an angle below its table and one it moved. + json!({ "qasm": "OPENQASM 3.0;\nqubit[4] q;\nh q;\nctrl(3) @ z q[0], q[1], q[2], q[3];\nrz(pi / 4) q[0];\np(2 * pi / 2**50) q[1];\np(pi / 2 + 2 * pi / 2**48) q[2];\n", "method": "exact", "shots": 8 }), + json!({ "qasm": "OPENQASM 3.0;\nqubit[4] q;\nh q;\nctrl(3) @ x q[0], q[1], q[2], q[3];\n", "method": "statevector", "shots": 8 }), json!({ "qasm": rot, "method": "statevector", "shots": 100, "observables": ["Z0"], "amplitudes": ["000"], "seed": 3 }), json!({ "qasm": bell, "shots": 100, "observables": ["Z0 Z1"] }), json!({ "qasm": bell, "method": "stabilizer", "shots": 100, "observables": ["Z0 Z1"], "noise": { "depolarizing_1q": 0.01, "readout": 0.02 } }), diff --git a/wai/wai-quantum/src/qasm.rs b/wai/wai-quantum/src/qasm.rs index a789a9eb0..abeb40538 100644 --- a/wai/wai-quantum/src/qasm.rs +++ b/wai/wai-quantum/src/qasm.rs @@ -37,6 +37,13 @@ //! the tests hold each lowering to the others. The bit-exact method takes the //! reader's program under its own restriction, dyadic angles //! ([`dyadic_circuit`], [`exact_circuit`]), refused with a code otherwise. +//! +//! **Gates under many controls.** [`read`] writes every gate in standard gates, +//! which for a gate under many controls doubles with each control. +//! [`read_whole`] keeps such a gate as one op ([`Op::is_whole`]), for the methods +//! that run it so: the dense state vector ([`Program::sv_ops`]) and the bit-exact +//! one ([`Program::dyadic`]). [`Program::lowered`] writes a whole program in +//! standard gates: what [`read`] gives of the same text, op for op. pub mod diag; pub mod lex; @@ -44,6 +51,7 @@ pub mod ast; pub mod parse; pub mod value; pub(crate) mod elab; +mod controls; mod unroll; /// OpenPulse: the calibrations read into a schedule on frames, for the pulse /// simulator (`quantum_pulse`). @@ -180,6 +188,11 @@ fn normalise(kind: Kind, given: usize, args: Vec) -> Vec { pub type CliffordOp = (Vec, Vec); /// One gate on named qubits. +/// +/// In a program [`read_whole`] gave, `qubits` may hold more qubits than the +/// kind's arity: the gate, a one-qubit one, under controls, the controls first +/// and the target last ([`Op::is_whole`]). [`read`] and [`parse`] never give +/// one. #[derive(Clone, Debug, PartialEq)] pub struct Op { pub kind: Kind, @@ -187,6 +200,19 @@ pub struct Op { pub params: Vec, } +impl Op { + /// Whether this is one gate under controls that the standard form writes + /// as many ([`read_whole`]). + pub fn is_whole(&self) -> bool { + self.qubits.len() > self.kind.arity().1 + } + + /// The controls of a whole gate, and none of any other. + pub fn controls(&self) -> &[u32] { + &self.qubits[..self.qubits.len().saturating_sub(self.kind.arity().1)] + } +} + /// Which qubit each bit holds once a program has run, for a program whose /// measurements all come at the end: a bit written twice holds the qubit it /// was written from last. Measurements at the end act on separate qubits and @@ -374,6 +400,22 @@ pub fn read_with(src: &str, inputs: &Inputs) -> Result { Ok(Reading { program, lines, diagnostics }) } +/// [`read`], each gate whose standard form would double with its controls +/// kept as one op ([`Op::is_whole`]), under up to 255 controls: for a method +/// that runs such a gate as one. Everything else reads as [`read`] reads it, +/// and [`Program::lowered`] gives the program [`read`] gives. +pub fn read_whole(src: &str) -> Result { + read_whole_with(src, &Inputs::new()) +} + +/// [`read_whole`] for a generator, at `inputs`. +pub fn read_whole_with(src: &str, inputs: &Inputs) -> Result { + let toks = lex::lex(src)?; + let (stmts, version) = parse::parse(src, &toks)?; + let (program, lines, diagnostics) = elab::elaborate_whole(src, &toks, &stmts, version, inputs)?; + Ok(Reading { program, lines, diagnostics }) +} + /// The integer `input`s a program declares (`input uint n;`, `input int k;`), /// in the order it declares them. A program that declares one is a /// generator: [`parse_with`] reads it for each value, and [`parse`] refuses it, @@ -664,6 +706,11 @@ impl Op { use Kind::*; let q = self.qubits.clone(); let p = &self.params; + if self.is_whole() { + let c = self.controls().len() as u32; + assert!(c <= 12, "{c} controls: a whole gate's dense matrix has 4^{} entries; run it through Program::sv_ops, or write it in standard gates (Program::lowered)", c + 1); + return Matrix { qubits: q, matrix: controlled(&one_qubit(self.kind, p), c) }; + } let matrix = match self.kind { Id | X | Y | Z | H | S | Sdg | T | Tdg | Sx | Sxdg | Rx | Ry | Rz | P | U => one_qubit(self.kind, p).to_vec(), Cx => controlled(&one_qubit(X, &[]), 1), @@ -747,8 +794,68 @@ pub(crate) fn dyadic(angle: f64) -> Option { None } +/// What lowering a program to the bit-exact circuit did to it, beside the +/// gates: what a result on that method states ([`Program::dyadic_with_report`]). +#[derive(Clone, Debug, Default, PartialEq)] +pub struct DyadicReport { + /// The global phase the lowering drops, in `2^33`rds of a turn: OpenQASM's + /// state is `e^{2πi·g/2^33}` times the circuit's. `rz`, `rx`, `ry`, `rxx`, + /// `ryy`, `rzz` and `u` become phase gates, each `e^{iθ/2}` from the + /// standard's matrix; a gate under a control keeps its phase. + pub global_phase: u64, + /// Angles that are not zero and ran as no phase: within the reader's + /// tolerance of a whole turn, below every entry of the table. + pub below_table: u64, + /// The largest of them, in radians from a whole turn. + pub largest_below_table: f64, + /// Angles moved to the dyadic one within the reader's tolerance by more + /// than a double's rounding of it. + pub moved: u64, + /// The largest such move, in radians. + pub largest_moved: f64, +} + +impl DyadicReport { + /// The global phase in radians, in `(−π, π]`. + pub fn global_phase_radians(&self) -> f64 { + const FULL: u64 = 1 << 33; + let signed = if self.global_phase > FULL / 2 { self.global_phase as f64 - FULL as f64 } else { self.global_phase as f64 }; + signed / FULL as f64 * std::f64::consts::TAU + } + + /// `e^{iθ/2}` dropped: the phase the standard's matrix has beyond the + /// lowered gate's. + fn drop_half(&mut self, theta: f64) { + const FULL: u64 = 1 << 33; + // θ in 2^32nds of a turn, whole turns kept: rz(2π) is −1. + let m = (theta / std::f64::consts::TAU * (1u64 << 32) as f64).round(); + let m = (m as i128).rem_euclid(FULL as i128) as u64; + self.global_phase = (self.global_phase + FULL - m) % FULL; + } + + /// What reading `angle` as the dyadic `m` (in `2^32`nds of a turn) moved. + fn read(&mut self, angle: f64, m: u64) { + let t = (angle / std::f64::consts::TAU).rem_euclid(1.0); + let at = m as f64 / (1u64 << 32) as f64; + let gap = (t - at).abs().min(1.0 - (t - at).abs()); + // A double's rounding of the dyadic angle moves nothing. + if gap <= 16.0 * f64::EPSILON * (angle.abs() / std::f64::consts::TAU) { + return; + } + let radians = gap * std::f64::consts::TAU; + if m == 0 { + self.below_table += 1; + self.largest_below_table = self.largest_below_table.max(radians); + } else { + self.moved += 1; + self.largest_moved = self.largest_moved.max(radians); + } + } +} + struct DyadicOut { c: Dyadic, + report: DyadicReport, } impl DyadicOut { @@ -759,6 +866,7 @@ impl DyadicOut { /// `diag(1, e^{iλ})` on `target` under `controls`: one `P(k)` per set bit. fn phase(&mut self, controls: &[u32], target: u32, lambda: f64) -> Result<(), Diagnostic> { let m = dyadic(lambda).ok_or_else(|| Diagnostic::new(diag::NOT_DYADIC, None, format!("the angle {lambda} is not a dyadic multiple of 2π (2πm/2^k, k ≤ 32)")))?; + self.report.read(lambda, m); for j in 0..32u16 { if m >> j & 1 == 1 { self.g(BaseGate::P, controls, target, 32 - j); @@ -797,12 +905,76 @@ impl DyadicOut { Ok(()) } + /// `rz(θ)` on `t` under `cs` (at least one): `p(θ)` under them, and the + /// `e^{−iθ/2}` a control keeps, on the last of them under the others. + fn rz_under(&mut self, cs: &[u32], t: u32, theta: f64) -> Result<(), Diagnostic> { + self.phase(cs, t, theta)?; + let (last, rest) = cs.split_last().expect("a whole gate has controls"); + self.phase(rest, *last, -theta / 2.0) + } + + /// A one-qubit gate under its controls, every gate of it under them all, + /// so an amplitude a control turns off is not touched. + fn whole(&mut self, op: &Op) -> Result<(), Diagnostic> { + use Kind::*; + let (cs, t, p) = (op.controls(), op.qubits[op.qubits.len() - 1], &op.params); + match op.kind { + X => self.g(BaseGate::X, cs, t, 0), + Y => self.g(BaseGate::Y, cs, t, 0), + Z => self.g(BaseGate::Z, cs, t, 0), + H => self.g(BaseGate::H, cs, t, 0), + S => self.g(BaseGate::S, cs, t, 0), + Sdg => self.g(BaseGate::Sdg, cs, t, 0), + T => self.g(BaseGate::T, cs, t, 0), + Tdg => self.g(BaseGate::Tdg, cs, t, 0), + P => self.phase(cs, t, p[0])?, + Sx | Sxdg => { + self.g(BaseGate::H, cs, t, 0); + self.g(if op.kind == Sx { BaseGate::S } else { BaseGate::Sdg }, cs, t, 0); + self.g(BaseGate::H, cs, t, 0); + } + Rz => self.rz_under(cs, t, p[0])?, + Rx => { + self.g(BaseGate::H, cs, t, 0); + self.rz_under(cs, t, p[0])?; + self.g(BaseGate::H, cs, t, 0); + } + Ry => { + self.g(BaseGate::Sdg, cs, t, 0); + self.g(BaseGate::H, cs, t, 0); + self.rz_under(cs, t, p[0])?; + self.g(BaseGate::H, cs, t, 0); + self.g(BaseGate::S, cs, t, 0); + } + // U(θ, φ, λ) = p(φ) ry(θ) p(λ). + U => { + self.phase(cs, t, p[2])?; + self.g(BaseGate::Sdg, cs, t, 0); + self.g(BaseGate::H, cs, t, 0); + self.rz_under(cs, t, p[0])?; + self.g(BaseGate::H, cs, t, 0); + self.g(BaseGate::S, cs, t, 0); + self.phase(cs, t, p[1])?; + } + _ => unreachable!("only a one-qubit gate stands whole"), + } + Ok(()) + } + /// One op in the dyadic gate set. fn op(&mut self, op: &Op) -> Result<(), Diagnostic> { + if op.is_whole() { + return self.whole(op); + } let o = self; let q = &op.qubits; let p = &op.params; use Kind::*; + match op.kind { + Rx | Ry | Rz | Rzz | Rxx | Ryy => o.report.drop_half(p[0]), + U => o.report.drop_half(p[0]), + _ => {} + } match op.kind { Id => {} X => o.g(BaseGate::X, &[], q[0], 0), @@ -1086,15 +1258,31 @@ impl Program { /// tensor networks and the noisy simulators (qubit 0 the most significant /// bit of their index). #[cfg(feature = "quantum_qasm")] + /// + /// A gate held whole is written in standard gates first; past what those + /// take this panics, so a caller holding a whole program checks + /// [`Program::lowered`] first, or takes [`Program::sv_ops`]. pub fn matrices(&self) -> Vec { + if self.has_whole() { + return self.standard().matrices(); + } self.ops.iter().map(Op::matrix).collect() } + /// The program in standard gates, for a lowering that takes no other. + #[cfg(feature = "quantum_qasm")] + fn standard(&self) -> Program { + self.lowered().unwrap_or_else(|d| panic!("{d}")) + } + /// Every gate as a matrix on at most two qubits: the input of the matrix /// product state. The three-qubit gates are decomposed exactly (Toffoli /// into CX and T gates, as qelib1.inc writes it). #[cfg(feature = "quantum_qasm")] pub fn local_matrices(&self) -> Vec { + if self.has_whole() { + return self.standard().local_matrices(); + } let op = |kind: Kind, qubits: &[u32]| Op { kind, qubits: qubits.to_vec(), params: vec![] }.matrix(); let ccx = |out: &mut Vec, a: u32, b: u32, c: u32| { use Kind::*; @@ -1130,6 +1318,9 @@ impl Program { /// dynamics. Exact up to a global phase, which no expectation value sees. #[cfg(feature = "quantum_qasm")] pub fn rotations(&self) -> RotCircuit { + if self.has_whole() { + return self.standard().rotations(); + } let mut out = RotCircuit::new(self.n_qubits); for op in &self.ops { rot(&mut out, op); @@ -1138,9 +1329,11 @@ impl Program { } /// The circuit in the dyadic gate set: the input of the bit-exact state - /// vector and the stabilizer tableau. Exact up to a global phase; refused - /// when an angle is not `2πm/2^k` (`k ≤ 32`), or the program is wider than - /// the dyadic circuit holds (255 qubits). + /// vector and the stabilizer tableau. Exact up to a global phase + /// ([`Program::dyadic_with_report`] says which); refused when an angle is + /// not `2πm/2^k` (`k ≤ 32`), or the program is wider than the dyadic circuit + /// holds (255 qubits). A gate held whole ([`Op::is_whole`]) is its gates + /// under all its controls, with no global phase. pub fn dyadic(&self) -> Result { self.lower_dyadic(false).map_err(String::from) } @@ -1152,11 +1345,139 @@ impl Program { self.lower_dyadic(true) } + /// [`Program::dyadic`], with what the lowering did beside the gates: the + /// global phase it dropped and the angles it read as another + /// ([`DyadicReport`]). + pub fn dyadic_with_report(&self) -> Result<(Dyadic, DyadicReport), String> { + self.lower_dyadic_reported(false).map_err(String::from) + } + + /// Whether any op is a gate held whole under its controls. + pub fn has_whole(&self) -> bool { + self.ops.iter().any(Op::is_whole) + } + + /// How many standard gates the program is written in, without writing + /// them: its ops' count for a program with none held whole. + pub fn standard_gates(&self) -> u128 { + self.ops.iter().fold(0u128, |n, o| n.saturating_add(if o.is_whole() { controls::whole_len(o.kind, &o.params, o.controls().len()) } else { 1 })) + } + + /// The program in standard gates: of a program [`read_whole`] gave, the + /// program [`read`] gives of the same text, op for op, its steps, timing + /// and records moved with them. Refused where [`read`] refuses it: more + /// controls on one gate, or more gates, than the standard form takes + /// ([`MAX_OPS`]). + pub fn lowered(&self) -> Result { + self.lowered_lines(&[]).map(|(p, _)| p) + } + + /// The program in standard gates, written only if it holds a gate whole: + /// what a consumer of standard gates reads a program through. + pub fn standard_form(&self) -> Result, Diagnostic> { + if self.has_whole() { self.lowered().map(std::borrow::Cow::Owned) } else { Ok(std::borrow::Cow::Borrowed(self)) } + } + + /// [`Program::lowered`] with each op's line (`lines` as a [`Reading`] holds + /// them, or empty for none). + pub fn lowered_lines(&self, lines: &[usize]) -> Result<(Program, Vec), Diagnostic> { + if !self.has_whole() { + return Ok((self.clone(), lines.to_vec())); + } + if self.ops.iter().any(|o| o.controls().len() > elab::MAX_CONTROLS as usize) { + return Err(Diagnostic::new(diag::TOO_MANY_CONTROLS, None, format!("written in standard gates, modifiers add at most {} controls", elab::MAX_CONTROLS))); + } + let total = self.standard_gates(); + if total > MAX_OPS as u128 { + return Err(Diagnostic::new(diag::TOO_MANY_GATES, None, format!("{total} gates written in standard gates; more than {MAX_OPS}"))); + } + struct Standard { + ops: Vec, + } + impl controls::Sink for Standard { + type Error = std::convert::Infallible; + fn gate(&mut self, kind: Kind, params: Vec, qubits: Vec) -> Result<(), Self::Error> { + self.ops.push(Op { kind, qubits, params }); + Ok(()) + } + fn whole(&self) -> bool { + false + } + } + let mut out = Standard { ops: Vec::with_capacity(total as usize) }; + // Where each op's gates start. + let mut at = Vec::with_capacity(self.ops.len() + 1); + let mut new_lines = Vec::with_capacity(if lines.is_empty() { 0 } else { total as usize }); + for (i, op) in self.ops.iter().enumerate() { + at.push(out.ops.len()); + if op.is_whole() { + let (t, cs) = op.qubits.split_last().expect("a whole gate has qubits"); + let Ok(_) = controls::ctrl_one(&mut out, op.kind, &op.params, cs, *t); + } else { + out.ops.push(op.clone()); + } + if let Some(&l) = lines.get(i) { + new_lines.resize(out.ops.len(), l); + } + } + at.push(out.ops.len()); + let dynamic = self.dynamic.as_ref().map(|steps| { + // Where each step lands, one past the end included: a jump may go there. + let mut step_at = Vec::with_capacity(steps.len() + 1); + let mut next = 0; + for s in steps { + step_at.push(next); + next += if let Instr::Gate(i) = s { at[*i + 1] - at[*i] } else { 1 }; + } + step_at.push(next); + let mut written = Vec::with_capacity(next); + for s in steps { + match s { + Instr::Gate(i) => written.extend((at[*i]..at[*i + 1]).map(Instr::Gate)), + Instr::JumpUnless(c, to) => written.push(Instr::JumpUnless(c.clone(), step_at[*to])), + Instr::Jump(to) => written.push(Instr::Jump(step_at[*to])), + other => written.push(other.clone()), + } + } + written + }); + let mut extra = self.extra.clone(); + for t in &mut extra.timing { + t.at = at[t.at]; + } + for n in &mut extra.native { + (n.first, n.end) = (at[n.first], at[n.end]); + } + Ok((Program { n_qubits: self.n_qubits, ops: out.ops, measured: self.measured.clone(), n_bits: self.n_bits, dynamic, extra }, new_lines)) + } + + /// The gates a dense state vector runs: each gate held whole as one + /// controlled gate, every other as its matrix. + #[cfg(feature = "quantum_qasm")] + pub fn sv_ops(&self) -> Vec { + use crate::quantum_sv::{Controlled, SvOp}; + self.ops + .iter() + .map(|o| { + if o.is_whole() { + let (t, cs) = o.qubits.split_last().expect("a whole gate has qubits"); + SvOp::Controlled(Controlled { controls: cs.to_vec(), target: *t, matrix: one_qubit(o.kind, &o.params) }) + } else { + SvOp::Gate(o.matrix()) + } + }) + .collect() + } + fn lower_dyadic(&self, native: bool) -> Result { + self.lower_dyadic_reported(native).map(|(c, _)| c) + } + + fn lower_dyadic_reported(&self, native: bool) -> Result<(Dyadic, DyadicReport), Diagnostic> { if self.n_qubits > 255 { return Err(Diagnostic::new(diag::DYADIC_WIDTH, None, format!("{} qubits; the dyadic circuit holds at most 255", self.n_qubits))); } - let mut o = DyadicOut { c: Dyadic::new(self.n_qubits as u8) }; + let mut o = DyadicOut { c: Dyadic::new(self.n_qubits as u8), report: DyadicReport::default() }; // The native forms hold only if they still stand where they were made. let n = &self.extra.native; let sound = native && n.iter().all(|x| x.first <= x.end && x.end <= self.ops.len()) && n.windows(2).all(|w| w[0].end <= w[1].first); @@ -1174,7 +1495,7 @@ impl Program { o.op(&self.ops[i])?; i += 1; } - Ok(o.c) + Ok((o.c, o.report)) } /// The circuit as Clifford gates on the wide tableau, exact up to a global @@ -1214,6 +1535,9 @@ impl Program { /// written as, and this is the product of the `e^{iθ}`. #[cfg(feature = "quantum_qasm")] pub fn product_measured(&self) -> Result { + if self.has_whole() { + return self.lowered().map_err(String::from)?.product_measured(); + } let one = complex(1.0, 0.0); let zero = complex(0.0, 0.0); let mul = |a: &[C], b: &[C; 4]| -> [C; 4] { @@ -1261,6 +1585,9 @@ impl Program { /// not a whole number of sixteenths of a turn. #[cfg(feature = "quantum_qasm")] pub fn clifford_t(&self) -> Result { + if self.has_whole() { + return self.lowered().map_err(String::from)?.clifford_t(); + } use crate::quantum_stabrank::{CliffordT, CtGate}; use Kind::*; let mut gates = Vec::new(); @@ -1353,7 +1680,29 @@ impl Program { use Kind::*; let mut out = Vec::new(); let mut ends = Vec::with_capacity(ops.len()); + // A gate held whole is Clifford only as its standard gates are: they are + // written one by one, and the first that is not ends it. + struct Each<'a> { + out: &'a mut Vec, + } + impl controls::Sink for Each<'_> { + type Error = String; + fn gate(&mut self, kind: Kind, params: Vec, qubits: Vec) -> Result<(), String> { + let (gates, _) = Program::lower_clifford(&[Op { kind, qubits, params }])?; + self.out.extend(gates); + Ok(()) + } + fn whole(&self) -> bool { + false + } + } for op in ops { + if op.is_whole() { + let (t, cs) = op.qubits.split_last().expect("a whole gate has qubits"); + controls::ctrl_one(&mut Each { out: &mut out }, op.kind, &op.params, cs, *t)?; + ends.push(out.len()); + continue; + } let q = &op.qubits; let p = &op.params; let not = || format!("{:?}{} is not a Clifford gate", op.kind, if p.is_empty() { String::new() } else { format!("({})", p.iter().map(|x| format!("{x}")).collect::>().join(", ")) }); @@ -1460,6 +1809,8 @@ impl Program { #[cfg(all(test, feature = "quantum_qasm"))] mod lang_tests; +#[cfg(all(test, feature = "quantum_qasm"))] +mod whole_tests; #[cfg(all(test, feature = "quantum_qasm"))] mod tests { diff --git a/wai/wai-quantum/src/qasm/controls.rs b/wai/wai-quantum/src/qasm/controls.rs new file mode 100644 index 000000000..d06f457a2 --- /dev/null +++ b/wai/wai-quantum/src/qasm/controls.rs @@ -0,0 +1,318 @@ +//! A gate under controls: as the standard gates it is written in, and as the +//! one op it stays where a method can run it whole. +//! +//! The standard form writes a phase on `m` qubits as `2^m − 1` `p` and `2^m − 2` +//! `cx`, so its length doubles with each control ([`phase_n`]). A method that +//! needs standard gates takes it (a device's compile, the tableau, a tensor +//! network, the noisy methods, the exports); the state vectors do not. Reading +//! a program with [`super::read_whole`], a gate whose standard form would double +//! stays one op: its kind names the one-qubit gate, its `qubits` hold the +//! controls and then the target ([`super::Op::is_whole`]). Everything else is +//! written as [`super::read`] writes it, gate for gate. +//! +//! One set of functions writes both forms, through a [`Sink`], so the reader's +//! standard form and [`super::Program::lowered`] of a whole program are one +//! lowering. + +use super::{Kind, NativeBase}; +use std::f64::consts::{FRAC_PI_2, FRAC_PI_4, PI}; + +/// Where a controlled gate's native form stands, for the bit-exact circuit. +pub(crate) struct Nat { + pub(crate) base: NativeBase, + pub(crate) angle: f64, + pub(crate) controls: Vec, + pub(crate) target: u32, +} + +/// What a lowering writes its gates to. +pub(crate) trait Sink { + type Error; + fn gate(&mut self, kind: Kind, params: Vec, qubits: Vec) -> Result<(), Self::Error>; + /// Whether a gate whose standard form would double stays one op. + fn whole(&self) -> bool; +} + +/// `x` on the last of `qs`, controlled by the others. +pub(crate) fn x_n(s: &mut S, qs: &[u32]) -> Result<(), S::Error> { + let t = qs[qs.len() - 1]; + match qs.len() { + 1 => s.gate(Kind::X, vec![], qs.to_vec()), + 2 => s.gate(Kind::Cx, vec![], qs.to_vec()), + 3 => s.gate(Kind::Ccx, vec![], qs.to_vec()), + _ if s.whole() => s.gate(Kind::X, vec![], qs.to_vec()), + _ => { + s.gate(Kind::H, vec![], vec![t])?; + phase_n(s, PI, qs)?; + s.gate(Kind::H, vec![], vec![t]) + } + } +} + +/// The phase e^{iθ} on the state in which all of `qs` are 1, and on no +/// other: `p`, `cp`, `cz` or `ccz` where one is that gate, and otherwise +/// from x₁⋯x_m = 2^{1−m} Σ_S (−1)^{|S|+1} ⊕_{i∈S} x_i over the nonempty +/// subsets S of the m qubits. Each subset's parity is gathered on its +/// highest qubit by `cx` in Gray-code order and turned by `p(±θ/2^{m−1})`: +/// 2^m − 1 of each, exact, with no global phase, and dyadic when θ is. +pub(crate) fn phase_n(s: &mut S, theta: f64, qs: &[u32]) -> Result<(), S::Error> { + let z = theta == PI; + match qs.len() { + 0 => return Ok(()), + 1 if z => return s.gate(Kind::Z, vec![], qs.to_vec()), + 1 => return s.gate(Kind::P, vec![theta], qs.to_vec()), + 2 if z => return s.gate(Kind::Cz, vec![], qs.to_vec()), + 2 => return s.gate(Kind::Cp, vec![theta], qs.to_vec()), + 3 if z => return s.gate(Kind::Ccz, vec![], qs.to_vec()), + _ => {} + } + if s.whole() { + return if z { s.gate(Kind::Z, vec![], qs.to_vec()) } else { s.gate(Kind::P, vec![theta], qs.to_vec()) }; + } + let a = theta / (1u64 << (qs.len() - 1)) as f64; + for j in 0..qs.len() { + let lead = qs[j]; + s.gate(Kind::P, vec![a], vec![lead])?; + for i in 1u64..1 << j { + // The Gray code's step from i − 1 to i flips this bit. + let bit = i.trailing_zeros() as usize; + s.gate(Kind::Cx, vec![], vec![qs[bit], lead])?; + let size = (i ^ (i >> 1)).count_ones() + 1; + s.gate(Kind::P, vec![if size % 2 == 1 { a } else { -a }], vec![lead])?; + } + // The code ends on the single bit j − 1: release it. + if j > 0 { + s.gate(Kind::Cx, vec![], vec![qs[j - 1], lead])?; + } + } + Ok(()) +} + +/// A one-qubit standard gate on `t` under the controls `cs` (at least +/// one), exactly: the gate the standard names where there is one, and +/// otherwise the target turned into a phase (`x` = `h·z·h`, `y` = +/// `s·x·sdg`, `h` = `ry(π/4)·z·ry(−π/4)`, `rz(θ)` = `e^{−iθ/2}·p(θ)`, `u` its +/// Z-Y-Z angles and their phase). Whole, a gate whose form here would go +/// through [`phase_n`]'s doubling is one op instead. +pub(crate) fn ctrl_one(s: &mut S, base: Kind, p: &[f64], cs: &[u32], t: u32) -> Result, S::Error> { + use Kind::*; + let all: Vec = cs.iter().copied().chain([t]).collect(); + let one = cs.len() == 1; + let nat = |base: NativeBase, angle: f64| Some(Nat { base, angle, controls: cs.to_vec(), target: t }); + Ok(match base { + Id => None, + X => { + x_n(s, &all)?; + nat(NativeBase::X, 0.0) + } + Y => { + if one { + s.gate(Cy, vec![], all)?; + } else if s.whole() && cs.len() >= 3 { + s.gate(Y, vec![], all)?; + } else { + s.gate(Sdg, vec![], vec![t])?; + x_n(s, &all)?; + s.gate(S, vec![], vec![t])?; + } + nat(NativeBase::Y, 0.0) + } + Z => { + phase_n(s, PI, &all)?; + nat(NativeBase::Z, 0.0) + } + H => { + if one { + s.gate(Ch, vec![], all)?; + } else if s.whole() && cs.len() >= 3 { + s.gate(H, vec![], all)?; + } else { + s.gate(Ry, vec![-FRAC_PI_4], vec![t])?; + phase_n(s, PI, &all)?; + s.gate(Ry, vec![FRAC_PI_4], vec![t])?; + } + nat(NativeBase::H, 0.0) + } + S | Sdg | T | Tdg | P => { + let (b, theta) = match base { + S => (NativeBase::S, FRAC_PI_2), + Sdg => (NativeBase::Sdg, -FRAC_PI_2), + T => (NativeBase::T, FRAC_PI_4), + Tdg => (NativeBase::Tdg, -FRAC_PI_4), + _ => (NativeBase::P, p[0]), + }; + // A phase of π is `z`, which `phase_n` names. + if s.whole() && !one && theta != PI { + s.gate(base, p.to_vec(), all)?; + } else { + phase_n(s, theta, &all)?; + } + nat(b, theta) + } + Rz => { + if one { + s.gate(Crz, vec![p[0]], all)?; + } else if s.whole() { + s.gate(Rz, vec![p[0]], all)?; + } else { + phase_n(s, p[0], &all)?; + phase_n(s, -p[0] / 2.0, cs)?; + } + None + } + Rx => { + if one { + s.gate(Crx, vec![p[0]], all)?; + } else if s.whole() { + s.gate(Rx, vec![p[0]], all)?; + } else { + s.gate(H, vec![], vec![t])?; + ctrl_one(s, Rz, p, cs, t)?; + s.gate(H, vec![], vec![t])?; + } + None + } + Ry => { + if one { + s.gate(Cry, vec![p[0]], all)?; + } else if s.whole() { + s.gate(Ry, vec![p[0]], all)?; + } else { + s.gate(Sdg, vec![], vec![t])?; + ctrl_one(s, Rx, p, cs, t)?; + s.gate(S, vec![], vec![t])?; + } + None + } + U => { + if one { + s.gate(Cu, vec![p[0], p[1], p[2], 0.0], all)?; + } else if s.whole() { + s.gate(U, p[..3].to_vec(), all)?; + } else { + // U(θ, φ, λ) = e^{i(φ+λ)/2} Rz(φ) Ry(θ) Rz(λ). + ctrl_one(s, Rz, &[p[2]], cs, t)?; + ctrl_one(s, Ry, &[p[0]], cs, t)?; + ctrl_one(s, Rz, &[p[1]], cs, t)?; + phase_n(s, (p[1] + p[2]) / 2.0, cs)?; + } + None + } + // sx = e^{iπ/4} rx(π/2). + Sx | Sxdg => { + if s.whole() && !one { + s.gate(base, vec![], all)?; + } else { + let sign = if base == Sx { 1.0 } else { -1.0 }; + ctrl_one(s, Rx, &[sign * FRAC_PI_2], cs, t)?; + phase_n(s, sign * FRAC_PI_4, cs)?; + } + None + } + _ => unreachable!("not a one-qubit gate"), + }) +} + +/// Any standard gate under the controls `cs`. +pub(crate) fn ctrl_gate(s: &mut S, kind: Kind, p: &[f64], q: &[u32], cs: &[u32]) -> Result, S::Error> { + use Kind::*; + let with = |extra: &[u32]| -> Vec { cs.iter().chain(extra).copied().collect() }; + Ok(match kind { + Id | X | Y | Z | H | S | Sdg | T | Tdg | P | Rx | Ry | Rz | U | Sx | Sxdg => ctrl_one(s, kind, p, cs, q[0])?, + Cx => ctrl_one(s, X, &[], &with(&q[..1]), q[1])?, + Cy => ctrl_one(s, Y, &[], &with(&q[..1]), q[1])?, + Cz => ctrl_one(s, Z, &[], &with(&q[..1]), q[1])?, + Ch => ctrl_one(s, H, &[], &with(&q[..1]), q[1])?, + Cp => ctrl_one(s, P, p, &with(&q[..1]), q[1])?, + Crx => ctrl_one(s, Rx, p, &with(&q[..1]), q[1])?, + Cry => ctrl_one(s, Ry, p, &with(&q[..1]), q[1])?, + Crz => ctrl_one(s, Rz, p, &with(&q[..1]), q[1])?, + Cu => { + // Controlled e^{iγ} U(θ, φ, λ). + let all = with(&q[..1]); + ctrl_one(s, U, &p[..3], &all, q[1])?; + phase_n(s, p[3], &all)?; + None + } + Swap => { + let (a, b) = (q[0], q[1]); + if cs.len() == 1 { + s.gate(Cswap, vec![], vec![cs[0], a, b])?; + } else { + s.gate(Cx, vec![], vec![b, a])?; + ctrl_one(s, X, &[], &with(&[a]), b)?; + s.gate(Cx, vec![], vec![b, a])?; + } + None + } + Iswap => { + ctrl_gate(s, Rxx, &[-FRAC_PI_2], q, cs)?; + ctrl_gate(s, Ryy, &[-FRAC_PI_2], q, cs)?; + None + } + Rxx | Ryy => { + let (a, b) = (q[0], q[1]); + let pre: &[Kind] = if kind == Rxx { &[H] } else { &[Sdg, H] }; + for &k in pre { + s.gate(k, vec![], vec![a])?; + s.gate(k, vec![], vec![b])?; + } + ctrl_gate(s, Rzz, p, q, cs)?; + let post: &[Kind] = if kind == Rxx { &[H] } else { &[H, S] }; + for &k in post { + s.gate(k, vec![], vec![a])?; + s.gate(k, vec![], vec![b])?; + } + None + } + Rzz => { + // exp(−iθZZ/2) = cx · (1 ⊗ rz(θ)) · cx. + s.gate(Cx, vec![], vec![q[0], q[1]])?; + ctrl_one(s, Rz, p, cs, q[1])?; + s.gate(Cx, vec![], vec![q[0], q[1]])?; + None + } + Ccx => ctrl_one(s, X, &[], &with(&q[..2]), q[2])?, + Ccz => ctrl_one(s, Z, &[], &with(&q[..2]), q[2])?, + Cswap => ctrl_gate(s, Swap, &[], &q[1..], &with(&q[..1]))?, + }) +} + +/// How many standard gates `phase_n` writes for a phase on `m` qubits, `z` +/// when the phase is π. +fn phase_len(m: usize, z: bool) -> u128 { + match m { + 0 => 0, + 1 | 2 => 1, + 3 if z => 1, + // `2^m − 1` `p` and `2^m − 2` `cx`; past the width a count means + // anything, it is simply more than any limit. + m if m >= 120 => u128::MAX >> 8, + m => (1u128 << (m + 1)) - 3, + } +} + +/// How many standard gates the whole op of `kind` and `params` on `cs` and +/// one target stands for, without writing them. +pub(crate) fn whole_len(kind: Kind, params: &[f64], c: usize) -> u128 { + use Kind::*; + let m = c + 1; + let rz = |c: usize, theta: f64| phase_len(c + 1, theta == PI).saturating_add(phase_len(c, -theta / 2.0 == PI)); + match kind { + X => phase_len(m, true).saturating_add(2), + Y => phase_len(m, true).saturating_add(4), + Z => phase_len(m, true), + H => phase_len(m, true).saturating_add(2), + S | Sdg | T | Tdg => phase_len(m, false), + P => phase_len(m, params[0] == PI), + Rz => rz(c, params[0]), + Rx => rz(c, params[0]).saturating_add(2), + Ry => rz(c, params[0]).saturating_add(4), + U => rz(c, params[2]).saturating_add(rz(c, params[0]).saturating_add(4)).saturating_add(rz(c, params[1])).saturating_add(phase_len(c, (params[1] + params[2]) / 2.0 == PI)), + Sx | Sxdg => { + let (r, g) = if kind == Sx { (FRAC_PI_2, FRAC_PI_4) } else { (-FRAC_PI_2, -FRAC_PI_4) }; + rz(c, r).saturating_add(2).saturating_add(phase_len(c, g == PI)) + } + _ => 1, + } +} diff --git a/wai/wai-quantum/src/qasm/diag.rs b/wai/wai-quantum/src/qasm/diag.rs index 60d9a1589..6dd165719 100644 --- a/wai/wai-quantum/src/qasm/diag.rs +++ b/wai/wai-quantum/src/qasm/diag.rs @@ -211,7 +211,7 @@ table! { NO_ROOT = "Q205", Refused, "`pow(r) @` with a fractional `r` where no exact gate exists here: a user gate, `u`, `cu`, or a rotation by 2π or more."; GLOBAL_PHASE = "Q206", Lowered, "`gphase(θ)`: a global phase, which no measurement sees, dropped; under controls it is a phase on the controls."; NO_CONTROLS = "Q207", Refused, "A control modifier that adds no control: `ctrl(0) @`."; - TOO_MANY_CONTROLS = "Q208", Refused, "Modifiers that add more controls than the reader lowers (16)."; + TOO_MANY_CONTROLS = "Q208", Refused, "Modifiers that add more controls than the reader lowers (16 written in standard gates, 255 on a gate a method holds whole)."; TOO_DEEP = "Q209", Refused, "Gate definitions or subroutine calls nested deeper than 32."; TOO_MANY_GATES = "Q210", Refused, "A program that expands to more gates than the reader holds (2 000 000)."; MODIFIER_PLACE = "Q211", Refused, "A modifier on something that is not a gate."; diff --git a/wai/wai-quantum/src/qasm/elab.rs b/wai/wai-quantum/src/qasm/elab.rs index 45b0330f1..0c098d90f 100644 --- a/wai/wai-quantum/src/qasm/elab.rs +++ b/wai/wai-quantum/src/qasm/elab.rs @@ -20,15 +20,19 @@ use super::diag::{self, Diagnostic}; use super::lex::{Tok, Token, Verb}; use super::parse::Version; use super::value::{self, Angle, Dur, Ty, Val}; +use super::controls::{self, Sink}; use super::{ Cond, Extra, Inputs, Instr, Kind, MAX_OPS, MAX_QUBITS, Native, NativeBase, Op, Output, OutputValue, Program, Timing, TimingKind, builtin, normalise, }; /// How deep gate definitions and subroutine calls may nest. pub(crate) const MAX_DEPTH: usize = 32; -/// The most controls modifiers may add: a phase on m qubits is written as -/// 2^m − 1 `cx` and as many `p`. +/// The most controls modifiers may add where a gate is written in standard +/// gates: a phase on m qubits is written as 2^m − 1 `p` and 2^m − 2 `cx`. pub(crate) const MAX_CONTROLS: u32 = 16; +/// The most controls modifiers may add where a gate stays one op +/// ([`super::read_whole`]): as many as the bit-exact circuit's op-log counts. +pub(crate) const MAX_WHOLE_CONTROLS: u32 = 255; /// The most statements and loop iterations a program may run on reading. pub(crate) const MAX_STEPS: u64 = 20_000_000; /// The most times one `while` may run on reading. @@ -195,14 +199,6 @@ struct Frame { envs: Vec>, } -/// Where a controlled gate's native form stands, for the bit-exact circuit. -struct Nat { - base: NativeBase, - angle: f64, - controls: Vec, - target: u32, -} - pub(crate) struct Elab<'a> { src: &'a str, version: Version, @@ -245,6 +241,8 @@ pub(crate) struct Elab<'a> { written: BTreeSet, /// When a gradient is asked: how each gate depends on the parameters. tan: Option, + /// Whether a gate whose standard form would double stays one op. + whole: bool, } /// The program `stmts` (read from `src`, its tokens `toks`) run into the @@ -253,6 +251,12 @@ pub(crate) fn elaborate(src: &str, toks: &[Token], stmts: &[Stmt], version: Vers elaborate_with(src, toks, stmts, version, inputs, None).map(|(p, l, d, _)| (p, l, d)) } +/// [`elaborate`], a gate whose standard form would double staying one op +/// ([`super::controls`]). +pub(crate) fn elaborate_whole(src: &str, toks: &[Token], stmts: &[Stmt], version: Version, inputs: &Inputs) -> R<(Program, Vec, Vec)> { + elaborate_form(src, toks, stmts, version, inputs, None, true).map(|(p, l, d, _)| (p, l, d)) +} + /// One op's parameters' derivatives by each of the program's parameters. pub(crate) type OpTangents = Vec>; @@ -260,6 +264,11 @@ pub(crate) type OpTangents = Vec>; /// `tan` names ([`Tan`]): for each op, for each of its parameters, its /// derivative by each name. pub(crate) fn elaborate_with(src: &str, toks: &[Token], stmts: &[Stmt], version: Version, inputs: &Inputs, tan: Option) -> R<(Program, Vec, Vec, Vec)> { + elaborate_form(src, toks, stmts, version, inputs, tan, false) +} + +#[allow(clippy::too_many_arguments)] +fn elaborate_form(src: &str, toks: &[Token], stmts: &[Stmt], version: Version, inputs: &Inputs, tan: Option, whole: bool) -> R<(Program, Vec, Vec, Vec)> { let mut e = Elab { src, version, @@ -298,6 +307,7 @@ pub(crate) fn elaborate_with(src: &str, toks: &[Token], stmts: &[Stmt], version: ones: BTreeSet::new(), written: BTreeSet::new(), tan, + whole, }; e.prescan(toks, stmts)?; e.block(stmts)?; @@ -307,6 +317,23 @@ pub(crate) fn elaborate_with(src: &str, toks: &[Token], stmts: &[Stmt], version: Ok((p, l, d, tangents)) } +/// The reader as what a controlled gate's lowering writes to: each gate an op +/// and a step, at the statement that made it. +struct Emit<'x, 'a> { + e: &'x mut Elab<'a>, + at: Loc, +} + +impl Sink for Emit<'_, '_> { + type Error = Diagnostic; + fn gate(&mut self, kind: Kind, params: Vec, qubits: Vec) -> R<()> { + self.e.push(kind, params, qubits, self.at) + } + fn whole(&self) -> bool { + self.e.whole + } +} + fn is_physical(name: &str) -> Option { name.strip_prefix('$').filter(|d| !d.is_empty() && d.bytes().all(|b| b.is_ascii_digit())).and_then(|d| d.parse().ok()) } @@ -488,10 +515,10 @@ impl<'a> Elab<'a> { let first = self.ops.len(); let nat = match g { G::Phase(t) => { - self.phase_n(*t, &cs, at)?; - Some(Nat { base: NativeBase::P, angle: *t, controls: cs[..cs.len() - 1].to_vec(), target: cs[cs.len() - 1] }) + controls::phase_n(&mut Emit { e: self, at }, *t, &cs)?; + Some(controls::Nat { base: NativeBase::P, angle: *t, controls: cs[..cs.len() - 1].to_vec(), target: cs[cs.len() - 1] }) } - G::Gate(k, ps, qs) => self.ctrl_gate(*k, ps, qs, &cs, at)?, + G::Gate(k, ps, qs) => controls::ctrl_gate(&mut Emit { e: self, at }, *k, ps, qs, &cs)?, G::Barrier(_) => unreachable!(), }; if let Some(n) = nat { @@ -505,225 +532,6 @@ impl<'a> Elab<'a> { } } - /// `x` on the last of `qs`, controlled by the others. - fn x_n(&mut self, qs: &[u32], at: Loc) -> R<()> { - let t = qs[qs.len() - 1]; - match qs.len() { - 1 => self.push(Kind::X, vec![], qs.to_vec(), at), - 2 => self.push(Kind::Cx, vec![], qs.to_vec(), at), - 3 => self.push(Kind::Ccx, vec![], qs.to_vec(), at), - _ => { - self.push(Kind::H, vec![], vec![t], at)?; - self.phase_n(PI, qs, at)?; - self.push(Kind::H, vec![], vec![t], at) - } - } - } - - /// The phase e^{iθ} on the state in which all of `qs` are 1, and on no - /// other: `p`, `cp`, `cz` or `ccz` where one is that gate, and otherwise - /// from x₁⋯x_m = 2^{1−m} Σ_S (−1)^{|S|+1} ⊕_{i∈S} x_i over the nonempty - /// subsets S of the m qubits. Each subset's parity is gathered on its - /// highest qubit by `cx` in Gray-code order and turned by `p(±θ/2^{m−1})`: - /// 2^m − 1 of each, exact, with no global phase, and dyadic when θ is. - fn phase_n(&mut self, theta: f64, qs: &[u32], at: Loc) -> R<()> { - let z = theta == PI; - match qs.len() { - 0 => return Ok(()), - 1 if z => return self.push(Kind::Z, vec![], qs.to_vec(), at), - 1 => return self.push(Kind::P, vec![theta], qs.to_vec(), at), - 2 if z => return self.push(Kind::Cz, vec![], qs.to_vec(), at), - 2 => return self.push(Kind::Cp, vec![theta], qs.to_vec(), at), - 3 if z => return self.push(Kind::Ccz, vec![], qs.to_vec(), at), - _ => {} - } - let a = theta / (1u64 << (qs.len() - 1)) as f64; - for j in 0..qs.len() { - let lead = qs[j]; - self.push(Kind::P, vec![a], vec![lead], at)?; - for i in 1u64..1 << j { - // The Gray code's step from i − 1 to i flips this bit. - let bit = i.trailing_zeros() as usize; - self.push(Kind::Cx, vec![], vec![qs[bit], lead], at)?; - let size = (i ^ (i >> 1)).count_ones() + 1; - self.push(Kind::P, vec![if size % 2 == 1 { a } else { -a }], vec![lead], at)?; - } - // The code ends on the single bit j − 1: release it. - if j > 0 { - self.push(Kind::Cx, vec![], vec![qs[j - 1], lead], at)?; - } - } - Ok(()) - } - - /// A one-qubit standard gate on `t` under the controls `cs` (at least - /// one), exactly: the gate the standard names where there is one, and - /// otherwise the target turned into a phase (`x` = `h·z·h`, `y` = - /// `s·x·sdg`, `h` = `ry(π/4)·z·ry(−π/4)`, `rz(θ)` = `e^{−iθ/2}·p(θ)`, `u` its - /// Z-Y-Z angles and their phase). - fn ctrl_one(&mut self, base: Kind, p: &[f64], cs: &[u32], t: u32, at: Loc) -> R> { - use Kind::*; - let all: Vec = cs.iter().copied().chain([t]).collect(); - let one = cs.len() == 1; - let nat = |base: NativeBase, angle: f64| Some(Nat { base, angle, controls: cs.to_vec(), target: t }); - Ok(match base { - Id => None, - X => { - self.x_n(&all, at)?; - nat(NativeBase::X, 0.0) - } - Y => { - if one { - self.push(Cy, vec![], all, at)?; - } else { - self.push(Sdg, vec![], vec![t], at)?; - self.x_n(&all, at)?; - self.push(S, vec![], vec![t], at)?; - } - nat(NativeBase::Y, 0.0) - } - Z => { - self.phase_n(PI, &all, at)?; - nat(NativeBase::Z, 0.0) - } - H => { - if one { - self.push(Ch, vec![], all, at)?; - } else { - self.push(Ry, vec![-FRAC_PI_4], vec![t], at)?; - self.phase_n(PI, &all, at)?; - self.push(Ry, vec![FRAC_PI_4], vec![t], at)?; - } - nat(NativeBase::H, 0.0) - } - S | Sdg | T | Tdg | P => { - let (b, theta) = match base { - S => (NativeBase::S, FRAC_PI_2), - Sdg => (NativeBase::Sdg, -FRAC_PI_2), - T => (NativeBase::T, FRAC_PI_4), - Tdg => (NativeBase::Tdg, -FRAC_PI_4), - _ => (NativeBase::P, p[0]), - }; - self.phase_n(theta, &all, at)?; - nat(b, theta) - } - Rz => { - if one { - self.push(Crz, vec![p[0]], all, at)?; - } else { - self.phase_n(p[0], &all, at)?; - self.phase_n(-p[0] / 2.0, cs, at)?; - } - None - } - Rx => { - if one { - self.push(Crx, vec![p[0]], all, at)?; - } else { - self.push(H, vec![], vec![t], at)?; - self.ctrl_one(Rz, p, cs, t, at)?; - self.push(H, vec![], vec![t], at)?; - } - None - } - Ry => { - if one { - self.push(Cry, vec![p[0]], all, at)?; - } else { - self.push(Sdg, vec![], vec![t], at)?; - self.ctrl_one(Rx, p, cs, t, at)?; - self.push(S, vec![], vec![t], at)?; - } - None - } - U => { - if one { - self.push(Cu, vec![p[0], p[1], p[2], 0.0], all, at)?; - } else { - // U(θ, φ, λ) = e^{i(φ+λ)/2} Rz(φ) Ry(θ) Rz(λ). - self.ctrl_one(Rz, &[p[2]], cs, t, at)?; - self.ctrl_one(Ry, &[p[0]], cs, t, at)?; - self.ctrl_one(Rz, &[p[1]], cs, t, at)?; - self.phase_n((p[1] + p[2]) / 2.0, cs, at)?; - } - None - } - // sx = e^{iπ/4} rx(π/2). - Sx | Sxdg => { - let s = if base == Sx { 1.0 } else { -1.0 }; - self.ctrl_one(Rx, &[s * FRAC_PI_2], cs, t, at)?; - self.phase_n(s * FRAC_PI_4, cs, at)?; - None - } - _ => unreachable!("not a one-qubit gate"), - }) - } - - /// Any standard gate under the controls `cs`. - fn ctrl_gate(&mut self, kind: Kind, p: &[f64], q: &[u32], cs: &[u32], at: Loc) -> R> { - use Kind::*; - let with = |extra: &[u32]| -> Vec { cs.iter().chain(extra).copied().collect() }; - Ok(match kind { - Id | X | Y | Z | H | S | Sdg | T | Tdg | P | Rx | Ry | Rz | U | Sx | Sxdg => self.ctrl_one(kind, p, cs, q[0], at)?, - Cx => self.ctrl_one(X, &[], &with(&q[..1]), q[1], at)?, - Cy => self.ctrl_one(Y, &[], &with(&q[..1]), q[1], at)?, - Cz => self.ctrl_one(Z, &[], &with(&q[..1]), q[1], at)?, - Ch => self.ctrl_one(H, &[], &with(&q[..1]), q[1], at)?, - Cp => self.ctrl_one(P, p, &with(&q[..1]), q[1], at)?, - Crx => self.ctrl_one(Rx, p, &with(&q[..1]), q[1], at)?, - Cry => self.ctrl_one(Ry, p, &with(&q[..1]), q[1], at)?, - Crz => self.ctrl_one(Rz, p, &with(&q[..1]), q[1], at)?, - Cu => { - // Controlled e^{iγ} U(θ, φ, λ). - let all = with(&q[..1]); - self.ctrl_one(U, &p[..3], &all, q[1], at)?; - self.phase_n(p[3], &all, at)?; - None - } - Swap => { - let (a, b) = (q[0], q[1]); - if cs.len() == 1 { - self.push(Cswap, vec![], vec![cs[0], a, b], at)?; - } else { - self.push(Cx, vec![], vec![b, a], at)?; - self.ctrl_one(X, &[], &with(&[a]), b, at)?; - self.push(Cx, vec![], vec![b, a], at)?; - } - None - } - Iswap => { - self.ctrl_gate(Rxx, &[-FRAC_PI_2], q, cs, at)?; - self.ctrl_gate(Ryy, &[-FRAC_PI_2], q, cs, at)?; - None - } - Rxx | Ryy => { - let (a, b) = (q[0], q[1]); - let pre: &[Kind] = if kind == Rxx { &[H] } else { &[Sdg, H] }; - for &k in pre { - self.push(k, vec![], vec![a], at)?; - self.push(k, vec![], vec![b], at)?; - } - self.ctrl_gate(Rzz, p, q, cs, at)?; - let post: &[Kind] = if kind == Rxx { &[H] } else { &[H, S] }; - for &k in post { - self.push(k, vec![], vec![a], at)?; - self.push(k, vec![], vec![b], at)?; - } - None - } - Rzz => { - // exp(−iθZZ/2) = cx · (1 ⊗ rz(θ)) · cx. - self.push(Cx, vec![], vec![q[0], q[1]], at)?; - self.ctrl_one(Rz, p, cs, q[1], at)?; - self.push(Cx, vec![], vec![q[0], q[1]], at)?; - None - } - Ccx => self.ctrl_one(X, &[], &with(&q[..2]), q[2], at)?, - Ccz => self.ctrl_one(Z, &[], &with(&q[..2]), q[2], at)?, - Cswap => self.ctrl_gate(Swap, &[], &q[1..], &with(&q[..1]), at)?, - }) - } - fn measure(&mut self, qs: &[u32], bs: &[u32], at: Loc) -> R<()> { if qs.len() != bs.len() { return self.fail(diag::MEASURE_LENGTHS, at, format!("{} qubits measured into {} bits", qs.len(), bs.len())); @@ -1842,8 +1650,9 @@ impl<'a> Elab<'a> { } None => 1, }; - if polarity.len() as i128 + n > MAX_CONTROLS as i128 { - return self.fail(diag::TOO_MANY_CONTROLS, *mat, format!("modifiers add at most {MAX_CONTROLS} controls here")); + let most = if self.whole { MAX_WHOLE_CONTROLS } else { MAX_CONTROLS }; + if polarity.len() as i128 + n > most as i128 { + return self.fail(diag::TOO_MANY_CONTROLS, *mat, format!("modifiers add at most {most} controls here{}", if self.whole { "" } else { ", written in standard gates; a job on the state vector or the bit-exact method holds a gate under as many as 255 as one" })); } polarity.extend(std::iter::repeat_n(*on, n as usize)); } diff --git a/wai/wai-quantum/src/qasm/whole_tests.rs b/wai/wai-quantum/src/qasm/whole_tests.rs new file mode 100644 index 000000000..fd7209707 --- /dev/null +++ b/wai/wai-quantum/src/qasm/whole_tests.rs @@ -0,0 +1,366 @@ +//! A gate under many controls, whole and in standard gates: the one lowering +//! both forms share, and what each path gives. + +use super::*; + +const C3Z: &str = "qubit[5] q;\nh q;\nctrl(3) @ z q[0], q[1], q[2], q[3];\n"; + +/// Programs that hold gates whole, of every form the modifiers write, with +/// what a program carries beside its gates. +const WHOLE: &[&str] = &[ + C3Z, + "qubit[5] q;\nh q;\nctrl(3) @ x q[0], q[1], q[2], q[3];\n", + "qubit[5] q;\nh q;\nctrl(3) @ y q[0], q[1], q[2], q[3];\n", + "qubit[5] q;\nh q;\nctrl(3) @ h q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\nctrl(2) @ s q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ sdg q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ t q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ tdg q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ p(0.3) q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ rz(0.3) q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ rz(-2 * pi) q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ rz(pi) q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ rx(0.3) q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ ry(0.3) q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ u(0.3, 0.4, 0.5) q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ sx q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ sxdg q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl @ cu(0.3, 0.4, 0.5, 0.6) q[0], q[1], q[2];\n", + "qubit[5] q;\nh q;\nctrl(2) @ cu(0.3, 0.4, 0.5, pi) q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\nctrl(2) @ swap q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\nctrl(2) @ iswap q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\nctrl(2) @ rzz(0.3) q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\nctrl(2) @ rxx(0.3) q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\nctrl(2) @ ryy(0.3) q[0], q[1], q[2], q[3];\n", + "qubit[3] q;\nh q;\nctrl(2) @ gphase(0.3) q[0], q[1];\n", + "qubit[4] q;\nh q;\nctrl(3) @ gphase(pi) q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nnegctrl(2) @ ctrl @ s q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\ninv @ ctrl(3) @ t q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\npow(2) @ ctrl(2) @ t q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nctrl(2) @ ctrl @ x q[0], q[1], q[2], q[3];\n", + "gate g a, b { ctrl @ s a, b; h b; }\nqubit[4] q;\nh q;\nctrl(2) @ g q[0], q[1], q[2], q[3];\n", + "qubit[3] a;\nqubit[3] b;\nh a;\nctrl(2) @ x a[0], a[1], a[2];\nctrl(3) @ z a[0], a[1], a[2], b[0];\nctrl(2) @ p(0.2) a[0], a[1], b[1];\n", + // A step between gates, a barrier, a delay and an output carried past them. + "qubit[5] q;\nbit[1] c;\nh q;\nc[0] = measure q[0];\nctrl(2) @ p(pi / 4) q[1], q[2], q[3];\nif (c[0] == 1) { ctrl(3) @ x q[1], q[2], q[3], q[4]; }\nctrl(2) @ t q[1], q[2], q[3];\nreset q[0];\n", + "qubit[4] q;\nbit[4] c;\nh q;\nbarrier q;\nctrl(3) @ z q[0], q[1], q[2], q[3];\nbarrier q[0], q[1];\ndelay[20ns] q[2];\nctrl(2) @ t q[0], q[1], q[2];\nx q[0];\nc = measure q;\n", + "OPENQASM 3.1;\nqubit[4] q;\noutput bit[2] o;\nh q;\nbox[100ns] { ctrl(2) @ p(0.5) q[0], q[1], q[2]; }\no[0] = measure q[0];\no[1] = measure q[3];\n", + "OPENQASM 3.1;\ninput uint n;\nqubit[n] q;\nfor uint i in [2:n - 2] { ctrl(2) @ p(0.1 * i) q[i - 2], q[i - 1], q[i]; ctrl(3) @ x q[i - 2], q[i - 1], q[i], q[i + 1]; }\n", +]; + +fn read_at(src: &str) -> (Inputs, Result) { + let ins: Inputs = if src.contains("input uint n") { [("n".to_string(), 6)].into_iter().collect() } else { Inputs::new() }; + let r = read_with(src, &ins); + (ins, r) +} + +/// What the reader gives in standard gates is what a whole reading lowers to, +/// everything it carries included; and the count says so without writing them. +#[test] +fn a_whole_program_lowers_to_what_the_reader_writes() { + let mut held = 0; + for src in WHOLE { + let (ins, standard) = read_at(src); + let standard = standard.unwrap_or_else(|d| panic!("{d}\n{src}")); + let whole = read_whole_with(src, &ins).unwrap(); + held += usize::from(whole.program.has_whole()); + assert_eq!(whole.diagnostics, standard.diagnostics, "{src}"); + assert_eq!(whole.program.standard_gates() as usize, standard.program.ops.len(), "{src}"); + let (lowered, lines) = whole.program.lowered_lines(&whole.lines).unwrap(); + assert_eq!(lowered, standard.program, "{src}"); + assert_eq!(lines, standard.lines, "{src}"); + // Lowered twice is lowered once; a standard program needs no writing. + assert_eq!(lowered.lowered().unwrap(), lowered); + assert!(matches!(lowered.standard_form().unwrap(), std::borrow::Cow::Borrowed(_))); + } + assert!(held >= WHOLE.len() - 3, "only {held} of {} held a gate whole", WHOLE.len()); +} + +/// The conformance corpus's programs and the course's reach every construct: +/// each reads to the same program by either way. A program with nothing to +/// hold whole reads the same in both. +#[test] +fn every_program_of_the_reader_s_corpus_reads_alike_both_ways() { + let bundle: serde_json::Value = serde_json::from_str(include_str!("../../../quantum-conformance/qasm3/bundle.json")).unwrap(); + let mut read_ok = 0; + for case in bundle["cases"].as_array().unwrap() { + let Some(src) = case["source"].as_str().or(case["text"].as_str()).or(case["qasm"].as_str()) else { continue }; + let ins: Inputs = case["inputs"].as_object().map(|o| o.iter().filter_map(|(k, v)| v.as_i64().map(|x| (k.clone(), x))).collect()).unwrap_or_default(); + match (read_with(src, &ins), read_whole_with(src, &ins)) { + (Ok(s), Ok(w)) => { + assert_eq!(w.program.lowered().unwrap(), s.program, "{src}"); + read_ok += 1; + } + (Err(a), Err(b)) => assert_eq!(a, b, "{src}"), + (a, b) => panic!("{src}\nstandard {:?}\nwhole {:?}", a.err(), b.err()), + } + } + assert!(read_ok >= 20, "only {read_ok} programs read"); +} + +/// Exactly the gates whose standard form doubles stand whole. +#[test] +fn only_what_would_double_stands_whole() { + let form = |src: &str| -> Vec<(Kind, usize)> { read_whole(src).unwrap().program.ops.iter().map(|o| (o.kind, o.qubits.len())).collect() }; + let at = |g: &str, c: usize| { + let qs: Vec = (0..c + 1).map(|i| format!("q[{i}]")).collect(); + form(&format!("qubit[{}] q;\nctrl({c}) @ {g} {};\n", c + 1, qs.join(", "))) + }; + use Kind::*; + assert_eq!(at("x", 1), [(Cx, 2)]); + assert_eq!(at("x", 2), [(Ccx, 3)]); + assert_eq!(at("x", 3), [(X, 4)]); + assert_eq!(at("z", 2), [(Ccz, 3)]); + assert_eq!(at("z", 3), [(Z, 4)]); + assert_eq!(at("y", 2), [(Sdg, 1), (Ccx, 3), (S, 1)]); + assert_eq!(at("y", 3), [(Y, 4)]); + assert_eq!(at("h", 2), [(Ry, 1), (Ccz, 3), (Ry, 1)]); + assert_eq!(at("h", 3), [(H, 4)]); + assert_eq!(at("p(pi)", 2), [(Ccz, 3)]); + assert_eq!(at("p(pi)", 3), [(Z, 4)]); + assert_eq!(at("p(0.5)", 1), [(Cp, 2)]); + assert_eq!(at("p(0.5)", 2), [(P, 3)]); + assert_eq!(at("t", 2), [(T, 3)]); + assert_eq!(at("rz(0.5)", 1), [(Crz, 2)]); + assert_eq!(at("rz(0.5)", 2), [(Rz, 3)]); + assert_eq!(at("u(0.1, 0.2, 0.3)", 1), [(Cu, 2)]); + assert_eq!(at("u(0.1, 0.2, 0.3)", 2), [(U, 3)]); + assert_eq!(at("sx", 2), [(Sx, 3)]); + // The reader itself never gives one. + for src in WHOLE { + assert!(!read_at(src).1.unwrap().program.has_whole(), "{src}"); + } + let g = &read_whole("qubit[4] q;\nctrl(3) @ x q[3], q[1], q[0], q[2];").unwrap().program.ops[0]; + assert!(g.is_whole()); + assert_eq!((g.controls(), g.qubits[3]), (&[3, 1, 0][..], 2)); +} + +/// As many controls as a register holds, whole; in standard gates they are +/// refused, each way saying what it can do. +#[test] +fn past_what_standard_gates_hold_a_gate_still_reads_whole() { + let qs: Vec = (0..21).map(|i| format!("q[{i}]")).collect(); + let src = format!("qubit[21] q;\nctrl(20) @ z {};\n", qs.join(", ")); + let d = read(&src).unwrap_err(); + assert!(d.code == diag::TOO_MANY_CONTROLS && d.message.contains("at most 16 controls") && d.message.contains("as many as 255"), "{d}"); + let p = read_whole(&src).unwrap().program; + assert_eq!((p.ops.len(), p.standard_gates()), (1, (1 << 22) - 3)); + let d = p.lowered().unwrap_err(); + assert!(d.code == diag::TOO_MANY_CONTROLS, "{d}"); + // 16 controls fit one standard form, and many of them pass its limit. + let qs: Vec = (0..17).map(|i| format!("q[{i}]")).collect(); + let many = format!("qubit[17] q;\nfor uint i in [0:15] {{ ctrl(16) @ z {}; }}\n", qs.join(", ")); + let p = read_whole(&many).unwrap().program; + assert_eq!(p.ops.len(), 16); + let d = p.lowered().unwrap_err(); + assert!(d.code == diag::TOO_MANY_GATES, "{d}"); + assert_eq!(read(&many).unwrap_err().code, diag::TOO_MANY_GATES); + let d = read_whole(&format!("qubit[300] q;\nctrl(256) @ z q[0:256];\n")).unwrap_err(); + assert_eq!(d.code, diag::TOO_MANY_CONTROLS); +} + +/// The bit-exact circuit holds a gate whole as one gate under all its +/// controls, or for an angle its phases, and touches nothing the controls +/// leave off. +#[test] +fn the_bit_exact_circuit_holds_a_whole_gate_under_its_controls() { + use crate::quantum::{BaseGate, Gate}; + let c = read_whole(C3Z).unwrap().program.dyadic().unwrap(); + assert_eq!(c.ops.len(), 6); + assert_eq!(c.ops[5], Gate { base: BaseGate::Z, controls: vec![0, 1, 2], target: 3, param: 0 }); + for (src, ops) in [ + ("qubit[4] q;\nctrl(3) @ x q[0], q[1], q[2], q[3];\n", 1), + ("qubit[4] q;\nctrl(3) @ y q[0], q[1], q[2], q[3];\n", 1), + ("qubit[4] q;\nctrl(3) @ h q[0], q[1], q[2], q[3];\n", 1), + ("qubit[4] q;\nctrl(2) @ t q[0], q[1], q[2];\n", 1), + // One phase gate per set bit of the angle's numerator. + ("qubit[4] q;\nctrl(2) @ p(3 * pi / 4) q[0], q[1], q[2];\n", 2), + // p(π/2) under both, and −π/4, seven eighths of a turn, three bits. + ("qubit[4] q;\nctrl(2) @ rz(pi / 2) q[0], q[1], q[2];\n", 4), + ("qubit[4] q;\nctrl(2) @ rx(pi / 2) q[0], q[1], q[2];\n", 6), + ] { + let c = read_whole(src).unwrap().program.dyadic().unwrap(); + assert_eq!(c.ops.len(), ops, "{src}"); + } + // A phase finer than its own table once halved 2^m times stays in reach. + let fine = "qubit[6] q;\nctrl(5) @ p(2 * pi / 2**32) q[0], q[1], q[2], q[3], q[4], q[5];\n"; + assert!(read(fine).unwrap().program.dyadic().is_err() && read_whole(fine).unwrap().program.dyadic().is_ok()); + // The control's phase stays right when the state has one: rz(2π) is −1. + let sv = read_whole("qubit[3] q;\nx q[0];\nx q[1];\nctrl(2) @ rz(2 * pi) q[0], q[1], q[2];\n").unwrap().program.dyadic().unwrap().simulate().unwrap(); + assert_eq!(sv.amps[0b011].re, -crate::quantum::ONE); +} + +/// The ideal state, in double precision, with qubit 0 the lowest bit of the +/// index as on the bit-exact method. +fn ideal(p: &Program) -> Vec<(f64, f64)> { + let mut sv = crate::quantum_sv::StateVector::zero(p.n_qubits).unwrap(); + sv.run_ops(&p.sv_ops(), 1).unwrap(); + let n = p.n_qubits; + (0..1usize << n).map(|x| (x.reverse_bits() >> (usize::BITS - n)).min(usize::MAX)).map(|r| (sv.re[r], sv.im[r])).collect() +} + +/// The Euclidean distance of a fixed-point state from an ideal one, the phase +/// that aligns them taken out. +fn distance(amps: &[crate::quantum::Amp], ideal: &[(f64, f64)]) -> f64 { + let scale = crate::quantum::ONE as f64; + let (mut re, mut im) = (0.0, 0.0); + for (a, b) in amps.iter().zip(ideal) { + let (x, y) = (a.re as f64 / scale, a.im as f64 / scale); + re += x * b.0 + y * b.1; + im += y * b.0 - x * b.1; + } + let m = re.hypot(im).max(f64::MIN_POSITIVE); + let (cr, ci) = (re / m, -im / m); + let mut d = 0.0; + for (a, b) in amps.iter().zip(ideal) { + let (x, y) = (a.re as f64 / scale, a.im as f64 / scale); + let (u, v) = (x * cr - y * ci - b.0, x * ci + y * cr - b.1); + d += u * u + v * v; + } + d.sqrt() +} + +/// What the old expansion and the whole gate give on the bit-exact method. They +/// are not the same bits where the expansion goes through inexact phases: its +/// `P(±θ/2^{m−1})` round at every amplitude, and the whole gate has no such +/// steps, so its state is nearer the ideal one, and both within the published +/// bound. Where the standard form writes no doubling they are the same op-log, +/// and so the same bits. Pinned here, so that every host holds both. +#[test] +fn the_whole_gate_is_nearer_the_ideal_state_than_its_expansion() { + let rows: &[(&str, &str, &str)] = &[ + // Program, the expansion's state hash (as the engine gave before gates + // stood whole, on arm64 and x86_64), and the whole gate's. + (C3Z, "181acaa4aad01230", "2402400329d5"), + ("qubit[5] q;\nh q;\nctrl(3) @ x q[0], q[1], q[2], q[3];\n", "8a504be7fc0299e8", "50b01fab0bfe"), + ("qubit[4] q;\nh q;\nctrl(2) @ p(pi / 8) q[0], q[1], q[2];\n", "13346662e1739d87", "d80c6943dc57"), + ]; + let hex = |b: &[u8]| b.iter().map(|x| format!("{x:02x}")).collect::(); + for (src, old, new) in rows { + let (standard, whole) = (read(src).unwrap().program.dyadic().unwrap(), read_whole(src).unwrap().program.dyadic().unwrap()); + assert!(whole.ops.len() < standard.ops.len()); + let (a, b) = (standard.simulate().unwrap(), whole.simulate().unwrap()); + assert_eq!(&hex(&a.statevector_hash())[..16], *old, "the standard form's bits moved: {src}"); + assert!(hex(&b.statevector_hash()).starts_with(new), "{src}: {}", hex(&b.statevector_hash())); + assert_ne!(a.amps, b.amps, "{src}"); + let id = ideal(&read_whole(src).unwrap().program); + let (da, db) = (distance(&a.amps, &id), distance(&b.amps, &id)); + // Rounding is bounded by quantum-sim.md §5: 1 + √2/2 units per component + // per inexact gate; here far fewer gates than components. + let unit = (crate::quantum::ONE as f64).recip(); + let bound = (1.0 + std::f64::consts::FRAC_1_SQRT_2) * unit * (2.0 * id.len() as f64).sqrt() * standard.ops.len() as f64; + assert!(da <= bound && db <= bound, "{src}: {da} and {db} against {bound}"); + assert!(db < da, "{src}: the whole gate {db}, its expansion {da}"); + } + // Where nothing doubles, the op-log is one and the bits are one. + for src in [ + "qubit[4] q;\nh q;\nt q[0];\nctrl(2) @ x q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nt q[0];\nctrl(2) @ z q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nt q[0];\nctrl(2) @ y q[0], q[1], q[2];\n", + "qubit[4] q;\nh q;\nt q[0];\nctrl(2) @ h q[0], q[1], q[2];\n", + "qubit[3] q;\nh q;\nctrl @ p(pi / 8) q[0], q[1];\n", + "qubit[3] q;\nh q;\nctrl @ swap q[0], q[1], q[2];\n", + "qubit[3] q;\nh q;\ncx q[0], q[1];\nrz(pi / 4) q[2];\n", + ] { + let (a, b) = (read(src).unwrap().program, read_whole(src).unwrap().program); + assert_eq!(a, b, "{src}"); + assert_eq!(a.dyadic().unwrap().ops, b.dyadic().unwrap().ops, "{src}"); + } +} + +/// The double-precision state vector of a whole gate against its expansion: +/// within the double-precision bound of the expansion's gates, for every form. +#[test] +fn the_state_vector_of_a_whole_gate_is_its_expansion_s_within_rounding() { + for src in WHOLE.iter().filter(|s| !s.contains("measure") && !s.contains("input")) { + let whole = read_whole(src).unwrap().program; + let standard = read(src).unwrap().program; + for width in [1, 3] { + let mut a = crate::quantum_sv::StateVector::zero(standard.n_qubits).unwrap(); + a.run(&standard.matrices(), width).unwrap(); + let mut b = crate::quantum_sv::StateVector::zero(whole.n_qubits).unwrap(); + b.run_ops(&whole.sv_ops(), width).unwrap(); + let d: f64 = a.re.iter().zip(&b.re).chain(a.im.iter().zip(&b.im)).map(|(x, y)| (x - y) * (x - y)).sum::().sqrt(); + // C(w) ≈ 64 units of 2^-53 per gate at this width, as in the corpus's bound. + let bound = standard.ops.len() as f64 * 64.0 * (f64::EPSILON / 2.0); + assert!(d <= bound, "{src}: {d} against {bound} at width {width}"); + } + } +} + +/// A program with no gate held whole runs as `matrices` and `run` run it, to +/// the bit, at every fusion width. +#[test] +fn a_run_without_a_whole_gate_is_the_run_it_was() { + let src = "qubit[12] q;\nh q;\nfor uint i in [0:10] { cp(0.3 * i) q[i], q[i + 1]; rx(0.1 * i) q[i]; }\nccx q[0], q[3], q[7];\n"; + let p = read_whole(src).unwrap().program; + assert!(!p.has_whole()); + for width in 1..=5 { + let mut a = crate::quantum_sv::StateVector::zero(12).unwrap(); + a.run(&p.matrices(), width).unwrap(); + let mut b = crate::quantum_sv::StateVector::zero(12).unwrap(); + b.run_ops(&p.sv_ops(), width).unwrap(); + assert_eq!(a, b, "width {width}"); + } +} + +/// `matrices`, `rotations` and the tableau on a whole program write its +/// standard gates, and a whole gate that is not Clifford says so at its first +/// standard gate that is not. +#[test] +fn a_lowering_that_needs_standard_gates_writes_them() { + for src in [C3Z, "qubit[4] q;\nh q;\nctrl(2) @ rz(0.3) q[0], q[1], q[2];\n"] { + let (w, s) = (read_whole(src).unwrap().program, read(src).unwrap().program); + let (a, b) = (w.matrices(), s.matrices()); + assert_eq!(a.len(), b.len()); + assert!(a.iter().zip(&b).all(|(x, y)| x.qubits == y.qubits && x.matrix == y.matrix)); + assert_eq!(w.rotations().ops.len(), s.rotations().ops.len()); + assert_eq!(w.local_matrices().len(), s.local_matrices().len()); + assert!(w.clifford().is_err() && s.clifford().is_err()); + } + // rz(2π) under two controls is a controlled Z on them: Clifford either way. + let src = "qubit[3] q;\nctrl(2) @ rz(2 * pi) q[0], q[1], q[2];\n"; + let (w, s) = (read_whole(src).unwrap().program, read(src).unwrap().program); + assert!(w.has_whole()); + assert_eq!(format!("{:?}", w.clifford().unwrap()), format!("{:?}", s.clifford().unwrap())); + assert!(w.clifford_t().is_ok() == s.clifford_t().is_ok()); + // Under 13 controls the refusal comes from one gate, not 32765. + let qs: Vec = (0..14).map(|i| format!("q[{i}]")).collect(); + let big = read_whole(&format!("qubit[14] q;\nctrl(13) @ z {};\n", qs.join(", "))).unwrap().program; + assert!(big.clifford().unwrap_err().contains("is not a Clifford gate")); +} + +/// The bit-exact lowering's report: the phase its gates drop, exactly, whole +/// turns counted, and the angles it read as another. +#[test] +fn the_bit_exact_report_states_what_the_lowering_did() { + let report = |src: &str| read_whole(src).unwrap().program.dyadic_with_report().unwrap().1; + // No phase: none dropped, none read. + assert_eq!(report("qubit[2] q;\nh q[0];\ncx q[0], q[1];\np(pi / 4) q[0];\ncrz(pi / 2) q[0], q[1];\n"), DyadicReport::default()); + // rz(θ) = e^{−iθ/2} p(θ): −π/8 for θ = π/4, in 2^33rds of a turn. + let r = report("qubit[1] q;\nrz(pi / 4) q[0];\n"); + assert_eq!(r.global_phase, (1 << 33) - (1 << 29)); + assert!((r.global_phase_radians() + std::f64::consts::FRAC_PI_8).abs() < 1e-15); + // A whole turn is −1, a half-turn's worth of phase, and two are 1. + assert_eq!(report("qubit[1] q;\nrz(2 * pi) q[0];\n").global_phase, 1 << 32); + assert_eq!(report("qubit[1] q;\nrz(4 * pi) q[0];\n").global_phase, 0); + for g in ["rx(pi / 2) q[0]", "ry(pi / 2) q[0]", "u(pi / 2, pi / 4, pi / 8) q[0]", "rzz(pi / 2) q[0], q[1]", "rxx(pi / 2) q[0], q[1]", "ryy(pi / 2) q[0], q[1]"] { + assert_eq!(report(&format!("qubit[2] q;\n{g};\n")).global_phase, (1 << 33) - (1 << 30), "{g}"); + } + // Under a control the phase is kept, whole or written out. + assert_eq!(report("qubit[3] q;\nctrl(2) @ rz(pi / 2) q[0], q[1], q[2];\n").global_phase, 0); + assert_eq!(report("qubit[2] q;\ncrz(pi / 2) q[0], q[1];\n").global_phase, 0); + // Below every entry of the table: not refused, and not silent. + let tiny = |k: u32| format!("qubit[1] q;\np(2 * pi / 2**{k}) q[0];\n"); + for k in [47, 48, 52, 60] { + let r = report(&tiny(k)); + assert_eq!(r.below_table, 1, "k = {k}"); + assert!((r.largest_below_table / (std::f64::consts::TAU / 2f64.powi(k as i32)) - 1.0).abs() < 1e-3, "k = {k}: {}", r.largest_below_table); + } + assert_eq!(report(&tiny(32)).below_table, 0); + assert!(read_whole(&tiny(40)).unwrap().program.dyadic().unwrap_err().ends_with("[Q500]")); + // A double's rounding of an angle on the grid moves nothing; more does. + assert_eq!(report("qubit[1] q;\np(pi / 7 * 7 / 4) q[0];\nrz(pi / 3 * 3) q[0];\n").moved, 0); + let moved = report("qubit[1] q;\np(pi / 2 + 2 * pi / 2**48) q[0];\n"); + assert_eq!((moved.moved, moved.below_table), (1, 0)); + assert!(moved.largest_moved > 0.0); +} diff --git a/wai/wai-quantum/src/quantum.rs b/wai/wai-quantum/src/quantum.rs index ad82b6ae6..c70418c21 100644 --- a/wai/wai-quantum/src/quantum.rs +++ b/wai/wai-quantum/src/quantum.rs @@ -722,6 +722,11 @@ impl Circuit { /// The shortcuts read only the matrix, so they hold for either gateset's table: /// circuit2's `P(k ≥ 18)` has `re == ONE` and `im ≠ 0`, which is the diagonal /// path, and only an exact `(−ONE, 0)` takes the negation. +/// +/// Under two or more controls the scan gives way to a walk of only the indices +/// the controls leave on ([`apply_under_controls`]): no pair depends on another, +/// so the order of the visits changes no bit, and a gate under `c` controls +/// costs `2^(n − c)`. fn apply(amps: &mut [Amp], n: u8, g: &Gate, gs: Gateset) { if matches!(g.base, BaseGate::I) { return; @@ -730,6 +735,11 @@ fn apply(amps: &mut [Amp], n: u8, g: &Gate, gs: Gateset) { let tbit = 1usize << g.target; let ctrl_mask: usize = g.controls.iter().fold(0usize, |acc, &c| acc | (1usize << c)); let dim = 1usize << n; + // A repeated control (circuit/1 keeps them) counts once in the mask. + if ctrl_mask.count_ones() >= 2 { + apply_under_controls(amps, dim, tbit, ctrl_mask, m); + return; + } let is_zero = |a: Amp| a.re == 0 && a.im == 0; let is_one = |a: Amp| a.re == ONE && a.im == 0; @@ -814,6 +824,45 @@ fn apply(amps: &mut [Amp], n: u8, g: &Gate, gs: Gateset) { } } +/// [`apply`] under controls: the same expression for each pair as the scan's, +/// its pairs found directly. The next free index comes from the last by +/// carrying through the fixed bits. +fn apply_under_controls(amps: &mut [Amp], dim: usize, tbit: usize, ctrl_mask: usize, m: [[Amp; 2]; 2]) { + let is_zero = |a: Amp| a.re == 0 && a.im == 0; + let is_one = |a: Amp| a.re == ONE && a.im == 0; + let fixed = ctrl_mask | tbit; + let groups = dim >> fixed.count_ones(); + let diagonal = is_one(m[0][0]) && is_zero(m[0][1]) && is_zero(m[1][0]); + let negate = diagonal && m[1][1].re == -ONE && m[1][1].im == 0; + let anti = is_zero(m[0][0]) && is_zero(m[1][1]); + let swap = anti && is_one(m[0][1]) && is_one(m[1][0]); + let real = m[0][0].im == 0 && m[0][1].im == 0 && m[1][0].im == 0 && m[1][1].im == 0; + let mut x = 0usize; + for _ in 0..groups { + let (i, j) = (x | ctrl_mask, x | fixed); + if negate { + amps[j] = Amp { re: -amps[j].re, im: -amps[j].im }; + } else if diagonal { + amps[j] = m[1][1].mul(amps[j]); + } else if swap { + amps.swap(i, j); + } else if anti { + let (a0, a1) = (amps[i], amps[j]); + amps[i] = m[0][1].mul(a1); + amps[j] = m[1][0].mul(a0); + } else if real { + let (a0, a1) = (amps[i], amps[j]); + amps[i] = Amp { re: fxmul(m[0][0].re, a0.re) + fxmul(m[0][1].re, a1.re), im: fxmul(m[0][0].re, a0.im) + fxmul(m[0][1].re, a1.im) }; + amps[j] = Amp { re: fxmul(m[1][0].re, a0.re) + fxmul(m[1][1].re, a1.re), im: fxmul(m[1][0].re, a0.im) + fxmul(m[1][1].re, a1.im) }; + } else { + let (a0, a1) = (amps[i], amps[j]); + amps[i] = m[0][0].mul(a0).add(m[0][1].mul(a1)); + amps[j] = m[1][0].mul(a0).add(m[1][1].mul(a1)); + } + x = (x | fixed).wrapping_add(1) & !fixed; + } +} + // --------------------------------------------------------------------------- // State vector + conformance // --------------------------------------------------------------------------- @@ -1623,6 +1672,58 @@ pub fn accept_corpus() -> Vec<(&'static str, Vec, Circuit, Option)> #[cfg(test)] mod tests { use super::*; + + /// A gate under two or more controls walks only its pairs: the bits of the + /// plain scan of every index, for each base gate, in each gateset, at any + /// choice of controls, a repeated control of circuit/1 among them. + #[test] + fn the_walk_under_controls_gives_the_scan_s_bits() { + fn scan(amps: &mut [Amp], g: &Gate, gs: Gateset) { + if matches!(g.base, BaseGate::I) { + return; + } + let m = g.base.matrix(g.param, gs); + let tbit = 1usize << g.target; + let mask = g.controls.iter().fold(0usize, |a, &c| a | 1usize << c); + for i in 0..amps.len() { + if i & tbit == 0 && i & mask == mask { + let j = i | tbit; + let (a0, a1) = (amps[i], amps[j]); + amps[i] = m[0][0].mul(a0).add(m[0][1].mul(a1)); + amps[j] = m[1][0].mul(a0).add(m[1][1].mul(a1)); + } + } + } + for gs in [Gateset::V1, Gateset::V2] { + let mut prep = Circuit::with_gateset(9, gs); + for q in 0..9 { + prep.h(q); + prep.t(q); + prep.p(5 + u16::from(q), q); + } + for q in 0..8 { + prep.cx(q, q + 1); + } + let start = prep.simulate().unwrap(); + for (controls, target) in [(vec![0u8, 1], 2u8), (vec![8, 3], 0), (vec![1, 5, 7], 8), (vec![0, 1, 2, 3, 4, 5, 6, 7], 8), (vec![8, 2, 4, 6], 3)] { + let bases = [(BaseGate::I, 0), (BaseGate::X, 0), (BaseGate::Y, 0), (BaseGate::Z, 0), (BaseGate::H, 0), (BaseGate::S, 0), (BaseGate::Sdg, 0), (BaseGate::T, 0), (BaseGate::Tdg, 0), (BaseGate::P, 1), (BaseGate::P, 2), (BaseGate::P, 9), (BaseGate::P, 32)]; + for (base, param) in bases { + let g = Gate { base, controls: controls.clone(), target, param }; + let (mut a, mut b) = (start.amps.clone(), start.amps.clone()); + apply(&mut a, 9, &g, gs); + scan(&mut b, &g, gs); + assert_eq!(a, b, "{g:?}"); + } + } + if gs == Gateset::V1 { + let g = Gate { base: BaseGate::H, controls: vec![0, 0, 1], target: 2, param: 0 }; + let (mut a, mut b) = (start.amps.clone(), start.amps.clone()); + apply(&mut a, 9, &g, gs); + scan(&mut b, &g, gs); + assert_eq!(a, b, "a repeated control"); + } + } + } /// The pre-optimisation `apply`, kept verbatim as an oracle. The fast paths /// are justified by an argument (`fxmul(ONE,x) == x`, `fxmul(0,x) == 0`), and /// an argument about fixed-point rounding is exactly the kind that is diff --git a/wai/wai-quantum/src/quantum_frame.rs b/wai/wai-quantum/src/quantum_frame.rs index f8b101de7..b5af8d437 100644 --- a/wai/wai-quantum/src/quantum_frame.rs +++ b/wai/wai-quantum/src/quantum_frame.rs @@ -43,14 +43,25 @@ //! instructions an error-correction experiment uses: //! - resets and measurements in Z and X, with measurement flip noise, and //! inverted measurement targets (`M !3`); -//! - `H`, `S`, `√X`, Paulis, `CX`, `CZ`, `SWAP`; -//! - X/Y/Z flips and one- and two-qubit depolarizing noise; +//! - `H`, `S`, `√X`, Paulis, the axis-cycling `C_XYZ` and `C_ZYX`, `CX`, `CZ`, +//! `SWAP`; +//! - X/Y/Z flips, one- and two-qubit depolarizing noise, correlated errors +//! (`E(p) X1 Y2 Z3`, also `CORRELATED_ERROR`) and one-qubit Pauli channels +//! (`PAULI_CHANNEL_1(px, py, pz)`); //! - detectors with their coordinates (`SHIFT_COORDS` applied), observables //! on measurement records and on Pauli targets (`OBSERVABLE_INCLUDE(0) X3 //! Z4`), and `REPEAT` blocks; //! - a tag on any instruction (`X_ERROR[leak](0.01) 2`): the tag of a noise //! instruction is the tag of every mechanism it makes. //! +//! A correlated error is a flip on a qubit of its own, handed to its targets by +//! `CX` and `CZ` and reset: a circuit with one holds one qubit more than its +//! text names ([`Circuit::qubits`]). A Pauli channel's exclusive outcomes become +//! independent X, Y and Z flips at the rates that give the same law, as a +//! depolarizing channel's do. A channel with no such rates (`(0.1, 0.1, 0)`: +//! its Z would need a rate below zero) is refused with its line, since a +//! detector error model of independent mechanisms cannot state it either. +//! //! An instruction outside that set is an error, not a skipped line. //! [`ErrorModel::to_dem_text`] writes a model with everything it holds //! (coordinates, tags, each decomposed mechanism's parts joined by `^`); @@ -158,6 +169,10 @@ impl core::fmt::Display for FrameError { /// The most operations a circuit may unroll to. pub const MAX_OPS: usize = 50_000_000; +/// While a circuit is read: the qubit a correlated error's flip is carried on, +/// numbered past the text's own once they are all known. +const CARRIER: u32 = u32::MAX; + /// Parse circuit text, unrolling `REPEAT` blocks and resolving `rec[-k]`. pub fn parse(text: &str) -> Result { let prog = crate::quantum_qec_text::parse_circuit(text).map_err(|e| FrameError::Parse { line: e.line, message: e.message })?; @@ -170,9 +185,47 @@ pub fn lower(prog: &crate::quantum_qec_text::CircuitText) -> Result = Vec::new(); lower_items(&prog.items, &mut c, &mut shift)?; + let carrier = c.qubits; + let mut carried = false; + for op in &mut c.ops { + if let Op::Noise1 { q, .. } | Op::Reset { q, .. } | Op::Cx(q, _) | Op::Cz(q, _) = op + && *q == CARRIER + { + *q = carrier; + carried = true; + } + } + if carried { + c.qubits += 1; + } Ok(c) } +/// The rates of independent X, Y and Z flips with the law of a channel whose +/// outcomes X, Y and Z are exclusive, at `px`, `py` and `pz`: the three +/// parities of a flip each multiply over independent channels and add over +/// exclusive ones, so `(1 − 2qx)² = ac/b`, `(1 − 2qy)² = ab/c`, `(1 − 2qz)² = +/// bc/a` with `a = 1 − 2(px + py)`, `b = 1 − 2(py + pz)`, `c = 1 − 2(px + pz)`. +/// A depolarizing channel is the case `px = py = pz`. None when no such rates +/// exist. +fn pauli_channel_rates(px: f64, py: f64, pz: f64) -> Option<[f64; 3]> { + if [px, py, pz].iter().filter(|&&p| p > 0.0).count() <= 1 { + return Some([px, py, pz]); + } + let (a, b, c) = (1.0 - 2.0 * (px + py), 1.0 - 2.0 * (py + pz), 1.0 - 2.0 * (px + pz)); + if a <= 0.0 || b <= 0.0 || c <= 0.0 { + return None; + } + let rate = |square: f64| -> Option { + // A rate of zero, up to the rounding of the products above. + if square > 1.0 + 8.0 * f64::EPSILON { + return None; + } + Some(((1.0 - square.min(1.0).sqrt()) / 2.0).max(0.0)) + }; + Some([rate(a * c / b)?, rate(a * b / c)?, rate(b * c / a)?]) +} + fn lower_items(items: &[crate::quantum_qec_text::Item], c: &mut Circuit, shift: &mut Vec) -> Result<(), FrameError> { use crate::quantum_qec_text::Item; for it in items { @@ -292,6 +345,15 @@ fn lower_instruction(i: &crate::quantum_qec_text::Instruction, c: &mut Circuit, _ => Op::SqrtX(q), })); } + // X → Y → Z → X: S then H on a frame. Its inverse: H then S, as S† is S + // on a frame. + "C_XYZ" | "C_ZYX" => { + let q = qubits(false)?; + touch(c, &q); + for q in q { + c.ops.extend(if name == "C_XYZ" { [Op::S(q), Op::H(q)] } else { [Op::H(q), Op::S(q)] }); + } + } "CX" | "CNOT" | "ZCX" | "CZ" | "ZCZ" | "SWAP" => { let p = pairs()?; for &(a, b) in &p { @@ -318,6 +380,52 @@ fn lower_instruction(i: &crate::quantum_qec_text::Instruction, c: &mut Circuit, touch(c, &q); c.ops.extend(q.into_iter().map(|q| Op::Noise1 { kind, p, q })); } + "PAULI_CHANNEL_1" => { + if nums.len() != 3 { + return Err(err("PAULI_CHANNEL_1 takes three probabilities: of X, of Y and of Z")); + } + let (px, py, pz) = (prob(0)?, prob(1)?, prob(2)?); + if px + py + pz > 1.0 + 8.0 * f64::EPSILON { + return Err(FrameError::BadProbability(px + py + pz)); + } + let rates = pauli_channel_rates(px, py, pz).ok_or_else(|| err(&format!("PAULI_CHANNEL_1({px}, {py}, {pz}): its exclusive outcomes have no form as independent X, Y and Z flips, which this simulator and a detector error model both need")))?; + let q = qubits(false)?; + touch(c, &q); + for q in q { + for (kind, p) in [Noise1::X, Noise1::Y, Noise1::Z].into_iter().zip(rates) { + if p > 0.0 { + c.ops.push(Op::Noise1 { kind, p, q }); + } + } + } + } + // The flip on a qubit of its own, handed on by `CX` (an X on the + // target) and `CZ` (a Z), then reset: every target flips together, in + // the frames forward and in the sensitivities backward. + "E" | "CORRELATED_ERROR" => { + if nums.len() != 1 { + return Err(err(&format!("{name} takes one probability"))); + } + let p = prob(0)?; + let mut handed = Vec::with_capacity(i.targets.len()); + for t in &i.targets { + match *t { + Target::Pauli { pauli, q, inverted: false } => { + touch(c, &[q]); + if pauli != 'Z' { + handed.push(Op::Cx(CARRIER, q)); + } + if pauli != 'X' { + handed.push(Op::Cz(CARRIER, q)); + } + } + _ => return Err(err(&format!("{name} takes Pauli targets, like X1 Y2 Z3"))), + } + } + c.ops.push(Op::Noise1 { kind: Noise1::X, p, q: CARRIER }); + c.ops.extend(handed); + c.ops.push(Op::Reset { basis: Basis::Z, q: CARRIER }); + } "DEPOLARIZE2" => { let p = prob(0)?; if p > 15.0 / 16.0 { @@ -1420,6 +1528,159 @@ mod tests { assert_eq!(parse_dem(reference).unwrap().to_text(), reference); } + /// Each outcome of a Pauli target of an observable, as the frame sees it: + /// the net flip of a noise instruction on one qubit, over many shots. + fn net_flips(noise: &str, shots: usize) -> [f64; 4] { + // Z and X parities read through two observables on one qubit: in |0⟩ a + // record reads the X part of the flip, and the Z part reaches a second + // record through H on a copy in |+⟩ of the same noise's frame. + let text = format!("R 0\n{noise} 0\nOBSERVABLE_INCLUDE(0) Z0\n"); + let c = parse(&text).unwrap(); + let s = sample(&c, shots, 3); + let x = (0..shots).filter(|&i| s.flips(i) & 1 == 1).count() as f64 / shots as f64; + let text = format!("RX 0\n{noise} 0\nOBSERVABLE_INCLUDE(0) X0\n"); + let c = parse(&text).unwrap(); + let s = sample(&c, shots, 4); + let z = (0..shots).filter(|&i| s.flips(i) & 1 == 1).count() as f64 / shots as f64; + let text = format!("R 0\nH 0\nS 0\n{noise} 0\nOBSERVABLE_INCLUDE(0) Y0\n"); + let c = parse(&text).unwrap(); + let s = sample(&c, shots, 5); + let y = (0..shots).filter(|&i| s.flips(i) & 1 == 1).count() as f64 / shots as f64; + [x, z, y, 0.0] + } + + /// The rates of independent flips give the exclusive channel's law, to the + /// rounding: its three parities, exactly. A depolarizing channel is the + /// case of equal probabilities, and a channel with no such rates has none. + #[test] + fn a_pauli_channel_s_rates_have_its_law() { + for (px, py, pz) in [(0.01, 0.02, 0.03), (0.2, 0.1, 0.05), (0.001, 0.001, 0.01), (0.1, 0.0, 0.0), (0.0, 0.0, 0.0), (0.2, 0.2, 0.2)] { + let [qx, qy, qz] = pauli_channel_rates(px, py, pz).unwrap(); + let f = |q: f64| 1.0 - 2.0 * q; + for (got, want) in [(f(qx) * f(qy), 1.0 - 2.0 * (px + py)), (f(qy) * f(qz), 1.0 - 2.0 * (py + pz)), (f(qx) * f(qz), 1.0 - 2.0 * (px + pz))] { + assert!((got - want).abs() < 1e-14, "({px}, {py}, {pz}): {got} against {want}"); + } + } + let [q, r, s] = pauli_channel_rates(0.03, 0.03, 0.03).unwrap(); + assert!((q - independent_rate(0.09, 1)).abs() < 1e-15 && q == r && r == s); + assert_eq!(pauli_channel_rates(0.1, 0.1, 0.0), None); + // Refused with its line, and not read as no noise. + let e = parse("R 0\nPAULI_CHANNEL_1(0.1, 0.1, 0) 0\nM 0\n").unwrap_err(); + assert!(e.to_string().starts_with("line 2:") && e.to_string().contains("no form as independent"), "{e}"); + assert!(matches!(parse("PAULI_CHANNEL_1(0.5, 0.4, 0.3) 0\n"), Err(FrameError::BadProbability(_)))); + assert!(matches!(parse("PAULI_CHANNEL_1(0.1) 0\n"), Err(FrameError::Parse { line: 1, .. }))); + } + + /// A Pauli channel as a sample sees it: an X target flips under Z and Y, a + /// Z target under X and Y, a Y target under X and Z. + #[test] + fn a_pauli_channel_samples_its_law() { + let (px, py, pz) = (0.05, 0.1, 0.15); + let [z_flips, x_flips, y_flips, _] = net_flips(&format!("PAULI_CHANNEL_1({px}, {py}, {pz})"), 400_000); + for (got, want) in [(z_flips, px + py), (x_flips, py + pz), (y_flips, px + pz)] { + assert!((got - want).abs() < 5.0 * (want * (1.0 - want) / 400_000.0).sqrt(), "{got} against {want}"); + } + } + + /// `C_XYZ` sends X to Y, Y to Z and Z to X, and `C_ZYX` undoes it, in the + /// frames forward and the sensitivities backward. + #[test] + fn the_cycling_gates_cycle_the_axes() { + // (prepared in, error before the gate, the target after it): an error + // flips a target exactly if the gate's image of it anticommutes. + for (gate, error, target, flips) in [ + ("C_XYZ", "X_ERROR(0.1)", "Y0", false), + ("C_XYZ", "X_ERROR(0.1)", "Z0", true), + ("C_XYZ", "X_ERROR(0.1)", "X0", true), + ("C_XYZ", "Y_ERROR(0.1)", "Z0", false), + ("C_XYZ", "Z_ERROR(0.1)", "X0", false), + ("C_ZYX", "Z_ERROR(0.1)", "Y0", false), + ("C_ZYX", "Y_ERROR(0.1)", "X0", false), + ("C_ZYX", "X_ERROR(0.1)", "Z0", false), + ] { + // A state fixed by the target's Pauli, by way of the gate itself. + let prep = match target { + "Z0" => "R 0", + "X0" => "RX 0", + _ => "R 0\nH 0\nS 0", + }; + let inverse = if gate == "C_XYZ" { "C_ZYX" } else { "C_XYZ" }; + let text = format!("{prep}\n{inverse} 0\n{error} 0\n{gate} 0\nOBSERVABLE_INCLUDE(0) {target}\n"); + let c = parse(&text).unwrap(); + let m = error_model(&c).unwrap(); + let got: Vec = m.mechanisms.iter().map(|x| x.observables).collect(); + assert_eq!(got, if flips { vec![1] } else { vec![] }, "{text}"); + let shots = 40_000; + let s = sample(&c, shots, 21); + let rate = (0..shots).filter(|&i| s.flips(i) & 1 == 1).count() as f64 / shots as f64; + assert!((rate - if flips { 0.1 } else { 0.0 }).abs() < 0.01, "{text}: {rate}"); + } + } + + /// A correlated error flips all its targets together, each by its Pauli, + /// on the shots it fires and no others: one mechanism with every symptom, + /// and two detectors firing on the same shots. The carrier is a qubit past + /// the text's own, and an error's tag is its mechanism's. + #[test] + fn a_correlated_error_flips_its_targets_together() { + let text = "R 0 1 2\nE[burst](0.25) X0 Y1\nCORRELATED_ERROR(0.125) X2\nM 0 1 2\nDETECTOR rec[-3]\nDETECTOR rec[-2]\nDETECTOR rec[-1]\n"; + let c = parse(text).unwrap(); + assert_eq!((c.qubits, c.measurements), (4, 3)); + let m = error_model(&c).unwrap(); + let got: Vec<(Vec, f64, Option)> = m.mechanisms.iter().map(|x| (x.detectors.clone(), x.probability, x.tag.clone())).collect(); + assert_eq!(got, vec![(vec![0, 1], 0.25, Some("burst".to_string())), (vec![2], 0.125, None)]); + let shots = 200_000; + let s = sample(&c, shots, 7); + assert!((0..shots).all(|i| s.fired(i).contains(&0) == s.fired(i).contains(&1)), "the two flip together"); + for (d, want) in [(0, 0.25), (2, 0.125)] { + let rate = s.count(d) as f64 / shots as f64; + assert!((rate - want).abs() < 5.0 * (want * (1.0 - want) / shots as f64).sqrt(), "D{d}: {rate}"); + } + // Each error draws anew: two in a row merge by the XOR rule, in both. + let two = parse("R 0\nE(0.1) X0\nE(0.2) X0\nM 0\nDETECTOR rec[-1]\n").unwrap(); + let want = 0.1 + 0.2 - 2.0 * 0.1 * 0.2; + assert!((error_model(&two).unwrap().mechanisms[0].probability - want).abs() < 1e-15); + let rate = sample(&two, shots, 9).count(0) as f64 / shots as f64; + assert!((rate - want).abs() < 5.0 * (want * (1.0 - want) / shots as f64).sqrt(), "{rate}"); + for bad in ["E(0.1) 0\n", "E(0.1, 0.2) X0\n", "E(0.1) !X0\n", "E X0\n"] { + assert!(matches!(parse(bad), Err(FrameError::Parse { line: 1, .. })), "{bad}"); + } + } + + /// The reference generator's colour-code memory, whose cycle turns the axes + /// with `C_XYZ`, reads and reaches that tool's model of it, mechanism for + /// mechanism (`tests/data/color_d3.dem`: flattened, like symptoms merged). + #[test] + fn the_reference_colour_code_has_the_reference_s_model() { + use std::collections::BTreeMap; + let symptoms = |line: &str| -> Option<(String, f64)> { + let rest = line.strip_prefix("error(")?; + let (p, s) = rest.split_once(')')?; + Some((s.trim().to_string(), p.parse().unwrap())) + }; + let text = include_str!("../tests/data/color_d3.circuit"); + assert!(text.contains("C_XYZ")); + let c = parse(text).unwrap(); + let ours: BTreeMap = error_model(&c).unwrap().to_text().lines().filter_map(symptoms).collect(); + let theirs: BTreeMap = include_str!("../tests/data/color_d3.dem").lines().filter_map(symptoms).collect(); + assert_eq!(ours.keys().collect::>(), theirs.keys().collect::>()); + for (k, q) in &theirs { + assert!((ours[k] / q - 1.0).abs() < 1e-9, "{k}: {} against {q}", ours[k]); + } + // The rates the sampler gives follow the model, at the detectors they reach. + let m = error_model(&c).unwrap(); + let shots = 200_000; + let s = sample(&c, shots, 13); + for d in 0..m.detectors { + let mut q = 0.0; + for mech in m.mechanisms.iter().filter(|x| x.detectors.contains(&d)) { + q = q + mech.probability - 2.0 * q * mech.probability; + } + let rate = s.count(d as usize) as f64 / shots as f64; + assert!((rate - q).abs() < 6.0 * (q * (1.0 - q) / shots as f64).sqrt().max(1e-4), "D{d}: {rate} against {q}"); + } + } + #[test] fn the_surface_code_model_is_graphlike() { for d in [3, 5] { diff --git a/wai/wai-quantum/src/quantum_mpsim.rs b/wai/wai-quantum/src/quantum_mpsim.rs index f95f4be2a..42648abe6 100644 --- a/wai/wai-quantum/src/quantum_mpsim.rs +++ b/wai/wai-quantum/src/quantum_mpsim.rs @@ -92,6 +92,15 @@ impl std::fmt::Display for MpsError { impl std::error::Error for MpsError {} +/// Why [`Chain::run_within`] stopped. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum MpsRunError { + Chain(MpsError), + /// The work passed the budget after `gate` of `gates` gates, the bond + /// having reached `max_bond_used`. + OutOfWork { gate: usize, gates: usize, work: u64, max_bond_used: usize }, +} + /// What a run's truncations cost. #[derive(Clone, Debug, PartialEq)] pub struct MpsReport { @@ -125,6 +134,7 @@ pub struct Chain { fidelity: f64, truncations: u64, updates: u64, + work: u64, } #[inline] @@ -198,6 +208,7 @@ impl Chain { fidelity: 1.0, truncations: 0, updates: 0, + work: 0, }) } @@ -210,6 +221,27 @@ impl Chain { Ok(c) } + /// [`Chain::run`], holding the run to `budget` units of work ([`Chain::work`]), + /// counted on the bonds it actually holds. It stops at the gate that passes + /// the budget; the meter changes no number of a run that finishes. + pub fn run_within(n: u32, gates: &[Gate], cfg: MpsConfig, budget: u64) -> Result { + let mut c = Chain::new(n, cfg).map_err(MpsRunError::Chain)?; + for (i, g) in gates.iter().enumerate() { + c.apply(g).map_err(|_| MpsRunError::Chain(MpsError::BadGate(i)))?; + if c.work > budget { + return Err(MpsRunError::OutOfWork { gate: i + 1, gates: gates.len(), work: c.work, max_bond_used: c.max_bond_used }); + } + } + Ok(c) + } + + /// The work so far: each two-site update at `(2χ)³`, `χ` the larger of the + /// two bonds it spans. The unit a job's work is planned in, with `χ` there + /// the bond asked for. + pub fn work(&self) -> u64 { + self.work + } + pub fn qubits(&self) -> u32 { self.n as u32 } @@ -328,6 +360,8 @@ impl Chain { /// A two-qubit gate on sites `i`, `i + 1`, its 4×4 matrix with site `i` /// the more significant bit; the center ends on `i + 1`. fn apply2_adjacent(&mut self, i: usize, g: &[C]) { + let chi = self.dl[i].max(self.dr[i + 1]) as u64; + self.work = self.work.saturating_add((2 * chi).saturating_pow(3)); self.move_center(i); let (dl, dc, dr) = (self.dl[i], self.dr[i], self.dr[i + 1]); let (rows, cols) = (dl * 2, 2 * dr); @@ -633,6 +667,38 @@ fn splitmix(s: &mut u64) -> u64 { #[cfg(test)] mod tests { use super::*; + + /// The meter counts the bonds a run holds and changes no number of it: a + /// run that finishes is the run without a meter; one that passes its + /// budget stops at the gate that passed it. + #[test] + fn the_meter_counts_the_bonds_reached_and_changes_nothing() { + // The 24-qubit QFT's entanglement stays low, far below the bond asked. + let n = 24; + let mut gates = Vec::new(); + for q in 0..n { + gates.push(Gate::h(q)); + for t in q + 1..n { + gates.push(Gate::cphase(t, q, core::f64::consts::PI / (1u64 << (t - q)) as f64)); + } + } + let cfg = MpsConfig { max_bond: 256, cutoff: 1e-12 }; + let plain = Chain::run(n, &gates, cfg).unwrap(); + let metered = Chain::run_within(n, &gates, cfg, u64::MAX).unwrap(); + assert_eq!(plain.report(), metered.report()); + assert_eq!(plain.amplitude(&[0; 24]).unwrap(), metered.amplitude(&[0; 24]).unwrap()); + let r = plain.report(); + assert!(r.max_bond_used < 64, "reached {}", r.max_bond_used); + // Below the bound at the bond asked, which is (2·256)³ an update. + assert_eq!(plain.work(), metered.work()); + assert!(plain.work() > 0 && plain.work() < r.updates * 512u64.pow(3) / 100, "{} over {} updates", plain.work(), r.updates); + match Chain::run_within(n, &gates, cfg, plain.work() / 2) { + Err(MpsRunError::OutOfWork { gate, gates: g, work, max_bond_used }) => { + assert!(gate < g && work > plain.work() / 2 && max_bond_used <= r.max_bond_used, "{gate} of {g}: {work}"); + } + other => panic!("{:?}", other.map(|c| c.report())), + } + } use crate::quantum_sv::StateVector; fn random_circuit(n: u32, depth: usize, seed: u64) -> Vec { diff --git a/wai/wai-quantum/src/quantum_sv.rs b/wai/wai-quantum/src/quantum_sv.rs index 00e2b3d62..02f169ed8 100644 --- a/wai/wai-quantum/src/quantum_sv.rs +++ b/wai/wai-quantum/src/quantum_sv.rs @@ -32,6 +32,11 @@ //! as without tiles, so the schedule never changes a bit. A gate of three //! or more qubits on the top qubits, which leaves the direct kernels too //! few blocks to share between threads, runs in tiles too. +//! - **Controlled gates.** A one-qubit gate under controls runs as one +//! ([`Controlled`], [`StateVector::run_ops`]): only the amplitudes every +//! control leaves on are visited, `2^(n − c)` of them under `c` controls, by +//! the same expressions as a one-qubit gate. Runs of other gates between such +//! gates fuse and tile as above; a run without one is exactly [`StateVector::run`]. //! - **Threads.** Every amplitude group is updated independently, so a gate's //! result does not depend on how the work is split. Reductions (norms, //! expectations, sampling) are summed in a fixed number of chunks, each in @@ -86,6 +91,22 @@ pub struct StateVector { pub im: Vec, } +/// A one-qubit gate under controls, as one gate: `matrix` (row-major, rows +/// outputs) acts on `target` wherever every one of `controls` reads 1. +#[derive(Clone, Debug)] +pub struct Controlled { + pub controls: Vec, + pub target: u32, + pub matrix: [C; 4], +} + +/// One gate of a run ([`StateVector::run_ops`]). +#[derive(Clone, Debug)] +pub enum SvOp { + Gate(Gate), + Controlled(Controlled), +} + /// Run `f` over `re`/`im` split into contiguous slices of whole `unit`s, /// threaded where the target has threads; `f` gets each slice and its offset. /// Each thread owns its slices, so nothing is shared. @@ -617,6 +638,112 @@ impl StateVector { Ok(()) } + fn check_controlled(&self, g: &Controlled, gi: usize) -> Result<(), SvError> { + let mut q = g.controls.clone(); + q.push(g.target); + q.sort_unstable(); + q.dedup(); + if q.len() != g.controls.len() + 1 || q.last().is_some_and(|&x| x >= self.n) { + return Err(SvError::BadGate(gi)); + } + Ok(()) + } + + /// Apply one gate under controls. + pub fn apply_controlled(&mut self, g: &Controlled) -> Result<(), SvError> { + self.check_controlled(g, 0)?; + self.controlled_unchecked(g); + Ok(()) + } + + /// Apply gates in order: each [`Controlled`] as one, and each run of other + /// gates between them as [`StateVector::run`] applies it, fused to `width`. + pub fn run_ops(&mut self, ops: &[SvOp], width: usize) -> Result<(), SvError> { + for (i, op) in ops.iter().enumerate() { + match op { + SvOp::Gate(g) => self.check(g, i)?, + SvOp::Controlled(c) => self.check_controlled(c, i)?, + } + } + let mut run: Vec = Vec::new(); + for op in ops { + match op { + SvOp::Gate(g) => run.push(g.clone()), + SvOp::Controlled(c) => { + if !run.is_empty() { + self.run(&run, width)?; + run.clear(); + } + self.controlled_unchecked(c); + } + } + } + if !run.is_empty() { + self.run(&run, width)?; + } + Ok(()) + } + + /// Visit each pair the controls leave on, in `2^(n − c − 1)` groups: the + /// next free index comes from the last by carrying through the fixed bits, + /// and a thread starts from where its share begins. Each pair goes through + /// [`pair`] or, for a diagonal gate, the diagonal path's expression, so a + /// group's amplitudes do not depend on how the groups are shared. + fn controlled_unchecked(&mut self, g: &Controlled) { + let n = self.n; + let tbit = 1usize << (n - 1 - g.target); + let cmask = g.controls.iter().fold(0usize, |m, &q| m | (1usize << (n - 1 - q))); + let fixed = cmask | tbit; + let mut pos: Vec = g.controls.iter().chain([&g.target]).map(|&q| n - 1 - q).collect(); + pos.sort_unstable(); + let groups = 1usize << (n as usize - pos.len()); + let m = g.matrix; + let (zero, one) = (|c: C| c.re == 0.0 && c.im == 0.0, |c: C| c.re == 1.0 && c.im == 0.0); + let diagonal = zero(m[1]) && zero(m[2]) && one(m[0]); + let swap = zero(m[0]) && zero(m[3]) && one(m[1]) && one(m[2]); + let raw = Raw { re: self.re.as_mut_ptr(), im: self.im.as_mut_ptr() }; + let walk = |first: usize, last: usize| { + let mut x = spread(first, &pos); + let c = m[3]; + for _ in first..last { + let (a, b) = (x | cmask, x | fixed); + // SAFETY: `a` and `b` are below `2^n`, every bit being one of + // the state's. No two groups share an index: a group is named + // by its free bits, and each thread walks a range of its own. + unsafe { + let (re, im) = (raw.re(), raw.im()); + if diagonal { + let (br, bi) = (*re.add(b), *im.add(b)); + *re.add(b) = c.re * br - c.im * bi; + *im.add(b) = c.re * bi + c.im * br; + } else if swap { + core::ptr::swap(re.add(a), re.add(b)); + core::ptr::swap(im.add(a), im.add(b)); + } else { + let (nr0, ni0, nr1, ni1) = pair(&m, *re.add(a), *im.add(a), *re.add(b), *im.add(b)); + *re.add(a) = nr0; + *im.add(a) = ni0; + *re.add(b) = nr1; + *im.add(b) = ni1; + } + } + x = ((x | fixed).wrapping_add(1)) & !fixed; + } + }; + let threads = threads_for(2 * groups).min(groups); + if threads <= 1 || cfg!(target_arch = "wasm32") { + walk(0, groups); + return; + } + let share = groups.div_ceil(threads); + std::thread::scope(|sc| { + for t in 0..threads { + let walk = &walk; + sc.spawn(move || walk(t * share, ((t + 1) * share).min(groups))); + } + }); + } + /// Apply gates in order, fused to `width` qubits first (`width` 0 or 1 /// applies them as given), in tiled passes ([`Schedule::DEFAULT`]). pub fn run(&mut self, gates: &[Gate], width: usize) -> Result<(), SvError> { @@ -1178,6 +1305,90 @@ fn embed(g: &Gate, onto: &[u32]) -> Vec { mod tests { use super::*; + /// `matrix` on `target` under `controls` as a dense gate. + fn dense(controls: &[u32], target: u32, m: [C; 4]) -> Gate { + let k = controls.len() + 1; + let d = 1usize << k; + let zero = C { re: 0.0, im: 0.0 }; + let one = C { re: 1.0, im: 0.0 }; + let mut out = vec![zero; d * d]; + for i in 0..d - 2 { + out[i * d + i] = one; + } + for r in 0..2 { + for c in 0..2 { + out[(d - 2 + r) * d + d - 2 + c] = m[r * 2 + c]; + } + } + Gate { qubits: controls.iter().copied().chain([target]).collect(), matrix: out } + } + + /// A gate under controls is the dense gate's amplitude for amplitude, at + /// any choice of controls and target, by every path a thread count takes; + /// a pass under a control never touches what the control leaves off. + #[test] + fn a_gate_under_controls_is_its_dense_gate_on_any_thread_count() { + use crate::gates::Gate as G; + let n = 11; + let start = || { + let mut sv = StateVector::zero(n).unwrap(); + let layer: Vec = (0..n).map(|q| G::ry(q, 0.3 + q as f64)).chain((0..n - 1).map(|q| G::cx(q, q + 1))).chain((0..n).map(|q| G::rz(q, 0.7 * q as f64))).collect(); + sv.run(&layer, 1).unwrap(); + sv + }; + let matrices: Vec<[C; 4]> = [G::x(0), G::y(0), G::z(0), G::h(0), G::s(0), G::t(0), G::phase(0, 0.3), G::rx(0, 0.3), G::ry(0, 0.3), G::rz(0, 0.3), G::sqrt_x(0)].iter().map(|g| [g.matrix[0], g.matrix[1], g.matrix[2], g.matrix[3]]).collect(); + for (cs, t) in [(vec![0, 1], 2), (vec![10, 3], 0), (vec![1, 5, 9], 10), (vec![0, 2, 4, 6, 8], 1), (vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0), (vec![0], 10)] { + for &m in &matrices { + let g = Controlled { controls: cs.clone(), target: t, matrix: m }; + let mut want = start(); + want.apply(&dense(&cs, t, m)).unwrap(); + for threads in [1, 2, 3, 8, 32] { + let got = with_forced_threads(Some(threads), || { + let mut sv = start(); + sv.apply_controlled(&g).unwrap(); + sv + }); + let close = |a: &[f64], b: &[f64]| a.iter().zip(b).all(|(x, y)| (x - y).abs() <= 4.0 * f64::EPSILON); + assert!(close(&got.re, &want.re) && close(&got.im, &want.im), "{cs:?} on {t}, {threads} threads"); + // Each thread count gives one set of bits. + let once = with_forced_threads(Some(1), || { + let mut sv = start(); + sv.apply_controlled(&g).unwrap(); + sv + }); + assert_eq!(got, once, "{cs:?} on {t}, {threads} threads"); + } + let mask = cs.iter().fold(0usize, |a, &q| a | 1 << (n - 1 - q)); + let (mut got, before) = (start(), start()); + got.apply_controlled(&g).unwrap(); + for x in 0..1usize << n { + if x & mask != mask { + assert_eq!((got.re[x].to_bits(), got.im[x].to_bits()), (before.re[x].to_bits(), before.im[x].to_bits()), "{x:b} under {cs:?}"); + } + } + } + } + } + + /// A gate under controls is checked as a gate is. + #[test] + fn a_gate_under_controls_must_fit_the_register() { + let m = [C { re: 0.0, im: 0.0 }, C { re: 1.0, im: 0.0 }, C { re: 1.0, im: 0.0 }, C { re: 0.0, im: 0.0 }]; + let mut sv = StateVector::zero(3).unwrap(); + for (controls, target) in [(vec![0, 0], 1), (vec![0, 1], 1), (vec![0, 3], 1), (vec![0, 1], 3)] { + assert_eq!(sv.apply_controlled(&Controlled { controls, target, matrix: m }), Err(SvError::BadGate(0))); + } + let ops = [SvOp::Gate(crate::gates::Gate::h(0)), SvOp::Controlled(Controlled { controls: vec![0, 0], target: 1, matrix: m })]; + assert_eq!(sv.run_ops(&ops, 3), Err(SvError::BadGate(1))); + // Refused before any gate ran. + assert_eq!(sv, StateVector::zero(3).unwrap()); + // X under every other qubit: one exchange. + sv.re[0b011] = 1.0; + sv.re[0] = 0.0; + sv.apply_controlled(&Controlled { controls: vec![1, 2], target: 0, matrix: m }).unwrap(); + assert_eq!(sv.re[0b111], 1.0); + } + fn rng(seed: u64) -> impl FnMut() -> f64 { let mut s = seed; move || { diff --git a/wai/wai-quantum/tests/data/color_d3.circuit b/wai/wai-quantum/tests/data/color_d3.circuit new file mode 100644 index 000000000..ed9ce2033 --- /dev/null +++ b/wai/wai-quantum/tests/data/color_d3.circuit @@ -0,0 +1,79 @@ +QUBIT_COORDS(0, 0) 0 +QUBIT_COORDS(1, 0) 1 +QUBIT_COORDS(2, 0) 2 +QUBIT_COORDS(3, 0) 3 +QUBIT_COORDS(0.5, 1) 4 +QUBIT_COORDS(1.5, 1) 5 +QUBIT_COORDS(2.5, 1) 6 +QUBIT_COORDS(1, 2) 7 +QUBIT_COORDS(2, 2) 8 +QUBIT_COORDS(1.5, 3) 9 +R 0 1 2 3 4 5 6 7 8 9 +X_ERROR(0.002) 0 1 2 3 4 5 6 7 8 9 +REPEAT 2 { + TICK + DEPOLARIZE1(0.002) 0 1 3 5 6 7 9 + C_XYZ 0 1 3 5 6 7 9 + DEPOLARIZE1(0.002) 0 1 3 5 6 7 9 + TICK + CX 5 4 3 2 + DEPOLARIZE2(0.002) 5 4 3 2 + TICK + CX 7 4 6 2 + DEPOLARIZE2(0.002) 7 4 6 2 + TICK + CX 1 4 6 8 + DEPOLARIZE2(0.002) 1 4 6 8 + TICK + CX 1 2 7 8 + DEPOLARIZE2(0.002) 1 2 7 8 + TICK + CX 5 2 9 8 + DEPOLARIZE2(0.002) 5 2 9 8 + TICK + CX 0 4 5 8 + DEPOLARIZE2(0.002) 0 4 5 8 + TICK + X_ERROR(0.002) 2 4 8 + MR 2 4 8 + X_ERROR(0.002) 2 4 8 +} +DETECTOR(2, 0, 0) rec[-3] rec[-6] +DETECTOR(0.5, 1, 0) rec[-2] rec[-5] +DETECTOR(2, 2, 0) rec[-1] rec[-4] +TICK +DEPOLARIZE1(0.002) 0 1 3 5 6 7 9 +C_XYZ 0 1 3 5 6 7 9 +DEPOLARIZE1(0.002) 0 1 3 5 6 7 9 +TICK +CX 5 4 3 2 +DEPOLARIZE2(0.002) 5 4 3 2 +TICK +CX 7 4 6 2 +DEPOLARIZE2(0.002) 7 4 6 2 +TICK +CX 1 4 6 8 +DEPOLARIZE2(0.002) 1 4 6 8 +TICK +CX 1 2 7 8 +DEPOLARIZE2(0.002) 1 2 7 8 +TICK +CX 5 2 9 8 +DEPOLARIZE2(0.002) 5 2 9 8 +TICK +CX 0 4 5 8 +DEPOLARIZE2(0.002) 0 4 5 8 +TICK +X_ERROR(0.002) 2 4 8 +MR 2 4 8 +X_ERROR(0.002) 2 4 8 +SHIFT_COORDS(0, 0, 1) +DETECTOR(2, 0, 0) rec[-3] rec[-6] rec[-9] +DETECTOR(0.5, 1, 0) rec[-2] rec[-5] rec[-8] +DETECTOR(2, 2, 0) rec[-1] rec[-4] rec[-7] +X_ERROR(0.002) 0 1 3 5 6 7 9 +M 0 1 3 5 6 7 9 +DETECTOR(2, 0, 1) rec[-3] rec[-4] rec[-5] rec[-6] rec[-10] +DETECTOR(0.5, 1, 1) rec[-2] rec[-4] rec[-6] rec[-7] rec[-9] +DETECTOR(2, 2, 1) rec[-1] rec[-2] rec[-3] rec[-4] rec[-8] +OBSERVABLE_INCLUDE(0) rec[-5] rec[-6] rec[-7] diff --git a/wai/wai-quantum/tests/data/color_d3.dem b/wai/wai-quantum/tests/data/color_d3.dem new file mode 100644 index 000000000..2cf5f5a38 --- /dev/null +++ b/wai/wai-quantum/tests/data/color_d3.dem @@ -0,0 +1,72 @@ +error(0.0006669335944047277) D0 +error(0.0074219502638438305) D0 L0 +error(0.00040026697524683395) D0 D1 +error(0.006500628512183747) D0 D1 L0 +error(0.00794764737171119) D0 D1 D2 +error(0.00013345794395852595) D0 D1 D2 D3 D4 L0 +error(0.001865528433372655) D0 D1 D2 D3 D4 D5 +error(0.00013345794395852595) D0 D1 D2 D4 +error(0.00040026697524683395) D0 D1 D2 D5 +error(0.00013345794395852595) D0 D1 D3 L0 +error(0.0021314129537955175) D0 D1 D3 D4 +error(0.0006669335944047277) D0 D1 D4 +error(0.00013345794395852595) D0 D1 D4 D5 +error(0.000533618081590258) D0 D1 D5 +error(0.006764038999123863) D0 D2 +error(0.000533618081590258) D0 D2 D3 L0 +error(0.0022643019897729626) D0 D2 D3 D5 +error(0.0017321774694031807) D0 D2 D4 +error(0.00013345794395852595) D0 D2 D4 D5 +error(0.00013345794395852595) D0 D2 D5 L0 +error(0.01200761440923498) D0 D3 +error(0.00013345794395852595) D0 D3 D4 L0 +error(0.00040026697524683395) D0 D3 D5 L0 +error(0.00013345794395852595) D0 D4 +error(0.0008002135231907214) D0 D4 L0 +error(0.000533618081590258) D0 D4 D5 +error(0.000533618081590258) D0 D5 +error(0.0074219502638438305) D1 L0 +error(0.006500628512183747) D1 D2 +error(0.000533618081590258) D1 D2 D3 +error(0.00013345794395852595) D1 D2 D3 D4 D5 +error(0.00013345794395852595) D1 D2 D4 L0 +error(0.0015995019184957544) D1 D2 D4 D5 +error(0.00026688026587144063) D1 D3 L0 +error(0.00026688026587144063) D1 D3 D4 +error(0.00040026697524683395) D1 D3 D5 +error(0.01239826888148279) D1 D4 +error(0.00026688026587144063) D1 D5 +error(0.006500628512183747) D2 +error(0.000533618081590258) D2 L0 +error(0.0014660797390328236) D2 D3 +error(0.001865173067674431) D2 D3 D4 +error(0.000533618081590258) D2 D3 D4 D5 +error(0.00013345794395852595) D2 D3 D5 +error(0.00013345794395852595) D2 D3 D5 L0 +error(0.0008002135231907214) D2 D4 +error(0.012268085484454384) D2 D5 +error(0.00026688026587144063) D3 +error(0.005971533505734127) D3 L0 +error(0.000533618081590258) D3 D4 +error(0.005047498883476306) D3 D4 L0 +error(0.00649877855081742) D3 D4 D5 +error(0.005707699784734814) D3 D5 +error(0.001066666666666516) D3 D5 D7 +error(0.006106043412479705) D3 D6 +error(0.001066666666666516) D3 D7 L0 +error(0.005971533505734127) D4 L0 +error(0.005047498883476306) D4 D5 +error(0.006106043412479705) D4 D7 +error(0.005047498883476306) D5 +error(0.00040026697524683395) D5 L0 +error(0.001066666666666516) D5 D6 +error(0.001066666666666516) D5 D6 D7 +error(0.001066666666666516) D5 D7 +error(0.006106043412479705) D5 D8 +error(0.0025314836092638973) D6 L0 +error(0.0025314836092638973) D6 D7 L0 +error(0.0025314836092638973) D6 D7 D8 +error(0.0025314836092638973) D6 D8 +error(0.0025314836092638973) D7 L0 +error(0.0025314836092638973) D7 D8 +error(0.0025314836092638973) D8 -- 2.54.0 (Apple Git-157) From 062f3718284592f6aed7e2ea6da636218b89ae63 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Fri, 6 Nov 2026 03:17:58 -0500 Subject: [PATCH 02/14] wai-quantum: the bit-exact method keeps its bits, and gates count standard gates Review of the first pass: - The bit-exact method's bits are the rounding of each gate it applies, so a gate held whole gives other bits than its standard gates. A job on exact now runs standard gates by default, and gives the hash it always gave; it holds such a gate whole only when asked, "options": {"controls": "whole"}. catalog::runs_whole takes the request, and the planner's bit-exact circuit is the one the method runs. - A result's and lint's `gates` count standard gates however the method ran them, as they always have, so a receipt's provenance is unchanged; `operations` (new, optional) says what a method holding gates whole ran. The schemas say so. - The comparison's driver follows the job path: whole on the state vector, standard on exact unless asked. - The tests hold the default bit-exact hash to the one before the change. Co-Authored-By: Claude Opus 5.5 --- ...-11-05-many-controlled-gates-stay-whole.md | 18 ++-- .../examples/cross_simulator.rs | 26 +++-- wai/wai-quantum/schemas/job-result.v1.json | 6 +- wai/wai-quantum/schemas/tools.v1.json | 6 +- wai/wai-quantum/src/engine/catalog.rs | 26 +++-- .../src/engine/catalog/whole_tests.rs | 96 ++++++++++++------- wai/wai-quantum/src/engine/job.rs | 9 +- .../src/engine/registry/builtin.rs | 2 +- wai/wai-quantum/src/engine/registry/mod.rs | 15 ++- wai/wai-quantum/src/engine/run.rs | 9 +- 10 files changed, 137 insertions(+), 76 deletions(-) diff --git a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md index 277c46e0d..fd106bdf3 100644 --- a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md +++ b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md @@ -1,12 +1,12 @@ -### wai-quantum: a gate under many controls stays one operation, the bit-exact method says what its lowering did, and the error-correction reader takes `C_XYZ`, `E` and `PAULI_CHANNEL_1` +### wai-quantum: a gate under many controls stays one operation on the state vector, the bit-exact method says what its lowering did, and the error-correction reader takes `C_XYZ`, `E` and `PAULI_CHANNEL_1` -**A request that changes what it gives.** A job on `exact` whose program holds a gate under controls that used to be written through a phase polynomial (`x`, `y`, `z` or `h` under three or more controls; `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` or `sxdg` under two or more) gives another `state_hash`, other integers and other seeded counts. The expansion's `P(±θ/2^{m−1})` round at each amplitude, and the gate held whole has no such steps, so the new integers are nearer the ideal state, by no more than the extension's published bound from the old ones; no two forms of such a gate can give one set of bits. `"options": {"controls": "standard"}` runs the expansion and gives the old hash, bit for bit. A result on `statevector` moves by double-precision rounding, within its bound. Every other program, every other method and every other request gives what it gave. +**What a result gives.** A job on `statevector` whose program holds a gate under controls that used to be written through a phase polynomial (`x`, `y`, `z` or `h` under three or more controls; `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` or `sxdg` under two or more) runs that gate as one operation; its amplitudes move by double-precision rounding, within the method's bound, and `"options": {"controls": "standard"}` gives the old bits. A job on `exact` gives the bits it gave, by default: the bit-exact method's bits are the rounding of each gate it applies, so it runs the standard gates unless the job asks for `"options": {"controls": "whole"}`, which holds such a gate whole under its controls, nearer the ideal state by no more than the extension's published bound and with another `state_hash`. Every other method and request gives what it gave. -- **The reader.** `qasm::read_whole` keeps a gate whose standard gates would double as one operation (`Op::is_whole`), under as many as 255 controls. `Program::lowered` writes it in standard gates: exactly what `qasm::read` gives of the same text, its steps, timing and records moved with it, one lowering behind both. `read` and `parse` give standard gates as they did, and refuse past 16 controls and past `MAX_OPS` as they did, saying what can run it. -- **The state vectors.** `StateVector::run_ops` applies such a gate as one (`Controlled`), visiting only the `2^(n − c)` amplitudes its controls leave on; a run without one is `run`, to the bit. The bit-exact simulator walks those indices too, with the scan's bits. Two Grover iterations on 14 qubits are 130 operations, not 131,186. -- **A job.** `exact` and `statevector` run such a gate as one, in programs that measure in the middle too. Their results' `gates` counts operations, and `standard_gates`, a new optional member, says what they are in standard gates. A job with `compile`, `noise`, `mitigate`, `target`, `provider` or a named `fabric` place runs standard gates as it did, as do the other methods, a registered method among them. Methods that need standard gates refuse what those cannot hold with `Q208` or `Q210`, and `auto` passes over them. `lint_qasm` counts as a job does. -- **What depended on the expansion** did not change, checked against this engine's output before the change on arm64 and x86_64: the reader's standard gates, compile, QIR and jeff export, the resource estimate's counts, the expected hashes of `quantum-conformance/` (they hold op-logs and no gate under more than one control). -- **The bit-exact method says what its lowering did** (`accuracy`, each only when there is something to say). `global_phase`: `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `u` become phase gates, so OpenQASM's state is `e^(i·radians)` times the amplitudes given; the phase is exact, in 2^33rds of a turn, whole turns counted. `below_table`: an angle of `2π/2^47` or less ran as no phase, as the table's arithmetic has it, and now says so here and in the plan's `why`. `moved_angles`: an angle within the reader's tolerance of a dyadic one, by more than a double's rounding of it. `Program::dyadic_with_report` gives all three. +- **The reader.** `qasm::read_whole` keeps a gate whose standard gates would double as one operation (`Op::is_whole`), under as many as 255 controls. `Program::lowered` writes it in standard gates: exactly what `qasm::read` gives of the same text, its steps, timing and records moved with it, one lowering behind both. `read` and `parse` give standard gates as they did, and refuse past 16 controls and past `MAX_OPS` as they did. +- **The state vector.** `StateVector::run_ops` applies such a gate as one (`Controlled`), visiting only the `2^(n − c)` amplitudes its controls leave on; a run without one is `run`, to the bit. Two Grover iterations on 14 qubits run as 130 operations, not 131,186 gates. Asked for, the bit-exact simulator holds the gate under its controls and walks only those indices too; a gate under two or more controls in standard gates (a Toffoli) takes the same walk, to the bit of the scan it replaces. +- **What a job counts.** `gates` counts standard gates however the method ran them, as it always has, so a receipt's provenance carries the count it carried; `operations`, a new optional member of a result and of `lint_qasm`, says what a method holding gates whole ran. A job with `compile`, `noise`, `mitigate`, `target`, `provider` or a named `fabric` place runs standard gates as it did, as do the other methods, a registered method among them. Methods that need standard gates refuse what those cannot hold with `Q208` or `Q210`, and `auto` passes over them. +- **What depended on the expansion** did not change: the reader's standard gates, the bit-exact method's hash, a compile, the QIR and jeff exports and the resource estimate's counts, each checked against this engine's output before the change, and the expected hashes of `quantum-conformance/`. +- **The bit-exact method says what its lowering did** (`accuracy`, each only when there is something to say). `global_phase`: `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `u` become phase gates, so OpenQASM's state is `e^(i·radians)` times the amplitudes given; the phase is exact, in 2^33rds of a turn, whole turns counted. `below_table`: an angle of `2π/2^47` or less ran as no phase, as the table's arithmetic has it, and now says so here and in the plan's `why`. `moved_angles`: an angle within the reader's tolerance of a dyadic one, by more than a double's rounding of it. - **The matrix-product job.** A job that names `mps` is no longer refused on an estimate at the bond it asks for: it runs under a meter of the bonds it holds (`Chain::run_within`, `Chain::work`), which changes no number, and stops with `J011`, saying where, if those pass one job's work. The 30-qubit QFT at `max_bond` 256 runs, and reaches far less. A job with `auto` is held to the estimate as it was, and told what naming the method does. -- **The error-correction text.** `C_XYZ` and `C_ZYX`; `E` (or `CORRELATED_ERROR`), a flip on a qubit of its own handed to its Pauli targets, so a circuit with one holds one qubit more than its text names; and `PAULI_CHANNEL_1`, as the independent flips with its law. A channel with no such flips (`PAULI_CHANNEL_1(0.1, 0.1, 0)`) is refused with its line. The reference generator's colour-code memory circuits run, their models equal to that tool's, mechanism for mechanism. -- **The corpus** ([quantum-cross-simulator/](quantum-cross-simulator/README.md)): rerun on both hosts, with the bit-exact method now held to OpenQASM's amplitudes with the phase its result states, nothing fitted, and before-and-after timings on one host. +- **The error-correction text.** `C_XYZ` and `C_ZYX`; `E` (or `CORRELATED_ERROR`), a flip on a qubit of its own handed to its Pauli targets, so a circuit with one holds one qubit more than its text names; and `PAULI_CHANNEL_1`, as the independent flips with its law. A channel with no such flips (`PAULI_CHANNEL_1(0.1, 0.1, 0)`) is refused with its line. +- **The corpus** ([quantum-cross-simulator/](quantum-cross-simulator/README.md)): rerun, with the bit-exact method's amplitudes held to OpenQASM's with the phase its result states, and before-and-after timings on one host. diff --git a/wai/wai-quantum-cli/examples/cross_simulator.rs b/wai/wai-quantum-cli/examples/cross_simulator.rs index badb8fa47..13b520b0f 100644 --- a/wai/wai-quantum-cli/examples/cross_simulator.rs +++ b/wai/wai-quantum-cli/examples/cross_simulator.rs @@ -11,11 +11,13 @@ //! its `kind`: //! //! - `state`: the program's whole state, written to `state_out` with qubit 0 as -//! the lowest bit of the index, each gate under many controls held as one, as -//! a job holds it. `method` `exact` writes `i64` pairs at scale `2^30` (with -//! the state's hash, its op-log, which an independent reader reruns, and the -//! global phase the job's result states); `statevector` writes `f64` pairs, at -//! fusion width `fusion`. +//! the lowest bit of the index, each gate under many controls held as a job +//! holds it: whole on `statevector`, in standard gates on `exact` unless +//! `controls` is `whole` (`standard` writes standard gates for both). `method` +//! `exact` writes `i64` pairs at scale `2^30` (with the state's hash, its +//! op-log, which an independent reader reruns, and the global phase the +//! job's result states); `statevector` writes `f64` pairs, at fusion width +//! `fusion`. //! - `job`: `request` through [`wai_quantum::engine::job::plan_and_run`], the //! engine's whole path: its plan, its run and its answers, unsealed. //! - `stabilizers`: the program on the tableau, and `⟨g⟩` of each Pauli string @@ -55,10 +57,20 @@ fn text<'a>(j: &'a Value, k: &str) -> Result<&'a str, String> { } fn state(j: &Value) -> Result { - let program = qasm::read_whole(text(j, "qasm")?).map_err(|d| d.to_string())?.program; + let method = text(j, "method")?; + // As a job runs it: a gate under many controls held whole on the state + // vector, and on the bit-exact method only when asked ("controls": "whole"); + // "controls": "standard" writes standard gates for both. + let whole = match j.get("controls").and_then(Value::as_str) { + Some("standard") => false, + Some("whole") => true, + _ => method == "statevector", + }; + let src = text(j, "qasm")?; + let program = if whole { qasm::read_whole(src) } else { qasm::read(src) }.map_err(|d| d.to_string())?.program; let n = program.n_qubits; let out = j.get("state_out").and_then(Value::as_str); - match text(j, "method")? { + match method { "exact" => { let (c, report) = program.dyadic_with_report()?; let t = Instant::now(); diff --git a/wai/wai-quantum/schemas/job-result.v1.json b/wai/wai-quantum/schemas/job-result.v1.json index a9f3172c7..cab97a6c1 100644 --- a/wai/wai-quantum/schemas/job-result.v1.json +++ b/wai/wai-quantum/schemas/job-result.v1.json @@ -50,12 +50,12 @@ "gates": { "type": "integer", "minimum": 0, - "description": "The operations the method ran. On exact and statevector a gate under many controls is one." + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." }, - "standard_gates": { + "operations": { "type": "integer", "minimum": 0, - "description": "When the method held a gate under many controls as one: how many gates the program is in standard gates, at most 2^53 - 1." + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "$ref": "#/$defs/accuracy" diff --git a/wai/wai-quantum/schemas/tools.v1.json b/wai/wai-quantum/schemas/tools.v1.json index f2972ebf1..137ce9965 100644 --- a/wai/wai-quantum/schemas/tools.v1.json +++ b/wai/wai-quantum/schemas/tools.v1.json @@ -63,12 +63,12 @@ "gates": { "type": "integer", "minimum": 0, - "description": "A gate under many controls counts one, as the state-vector methods run it." + "description": "The program's gates in standard gates, at most 2^53 - 1." }, - "standard_gates": { + "operations": { "type": "integer", "minimum": 0, - "description": "When a gate under many controls counted one: how many gates the program is in standard gates, at most 2^53 - 1." + "description": "When a gate under many controls would double in standard gates: the operations a job on the state vector runs, each such gate one." }, "bits": { "type": "integer", diff --git a/wai/wai-quantum/src/engine/catalog.rs b/wai/wai-quantum/src/engine/catalog.rs index b635ebfcc..f2a46487c 100644 --- a/wai/wai-quantum/src/engine/catalog.rs +++ b/wai/wai-quantum/src/engine/catalog.rs @@ -342,10 +342,24 @@ impl Request { } } -/// Whether a built-in method runs a gate under many controls as one: every -/// other takes the program in standard gates. -pub(crate) fn runs_whole(method: &str) -> bool { - matches!(method, "exact" | "statevector") +/// Whether a built-in method runs a gate under many controls as one: the +/// state vector, and the bit-exact method when the job asks for it with +/// `"options": {"controls": "whole"}`. Every other takes the program in +/// standard gates. The bit-exact method takes them by default because its bits +/// are the rounding of each gate it applies: the standard gates give the bits +/// it always gave, and the gate held whole gives others. +pub(crate) fn runs_whole(method: &str, v: &Value) -> bool { + match method { + "statevector" => true, + "exact" => whole_asked(v), + _ => false, + } +} + +/// Whether the job asks for a gate under many controls held whole on the +/// bit-exact method too: `"options": {"controls": "whole"}`. +pub(crate) fn whole_asked(v: &Value) -> bool { + v.pointer("/options/controls").and_then(Value::as_str) == Some("whole") } /// Whether this job may hold a gate under many controls as one op @@ -355,8 +369,8 @@ pub(crate) fn runs_whole(method: &str) -> bool { /// target or a provider, compiled to its gates; not when the job names a /// place on the fabric, where every member runs the standard gates and the /// state is the CPU's, bit for bit; and not when it asks for -/// `"options": {"controls": "standard"}`, which reproduces a result made in -/// standard gates, bit for bit. +/// `"options": {"controls": "standard"}`, which reproduces a state-vector +/// result made in standard gates, bit for bit. pub(crate) fn may_run_whole(v: &Value) -> bool { let absent = |k: &str| v.get(k).is_none_or(Value::is_null); absent("compile") diff --git a/wai/wai-quantum/src/engine/catalog/whole_tests.rs b/wai/wai-quantum/src/engine/catalog/whole_tests.rs index ef01435b8..144badab4 100644 --- a/wai/wai-quantum/src/engine/catalog/whole_tests.rs +++ b/wai/wai-quantum/src/engine/catalog/whole_tests.rs @@ -45,8 +45,8 @@ const BEFORE: &[(&str, &str, usize, &str, &str, &str, &str, &str, &str)] = &[ /// What needs standard gates gives what it gave, byte for byte: the reader's /// `read`, a compile, the QIR and jeff exports, the resource estimate, and the -/// bit-exact method asked for standard gates, which reproduces a hash made -/// before gates stood whole. +/// bit-exact method, by default and asked for standard gates, whose hash is the +/// one made before gates stood whole. #[test] fn what_takes_standard_gates_gives_what_it_gave() { for (name, src, ops, digest, state, compiled, qir, jeff, counts) in BEFORE { @@ -57,11 +57,16 @@ fn what_takes_standard_gates_gives_what_it_gave() { t += &format!("{:?} {:?} {:?}\n", o.kind, o.qubits, o.params.iter().map(|x| x.to_bits()).collect::>()); } assert_eq!(hx(t.as_bytes()), *digest, "{name}: the standard gates"); - let job = json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": ["0".repeat(p.n_qubits as usize)], "options": { "controls": "standard" } }); - let (_, out) = plan_and_run(&job, CAP).unwrap(); - assert_eq!(&out["state_hash"].as_str().unwrap()[..16], *state, "{name}: the bit-exact hash"); + for options in [json!({}), json!({ "controls": "standard" })] { + let job = json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": ["0".repeat(p.n_qubits as usize)], "options": options }); + let (_, out) = plan_and_run(&job, CAP).unwrap(); + assert_eq!(&out["state_hash"].as_str().unwrap()[..16], *state, "{name}: the bit-exact hash, options {options}"); + assert_eq!(out["gates"], json!(*ops), "{name}: {out}"); + assert!(out.get("operations").is_none(), "{name}: {out}"); + } + // The receipt's provenance counts the same gates on the state vector, held whole or not. + let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 0, "amplitudes": ["0".repeat(p.n_qubits as usize)] }), CAP).unwrap(); assert_eq!(out["gates"], json!(*ops), "{name}: {out}"); - assert!(out.get("standard_gates").is_none(), "{name}: {out}"); assert_eq!(hx(compile::compile(&p, &compile::Options::default()).unwrap().qasm.as_bytes()), *compiled, "{name}: the compile"); assert_eq!(hx(&formats::write(formats::Format::Qir, &p, None).unwrap().bytes), *qir, "{name}: QIR"); assert_eq!(hx(&formats::write(formats::Format::Jeff, &p, None).unwrap().bytes), *jeff, "{name}: jeff"); @@ -88,9 +93,10 @@ fn grover(n: usize, iterations: usize) -> String { s } -/// Two Grover iterations on 14 qubits run as 130 gates, not 131,186, on both -/// state-vector methods, and say how many they are in standard gates. The -/// marked state's amplitude is the closed form's, within each method's bound. +/// Two Grover iterations on 14 qubits run as 130 operations, not 131,186 +/// gates, on the state vector, and on the bit-exact method when the job asks +/// for it; `gates` still counts the standard gates. The marked state's +/// amplitude is the closed form's, within each method's bound. #[test] fn a_job_on_the_state_vectors_holds_the_gate_whole() { let (n, k) = (14usize, 2usize); @@ -98,19 +104,34 @@ fn a_job_on_the_state_vectors_holds_the_gate_whole() { let marked = "1".repeat(n); let theta = (2f64.powf(-(n as f64) / 2.0)).asin(); let want = ((2 * k + 1) as f64 * theta).sin(); - for (method, gates, bound) in [("exact", 130, 1e-5), ("statevector", 130, 1e-12)] { - let job = json!({ "qasm": src, "method": method, "shots": 0, "amplitudes": [marked] }); + for (method, options, bound) in [("exact", json!({ "controls": "whole" }), 1e-5), ("statevector", json!({}), 1e-12)] { + let job = json!({ "qasm": src, "method": method, "shots": 0, "amplitudes": [marked], "options": options }); let (plan, out) = plan_and_run(&job, CAP).unwrap(); - assert_eq!((plan.method.as_str(), out["gates"].as_u64()), (method, Some(gates)), "{out}"); - assert_eq!(out["standard_gates"], 131_186, "{out}"); + assert_eq!((plan.method.as_str(), out["operations"].as_u64(), out["gates"].as_u64()), (method, Some(130), Some(131_186)), "{out}"); let a = &out["amplitudes"][0]; assert!((a["re"].as_f64().unwrap().hypot(a["im"].as_f64().unwrap()) - want.abs()).abs() < bound, "{method}: {a}, want {want}"); } - // The bit-exact method's bits are the same on every host: this test holds them there. - let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": [marked] }), CAP).unwrap(); + // The bit-exact method's bits are the same on every host: this test holds + // the whole form's there. + let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": [marked], "options": { "controls": "whole" } }), CAP).unwrap(); assert_eq!(&out["state_hash"].as_str().unwrap()[..16], "454d8a59c85c788b", "{out}"); } +/// Not asked, the bit-exact method runs standard gates: its bits are the ones +/// `read` gives, as they were before a gate stood whole, and it runs no +/// operation held whole. +#[test] +fn the_bit_exact_method_keeps_its_bits_unless_asked() { + let src = grover(9, 2); + let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": ["1".repeat(9)] }), CAP).unwrap(); + let want = qasm::read(&src).unwrap().program.dyadic().unwrap().simulate().unwrap().statevector_hash(); + assert_eq!(out["state_hash"].as_str().unwrap(), want.iter().map(|b| format!("{b:02x}")).collect::(), "{out}"); + assert!(out.get("operations").is_none(), "{out}"); + let (_, whole) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": ["1".repeat(9)], "options": { "controls": "whole" } }), CAP).unwrap(); + assert_ne!(whole["state_hash"], out["state_hash"], "the whole form rounds otherwise"); + assert_eq!(whole["gates"], out["gates"], "{whole}"); +} + /// Asked for standard gates, or placed on the fabric, the job takes them all, /// and its state is the old one's to the bit on the bit-exact method. #[test] @@ -123,8 +144,9 @@ fn a_job_can_ask_for_standard_gates() { }; let whole = run(json!({ "method": "statevector" })); let standard = run(json!({ "method": "statevector", "options": { "controls": "standard" } })); - assert!(whole["gates"].as_u64().unwrap() < standard["gates"].as_u64().unwrap()); - assert_eq!(whole["standard_gates"], standard["gates"]); + assert!(whole["operations"].as_u64().unwrap() < standard["gates"].as_u64().unwrap()); + assert_eq!(whole["gates"], standard["gates"]); + assert!(standard.get("operations").is_none(), "{standard}"); let d = (whole["amplitudes"][0]["re"].as_f64().unwrap() - standard["amplitudes"][0]["re"].as_f64().unwrap()).abs(); assert!(d < 1e-12, "{d}"); let e = run(json!({ "method": "exact", "options": { "controls": "standard" } })); @@ -135,7 +157,7 @@ fn a_job_can_ask_for_standard_gates() { { let cpu = run(json!({ "method": "statevector", "fabric": "cpu" })); assert_eq!(cpu["gates"], standard["gates"], "{cpu}"); - assert!(cpu.get("standard_gates").is_none(), "{cpu}"); + assert!(cpu.get("operations").is_none(), "{cpu}"); } } @@ -147,13 +169,13 @@ fn every_other_method_takes_standard_gates() { let standard = qasm::read(src).unwrap().program.ops.len(); let bits = "011111"; let (_, sv) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "amplitudes": [bits] }), CAP).unwrap(); - assert_eq!((sv["gates"].as_u64(), sv["standard_gates"].as_u64()), (Some(8), Some(standard as u64))); + assert_eq!((sv["operations"].as_u64(), sv["gates"].as_u64()), (Some(8), Some(standard as u64))); let a = |v: &Value, k: &str| v["amplitudes"][0][k].as_f64().unwrap(); for method in ["mps", "tensor_network"] { let (p, out) = plan_and_run(&json!({ "qasm": src, "method": method, "amplitudes": [bits] }), CAP).unwrap(); assert_eq!(p.method, method); assert_eq!(out["gates"].as_u64(), Some(standard as u64), "{method}: {out}"); - assert!(out.get("standard_gates").is_none(), "{method}: {out}"); + assert!(out.get("operations").is_none(), "{method}: {out}"); assert!((a(&out, "re") - a(&sv, "re")).abs() < 1e-9 && (a(&out, "im") - a(&sv, "im")).abs() < 1e-9, "{method}: {out}, {sv}"); } let (p, out) = plan_and_run(&json!({ "qasm": src, "noise": { "depolarizing_1q": 0.0001 }, "shots": 16 }), CAP).unwrap(); @@ -162,22 +184,26 @@ fn every_other_method_takes_standard_gates() { assert_eq!((p.method.as_str(), out["gates"].as_u64()), ("pauli", Some(standard as u64)), "{out}"); // A compile writes standard gates: the job runs what it wrote. let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 4, "compile": { "basis": "standard", "level": 0 } }), CAP).unwrap(); - assert!(out.get("standard_gates").is_none() && out["compiled"].is_object(), "{out}"); + assert!(out.get("operations").is_none() && out["compiled"].is_object(), "{out}"); } -/// Past what standard gates can hold: 20 controls run whole on both state -/// vectors, and `auto` takes them there. Everything that needs standard gates -/// refuses, naming why, and a Clifford check takes one gate to say no. +/// Past what standard gates can hold: 20 controls run whole on the state +/// vector, on the bit-exact method asked to, and under `auto`. Everything that +/// needs standard gates refuses, naming why (the bit-exact method by default +/// among them), and a Clifford check takes one gate to say no. #[test] fn past_the_standard_form_only_the_state_vectors_take_it() { let (n, marked) = (21, "1".repeat(21)); let src = format!("qubit[{n}] q;\nx q;\nctrl(20) @ z {};\nctrl(20) @ x {};\n", wide(n), wide(n)); - for method in ["exact", "statevector", "auto"] { - let (p, out) = plan_and_run(&json!({ "qasm": src, "method": method, "shots": 0, "amplitudes": [marked] }), CAP).unwrap(); - assert!(runs_whole(&p.method), "{method}: {}", p.why); - assert_eq!(out["gates"], 23, "{out}"); - assert_eq!(out["standard_gates"].as_u64(), Some(qasm::read_whole(&src).unwrap().program.standard_gates() as u64), "{out}"); + for (method, options) in [("exact", json!({ "controls": "whole" })), ("statevector", json!({})), ("auto", json!({}))] { + let job = json!({ "qasm": src, "method": method, "shots": 0, "amplitudes": [marked], "options": options }); + let (p, out) = plan_and_run(&job, CAP).unwrap(); + assert!(runs_whole(&p.method, &job), "{method}: {}", p.why); + assert_eq!(out["operations"], 23, "{out}"); + assert_eq!(out["gates"].as_u64(), Some(qasm::read_whole(&src).unwrap().program.standard_gates() as u64), "{out}"); } + let e = plan(&json!({ "qasm": src, "method": "exact", "amplitudes": [marked] }), CAP).unwrap_err(); + assert!(e.contains("Q208"), "{e}"); for method in ["mps", "tensor_network", "stabilizer", "pauli"] { let e = plan(&json!({ "qasm": src, "method": method, "amplitudes": [marked], "observables": if method == "pauli" { json!(["Z0"]) } else { json!([]) } }), CAP).unwrap_err(); assert!(e.contains("J011") || e.contains("Q208") || e.contains("Clifford") || e.contains("expectation"), "{method}: {e}"); @@ -193,8 +219,8 @@ fn past_the_standard_form_only_the_state_vectors_take_it() { assert!(e.contains("Q208"), "{e}"); // lint says what a job takes. let l = crate::engine::job::lint(&src); - assert_eq!((l["ok"].as_bool(), l["gates"].as_u64()), (Some(true), Some(23)), "{l}"); - assert!(l["standard_gates"].as_u64().unwrap() > 1 << 22, "{l}"); + assert_eq!((l["ok"].as_bool(), l["operations"].as_u64()), (Some(true), Some(23)), "{l}"); + assert!(l["gates"].as_u64().unwrap() > 1 << 22, "{l}"); } /// Between measurements too: a gate in a branch runs whole, each expectation @@ -209,8 +235,8 @@ fn a_gate_in_a_program_that_measures_runs_whole() { }; let (_, whole) = plan_and_run(&job(json!({})), CAP).unwrap(); let (_, standard) = plan_and_run(&job(json!({ "options": { "controls": "standard" } })), CAP).unwrap(); - assert_eq!(whole["gates"].as_u64(), Some(8), "{whole}"); - assert_eq!(whole["standard_gates"], standard["gates"], "{whole}"); + assert_eq!(whole["operations"].as_u64(), Some(8), "{whole}"); + assert_eq!(whole["gates"], standard["gates"], "{whole}"); assert!(whole["dynamic"].is_object(), "{whole}"); for i in 0..2 { let (a, b) = (whole["expectations"][i]["value"].as_f64().unwrap(), standard["expectations"][i]["value"].as_f64().unwrap()); @@ -227,7 +253,7 @@ fn a_verdict_holds_a_whole_run_to_its_intent() { let want = json!({ "distribution": { "01111": 1.0 } }); let (_, out) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 8, "intent": want }), CAP).unwrap(); assert_eq!(out["verdict"]["holds"], true, "{out}"); - assert!(out["standard_gates"].as_u64().unwrap() > out["gates"].as_u64().unwrap()); + assert!(out["gates"].as_u64().unwrap() > out["operations"].as_u64().unwrap()); } /// A registered method, which takes the program as the reader's standard @@ -273,7 +299,7 @@ fn a_registered_method_sees_standard_gates() { let p = reg.plan(&job, CAP).unwrap(); assert!(p.why.starts_with(&format!("{} standard gates", qasm::read(&src).unwrap().program.ops.len())), "{}", p.why); let out = reg.run(&job, &p).unwrap(); - assert!(out.get("standard_gates").is_none(), "{out}"); + assert!(out.get("operations").is_none(), "{out}"); assert_eq!(out["gates"].as_u64().unwrap() as usize, qasm::read(&src).unwrap().program.ops.len()); } diff --git a/wai/wai-quantum/src/engine/job.rs b/wai/wai-quantum/src/engine/job.rs index 216a17315..23dc6a13f 100644 --- a/wai/wai-quantum/src/engine/job.rs +++ b/wai/wai-quantum/src/engine/job.rs @@ -74,9 +74,9 @@ pub fn did_of(key_hex: &str) -> Option { /// gates, bits and measurements (and its steps, when it is dynamic), or /// `{"ok": false}` with the problem, its line, and its diagnostic code, /// column and length (`qasm::diag`). The warnings and notes the reader gave -/// a program it read are under `diagnostics`, when there are any. A gate under -/// many controls is one gate, as a job on the state vectors runs it, and -/// `standard_gates` then says how many it is in standard gates. +/// a program it read are under `diagnostics`, when there are any. `gates` counts +/// standard gates; where a gate under many controls would double in them, a job +/// on the state vector runs it as one, and `operations` says how many it runs. pub fn lint(src: &str) -> Value { lint_with(src, &crate::qasm::Inputs::new()) } @@ -96,7 +96,8 @@ pub fn lint_with(src: &str, inputs: &crate::qasm::Inputs) -> Value { "dynamic_steps": p.dynamic.as_ref().map(Vec::len), }); if p.has_whole() { - v["standard_gates"] = json!(p.standard_gates().min((1u128 << 53) - 1) as u64); + v["gates"] = json!(p.standard_gates().min((1u128 << 53) - 1) as u64); + v["operations"] = json!(p.ops.len()); } if !r.diagnostics.is_empty() { v["diagnostics"] = Value::Array(r.diagnostics.iter().map(|d| d.to_json()).collect()); diff --git a/wai/wai-quantum/src/engine/registry/builtin.rs b/wai/wai-quantum/src/engine/registry/builtin.rs index d1ad8743c..bacd86f4d 100644 --- a/wai/wai-quantum/src/engine/registry/builtin.rs +++ b/wai/wai-quantum/src/engine/registry/builtin.rs @@ -101,7 +101,7 @@ impl Method for BuiltinMethod { // A method that runs gates whole takes the program as read. A tableau // needs standard gates only for a circuit that is Clifford, which the // first gate that is not settles without writing the rest. - let request = if catalog::runs_whole(self.name) || (self.name == "stabilizer" && job.clifford().is_err()) { job.as_read()? } else { job.request()? }; + let request = if catalog::runs_whole(self.name, job.json()) || (self.name == "stabilizer" && job.clifford().is_err()) { job.as_read()? } else { job.request()? }; catalog::try_method(self.name, request, job.dyadic(), job.clifford(), job.job_bytes()) } fn run(&self, job: &Job<'_>, plan: &Plan, out: &mut Value) -> Result<(), String> { diff --git a/wai/wai-quantum/src/engine/registry/mod.rs b/wai/wai-quantum/src/engine/registry/mod.rs index 9d5763b15..713da91ed 100644 --- a/wai/wai-quantum/src/engine/registry/mod.rs +++ b/wai/wai-quantum/src/engine/registry/mod.rs @@ -607,12 +607,17 @@ impl<'a> Job<'a> { self.channels.iter().filter(|c| !c.identity.is_builtin()) } - /// The program as the bit-exact simulator's circuit, or why not: a gate - /// held whole is one gate of it. + /// The program as the bit-exact simulator's circuit, or why not: in the + /// gates the method runs, standard ones unless the job asks for a gate held + /// whole (`"options": {"controls": "whole"}`), when it is one gate of it. pub fn dyadic(&self) -> &Result { - self.dyadic.get_or_init(|| match self.request { - Some(r) => r.program.dyadic(), - None => Err("no program read".into()), + self.dyadic.get_or_init(|| { + let r = if super::catalog::whole_asked(self.json) { self.as_read() } else { self.request() }; + match r { + Ok(r) => r.program.dyadic(), + Err(_) if self.request.is_none() => Err("no program read".into()), + Err(e) => Err(e), + } }) } diff --git a/wai/wai-quantum/src/engine/run.rs b/wai/wai-quantum/src/engine/run.rs index b091fc82e..b0d225d2a 100644 --- a/wai/wai-quantum/src/engine/run.rs +++ b/wai/wai-quantum/src/engine/run.rs @@ -275,7 +275,7 @@ fn run_job(reg: &Registry, request: &Value, plan: &Plan, passes: &mut Option Date: Fri, 6 Nov 2026 07:16:11 -0500 Subject: [PATCH 03/14] wai-quantum: the command line's committed tool list and docs follow the schemas, and the new code is clippy-clean - The job request's `options` says what `controls` does now: whole on the state vector by default, standard on the bit-exact method unless "whole". - docs/local-mcp.json and docs/llms-full.txt regenerated from the binary (WAI_QUANTUM_BLESS=1); the command line's tests and smoke.sh pass. - Clippy's findings in this branch's new code fixed; the crate's older findings are left as they are (clippy is not a gate on it). - The changelog says that a bit-exact result now carries its accuracy members, so its JSON and receipt hold them. Checked on Linux aarch64: the engine's tests with every feature (library and integration, 14 targets), its debug test build, every feature subset the workflows check under -D warnings, and the command line's tests and smoke checks; the library tests on x86_64 too. Co-Authored-By: Claude Opus 5.5 --- ...-11-05-many-controlled-gates-stay-whole.md | 2 +- wai/wai-quantum-cli/docs/llms-full.txt | 4 +- wai/wai-quantum-cli/docs/local-mcp.json | 458 +++++++++++++++++- wai/wai-quantum/schemas/job-request.v1.json | 2 +- .../src/engine/catalog/whole_tests.rs | 5 +- wai/wai-quantum/src/qasm/elab.rs | 2 +- wai/wai-quantum/src/qasm/whole_tests.rs | 4 +- 7 files changed, 455 insertions(+), 22 deletions(-) diff --git a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md index fd106bdf3..ac0cf3b37 100644 --- a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md +++ b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md @@ -1,6 +1,6 @@ ### wai-quantum: a gate under many controls stays one operation on the state vector, the bit-exact method says what its lowering did, and the error-correction reader takes `C_XYZ`, `E` and `PAULI_CHANNEL_1` -**What a result gives.** A job on `statevector` whose program holds a gate under controls that used to be written through a phase polynomial (`x`, `y`, `z` or `h` under three or more controls; `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` or `sxdg` under two or more) runs that gate as one operation; its amplitudes move by double-precision rounding, within the method's bound, and `"options": {"controls": "standard"}` gives the old bits. A job on `exact` gives the bits it gave, by default: the bit-exact method's bits are the rounding of each gate it applies, so it runs the standard gates unless the job asks for `"options": {"controls": "whole"}`, which holds such a gate whole under its controls, nearer the ideal state by no more than the extension's published bound and with another `state_hash`. Every other method and request gives what it gave. +**What a result gives.** A job on `statevector` whose program holds a gate under controls that used to be written through a phase polynomial (`x`, `y`, `z` or `h` under three or more controls; `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` or `sxdg` under two or more) runs that gate as one operation; its amplitudes move by double-precision rounding, within the method's bound, and `"options": {"controls": "standard"}` gives the old bits. A job on `exact` gives the bits it gave, by default: the bit-exact method's bits are the rounding of each gate it applies, so it runs the standard gates unless the job asks for `"options": {"controls": "whole"}`, which holds such a gate whole under its controls, nearer the ideal state by no more than the extension's published bound and with another `state_hash`. A result on `exact` also says, in `accuracy`, the global phase its lowering drops and any angle it ran as no phase or moved (below), so a job whose program holds `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` or `u`, or such an angle, gives the same bits and hash in a result whose JSON, and so whose receipt, holds those members too. Every other method and request gives what it gave. - **The reader.** `qasm::read_whole` keeps a gate whose standard gates would double as one operation (`Op::is_whole`), under as many as 255 controls. `Program::lowered` writes it in standard gates: exactly what `qasm::read` gives of the same text, its steps, timing and records moved with it, one lowering behind both. `read` and `parse` give standard gates as they did, and refuse past 16 controls and past `MAX_OPS` as they did. - **The state vector.** `StateVector::run_ops` applies such a gate as one (`Controlled`), visiting only the `2^(n − c)` amplitudes its controls leave on; a run without one is `run`, to the bit. Two Grover iterations on 14 qubits run as 130 operations, not 131,186 gates. Asked for, the bit-exact simulator holds the gate under its controls and walks only those indices too; a gate under two or more controls in standard gates (a Toffoli) takes the same walk, to the bit of the scan it replaces. diff --git a/wai/wai-quantum-cli/docs/llms-full.txt b/wai/wai-quantum-cli/docs/llms-full.txt index 4ab3f937f..2d19b415c 100644 --- a/wai/wai-quantum-cli/docs/llms-full.txt +++ b/wai/wai-quantum-cli/docs/llms-full.txt @@ -1067,7 +1067,7 @@ Each construct below is supported (read as the language defines it), lowered (re | Construct | Status | Codes | |---|---|---| -| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls | Q201, Q207, Q208 | +| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` or `exact` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`) | Q201, Q207, Q208 | | `inv @` on any gate | lowered exactly: each gate's inverse, in reverse order | Q202 | | `pow(k) @`, `k` a whole number | lowered exactly: angles scaled or the gate repeated; negative `k` repeats the inverse | Q203 | | `pow(r) @`, `r` fractional | lowered where an exact principal root exists (`pow(1/2) @ x` is `sx`; rotations by less than 2π; phases; controlled forms); refused otherwise (`u`, `cu`, user gates) | Q204, Q205 | @@ -1234,7 +1234,7 @@ Every code: | `Q205` | refused | `pow(r) @` with a fractional `r` where no exact gate exists here: a user gate, `u`, `cu`, or a rotation by 2π or more. | | `Q206` | lowered | `gphase(θ)`: a global phase, which no measurement sees, dropped; under controls it is a phase on the controls. | | `Q207` | refused | A control modifier that adds no control: `ctrl(0) @`. | -| `Q208` | refused | Modifiers that add more controls than the reader lowers (16). | +| `Q208` | refused | Modifiers that add more controls than the reader lowers (16 written in standard gates, 255 on a gate a method holds whole). | | `Q209` | refused | Gate definitions or subroutine calls nested deeper than 32. | | `Q210` | refused | A program that expands to more gates than the reader holds (2 000 000). | | `Q211` | refused | A modifier on something that is not a gate. | diff --git a/wai/wai-quantum-cli/docs/local-mcp.json b/wai/wai-quantum-cli/docs/local-mcp.json index c2fa94a3e..9aebf6211 100644 --- a/wai/wai-quantum-cli/docs/local-mcp.json +++ b/wai/wai-quantum-cli/docs/local-mcp.json @@ -727,7 +727,7 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." }, "compile": { "type": "object", @@ -1442,7 +1442,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -1466,6 +1472,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -4357,7 +4428,7 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." }, "compile": { "type": "object", @@ -5070,7 +5141,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -5094,6 +5171,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -9914,7 +10056,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates in standard gates, at most 2^53 - 1." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When a gate under many controls would double in standard gates: the operations a job on the state vector runs, each such gate one." }, "bits": { "type": "integer", @@ -30531,7 +30679,7 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." }, "compile": { "type": "object", @@ -31246,7 +31394,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -31270,6 +31424,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -34161,7 +34380,7 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." }, "compile": { "type": "object", @@ -34874,7 +35093,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -34898,6 +35123,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -50037,7 +50327,7 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." }, "compile": { "type": "object", @@ -50752,7 +51042,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -50776,6 +51072,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -53667,7 +54028,7 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." }, "compile": { "type": "object", @@ -54380,7 +54741,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -54404,6 +54771,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, diff --git a/wai/wai-quantum/schemas/job-request.v1.json b/wai/wai-quantum/schemas/job-request.v1.json index 8692009f0..774f108ab 100644 --- a/wai/wai-quantum/schemas/job-request.v1.json +++ b/wai/wai-quantum/schemas/job-request.v1.json @@ -137,7 +137,7 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: \"standard\" runs a gate under many controls in standard gates on exact and statevector too, which reproduces a result made that way, bit for bit." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." }, "compile": { "$ref": "compile-result.v1.json#/$defs/options" diff --git a/wai/wai-quantum/src/engine/catalog/whole_tests.rs b/wai/wai-quantum/src/engine/catalog/whole_tests.rs index 144badab4..9d1278f65 100644 --- a/wai/wai-quantum/src/engine/catalog/whole_tests.rs +++ b/wai/wai-quantum/src/engine/catalog/whole_tests.rs @@ -16,6 +16,7 @@ fn hx(b: &[u8]) -> String { /// standard gates and their digest, the bit-exact state hash, the compile's /// output, the QIR and jeff exports and the resource estimate's counts. #[rustfmt::skip] +#[allow(clippy::type_complexity)] const BEFORE: &[(&str, &str, usize, &str, &str, &str, &str, &str, &str)] = &[ ("c3z", "qubit[5] q;\nh q;\nctrl(3) @ z q[0], q[1], q[2], q[3];\n", 34, "29718f9ab500304a", "181acaa4aad01230", "f23087907c80c69d", "c8c5157978bce0e3", "5483575a012810bb", "747ea02fde8aeaca"), ("c3x", "qubit[5] q;\nh q;\nctrl(3) @ x q[0], q[1], q[2], q[3];\n", 36, "7a786cc271f2501b", "8a504be7fc0299e8", "19be6f5bfc085d84", "0c304a3bc21ab20d", "c35804da5d616eb1", "d7c18a0142c206a0"), @@ -321,7 +322,7 @@ fn a_bit_exact_result_states_its_global_phase() { let (_, sv) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 0, "amplitudes": bits }), CAP).unwrap(); let stated = exact["accuracy"]["global_phase"]["radians"].as_f64(); match phase { - Some(p) if p == 0.0 => assert!(exact["accuracy"].get("global_phase").is_none(), "{exact}"), + Some(0.0) => assert!(exact["accuracy"].get("global_phase").is_none(), "{exact}"), Some(p) => assert!((stated.unwrap() - p).abs() < 1e-14, "{exact}"), None => assert!(stated.is_some(), "{exact}"), } @@ -396,7 +397,7 @@ fn a_named_matrix_product_job_is_held_to_the_bond_it_reaches() { let e = try_method("mps", &r, &Err("".into()), &Err("".into()), CAP).unwrap_err(); assert!(e.contains("name method mps"), "{e}"); // More than a job may take at the smallest bond there is: refused now. - let far = format!("qubit[4096] q;\nfor uint i in [0:799999] {{ cx q[0], q[4095]; }}\n"); + let far = "qubit[4096] q;\nfor uint i in [0:799999] { cx q[0], q[4095]; }\n"; let e = plan(&json!({ "qasm": far, "method": "mps", "shots": 1 }), CAP).unwrap_err(); assert!(e.contains("[J011]") && e.contains("more work than one job may take"), "{e}"); } diff --git a/wai/wai-quantum/src/qasm/elab.rs b/wai/wai-quantum/src/qasm/elab.rs index 0c098d90f..3d077eca1 100644 --- a/wai/wai-quantum/src/qasm/elab.rs +++ b/wai/wai-quantum/src/qasm/elab.rs @@ -267,7 +267,7 @@ pub(crate) fn elaborate_with(src: &str, toks: &[Token], stmts: &[Stmt], version: elaborate_form(src, toks, stmts, version, inputs, tan, false) } -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::type_complexity)] fn elaborate_form(src: &str, toks: &[Token], stmts: &[Stmt], version: Version, inputs: &Inputs, tan: Option, whole: bool) -> R<(Program, Vec, Vec, Vec)> { let mut e = Elab { src, diff --git a/wai/wai-quantum/src/qasm/whole_tests.rs b/wai/wai-quantum/src/qasm/whole_tests.rs index fd7209707..625243ef6 100644 --- a/wai/wai-quantum/src/qasm/whole_tests.rs +++ b/wai/wai-quantum/src/qasm/whole_tests.rs @@ -154,7 +154,7 @@ fn past_what_standard_gates_hold_a_gate_still_reads_whole() { let d = p.lowered().unwrap_err(); assert!(d.code == diag::TOO_MANY_GATES, "{d}"); assert_eq!(read(&many).unwrap_err().code, diag::TOO_MANY_GATES); - let d = read_whole(&format!("qubit[300] q;\nctrl(256) @ z q[0:256];\n")).unwrap_err(); + let d = read_whole("qubit[300] q;\nctrl(256) @ z q[0:256];\n").unwrap_err(); assert_eq!(d.code, diag::TOO_MANY_CONTROLS); } @@ -195,7 +195,7 @@ fn ideal(p: &Program) -> Vec<(f64, f64)> { let mut sv = crate::quantum_sv::StateVector::zero(p.n_qubits).unwrap(); sv.run_ops(&p.sv_ops(), 1).unwrap(); let n = p.n_qubits; - (0..1usize << n).map(|x| (x.reverse_bits() >> (usize::BITS - n)).min(usize::MAX)).map(|r| (sv.re[r], sv.im[r])).collect() + (0..1usize << n).map(|x| x.reverse_bits() >> (usize::BITS - n)).map(|r| (sv.re[r], sv.im[r])).collect() } /// The Euclidean distance of a fixed-point state from an ideal one, the phase -- 2.54.0 (Apple Git-157) From da3599b322fcb315ee584c47a556c8ad16caaef6 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Fri, 6 Nov 2026 07:18:43 -0500 Subject: [PATCH 04/14] wai-quantum: before_after.py compares a host by what it is, not its load, and shows the operations each build ran Co-Authored-By: Claude Opus 5.5 --- wai/quantum-cross-simulator/tools/before_after.py | 6 ++++-- wai/quantum-cross-simulator/tools/report.py | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/wai/quantum-cross-simulator/tools/before_after.py b/wai/quantum-cross-simulator/tools/before_after.py index 2b3beacb1..c4aff74c2 100644 --- a/wai/quantum-cross-simulator/tools/before_after.py +++ b/wai/quantum-cross-simulator/tools/before_after.py @@ -12,7 +12,9 @@ import sys def main(): before, after = (json.load(open(p)) for p in sys.argv[1:3]) - if before["host"] != after["host"] or before["repeat"] != after["repeat"]: + # The host's identity, not its load at the moment each run began. + same = lambda h: {k: v for k, v in h.items() if k != "load_average"} + if same(before["host"]) != same(after["host"]) or before["repeat"] != after["repeat"]: sys.exit("before_after.py: two hosts, or two repeat counts: these timings do not compare") index = {(r["case"], r["engine"], r["threads"]): r for r in before["rows"]} rows = [] @@ -20,7 +22,7 @@ def main(): was = index.get((r["case"], r["engine"], r["threads"])) if was is not None: rows.append({"case": r["case"], "what": r["what"], "engine": r["engine"], "threads": r["threads"], "before": {k: v for k, v in was.items() if k not in ("case", "what", "engine", "threads")}, "after": {k: v for k, v in r.items() if k not in ("case", "what", "engine", "threads")}}) - out = {"about": "One host's timings of two builds of the engine under test, one straight after the other: tools/perf.py run on each, tools/before_after.py putting them side by side.", "host": after["host"], "versions": after["versions"], "before": before["engine_under_test"], "after": after["engine_under_test"], "repeat": after["repeat"], "rows": rows} + out = {"about": "One host's timings of two builds of the engine under test, one straight after the other: tools/perf.py run on each, tools/before_after.py putting them side by side.", "timers": after.get("timers"), "host": after["host"], "versions": after["versions"], "before": before["engine_under_test"], "after": after["engine_under_test"], "repeat": after["repeat"], "rows": rows} with open(sys.argv[3], "w") as f: json.dump(out, f, indent=1) f.write("\n") diff --git a/wai/quantum-cross-simulator/tools/report.py b/wai/quantum-cross-simulator/tools/report.py index cde66d334..cf5c75be8 100644 --- a/wai/quantum-cross-simulator/tools/report.py +++ b/wai/quantum-cross-simulator/tools/report.py @@ -166,13 +166,13 @@ def results_section(): p = json.load(open(path)) out.append("### `%s`" % os.path.basename(path)) out.append("") - out.append("Host: %s. The same driver and circuits, with the engine before and after a gate under many controls stood whole: the engine's own call, the median of %d runs (the minimum in brackets), one build straight after the other." % (host_line(p), p["repeat"])) + out.append("Host: %s. The same harness and circuits, with the engine under test built before and after a gate under many controls stood whole on its state vector, one build straight after the other: each figure is the engine's own call, the median of %d runs (the minimum in brackets), and ops are the operations it ran." % (host_line(p), p["repeat"])) out.append("") - out.append("| case | engine | threads | before: seconds, median (min) | after: seconds, median (min) | load average before → after |") - out.append("|---|---|---|---|---|---|") + out.append("| case | engine | threads | before: ops | before: seconds, median (min) | after: ops | after: seconds, median (min) | load average before → after |") + out.append("|---|---|---|---|---|---|---|---|") for row in p["rows"]: cell = lambda r: ("not run: %s" % r["not_run"][:90]) if r.get("not_run") else "%s (%s)" % (fmt_seconds(r["seconds_median"]), fmt_seconds(r["seconds_min"])) - out.append("| %s | `%s` | %s | %s | %s | %s → %s |" % (row["case"], row["engine"], row["threads"], cell(row["before"]), cell(row["after"]), row["before"]["load_before"][0], row["after"]["load_before"][0])) + out.append("| %s | `%s` | %s | %s | %s | %s | %s | %s → %s |" % (row["case"], row["engine"], row["threads"], row["before"].get("ops") or "", cell(row["before"]), row["after"].get("ops") or "", cell(row["after"]), row["before"]["load_before"][0], row["after"]["load_before"][0])) out.append("") return "\n".join(out).rstrip() + "\n" -- 2.54.0 (Apple Git-157) From d4282f6800c8c3d7d5eb4370bfede44b0f35d5fc Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Fri, 6 Nov 2026 07:45:40 -0500 Subject: [PATCH 05/14] wai-quantum: the feature matrix says the bit-exact method holds a gate whole only when asked Co-Authored-By: Claude Opus 5.5 --- wai/wai-quantum/docs/qasm-feature-matrix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wai/wai-quantum/docs/qasm-feature-matrix.md b/wai/wai-quantum/docs/qasm-feature-matrix.md index 3e02357cf..f96e26e91 100644 --- a/wai/wai-quantum/docs/qasm-feature-matrix.md +++ b/wai/wai-quantum/docs/qasm-feature-matrix.md @@ -109,7 +109,7 @@ and in the browser build. | Construct | Status | Codes | |---|---|---| -| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` or `exact` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`) | Q201, Q207, Q208 | +| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`); `exact` does so only when asked (`"options": {"controls": "whole"}`), since its bits are those of the gates it applies | Q201, Q207, Q208 | | `inv @` on any gate | lowered exactly: each gate's inverse, in reverse order | Q202 | | `pow(k) @`, `k` a whole number | lowered exactly: angles scaled or the gate repeated; negative `k` repeats the inverse | Q203 | | `pow(r) @`, `r` fractional | lowered where an exact principal root exists (`pow(1/2) @ x` is `sx`; rotations by less than 2π; phases; controlled forms); refused otherwise (`u`, `cu`, user gates) | Q204, Q205 | -- 2.54.0 (Apple Git-157) From 6f8f5d2b1e8bd7598a0e4b2397d23c5c49f710e0 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Fri, 6 Nov 2026 13:51:21 -0500 Subject: [PATCH 06/14] wai-quantum: tests for the review of the reader-scaling branch, before its fixes Each fails on c16cb2086: a whole gate too large for standard gates hangs the Clifford check; a tiny phase under many controls reads as Clifford; the mps meter charges no move of the center, and holds the budget only per gate; Pauli channels with exact independent rates above 1/2 are refused; the carrier's index is accepted in text; C_XYZ takes arguments. Co-Authored-By: Claude Opus 5.5 --- .../src/engine/catalog/whole_tests.rs | 47 ++++++++++++++++ wai/wai-quantum/src/quantum_frame.rs | 45 +++++++++++++++ wai/wai-quantum/src/quantum_mpsim.rs | 55 +++++++++++++++++++ 3 files changed, 147 insertions(+) diff --git a/wai/wai-quantum/src/engine/catalog/whole_tests.rs b/wai/wai-quantum/src/engine/catalog/whole_tests.rs index 9d1278f65..79a5e0466 100644 --- a/wai/wai-quantum/src/engine/catalog/whole_tests.rs +++ b/wai/wai-quantum/src/engine/catalog/whole_tests.rs @@ -401,3 +401,50 @@ fn a_named_matrix_product_job_is_held_to_the_bond_it_reaches() { let e = plan(&json!({ "qasm": far, "method": "mps", "shots": 1 }), CAP).unwrap_err(); assert!(e.contains("[J011]") && e.contains("more work than one job may take"), "{e}"); } + +/// A gate whose standard gates would pass what a program may hold is refused +/// before any is written, wherever they would be: a few hundred bytes of text +/// once asked the Clifford check for 2^42 gates, and the planner held a job's +/// thread while its memory grew without limit. `p(0)` under 24 controls stands +/// for 2^25 gates, and twenty of them under 16 for 2^21 more than a program +/// holds; each such check answers at once, and a method that does not read the +/// Clifford or bit-exact circuit never writes it. +#[test] +fn a_gate_too_large_for_standard_gates_is_refused_before_they_are_written() { + let grover = |n: usize| format!("qubit[{n}] q;\nh q;\nctrl({}) @ z {};\n", n - 1, wide(n)); + let cases = [ + format!("qubit[42] q;\nctrl(41) @ z {};\n", wide(42)), + format!("qubit[42] q;\nctrl(41) @ x {};\n", wide(42)), + format!("qubit[40] q;\nctrl(39) @ t {};\n", wide(40)), + grover(42), + format!("qubit[25] q;\nctrl(24) @ p(0) {};\n", wide(25)), + format!("qubit[17] q;\nfor uint i in [0:19] {{ ctrl(16) @ p(0) {}; }}\n", wide(17)), + ]; + for src in &cases { + let t = std::time::Instant::now(); + let p = qasm::read_whole(src).unwrap().program; + let e = p.clifford().unwrap_err(); + assert!(e.contains("Q208") || e.contains("Q210"), "{src}: {e}"); + for method in ["statevector", "stabilizer", "auto"] { + let _ = plan(&json!({ "qasm": src, "method": method, "shots": 16 }), CAP); + } + let _ = plan(&json!({ "qasm": src, "method": "statevector", "shots": 16, "dry_run": true }), CAP); + assert!(t.elapsed() < std::time::Duration::from_secs(10), "{src}: {:?}", t.elapsed()); + } +} + +/// The whole gate's Clifford check reads the phases its standard gates take +/// exactly: θ/2^(m−1) under m qubits is no quarter turn unless θ makes it one, +/// however small, so `p(1e-7)` under 16 controls is not taken for the +/// identity, while `p(0)` under them is the identity, and `rz(2π)` under two is +/// a controlled Z on them. +#[test] +fn a_tiny_phase_under_many_controls_is_not_read_as_clifford() { + let q = wide(17); + let not = qasm::read_whole(&format!("qubit[17] q;\nctrl(16) @ p(1e-7) {q};\n")).unwrap().program; + assert!(not.clifford().is_err(), "a phase of 1e-7 under 16 controls taken for Clifford"); + let id = qasm::read_whole(&format!("qubit[17] q;\nctrl(16) @ p(0) {q};\n")).unwrap().program; + assert!(id.clifford().is_ok()); + let cz = qasm::read_whole("qubit[3] q;\nctrl(2) @ rz(2 * pi) q[0], q[1], q[2];\n").unwrap().program; + assert!(cz.clifford().is_ok()); +} diff --git a/wai/wai-quantum/src/quantum_frame.rs b/wai/wai-quantum/src/quantum_frame.rs index b5af8d437..7baf6990c 100644 --- a/wai/wai-quantum/src/quantum_frame.rs +++ b/wai/wai-quantum/src/quantum_frame.rs @@ -1549,6 +1549,51 @@ mod tests { [x, z, y, 0.0] } + /// Every channel whose exclusive law independent flips can give is taken: + /// a rate above 1/2 among them, or a parity of zero, as in (0.25, 0.25, + /// 0.25), the depolarizing channel DEPOLARIZE1(0.75) also is. Its three + /// parities are the channel's, exactly. + #[test] + fn a_pauli_channel_with_independent_rates_above_one_half_is_taken() { + for (px, py, pz) in [(0.6, 0.3, 0.05), (0.7, 0.1, 0.1), (0.01, 0.01, 0.9), (0.25, 0.25, 0.25), (0.5, 0.5, 0.0), (0.1, 0.1, 0.4)] { + let [qx, qy, qz] = pauli_channel_rates(px, py, pz).unwrap_or_else(|| panic!("({px}, {py}, {pz}) refused")); + for q in [qx, qy, qz] { + assert!((0.0..=1.0).contains(&q), "({px}, {py}, {pz}): rate {q}"); + } + let f = |q: f64| 1.0 - 2.0 * q; + for (got, want) in [(f(qx) * f(qy), 1.0 - 2.0 * (px + py)), (f(qy) * f(qz), 1.0 - 2.0 * (py + pz)), (f(qx) * f(qz), 1.0 - 2.0 * (px + pz))] { + assert!((got - want).abs() < 1e-14, "({px}, {py}, {pz}): {got} against {want}"); + } + assert!(parse(&format!("R 0\nPAULI_CHANNEL_1({px}, {py}, {pz}) 0\nM 0\nDETECTOR rec[-1]\n")).is_ok()); + } + } + + /// The qubit a correlated error is carried on is no qubit the text may + /// name: noise on it would reach the error's targets, or be reset away. + #[test] + fn the_carrier_s_index_is_refused_in_text() { + for text in [ + "R 0\nX_ERROR(0.1) 4294967295\nM 0\nDETECTOR rec[-1]\n", + "R 1\nX_ERROR(0.1) 4294967295\nE(0.2) X1\nM 1\nDETECTOR rec[-1]\n", + "R 0 1\nX_ERROR(0.3) 4294967295\nE(0.01) X1\nCX 4294967295 0\nM 0\nDETECTOR rec[-1]\n", + "R 0\nE(0.1) X4294967295\nM 0\nDETECTOR rec[-1]\n", + ] { + let e = parse(text).map(|c| c.qubits).unwrap_err(); + assert!(e.to_string().contains("4294967295"), "{text}: {e}"); + } + } + + /// `C_XYZ` and `C_ZYX` take no arguments, and are refused with one, as the + /// reference tool refuses them. + #[test] + fn the_cycling_gates_take_no_arguments() { + for text in ["R 0\nC_XYZ(0.1) 0\nM 0\n", "R 0\nC_ZYX(0.5, 7) 0\nM 0\n"] { + let e = parse(text).map(|c| c.qubits).unwrap_err(); + assert!(e.to_string().starts_with("line 2:"), "{text}: {e}"); + } + assert!(parse("R 0\nC_XYZ 0\nC_ZYX 0\nM 0\n").is_ok()); + } + /// The rates of independent flips give the exclusive channel's law, to the /// rounding: its three parities, exactly. A depolarizing channel is the /// case of equal probabilities, and a channel with no such rates has none. diff --git a/wai/wai-quantum/src/quantum_mpsim.rs b/wai/wai-quantum/src/quantum_mpsim.rs index 42648abe6..cb90eb20d 100644 --- a/wai/wai-quantum/src/quantum_mpsim.rs +++ b/wai/wai-quantum/src/quantum_mpsim.rs @@ -668,6 +668,61 @@ fn splitmix(s: &mut u64) -> u64 { mod tests { use super::*; + /// Rotations and a brickwork of cx on `n` qubits, `layers` deep: enough to + /// fill the chain to the bond its cfg allows in the middle. + fn saturating(n: u32, layers: usize) -> Vec { + let mut gates = Vec::new(); + for layer in 0..layers { + for q in 0..n { + gates.push(Gate::rx(q, 0.3 + 0.1 * q as f64 + 0.07 * layer as f64)); + gates.push(Gate::ry(q, 0.5 + 0.03 * q as f64)); + } + for q in (layer as u32 % 2..n - 1).step_by(2) { + gates.push(Gate::cx(q, q + 1)); + } + } + gates + } + + /// Moving the orthogonality center across a full chain is QR at the bonds + /// it holds, and the meter charges it: a gate at each end of a saturated + /// chain moves the center across it twice. Charged only at the ends' own + /// bonds (at most 4 there), the pair cost 1024 units and took the time of + /// ~2(n − 3) moves at the middle's bond. + #[test] + fn the_meter_charges_each_move_of_the_center() { + let n = 24; + let cfg = MpsConfig { max_bond: 32, cutoff: 1e-12 }; + let mut c = Chain::run(n, &saturating(n, 12), cfg).unwrap(); + assert!(c.report().max_bond_used >= 16, "{:?}", c.report()); + let before = c.work(); + c.apply(&Gate::cx(0, 1)).unwrap(); + c.apply(&Gate::cx(n - 2, n - 1)).unwrap(); + let hop = c.work() - before; + assert!(hop > 20 * 16u64.pow(3), "{hop} units for two crossings of a chain at bond 16 or more"); + } + + /// The budget is held at each two-site update, not after a whole gate: a + /// gate that crosses the chain stops at the update that passes it. + #[test] + fn a_far_gate_stops_at_the_update_that_passes_the_budget() { + let n = 24u32; + let chi = 32u64; + let cfg = MpsConfig { max_bond: chi as usize, cutoff: 1e-12 }; + let mut gates = saturating(n, 12); + let base = Chain::run(n, &gates, cfg).unwrap().work(); + gates.push(Gate::cx(0, n - 1)); + let budget = base + 1; + match Chain::run_within(n, &gates, cfg, budget) { + Err(MpsRunError::OutOfWork { work, .. }) => { + // One update, and the moves of the center before it, at the bond. + let one = (2 * chi).pow(3) + n as u64 * 4 * chi.pow(3); + assert!(work - budget <= one, "passed the budget by {} units, more than one update's {one}", work - budget); + } + other => panic!("{:?}", other.map(|c| c.report())), + } + } + /// The meter counts the bonds a run holds and changes no number of it: a /// run that finishes is the run without a meter; one that passes its /// budget stops at the gate that passed it. -- 2.54.0 (Apple Git-157) From baff4c2a9bc62fb752c74dd2054b6fe070543122 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Fri, 6 Nov 2026 14:33:41 -0500 Subject: [PATCH 07/14] wai-quantum: the review's fixes on the reader-scaling branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The Clifford check of a program holding a gate whole counts its standard gates first (Program::standard_within, the count `lowered` already used) and refuses past 16 controls (Q208) and past MAX_OPS (Q210) before writing any. `ctrl(41) @ z` on 42 qubits, `ctrl(39) @ t`, a Grover iteration on 42 qubits, `ctrl(24) @ p(0)` and a loop of `ctrl(16) @ p(0)` hung the planner (each method, `auto` and a dry run) with memory growing; they are refused at once. - A method's plan makes only the circuit it reads: the bit-exact circuit for `exact`, the Clifford gates for `stabilizer`. - The whole gate's standard gates are read exactly in that check: a phase under many controls smaller than the reader's tolerance (`ctrl(16) @ p(1e-7)`) is not taken for none. - The mps meter counts each move of the orthogonality center and each one-qubit gate, and holds the budget at each two-site update, inside a gate that crosses the chain. The plan walks the same steps at the bond asked for (WorkBound, over Program::local_steps, the walk local_matrices writes), so it still bounds the meter. - PAULI_CHANNEL_1 takes every channel independent flips can give, rates above 1/2 and parities of zero among them. - The frame reader refuses qubit 4294967295, the carrier's index, and a correlated error whose carrier has no index left (4294967294 named), at their lines; C_XYZ and C_ZYX refuse arguments. - The pinned mps job's digest moves with its plan's work, which now counts its one-qubit gates (975d7a6a… before); the CLI's llms-full.txt is regenerated (its feature table already said `exact` holds a gate whole only when asked). Co-Authored-By: Claude Opus 5.5 --- ...-11-05-many-controlled-gates-stay-whole.md | 6 +- wai/wai-quantum-cli/docs/llms-full.txt | 2 +- wai/wai-quantum/src/engine/catalog.rs | 41 ++++-- wai/wai-quantum/src/engine/job.rs | 4 +- .../src/engine/registry/builtin.rs | 8 +- wai/wai-quantum/src/qasm.rs | 97 +++++++++---- wai/wai-quantum/src/quantum_frame.rs | 83 +++++++++--- wai/wai-quantum/src/quantum_mpsim.rs | 127 +++++++++++++++--- 8 files changed, 286 insertions(+), 82 deletions(-) diff --git a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md index ac0cf3b37..c808cf32d 100644 --- a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md +++ b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md @@ -2,11 +2,11 @@ **What a result gives.** A job on `statevector` whose program holds a gate under controls that used to be written through a phase polynomial (`x`, `y`, `z` or `h` under three or more controls; `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` or `sxdg` under two or more) runs that gate as one operation; its amplitudes move by double-precision rounding, within the method's bound, and `"options": {"controls": "standard"}` gives the old bits. A job on `exact` gives the bits it gave, by default: the bit-exact method's bits are the rounding of each gate it applies, so it runs the standard gates unless the job asks for `"options": {"controls": "whole"}`, which holds such a gate whole under its controls, nearer the ideal state by no more than the extension's published bound and with another `state_hash`. A result on `exact` also says, in `accuracy`, the global phase its lowering drops and any angle it ran as no phase or moved (below), so a job whose program holds `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` or `u`, or such an angle, gives the same bits and hash in a result whose JSON, and so whose receipt, holds those members too. Every other method and request gives what it gave. -- **The reader.** `qasm::read_whole` keeps a gate whose standard gates would double as one operation (`Op::is_whole`), under as many as 255 controls. `Program::lowered` writes it in standard gates: exactly what `qasm::read` gives of the same text, its steps, timing and records moved with it, one lowering behind both. `read` and `parse` give standard gates as they did, and refuse past 16 controls and past `MAX_OPS` as they did. +- **The reader.** `qasm::read_whole` keeps a gate whose standard gates would double as one operation (`Op::is_whole`), under as many as 255 controls. `Program::lowered` writes it in standard gates: exactly what `qasm::read` gives of the same text, its steps, timing and records moved with it, one lowering behind both. `read` and `parse` give standard gates as they did, and refuse past 16 controls and past `MAX_OPS` as they did. The Clifford check of a program holding a gate whole counts its standard gates first and refuses what `read` refuses, with `Q208` or `Q210`, before writing any; it reads those gates' phases exactly, so a phase under many controls too small for the reader's tolerance (`ctrl(16) @ p(1e-7)`) is not taken for none. A method's plan makes only the circuit it reads: the bit-exact circuit for `exact`, the Clifford gates for `stabilizer`. - **The state vector.** `StateVector::run_ops` applies such a gate as one (`Controlled`), visiting only the `2^(n − c)` amplitudes its controls leave on; a run without one is `run`, to the bit. Two Grover iterations on 14 qubits run as 130 operations, not 131,186 gates. Asked for, the bit-exact simulator holds the gate under its controls and walks only those indices too; a gate under two or more controls in standard gates (a Toffoli) takes the same walk, to the bit of the scan it replaces. - **What a job counts.** `gates` counts standard gates however the method ran them, as it always has, so a receipt's provenance carries the count it carried; `operations`, a new optional member of a result and of `lint_qasm`, says what a method holding gates whole ran. A job with `compile`, `noise`, `mitigate`, `target`, `provider` or a named `fabric` place runs standard gates as it did, as do the other methods, a registered method among them. Methods that need standard gates refuse what those cannot hold with `Q208` or `Q210`, and `auto` passes over them. - **What depended on the expansion** did not change: the reader's standard gates, the bit-exact method's hash, a compile, the QIR and jeff exports and the resource estimate's counts, each checked against this engine's output before the change, and the expected hashes of `quantum-conformance/`. - **The bit-exact method says what its lowering did** (`accuracy`, each only when there is something to say). `global_phase`: `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `u` become phase gates, so OpenQASM's state is `e^(i·radians)` times the amplitudes given; the phase is exact, in 2^33rds of a turn, whole turns counted. `below_table`: an angle of `2π/2^47` or less ran as no phase, as the table's arithmetic has it, and now says so here and in the plan's `why`. `moved_angles`: an angle within the reader's tolerance of a dyadic one, by more than a double's rounding of it. -- **The matrix-product job.** A job that names `mps` is no longer refused on an estimate at the bond it asks for: it runs under a meter of the bonds it holds (`Chain::run_within`, `Chain::work`), which changes no number, and stops with `J011`, saying where, if those pass one job's work. The 30-qubit QFT at `max_bond` 256 runs, and reaches far less. A job with `auto` is held to the estimate as it was, and told what naming the method does. -- **The error-correction text.** `C_XYZ` and `C_ZYX`; `E` (or `CORRELATED_ERROR`), a flip on a qubit of its own handed to its Pauli targets, so a circuit with one holds one qubit more than its text names; and `PAULI_CHANNEL_1`, as the independent flips with its law. A channel with no such flips (`PAULI_CHANNEL_1(0.1, 0.1, 0)`) is refused with its line. +- **The matrix-product job.** A job that names `mps` is no longer refused on an estimate at the bond it asks for: it runs under a meter of the bonds it holds (`Chain::run_within`, `Chain::work`), which changes no number, and stops with `J011`, saying where, if those pass one job's work. The meter counts each two-site update, each move of the orthogonality center and each one-qubit gate, and holds the budget at each update, inside a gate that crosses the chain too. The 30-qubit QFT at `max_bond` 256 runs, and reaches far less. A job with `auto` is held to the estimate, and told what naming the method does. The estimate now walks the same steps at the bond asked for (`WorkBound`), so it bounds the meter: a plan's `work` for `mps` is larger than before where gates move the center far, and `auto` passes over `mps` for a few circuits it took before. +- **The error-correction text.** `C_XYZ` and `C_ZYX`; `E` (or `CORRELATED_ERROR`), a flip on a qubit of its own handed to its Pauli targets, so a circuit with one holds one qubit more than its text names; and `PAULI_CHANNEL_1`, as the independent flips with its law, a rate above 1/2 among them where the law needs one (`(0.6, 0.3, 0.05)`). A channel with no such flips (`PAULI_CHANNEL_1(0.1, 0.1, 0)`) is refused with its line. `C_XYZ` and `C_ZYX` take no arguments and refuse one. A text may not name qubit 4294967295, the index the carrier is read under, nor leave a correlated error no index for its carrier (qubit 4294967294 named); both are refused with their line. - **The corpus** ([quantum-cross-simulator/](quantum-cross-simulator/README.md)): rerun, with the bit-exact method's amplitudes held to OpenQASM's with the phase its result states, and before-and-after timings on one host. diff --git a/wai/wai-quantum-cli/docs/llms-full.txt b/wai/wai-quantum-cli/docs/llms-full.txt index 2d19b415c..08effd773 100644 --- a/wai/wai-quantum-cli/docs/llms-full.txt +++ b/wai/wai-quantum-cli/docs/llms-full.txt @@ -1067,7 +1067,7 @@ Each construct below is supported (read as the language defines it), lowered (re | Construct | Status | Codes | |---|---|---| -| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` or `exact` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`) | Q201, Q207, Q208 | +| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`); `exact` does so only when asked (`"options": {"controls": "whole"}`), since its bits are those of the gates it applies | Q201, Q207, Q208 | | `inv @` on any gate | lowered exactly: each gate's inverse, in reverse order | Q202 | | `pow(k) @`, `k` a whole number | lowered exactly: angles scaled or the gate repeated; negative `k` repeats the inverse | Q203 | | `pow(r) @`, `r` fractional | lowered where an exact principal root exists (`pow(1/2) @ x` is `sx`; rotations by less than 2π; phases; controlled forms); refused otherwise (`u`, `cu`, user gates) | Q204, Q205 | diff --git a/wai/wai-quantum/src/engine/catalog.rs b/wai/wai-quantum/src/engine/catalog.rs index f2a46487c..ca49a99f3 100644 --- a/wai/wai-quantum/src/engine/catalog.rs +++ b/wai/wai-quantum/src/engine/catalog.rs @@ -698,10 +698,15 @@ pub fn mps_bond(r: &Request) -> usize { r.options.get("max_bond").and_then(Value::as_u64).map(|b| b as usize).unwrap_or(MPS_DEFAULT_BOND).clamp(1, MPS_MAX_BOND) } -/// An `mps` job's work: its two-site updates (each two-qubit gate and the -/// swaps that route it) at `(2χ)³` each, and its shots at `n·χ²` each. +/// An `mps` job's work: the bound [`WorkBound`](crate::quantum_mpsim::WorkBound) +/// puts on the chain's run of its gates at bond `chi` (each two-site update, +/// with the swaps that route a gate, at `(2χ)³`, each move of the +/// orthogonality center at `4χ³`, each one-qubit gate at `4χ²`), and its +/// shots at `n·χ²` each. pub fn mps_work(r: &Request, chi: u64) -> u64 { - mps_updates(r).saturating_mul((2 * chi).pow(3)).saturating_add(mps_shots_work(r, chi)) + let mut bound = crate::quantum_mpsim::WorkBound::new(chi); + r.program.local_steps(|_, qubits, _| bound.gate(qubits)); + bound.work().saturating_add(mps_shots_work(r, chi)) } /// An `mps` job's shots, at bond `chi`, in [`mps_work`]'s unit. @@ -709,16 +714,6 @@ pub(crate) fn mps_shots_work(r: &Request, chi: u64) -> u64 { r.shots.saturating_mul(r.program.n_qubits as u64 * chi * chi * 2) } -/// An `mps` job's two-site updates: each two-qubit gate and the swaps that -/// route it. -fn mps_updates(r: &Request) -> u64 { - r.program.ops.iter().map(|o| match o.qubits.as_slice() { - [a, b] => 2 * (a.abs_diff(*b) as u64).saturating_sub(1) + 1, - [a, b, c] => 15 * (1 + 2 * (a.abs_diff(*b).max(b.abs_diff(*c)).max(a.abs_diff(*c)) as u64)), - _ => 0, - }).sum() -} - /// A `cutrank` job's state: the program's Clifford part as a graph form with /// its closing one-qubit gates, summed along an order found by seeded /// searches. The planner makes one short search, enough to bound the job's @@ -1349,6 +1344,26 @@ mod tests { const CAP: u64 = 72 * GIB; + /// The work an `mps` job is planned at bounds the meter of its run: the + /// moves of the orthogonality center (gates at the two ends of a chain + /// whose middle holds the bond, in turn), and the gates a three-qubit gate + /// is written in, among it. + #[test] + fn the_mps_plan_bounds_its_run() { + use crate::quantum_mpsim::{Chain, MpsConfig}; + let fill = "qubit[12] q; h q; for uint l in [0:5] { rx(0.3) q; for uint k in [0:5] { cx q[2 * k], q[2 * k + 1]; } ry(0.4) q; for uint k in [0:4] { cx q[2 * k + 1], q[2 * k + 2]; } }"; + let ends = format!("{fill} for uint i in [0:29] {{ cx q[0], q[1]; rx(0.3) q[0]; cx q[10], q[11]; ry(0.2) q[11]; }}"); + let wide = "qubit[12] q; h q; ccx q[0], q[6], q[11]; cx q[11], q[0]; rx(0.3) q; cswap q[2], q[9], q[5]; ccz q[10], q[1], q[4]; cx q[0], q[11]; ry(0.2) q; cx q[3], q[8]; cx q[11], q[1]; t q[7];"; + for src in [ends.as_str(), wide] { + let program = crate::qasm::read(src).unwrap().program; + for chi in [2u64, 8, 64] { + let p = plan(&job(src, json!({ "method": "mps", "shots": 1, "options": { "max_bond": chi } })), CAP).unwrap(); + let c = Chain::run(12, &program.local_matrices(), MpsConfig { max_bond: chi as usize, cutoff: 1e-12 }).unwrap(); + assert!(c.work() > 0 && c.work() <= p.work, "bond {chi}: the run's {} over the plan's {}", c.work(), p.work); + } + } + } + #[test] fn auto_picks_the_strongest_method_the_circuit_admits() { let bell = "qubit[2] q; h q[0]; cx q[0], q[1];"; diff --git a/wai/wai-quantum/src/engine/job.rs b/wai/wai-quantum/src/engine/job.rs index 23dc6a13f..ca572926a 100644 --- a/wai/wai-quantum/src/engine/job.rs +++ b/wai/wai-quantum/src/engine/job.rs @@ -208,7 +208,9 @@ pub(crate) mod tests { (r#"{"qasm":"OPENQASM 3.0; qubit[2] q; bit[2] c; rx(0.4) q[0]; c[0] = measure q[0]; if (c[0]) x q[1]; c[1] = measure q[1];","shots":200,"observables":["Z1"]}"#, "261d5a754f17fa22d4dc308cd98f2d8accd89dd646716d6992770ecbe5d52acf"), // Its result's compiled names its gate set basis (once target): d714ea13… before. (r#"{"qasm":"OPENQASM 3.0; qubit[1] q; rx(0.4) q[0];","shots":100,"compile":{"epsilon":0.001}}"#, "b17615c95113dc7e80acfcd8825d1b3a7954bf71a71d1a121e1e6327703eecb2"), - (r#"{"qasm":"OPENQASM 3.0; qubit[30] q; rx(0.3) q; cx q[0], q[1];","shots":20,"method":"mps"}"#, "975d7a6a5107df2090c6a17422a8a467bff4027a7a0e84d6d3d3acda659f27fc"), + // Its plan's work counts its one-qubit gates, as the meter it bounds + // does (quantum_mpsim::WorkBound): 975d7a6a… before. + (r#"{"qasm":"OPENQASM 3.0; qubit[30] q; rx(0.3) q; cx q[0], q[1];","shots":20,"method":"mps"}"#, "c5ebfc80f6a1b8f2784f275a434903fc81a9a363b4dbac4203a21f09497d4146"), (r#"{"qasm":"OPENQASM 3.0;\ninclude \"mine.inc\";\nqubit[2] q;\nh q;\n","shots":64}"#, "93092f1fa723c2d7b088e5b047efd6e5ccdc42e1a14657d88dfd44df7b84bd52"), ]; diff --git a/wai/wai-quantum/src/engine/registry/builtin.rs b/wai/wai-quantum/src/engine/registry/builtin.rs index bacd86f4d..e960c3a84 100644 --- a/wai/wai-quantum/src/engine/registry/builtin.rs +++ b/wai/wai-quantum/src/engine/registry/builtin.rs @@ -102,7 +102,13 @@ impl Method for BuiltinMethod { // needs standard gates only for a circuit that is Clifford, which the // first gate that is not settles without writing the rest. let request = if catalog::runs_whole(self.name, job.json()) || (self.name == "stabilizer" && job.clifford().is_err()) { job.as_read()? } else { job.request()? }; - catalog::try_method(self.name, request, job.dyadic(), job.clifford(), job.job_bytes()) + // Each circuit is made only for the method that reads it: making one + // writes the program's gates, which no other method needs. + let unread = format!("{} does not read this circuit", self.name); + let (no_dyadic, no_clifford) = (Err(unread.clone()), Err(unread)); + let dyadic = if self.name == "exact" { job.dyadic() } else { &no_dyadic }; + let clifford = if self.name == "stabilizer" { job.clifford() } else { &no_clifford }; + catalog::try_method(self.name, request, dyadic, clifford, job.job_bytes()) } fn run(&self, job: &Job<'_>, plan: &Plan, out: &mut Value) -> Result<(), String> { crate::engine::run::run_builtin(self.name, job, plan, out) diff --git a/wai/wai-quantum/src/qasm.rs b/wai/wai-quantum/src/qasm.rs index abeb40538..cbc2e1a3d 100644 --- a/wai/wai-quantum/src/qasm.rs +++ b/wai/wai-quantum/src/qasm.rs @@ -1283,35 +1283,50 @@ impl Program { if self.has_whole() { return self.standard().local_matrices(); } - let op = |kind: Kind, qubits: &[u32]| Op { kind, qubits: qubits.to_vec(), params: vec![] }.matrix(); - let ccx = |out: &mut Vec, a: u32, b: u32, c: u32| { - use Kind::*; - for (k, q) in [ - (H, vec![c]), (Cx, vec![b, c]), (Tdg, vec![c]), (Cx, vec![a, c]), (T, vec![c]), (Cx, vec![b, c]), (Tdg, vec![c]), (Cx, vec![a, c]), - (T, vec![b]), (T, vec![c]), (H, vec![c]), (Cx, vec![a, b]), (T, vec![a]), (Tdg, vec![b]), (Cx, vec![a, b]), - ] { - out.push(op(k, &q)); + let mut out = Vec::with_capacity(self.ops.len()); + self.local_steps(|kind, qubits, params| out.push(Op { kind, qubits: qubits.to_vec(), params: params.to_vec() }.matrix())); + out + } + + /// The gates [`local_matrices`](Program::local_matrices) writes, in order, + /// each given to `each` as its kind, qubits and parameters, without + /// writing any: what the matrix product state's work is planned on. Of a + /// program in standard gates (one that holds a gate whole is walked as + /// read). + #[cfg(feature = "quantum_qasm")] + pub fn local_steps(&self, mut each: impl FnMut(Kind, &[u32], &[f64])) { + use Kind::*; + // Toffoli on (a, b, c), its gates on [a, b, c][i]. + const CCX: [(Kind, &[usize]); 15] = [ + (H, &[2]), (Cx, &[1, 2]), (Tdg, &[2]), (Cx, &[0, 2]), (T, &[2]), (Cx, &[1, 2]), (Tdg, &[2]), (Cx, &[0, 2]), + (T, &[1]), (T, &[2]), (H, &[2]), (Cx, &[0, 1]), (T, &[0]), (Tdg, &[1]), (Cx, &[0, 1]), + ]; + let ccx = |each: &mut dyn FnMut(Kind, &[u32], &[f64]), abc: [u32; 3]| { + let mut q = [0u32; 2]; + for (k, at) in CCX { + for (j, &i) in at.iter().enumerate() { + q[j] = abc[i]; + } + each(k, &q[..at.len()], &[]); } }; - let mut out = Vec::with_capacity(self.ops.len()); for o in &self.ops { let q = &o.qubits; match o.kind { - Kind::Ccx => ccx(&mut out, q[0], q[1], q[2]), - Kind::Ccz => { - out.push(op(Kind::H, &[q[2]])); - ccx(&mut out, q[0], q[1], q[2]); - out.push(op(Kind::H, &[q[2]])); + Ccx => ccx(&mut each, [q[0], q[1], q[2]]), + Ccz => { + each(H, &[q[2]], &[]); + ccx(&mut each, [q[0], q[1], q[2]]); + each(H, &[q[2]], &[]); } - Kind::Cswap => { - out.push(op(Kind::Cx, &[q[2], q[1]])); - ccx(&mut out, q[0], q[1], q[2]); - out.push(op(Kind::Cx, &[q[2], q[1]])); + Cswap => { + each(Cx, &[q[2], q[1]], &[]); + ccx(&mut each, [q[0], q[1], q[2]]); + each(Cx, &[q[2], q[1]], &[]); } - _ => out.push(o.matrix()), + _ => each(o.kind, q, &o.params), } } - out } /// The circuit as Pauli rotations and Cliffords: the input of sparse Pauli @@ -1360,7 +1375,11 @@ impl Program { /// How many standard gates the program is written in, without writing /// them: its ops' count for a program with none held whole. pub fn standard_gates(&self) -> u128 { - self.ops.iter().fold(0u128, |n, o| n.saturating_add(if o.is_whole() { controls::whole_len(o.kind, &o.params, o.controls().len()) } else { 1 })) + Self::standard_count(&self.ops) + } + + fn standard_count(ops: &[Op]) -> u128 { + ops.iter().fold(0u128, |n, o| n.saturating_add(if o.is_whole() { controls::whole_len(o.kind, &o.params, o.controls().len()) } else { 1 })) } /// The program in standard gates: of a program [`read_whole`] gave, the @@ -1372,6 +1391,20 @@ impl Program { self.lowered_lines(&[]).map(|(p, _)| p) } + /// How many standard gates `ops` are, refused, as `read` refuses them, when a + /// gate has more controls than the standard form takes or they come to more + /// than a program may hold: counted without writing them. + fn standard_within(ops: &[Op]) -> Result { + if ops.iter().any(|o| o.controls().len() > elab::MAX_CONTROLS as usize) { + return Err(Diagnostic::new(diag::TOO_MANY_CONTROLS, None, format!("written in standard gates, modifiers add at most {} controls", elab::MAX_CONTROLS))); + } + let total = Self::standard_count(ops); + if total > MAX_OPS as u128 { + return Err(Diagnostic::new(diag::TOO_MANY_GATES, None, format!("{total} gates written in standard gates; more than {MAX_OPS}"))); + } + Ok(total) + } + /// The program in standard gates, written only if it holds a gate whole: /// what a consumer of standard gates reads a program through. pub fn standard_form(&self) -> Result, Diagnostic> { @@ -1384,13 +1417,7 @@ impl Program { if !self.has_whole() { return Ok((self.clone(), lines.to_vec())); } - if self.ops.iter().any(|o| o.controls().len() > elab::MAX_CONTROLS as usize) { - return Err(Diagnostic::new(diag::TOO_MANY_CONTROLS, None, format!("written in standard gates, modifiers add at most {} controls", elab::MAX_CONTROLS))); - } - let total = self.standard_gates(); - if total > MAX_OPS as u128 { - return Err(Diagnostic::new(diag::TOO_MANY_GATES, None, format!("{total} gates written in standard gates; more than {MAX_OPS}"))); - } + let total = Self::standard_within(&self.ops)?; struct Standard { ops: Vec, } @@ -1678,16 +1705,28 @@ impl Program { #[cfg(feature = "quantum_qasm")] pub(crate) fn lower_clifford(ops: &[Op]) -> Result<(Vec, Vec), String> { use Kind::*; + // A gate held whole is checked in its standard gates, so it is held to + // what `lowered` holds them to before any is written: past that, a few + // bytes of text would ask for 2^(m+1) of them. + if ops.iter().any(Op::is_whole) { + Self::standard_within(ops).map_err(String::from)?; + } let mut out = Vec::new(); let mut ends = Vec::with_capacity(ops.len()); // A gate held whole is Clifford only as its standard gates are: they are - // written one by one, and the first that is not ends it. + // written one by one, and the first that is not ends it. Their phases + // are read exactly: θ/2^(m−1) under m qubits is a quarter turn only when + // it is one, and a phase smaller than the reader's tolerance there is no + // zero, which `quarter` would take it for (every one of 2^m of them). struct Each<'a> { out: &'a mut Vec, } impl controls::Sink for Each<'_> { type Error = String; fn gate(&mut self, kind: Kind, params: Vec, qubits: Vec) -> Result<(), String> { + if let Some(&p) = params.iter().find(|&&p| p != 0.0 && p.abs() < std::f64::consts::FRAC_PI_4) { + return Err(format!("{kind:?}({p}) in a gate under many controls is not a Clifford gate")); + } let (gates, _) = Program::lower_clifford(&[Op { kind, qubits, params }])?; self.out.extend(gates); Ok(()) diff --git a/wai/wai-quantum/src/quantum_frame.rs b/wai/wai-quantum/src/quantum_frame.rs index 7baf6990c..954c37d1a 100644 --- a/wai/wai-quantum/src/quantum_frame.rs +++ b/wai/wai-quantum/src/quantum_frame.rs @@ -58,9 +58,12 @@ //! `CX` and `CZ` and reset: a circuit with one holds one qubit more than its //! text names ([`Circuit::qubits`]). A Pauli channel's exclusive outcomes become //! independent X, Y and Z flips at the rates that give the same law, as a -//! depolarizing channel's do. A channel with no such rates (`(0.1, 0.1, 0)`: -//! its Z would need a rate below zero) is refused with its line, since a -//! detector error model of independent mechanisms cannot state it either. +//! depolarizing channel's do, a rate above 1/2 among them when the law needs +//! one. A channel with no such rates (`(0.1, 0.1, 0)`: its Z would need a rate +//! below zero) is refused with its line, since a detector error model of +//! independent mechanisms cannot state it either. The qubit a correlated +//! error is carried on is numbered past the text's own, so a text may not +//! name qubit 4294967295. //! //! An instruction outside that set is an error, not a skipped line. //! [`ErrorModel::to_dem_text`] writes a model with everything it holds @@ -196,34 +199,61 @@ pub fn lower(prog: &crate::quantum_qec_text::CircuitText) -> Result Option { + use crate::quantum_qec_text::Item; + items.iter().find_map(|it| match it { + Item::Op(i) => names.contains(&i.name.as_str()).then_some(i.line), + Item::Repeat { body, .. } => first_line(body, names), + }) +} + /// The rates of independent X, Y and Z flips with the law of a channel whose -/// outcomes X, Y and Z are exclusive, at `px`, `py` and `pz`: the three +/// outcomes X, Y and Z are exclusive, at `px`, `py` and `pz`. The three /// parities of a flip each multiply over independent channels and add over -/// exclusive ones, so `(1 − 2qx)² = ac/b`, `(1 − 2qy)² = ab/c`, `(1 − 2qz)² = -/// bc/a` with `a = 1 − 2(px + py)`, `b = 1 − 2(py + pz)`, `c = 1 − 2(px + pz)`. -/// A depolarizing channel is the case `px = py = pz`. None when no such rates -/// exist. +/// exclusive ones: with `u = 1 − 2q` for each rate `q`, `ux·uy = a`, `uy·uz = +/// b` and `ux·uz = c`, where `a = 1 − 2(px + py)`, `b = 1 − 2(py + pz)` and +/// `c = 1 − 2(px + pz)`. With none of them zero, `ux² = ac/b`, `uy² = ab/c` +/// and `uz² = bc/a`: rates exist when `abc > 0` and no square passes 1, and of +/// the two signs they take, the smaller rates are given. A parity of zero +/// makes a rate 1/2: with one nonzero, the two rates it is the product of +/// give it and the third is 1/2; with none, each is (the channel (1/4, 1/4, +/// 1/4), which is `DEPOLARIZE1(0.75)`). A rate may pass 1/2, a flip more +/// likely than not. A depolarizing channel is the case `px = py = pz`. None +/// when no such rates exist: two parities nonzero and one zero, or a square +/// past 1. fn pauli_channel_rates(px: f64, py: f64, pz: f64) -> Option<[f64; 3]> { if [px, py, pz].iter().filter(|&&p| p > 0.0).count() <= 1 { return Some([px, py, pz]); } let (a, b, c) = (1.0 - 2.0 * (px + py), 1.0 - 2.0 * (py + pz), 1.0 - 2.0 * (px + pz)); - if a <= 0.0 || b <= 0.0 || c <= 0.0 { - return None; - } - let rate = |square: f64| -> Option { - // A rate of zero, up to the rounding of the products above. - if square > 1.0 + 8.0 * f64::EPSILON { - return None; + let u = match (a != 0.0, b != 0.0, c != 0.0) { + (true, true, true) => { + // abc > 0: an even number of them below zero. + if ([a, b, c].iter().filter(|&&x| x < 0.0).count()) % 2 == 1 { + return None; + } + // At most 1, up to the rounding of the products. + let size = |square: f64| (square <= 1.0 + 8.0 * f64::EPSILON).then(|| square.min(1.0).sqrt()); + let u = [size(a * c / b)?.copysign(a), size(a * b / c)?, size(b * c / a)?.copysign(b)]; + if u.iter().sum::() >= 0.0 { u } else { u.map(|x| -x) } } - Some(((1.0 - square.min(1.0).sqrt()) / 2.0).max(0.0)) + (false, false, false) => [0.0; 3], + (true, false, false) => [a, 1.0, 0.0], + (false, true, false) => [0.0, 1.0, b], + (false, false, true) => [c, 0.0, 1.0], + _ => return None, }; - Some([rate(a * c / b)?, rate(a * b / c)?, rate(b * c / a)?]) + Some(u.map(|x| ((1.0 - x) / 2.0).clamp(0.0, 1.0))) } fn lower_items(items: &[crate::quantum_qec_text::Item], c: &mut Circuit, shift: &mut Vec) -> Result<(), FrameError> { @@ -304,6 +334,10 @@ fn lower_instruction(i: &crate::quantum_qec_text::Instruction, c: &mut Circuit, } }, }; + // The carrier's index is not the text's to name, and no qubit past it is. + if i.targets.iter().any(|t| matches!(*t, Target::Qubit { q, .. } | Target::Pauli { q, .. } if q == CARRIER)) { + return Err(err(&format!("qubit {CARRIER} is past the last qubit a circuit may name"))); + } let before = c.ops.len(); match name { "TICK" | "QUBIT_COORDS" => {} @@ -348,6 +382,9 @@ fn lower_instruction(i: &crate::quantum_qec_text::Instruction, c: &mut Circuit, // X → Y → Z → X: S then H on a frame. Its inverse: H then S, as S† is S // on a frame. "C_XYZ" | "C_ZYX" => { + if !nums.is_empty() { + return Err(err(&format!("{name} takes no arguments"))); + } let q = qubits(false)?; touch(c, &q); for q in q { @@ -1583,6 +1620,16 @@ mod tests { } } + /// A text whose qubits reach 4294967294 leaves the carrier no index: a + /// circuit with a correlated error is refused at the error's line. + #[test] + fn a_correlated_error_with_no_index_left_for_its_carrier_is_refused() { + for (text, line) in [("R 0\nE(0.1) X1\nX_ERROR(0.1) 4294967294\nM 0\nDETECTOR rec[-1]\n", 2), ("R 0\nX 4294967294\nREPEAT 2 {\n CORRELATED_ERROR(0.1) Z0\n}\nM 0\n", 4)] { + let e = parse(text).map(|c| c.qubits).unwrap_err(); + assert!(e.to_string().starts_with(&format!("line {line}:")) && e.to_string().contains("4294967294"), "{text}: {e}"); + } + } + /// `C_XYZ` and `C_ZYX` take no arguments, and are refused with one, as the /// reference tool refuses them. #[test] diff --git a/wai/wai-quantum/src/quantum_mpsim.rs b/wai/wai-quantum/src/quantum_mpsim.rs index cb90eb20d..4c1a6e3f6 100644 --- a/wai/wai-quantum/src/quantum_mpsim.rs +++ b/wai/wai-quantum/src/quantum_mpsim.rs @@ -78,6 +78,8 @@ pub enum MpsError { BadGate(usize), /// A bit string or Pauli string that does not fit the chain. BadQuery(String), + /// The work passed the budget [`Chain::run_within`] holds a run to. + OverBudget, } impl std::fmt::Display for MpsError { @@ -86,6 +88,7 @@ impl std::fmt::Display for MpsError { MpsError::TooManyQubits(n) => write!(f, "{n} qubits; a chain holds at most {MAX_QUBITS}"), MpsError::BadGate(i) => write!(f, "gate {i} is not a one- or two-qubit gate on the chain"), MpsError::BadQuery(why) => write!(f, "{why}"), + MpsError::OverBudget => write!(f, "the work passed the run's budget"), } } } @@ -96,8 +99,9 @@ impl std::error::Error for MpsError {} #[derive(Clone, Debug, PartialEq, Eq)] pub enum MpsRunError { Chain(MpsError), - /// The work passed the budget after `gate` of `gates` gates, the bond - /// having reached `max_bond_used`. + /// The work passed the budget in gate `gate` (from 1) of `gates`, at the + /// two-site update that passed it, the bond having reached + /// `max_bond_used`. OutOfWork { gate: usize, gates: usize, work: u64, max_bond_used: usize }, } @@ -135,6 +139,7 @@ pub struct Chain { truncations: u64, updates: u64, work: u64, + budget: u64, } #[inline] @@ -189,6 +194,53 @@ fn qr(cols: &[Vec], rows: usize) -> (Vec>, Vec>) { (q, r) } +/// An upper bound on [`Chain::work`] for a run of gates, at bond `chi` at +/// most: the walk [`Chain::apply`] makes, each two-site update at `(2χ)³`, +/// each move of the orthogonality center at `4χ³`, each one-qubit gate at +/// `4χ²`. What a job's work is planned in. Each gate is counted in a few +/// operations, however far apart its qubits are. +#[derive(Clone, Debug)] +pub struct WorkBound { + chi: u64, + center: u64, + work: u64, +} + +impl WorkBound { + /// A run from `|0…0⟩`, its center on the first site. + pub fn new(chi: u64) -> WorkBound { + WorkBound { chi, center: 0, work: 0 } + } + + /// One gate on these qubits; a gate on more than two counts nothing (the + /// chain refuses it). + pub fn gate(&mut self, qubits: &[u32]) { + let chi = self.chi; + match *qubits { + [_] => self.work = self.work.saturating_add(chi.saturating_mul(chi).saturating_mul(4)), + [a, b] if a != b => { + // `hi − lo` swaps down, the gate, and as many swaps back: the + // first update at `hi − 1` (`lo` when they are neighbours), + // each next one down two moves on, each one back up none, and + // the center left on `hi`. + let (lo, hi) = (a.min(b) as u64, a.max(b) as u64); + let d = hi - lo; + let moves = self.center.abs_diff(hi - 1).saturating_add(2 * (d - 1)); + let update = (2 * chi).saturating_pow(3); + let shift = chi.saturating_pow(3).saturating_mul(4); + self.work = self.work.saturating_add((2 * d - 1).saturating_mul(update)).saturating_add(moves.saturating_mul(shift)); + self.center = hi; + } + _ => {} + } + } + + /// The bound so far. + pub fn work(&self) -> u64 { + self.work + } +} + impl Chain { /// `|0…0⟩` on `n` qubits. pub fn new(n: u32, cfg: MpsConfig) -> Result { @@ -209,6 +261,7 @@ impl Chain { truncations: 0, updates: 0, work: 0, + budget: u64::MAX, }) } @@ -222,22 +275,27 @@ impl Chain { } /// [`Chain::run`], holding the run to `budget` units of work ([`Chain::work`]), - /// counted on the bonds it actually holds. It stops at the gate that passes - /// the budget; the meter changes no number of a run that finishes. + /// counted on the bonds it actually holds. It stops at the two-site update + /// or one-qubit gate that passes the budget, inside a gate that crosses + /// the chain too; the meter changes no number of a run that finishes. pub fn run_within(n: u32, gates: &[Gate], cfg: MpsConfig, budget: u64) -> Result { let mut c = Chain::new(n, cfg).map_err(MpsRunError::Chain)?; + c.budget = budget; for (i, g) in gates.iter().enumerate() { - c.apply(g).map_err(|_| MpsRunError::Chain(MpsError::BadGate(i)))?; - if c.work > budget { - return Err(MpsRunError::OutOfWork { gate: i + 1, gates: gates.len(), work: c.work, max_bond_used: c.max_bond_used }); + match c.apply(g) { + Ok(()) => {} + Err(MpsError::OverBudget) => return Err(MpsRunError::OutOfWork { gate: i + 1, gates: gates.len(), work: c.work, max_bond_used: c.max_bond_used }), + Err(_) => return Err(MpsRunError::Chain(MpsError::BadGate(i))), } } Ok(c) } /// The work so far: each two-site update at `(2χ)³`, `χ` the larger of the - /// two bonds it spans. The unit a job's work is planned in, with `χ` there - /// the bond asked for. + /// two bonds it spans; each move of the orthogonality center at the + /// products its QR and its multiplication take (at most `4χ³`); each + /// one-qubit gate at `4·dl·dr`. The unit a job's work is planned in + /// ([`WorkBound`]), with `χ` there the bond asked for. pub fn work(&self) -> u64 { self.work } @@ -267,6 +325,8 @@ impl Chain { let cols: Vec> = (0..dr).map(|r| (0..rows).map(|ls| self.a[i][ls * dr + r]).collect()).collect(); let (q, rm) = qr(&cols, rows); let k = q.len(); + let ndr = self.dr[i + 1]; + self.charge((rows * dr * k + k * dr * 2 * ndr) as u64); let mut na = vec![C::ZERO; rows * k]; for (c, qc) in q.iter().enumerate() { for ls in 0..rows { @@ -274,7 +334,7 @@ impl Chain { } } // A[i+1] ← R · A[i+1]. - let (ndr, nb_old) = (self.dr[i + 1], &self.a[i + 1]); + let nb_old = &self.a[i + 1]; let mut nb = vec![C::ZERO; k * 2 * ndr]; for c in 0..k { for j in 0..dr { @@ -307,6 +367,8 @@ impl Chain { let cols: Vec> = (0..dl).map(|l| (0..width).map(|sr| self.a[i][l * width + sr].conj()).collect()).collect(); let (q, rm) = qr(&cols, width); let k = q.len(); + let (pdl, pdr) = (self.dl[i - 1], self.dr[i - 1]); + self.charge((width * dl * k + pdl * 2 * k * pdr) as u64); // A[i] ← Q† as (k, 2, dr). let mut na = vec![C::ZERO; k * width]; for (c, qc) in q.iter().enumerate() { @@ -315,8 +377,7 @@ impl Chain { } } // A[i−1] ← A[i−1] · R†. - let (pdl, old) = (self.dl[i - 1], &self.a[i - 1]); - let pdr = self.dr[i - 1]; + let old = &self.a[i - 1]; let mut nb = vec![C::ZERO; pdl * 2 * k]; for l in 0..pdl { for s in 0..2 { @@ -345,8 +406,19 @@ impl Chain { } } + /// Adds `units` to the work. + fn charge(&mut self, units: u64) { + self.work = self.work.saturating_add(units); + } + + /// Whether the work is still within the budget. + fn within(&self) -> Result<(), MpsError> { + if self.work > self.budget { Err(MpsError::OverBudget) } else { Ok(()) } + } + fn apply1(&mut self, i: usize, g: &[C]) { let (dl, dr) = (self.dl[i], self.dr[i]); + self.charge((4 * dl * dr) as u64); let a = &mut self.a[i]; for l in 0..dl { for r in 0..dr { @@ -361,7 +433,7 @@ impl Chain { /// the more significant bit; the center ends on `i + 1`. fn apply2_adjacent(&mut self, i: usize, g: &[C]) { let chi = self.dl[i].max(self.dr[i + 1]) as u64; - self.work = self.work.saturating_add((2 * chi).saturating_pow(3)); + self.charge((2 * chi).saturating_pow(3)); self.move_center(i); let (dl, dc, dr) = (self.dl[i], self.dr[i], self.dr[i + 1]); let (rows, cols) = (dl * 2, 2 * dr); @@ -489,13 +561,14 @@ impl Chain { } /// Applies a one- or two-qubit gate (its matrix with `qubits[0]` the - /// most significant bit). + /// most significant bit). Under a budget ([`Chain::run_within`]) it stops + /// at the update that passes it, the chain then part way through the gate. pub fn apply(&mut self, g: &Gate) -> Result<(), MpsError> { let n = self.n; match *g.qubits.as_slice() { [q] if (q as usize) < n && g.matrix.len() == 4 => { self.apply1(q as usize, &g.matrix); - Ok(()) + self.within() } [a, b] if a != b && (a as usize) < n && (b as usize) < n && g.matrix.len() == 16 => { let (a, b) = (a as usize, b as usize); @@ -508,13 +581,17 @@ impl Chain { }; let (lo, hi) = (a.min(b), a.max(b)); let swap = Gate::swap(0, 1).matrix; - // Bring `hi` down next to `lo`, apply, and take it back. + // Bring `hi` down next to `lo`, apply, and take it back. (The + // walk [`WorkBound`] counts.) for k in (lo + 1..hi).rev() { self.apply2_adjacent(k, &swap); + self.within()?; } self.apply2_adjacent(lo, &m); + self.within()?; for k in lo + 1..hi { self.apply2_adjacent(k, &swap); + self.within()?; } Ok(()) } @@ -702,6 +779,24 @@ mod tests { assert!(hop > 20 * 16u64.pow(3), "{hop} units for two crossings of a chain at bond 16 or more"); } + /// The walk a plan bounds the work on holds the meter from above, on + /// circuits whose gates jump across the chain and at bonds it fills. + #[test] + fn the_bound_holds_the_meter() { + for (n, seed) in [(10u32, 1u64), (16, 2), (24, 3)] { + for chi in [2usize, 8, 32] { + let mut gates = random_circuit(n, 5, seed); + gates.extend([Gate::cx(0, n - 1), Gate::h(n / 2), Gate::cx(n - 1, 1), Gate::cx(n / 2, n / 2 - 1)]); + let c = Chain::run(n, &gates, MpsConfig { max_bond: chi, cutoff: 1e-12 }).unwrap(); + let mut bound = WorkBound::new(chi as u64); + for g in &gates { + bound.gate(&g.qubits); + } + assert!(c.work() > 0 && c.work() <= bound.work(), "{n} qubits at bond {chi}: run {} over bound {}", c.work(), bound.work()); + } + } + } + /// The budget is held at each two-site update, not after a whole gate: a /// gate that crosses the chain stops at the update that passes it. #[test] -- 2.54.0 (Apple Git-157) From eb504d6b2c471ccfe9fa5c5b436955eaef88ef23 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Sat, 7 Nov 2026 01:32:16 -0500 Subject: [PATCH 08/14] wai-quantum: tests for the rest of the reader-scaling review, before its fixes Two seams with no behaviour come with them: a test's budget for an mps run, and a plan's `metered`, false everywhere so far. Co-Authored-By: Claude Opus 5.5 --- wai/wai-quantum-cli/src/mcp.rs | 12 + wai/wai-quantum-service/src/jobs.rs | 18 +- wai/wai-quantum/src/engine/catalog.rs | 8 +- .../src/engine/catalog/whole_tests.rs | 230 +++++++++++++++++- wai/wai-quantum/src/engine/pulse.rs | 1 + wai/wai-quantum/src/engine/registry/tests.rs | 12 +- wai/wai-quantum/src/engine/run.rs | 21 +- wai/wai-quantum/src/engine/schema.rs | 1 + wai/wai-quantum/src/engine/sets.rs | 1 + wai/wai-quantum/src/engine/targets/job.rs | 2 +- wai/wai-quantum/src/qasm/whole_tests.rs | 19 +- wai/wai-quantum/src/quantum_frame.rs | 12 + wai/wai-quantum/src/quantum_mpsim.rs | 22 +- 13 files changed, 337 insertions(+), 22 deletions(-) diff --git a/wai/wai-quantum-cli/src/mcp.rs b/wai/wai-quantum-cli/src/mcp.rs index ba5264654..70b0d8144 100644 --- a/wai/wai-quantum-cli/src/mcp.rs +++ b/wai/wai-quantum-cli/src/mcp.rs @@ -1030,6 +1030,18 @@ mod tests { SigningKey::from_bytes(&[5; 32]) } + /// An agent reaches what the docs say a job on the state vector holds: a + /// gate under 20 controls runs, its verdict beside it. + #[test] + fn a_gate_past_16_controls_runs_over_mcp() { + let qs: Vec = (0..21).map(|i| format!("q[{i}]")).collect(); + let args = json!({ "qasm": format!("OPENQASM 3.0;\nqubit[21] q;\nx q;\nctrl(20) @ z {};\n", qs.join(", ")), "method": "statevector", "shots": 0, "amplitudes": ["1".repeat(21)] }); + let r = handle(&json!({ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "run_quantum_circuit", "arguments": args } }), 1, &key(), &mut Client::default()).unwrap()["result"].clone(); + assert_eq!(r["isError"], false, "{r}"); + assert_eq!(r["structuredContent"]["result"]["operations"], 22, "{r}"); + assert_eq!(r["structuredContent"]["result"]["verdict"]["level"], "executed", "{r}"); + } + /// A run takes its program in another format as the job service's run /// tools take it: the same `source`, read to its qasm first, and the same /// refusal, the reader's code before the job layer's. diff --git a/wai/wai-quantum-service/src/jobs.rs b/wai/wai-quantum-service/src/jobs.rs index 2ef436530..57978a23b 100644 --- a/wai/wai-quantum-service/src/jobs.rs +++ b/wai/wai-quantum-service/src/jobs.rs @@ -1363,7 +1363,7 @@ mod tests { use super::*; fn plan(memory_bytes: u64) -> Plan { - Plan { method: "statevector".into(), why: "test".into(), memory_bytes, work: 1, qubits: 3, target: None } + Plan { method: "statevector".into(), why: "test".into(), memory_bytes, work: 1, qubits: 3, target: None, metered: false } } fn config() -> Config { @@ -1795,10 +1795,24 @@ mod tests { let _ = std::fs::remove_dir_all(&dir); } + /// A job that ran under a meter was planned at what its meter allows, not + /// at what it took: its time says nothing of the method's rate. + #[test] + fn a_metered_job_does_not_set_the_rate() { + let s = Service::new(config()); + let p = Plan { method: "mps".into(), why: "".into(), memory_bytes: 1, work: 1_000_000_000, qubits: 30, target: None, metered: true }; + for _ in 0..3 { + let job = Job { id: job_id(), client: "x".into(), request: json!({}), plan: p.clone(), work: Work::One, status: Status::Done, submitted_ms: 0, started_ms: None, finished_ms: Some(1), result: Some(json!({ "elapsed_ms": 500, "energy": { "joules_micro": 5_000_000, "energy_uncertainty": { "window_us": 500_000 } } })), error: None, peak_rss: 0, digests: Digests::default(), key: None, interruptions: Vec::new(), child: None }; + s.time(&job); + } + let (t, _) = s.estimate(&p); + assert!(t["basis"].as_str().unwrap().contains("nominal"), "{t}"); + } + #[test] fn the_estimate_says_its_basis_nominal_then_measured_here() { let s = Service::new(config()); - let p = Plan { method: "statevector".into(), why: "".into(), memory_bytes: 1, work: 2_000_000_000, qubits: 20, target: None }; + let p = Plan { method: "statevector".into(), why: "".into(), memory_bytes: 1, work: 2_000_000_000, qubits: 20, target: None, metered: false }; let (t, e) = s.estimate(&p); assert!((t["seconds"].as_f64().unwrap() - 2.0).abs() < 1e-9 && t["basis"].as_str().unwrap().contains("nominal"), "{t}"); assert!(e.get("unestimated").is_some(), "{e}"); diff --git a/wai/wai-quantum/src/engine/catalog.rs b/wai/wai-quantum/src/engine/catalog.rs index ca49a99f3..1e8abc608 100644 --- a/wai/wai-quantum/src/engine/catalog.rs +++ b/wai/wai-quantum/src/engine/catalog.rs @@ -109,6 +109,10 @@ pub struct Plan { /// target (`engine::targets::job`). #[serde(default, skip_serializing_if = "Option::is_none")] pub target: Option, + /// The run is held to `work` by a meter of what it reaches, and may take + /// far less: `work` says nothing of how fast the method goes. + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub metered: bool, } /// The work a method does in a second, nominally, for a time estimate on a @@ -849,7 +853,7 @@ fn try_dynamic(method: &str, r: &Request, clifford: &Result { // At least two states (a branch's copy beside the state it left), @@ -961,7 +965,7 @@ pub fn stabilizer_rank_work(c: &crate::quantum_stabrank::CliffordT, amplitude_te pub(crate) fn try_method(method: &str, r: &Request, dyadic: &Result, clifford: &Result, String>, cap: u64) -> Result { let n = r.program.n_qubits; let gates = r.program.ops.len() as u64; - let plan = |memory_bytes: u64, work: u64, why: String| Plan { method: method.into(), why, memory_bytes, work, qubits: n, target: None }; + let plan = |memory_bytes: u64, work: u64, why: String| Plan { method: method.into(), why, memory_bytes, work, qubits: n, target: None, metered: false }; let counts = r.shots > 0; let wants_amplitudes = !r.amplitudes.is_empty(); let wants_expectations = !r.observables.is_empty(); diff --git a/wai/wai-quantum/src/engine/catalog/whole_tests.rs b/wai/wai-quantum/src/engine/catalog/whole_tests.rs index 79a5e0466..eaffa8aa4 100644 --- a/wai/wai-quantum/src/engine/catalog/whole_tests.rs +++ b/wai/wai-quantum/src/engine/catalog/whole_tests.rs @@ -215,9 +215,6 @@ fn past_the_standard_form_only_the_state_vectors_take_it() { assert!(e.contains("Q208"), "{e}"); let e = plan(&json!({ "qasm": src, "amplitudes": [marked], "noise": { "dephasing": 0.01 } }), CAP).unwrap_err(); assert!(e.contains("Q208"), "{e}"); - // A verdict reads standard gates, so a job that asks for one is held to them. - let e = plan(&json!({ "qasm": src, "amplitudes": [marked], "verdict": true }), CAP).unwrap_err(); - assert!(e.contains("Q208"), "{e}"); // lint says what a job takes. let l = crate::engine::job::lint(&src); assert_eq!((l["ok"].as_bool(), l["operations"].as_u64()), (Some(true), Some(23)), "{l}"); @@ -283,7 +280,7 @@ fn a_registered_method_sees_standard_gates() { fn plan(&self, job: &Job<'_>) -> Result { let r = job.request()?; assert!(!r.program.has_whole()); - Ok(Plan { method: "looks".into(), why: format!("{} standard gates", r.program.ops.len()), memory_bytes: 1, work: 1, qubits: r.program.n_qubits, target: None }) + Ok(Plan { method: "looks".into(), why: format!("{} standard gates", r.program.ops.len()), memory_bytes: 1, work: 1, qubits: r.program.n_qubits, target: None, metered: false }) } fn run(&self, job: &Job<'_>, _: &Plan, out: &mut Value) -> Result<(), String> { let r = job.request()?; @@ -337,9 +334,9 @@ fn a_bit_exact_result_states_its_global_phase() { // Whole, the phase of a rotation under controls stays in the amplitudes. let src = "qubit[3] q;\nx q[0];\nx q[1];\nh q[2];\nctrl(2) @ rz(pi / 2) q[0], q[1], q[2];\n"; let bits = ["011", "111"]; - let (_, exact) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": bits }), CAP).unwrap(); + let (_, exact) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": bits, "options": { "controls": "whole" } }), CAP).unwrap(); let (_, sv) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 0, "amplitudes": bits }), CAP).unwrap(); - assert!(exact["accuracy"].get("global_phase").is_none(), "{exact}"); + assert!(exact["operations"].is_u64() && exact["accuracy"].get("global_phase").is_none(), "{exact}"); for i in 0..2 { for k in ["re", "im"] { assert!((exact["amplitudes"][i][k].as_f64().unwrap() - sv["amplitudes"][i][k].as_f64().unwrap()).abs() < 1e-6, "{exact} against {sv}"); @@ -382,7 +379,7 @@ fn a_named_matrix_product_job_is_held_to_the_bond_it_reaches() { let zero = "0".repeat(n); let job = json!({ "qasm": src, "method": "mps", "amplitudes": [zero], "options": { "max_bond": 256 } }); let p = plan(&job, CAP).unwrap(); - assert!(p.work > MPS_MAX_WORK && p.why.contains("metered"), "{p:?}"); + assert!(p.metered && p.why.contains("metered"), "{p:?}"); let (_, out) = plan_and_run(&job, CAP).unwrap(); assert_eq!(out["accuracy"]["max_bond"], 256, "{out}"); let used = out["accuracy"]["max_bond_used"].as_u64().unwrap(); @@ -448,3 +445,222 @@ fn a_tiny_phase_under_many_controls_is_not_read_as_clifford() { let cz = qasm::read_whole("qubit[3] q;\nctrl(2) @ rz(2 * pi) q[0], q[1], q[2];\n").unwrap().program; assert!(cz.clifford().is_ok()); } + +/// A verdict with no intent needs no standard form: the run it states goes on +/// past 16 controls, and the verdict of the text says so too. An intent is +/// checked in standard gates, so a job with one is refused where they cannot +/// hold it, on its line. +#[test] +fn a_verdict_with_no_intent_holds_a_run_past_the_standard_form() { + let (n, marked) = (21, "1".repeat(21)); + let src = format!("qubit[{n}] q;\nx q;\nctrl(20) @ z {};\n", wide(n)); + let job = json!({ "qasm": src, "method": "statevector", "shots": 0, "amplitudes": [marked], "verdict": true }); + let (_, out) = plan_and_run(&job, CAP).unwrap(); + assert_eq!((out["verdict"]["level"].as_str(), out["operations"].as_u64()), (Some("executed"), Some(22)), "{out}"); + assert_eq!(crate::engine::verdict::of_text(&src)["parsed"]["ok"], true); + let e = plan(&json!({ "qasm": src, "shots": 16, "intent": { "distribution": { "0": 1.0 } } }), CAP).unwrap_err(); + assert!(e.starts_with("line 3:") && e.contains("Q208"), "{e}"); +} + +/// A method that needs standard gates, named, refuses as the reader does: on +/// the line, with the reader's code. +#[test] +fn a_named_method_on_standard_gates_refuses_as_the_reader_does() { + let src = format!("qubit[18] q;\nh q;\n\nctrl(17) @ z {};\n", wide(18)); + for method in ["exact", "mps", "pauli", "stabilizer", "tensor_network"] { + let job = json!({ "qasm": src, "method": method, "amplitudes": ["0".repeat(18)], "observables": if method == "pauli" { json!(["Z0"]) } else { json!([]) } }); + let e = plan(&job, CAP).unwrap_err(); + assert!(e.starts_with("line 4:"), "{method}: {e}"); + assert_eq!(crate::engine::refusal::refusal_json(&e)["code"], "Q208", "{method}: {e}"); + } + let many = format!("qubit[17] q;\nfor uint i in [0:99] {{\n ctrl(16) @ z {};\n}}\n", wide(17)); + let e = plan(&json!({ "qasm": many, "method": "exact", "shots": 16 }), CAP).unwrap_err(); + assert!(e.starts_with("line ") && e.contains("Q210"), "{e}"); + assert_eq!(crate::engine::refusal::refusal_json(&e)["code"], "Q210", "{e}"); +} + +/// lint counts a dynamic program's steps as it counts its gates: in standard +/// gates, what the reader's `read` holds. +#[test] +fn lint_counts_a_program_s_steps_in_standard_gates() { + let src = "qubit[5] q;\nbit[1] c;\nh q;\nc[0] = measure q[0];\nif (c[0] == 1) { ctrl(3) @ x q[1], q[2], q[3], q[4]; }\nctrl(3) @ z q[1], q[2], q[3], q[4];\n"; + let l = crate::engine::job::lint(src); + let p = qasm::read(src).unwrap().program; + assert_eq!(l["gates"].as_u64(), Some(p.ops.len() as u64), "{l}"); + assert_eq!(l["dynamic_steps"].as_u64(), Some(p.dynamic.as_ref().unwrap().len() as u64), "{l}"); +} + +/// `exact` past 16 controls is told how to ask, by the job and by the reader. +#[test] +fn the_refusal_past_16_controls_names_the_option() { + let src = format!("qubit[18] q;\nctrl(17) @ z {};\n", wide(18)); + let e = plan(&json!({ "qasm": src, "method": "exact", "amplitudes": ["0".repeat(18)] }), CAP).unwrap_err(); + assert!(e.contains("\"controls\": \"whole\""), "{e}"); + let e = qasm::read_whole(&src).unwrap().program.lowered().unwrap_err().to_string(); + assert!(e.contains("\"controls\": \"whole\""), "{e}"); +} + +/// `options.controls` is read: another value is refused, and so is `whole` +/// where the job cannot hold a gate whole; the methods list names it. +#[test] +fn options_controls_is_read_and_not_ignored() { + let src = "qubit[4] q;\nh q;\nctrl(2) @ t q[0], q[1], q[2];\n"; + for bad in [json!("Whole"), json!("wholes"), json!(1), json!(true)] { + let e = plan(&json!({ "qasm": src, "method": "exact", "shots": 8, "options": { "controls": bad } }), CAP).unwrap_err(); + assert!(e.contains("J003") && e.contains("controls"), "{bad}: {e}"); + } + let whole = |extra: Value| { + let mut j = json!({ "qasm": src, "shots": 8, "options": { "controls": "whole" } }); + j.as_object_mut().unwrap().extend(extra.as_object().unwrap().clone()); + j + }; + for extra in [json!({ "compile": { "epsilon": 0.001 } }), json!({ "noise": { "dephasing": 0.01 } }), json!({ "fabric": "cpu" }), json!({ "method": "mps" }), json!({ "method": "stabilizer" }), json!({ "method": "pauli", "observables": ["Z0"] })] { + let e = plan(&whole(extra.clone()), CAP).unwrap_err(); + assert!(e.contains("J003") && e.contains("whole"), "{extra}: {e}"); + } + for ok in [json!({ "method": "exact" }), json!({ "method": "statevector" }), json!({ "method": "auto" })] { + plan(&whole(ok.clone()), CAP).unwrap_or_else(|e| panic!("{ok}: {e}")); + } + plan(&json!({ "qasm": src, "shots": 8, "noise": { "dephasing": 0.01 }, "options": { "controls": "standard" } }), CAP).unwrap(); + for m in ["exact", "statevector"] { + assert!(method_text(m)["options"]["controls"].is_string(), "{m}: {}", method_text(m)); + } +} + +/// What a bit-exact result's phase is held to: method statevector's state, of +/// the program that ran. `U` and `gphase` are where the language's own state +/// differs from it, and the note says which it is. +#[test] +fn the_stated_phase_is_relative_to_the_state_vector() { + for body in ["U(pi / 2, 0, 0) q[0];\n", "u3(pi / 2, pi / 4, pi / 8) q[0];\n", "gphase(pi / 2);\nh q[0];\nrz(pi / 4) q[0];\n"] { + let src = format!("qubit[1] q;\n{body}"); + let bits = ["0", "1"]; + let (_, exact) = plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": bits }), CAP).unwrap(); + let (_, sv) = plan_and_run(&json!({ "qasm": src, "method": "statevector", "shots": 0, "amplitudes": bits }), CAP).unwrap(); + let g = &exact["accuracy"]["global_phase"]; + let note = g["note"].as_str().unwrap(); + assert!(note.contains("method statevector") && note.contains("gphase") && note.contains("U") && !note.contains("OpenQASM's state"), "{note}"); + let (c, s) = (g["radians"].as_f64().unwrap().cos(), g["radians"].as_f64().unwrap().sin()); + for i in 0..2 { + let (ar, ai) = (exact["amplitudes"][i]["re"].as_f64().unwrap(), exact["amplitudes"][i]["im"].as_f64().unwrap()); + let (br, bi) = (sv["amplitudes"][i]["re"].as_f64().unwrap(), sv["amplitudes"][i]["im"].as_f64().unwrap()); + assert!((ar * c - ai * s - br).abs() < 1e-6 && (ar * s + ai * c - bi).abs() < 1e-6, "{body}: {exact} against {sv}"); + } + } +} + +/// Asked for, the bit-exact method's gate under controls is the state vector's, +/// gate by gate, in every amplitude. +#[test] +fn the_bit_exact_whole_form_gives_the_state_vector_s_amplitudes() { + let bits: Vec = (0..16).map(|i| format!("{i:04b}")).collect(); + for g in ["x", "y", "z", "h", "s", "sdg", "t", "tdg", "sx", "sxdg", "p(pi / 8)", "rz(pi / 4)", "rx(pi / 4)", "ry(pi / 4)", "u(pi / 2, pi / 4, pi / 8)"] { + let src = format!("qubit[4] q;\nh q;\nt q[2];\nh q[2];\nt q[3];\nctrl(2) @ {g} q[0], q[1], q[2];\nctrl(3) @ {g} q[3], q[0], q[1], q[2];\nh q[2];\n"); + let job = |method: &str, options: Value| json!({ "qasm": src, "method": method, "shots": 0, "amplitudes": bits, "options": options }); + let (_, exact) = plan_and_run(&job("exact", json!({ "controls": "whole" })), CAP).unwrap(); + let (_, sv) = plan_and_run(&job("statevector", json!({})), CAP).unwrap(); + assert!(exact["operations"].as_u64().is_some(), "{g}: {exact}"); + for i in 0..16 { + for k in ["re", "im"] { + let (a, b) = (exact["amplitudes"][i][k].as_f64().unwrap(), sv["amplitudes"][i][k].as_f64().unwrap()); + assert!((a - b).abs() < 1e-6, "{g}: amplitude {i}, {k}: {a} against {b}"); + } + } + } +} + +/// Every number the bit-exact accuracy states, read back. +#[test] +fn a_bit_exact_result_s_accuracy_members_hold_what_they_say() { + let run = |src: &str| plan_and_run(&json!({ "qasm": src, "method": "exact", "shots": 0, "amplitudes": ["0"] }), CAP).unwrap().1; + let out = run("qubit[1] q;\nrz(pi / 4) q[0];\n"); + assert_eq!(out["accuracy"]["global_phase"]["turns_over_2_33"].as_u64(), Some((1 << 33) - (1 << 29)), "{out}"); + let out = run("qubit[1] q;\np(2 * pi / 2**50) q[0];\n"); + let want = std::f64::consts::TAU / 2f64.powi(50); + assert!((out["accuracy"]["below_table"]["largest_radians"].as_f64().unwrap() / want - 1.0).abs() < 1e-3, "{out}"); + let out = run("qubit[1] q;\np(pi / 2 + 2 * pi / 2**48) q[0];\n"); + let want = std::f64::consts::TAU / 2f64.powi(48); + let m = &out["accuracy"]["moved_angles"]; + assert_eq!(m["angles"], 1, "{out}"); + assert!((m["largest_radians"].as_f64().unwrap() / want - 1.0).abs() < 1e-2, "{out}"); + assert!(m["note"].as_str().unwrap().contains("1e-14"), "{out}"); + // A double's rounding of an angle on the grid moves nothing: angles whose + // turn does not come back exactly, and an angle's report says none moved. + let mut seen = 0; + for k in 1..4000u64 { + let m = k.wrapping_mul(2654435761) % (1 << 32); + let at = m as f64 / (1u64 << 32) as f64; + let angle = at * std::f64::consts::TAU; + if (angle / std::f64::consts::TAU).rem_euclid(1.0) == at { + continue; + } + seen += 1; + let (_, r) = qasm::read(&format!("qubit[1] q;\np({angle:e}) q[0];\n")).unwrap().program.dyadic_with_report().unwrap(); + assert_eq!((r.moved, r.below_table), (0, 0), "{angle:e}"); + } + assert!(seen > 10, "{seen}"); +} + +/// A program that entangles, for a job the meter watches: `n` qubits, `layers` +/// of rotations and a brickwork of cx. +fn entangling(n: usize, layers: usize) -> String { + let mut s = format!("qubit[{n}] q;\n"); + for l in 0..layers { + s += "rx(0.3) q;\nry(0.4) q;\n"; + for k in (l % 2..n - 1).step_by(2) { + s += &format!("cx q[{k}], q[{}];\n", k + 1); + } + } + s +} + +/// A job the meter stops: at the bond the chain holds, with a refusal that says +/// where, and for its shots, once the chain has run. +#[test] +fn the_meter_stops_a_job_that_passes_its_budget() { + use crate::engine::run::MPS_BUDGET; + use crate::quantum_mpsim::{Chain, MpsConfig}; + let (n, chi) = (14usize, 16u64); + let src = entangling(n, 8); + let job = json!({ "qasm": src, "method": "mps", "shots": 200, "options": { "max_bond": chi } }); + let (_, free) = plan_and_run(&job, CAP).unwrap(); + let used = free["accuracy"]["max_bond_used"].as_u64().unwrap(); + assert!(used > 4, "reached {used}"); + let p = qasm::read(&src).unwrap().program; + let chain = Chain::run(n as u32, &p.local_matrices(), MpsConfig { max_bond: chi as usize, cutoff: 1e-12 }).unwrap(); + assert!(chain.work() > 8 * chain.report().updates, "{} units over {} updates", chain.work(), chain.report().updates); + let plan = plan(&job, CAP).unwrap(); + let r = read(&job).unwrap(); + let at = |budget: u64| { + MPS_BUDGET.set(Some(budget)); + let e = crate::engine::run::run(&job, &plan); + MPS_BUDGET.set(None); + e + }; + let e = at(chain.work() / 2).unwrap_err(); + assert!(e.contains("[J011]") && e.contains("units of work") && e.contains("stopped"), "{e}"); + // The chain within it, its shots at the bond it reached not. + let e = at(chain.work() + mps_shots_work(&r, 1) + 1).unwrap_err(); + assert!(e.contains("[J011]") && e.contains("shots"), "{e}"); + let answer = at(chain.work() + mps_shots_work(&r, used)).unwrap(); + assert_eq!(answer["counts"], free["counts"]); +} + +/// A plan for a job that runs metered says what it may take: the work the +/// meter holds it to, so a dry run's time is the meter's, and that it is held. +#[test] +fn a_metered_plan_states_the_work_its_meter_allows() { + let n = 30usize; + let mut src = format!("qubit[{n}] q;\n"); + for q in 0..n { + src += &format!("h q[{q}];\n"); + for t in q + 1..n { + src += &format!("cp(pi / 2**{}) q[{t}], q[{q}];\n", t - q); + } + } + let p = plan(&json!({ "qasm": src, "method": "mps", "amplitudes": ["0".repeat(n)], "options": { "max_bond": 256 } }), CAP).unwrap(); + assert_eq!((p.work, p.metered), (MPS_MAX_WORK, true), "{p:?}"); + assert!(p.why.contains("metered"), "{p:?}"); + let p = plan(&json!({ "qasm": src, "method": "mps", "amplitudes": ["0".repeat(n)], "options": { "max_bond": 32 } }), CAP).unwrap(); + assert!(!p.metered, "{p:?}"); +} diff --git a/wai/wai-quantum/src/engine/pulse.rs b/wai/wai-quantum/src/engine/pulse.rs index 2a5440c00..18c62938f 100644 --- a/wai/wai-quantum/src/engine/pulse.rs +++ b/wai/wai-quantum/src/engine/pulse.rs @@ -460,6 +460,7 @@ pub fn plan(v: &Value, job_bytes: u64) -> Result { work: p.plan.work, qubits: p.plan.qubits.len() as u32, target: None, + metered: false, }) } diff --git a/wai/wai-quantum/src/engine/registry/tests.rs b/wai/wai-quantum/src/engine/registry/tests.rs index c38edc8e1..ff05fbdc1 100644 --- a/wai/wai-quantum/src/engine/registry/tests.rs +++ b/wai/wai-quantum/src/engine/registry/tests.rs @@ -61,7 +61,7 @@ impl Method for BasisTable { if !r.observables.is_empty() { return Err("basis_table answers counts and amplitudes".into()); } - Ok(Plan { method: "basis_table".into(), why: format!("a permutation of basis states on {} qubits, followed bit by bit", r.program.n_qubits), memory_bytes: 1 << 20, work: r.program.ops.len() as u64, qubits: r.program.n_qubits, target: None }) + Ok(Plan { method: "basis_table".into(), why: format!("a permutation of basis states on {} qubits, followed bit by bit", r.program.n_qubits), memory_bytes: 1 << 20, work: r.program.ops.len() as u64, qubits: r.program.n_qubits, target: None, metered: false }) } fn run(&self, job: &Job<'_>, _: &Plan, out: &mut Value) -> Result<(), String> { let r = job.request()?; @@ -99,7 +99,7 @@ impl Method for Rogue { } fn plan(&self, job: &Job<'_>) -> Result { let method = if self.0 == "rogue_plan" { "exact".to_string() } else { self.0.to_string() }; - Ok(Plan { method, why: "rogue".into(), memory_bytes: 1, work: 1, qubits: job.request()?.program.n_qubits, target: None }) + Ok(Plan { method, why: "rogue".into(), memory_bytes: 1, work: 1, qubits: job.request()?.program.n_qubits, target: None, metered: false }) } fn run(&self, _: &Job<'_>, _: &Plan, out: &mut Value) -> Result<(), String> { match self.0 { @@ -108,6 +108,10 @@ impl Method for Rogue { out["method"] = json!("exact"); } "rogue_class" => out["accuracy"] = json!({ "class": "bit-exact" }), + "rogue_operations" => { + out["accuracy"] = json!({ "class": "exact" }); + out["operations"] = json!(1); + } _ => out["accuracy"] = json!({ "class": "exact" }), } Ok(()) @@ -512,11 +516,11 @@ fn registration_refuses_what_it_cannot_hold() { #[test] fn a_registered_method_s_result_is_held_to_the_contract() { let mut h = Registry::with_builtins(); - for n in ["rogue_method", "rogue_class", "rogue_plan"] { + for n in ["rogue_method", "rogue_class", "rogue_plan", "rogue_operations"] { h.register(Component::method(Rogue(n))).unwrap(); } let job = |m: &str| json!({ "qasm": "OPENQASM 3.0;\nqubit[1] q;\nx q[0];\n", "shots": 1, "method": m }); - for m in ["rogue_method", "rogue_class", "rogue_plan"] { + for m in ["rogue_method", "rogue_class", "rogue_plan", "rogue_operations"] { let e = h.plan_and_run(&job(m), CAP).unwrap_err(); assert_eq!(codes_in(&e).last().copied(), Some("J064"), "{m}: {e}"); } diff --git a/wai/wai-quantum/src/engine/run.rs b/wai/wai-quantum/src/engine/run.rs index b0d225d2a..eaf6d36e8 100644 --- a/wai/wai-quantum/src/engine/run.rs +++ b/wai/wai-quantum/src/engine/run.rs @@ -45,6 +45,21 @@ fn index_of(bits: &str, n: u32, pos: impl Fn(u32) -> u32) -> usize { x } +/// A test's budget for an `mps` run, in place of [`catalog::MPS_MAX_WORK`]. +#[cfg(test)] +thread_local! { + pub(crate) static MPS_BUDGET: std::cell::Cell> = const { std::cell::Cell::new(None) }; +} + +/// The work an `mps` run is held to. +fn mps_budget() -> u64 { + #[cfg(test)] + if let Some(b) = MPS_BUDGET.get() { + return b; + } + catalog::MPS_MAX_WORK +} + /// What the bit-exact method promises of a result, and what the lowering to /// its gates did to the program, so that neither is silent: the global phase /// by which its amplitudes differ from OpenQASM's, and the angles below its @@ -604,12 +619,12 @@ pub(crate) fn run_builtin(method: &str, job: &Job<'_>, plan: &Plan, out: &mut Va let gates = r.program.local_matrices(); // The plan's work bounds this run from above at the bond asked for; // the run is held to the bond it reaches. - let mut chain = Chain::run_within(n, &gates, MpsConfig { max_bond: chi, cutoff }, catalog::MPS_MAX_WORK.saturating_sub(catalog::mps_shots_work(r, 1))).map_err(|e| match e { + let mut chain = Chain::run_within(n, &gates, MpsConfig { max_bond: chi, cutoff }, mps_budget().saturating_sub(catalog::mps_shots_work(r, 1))).map_err(|e| match e { crate::quantum_mpsim::MpsRunError::Chain(e) => e.to_string(), - crate::quantum_mpsim::MpsRunError::OutOfWork { gate, gates, work, max_bond_used } => crate::engine::refusal::tag(crate::engine::refusal::METHOD_REFUSES, format!("stopped after {gate} of {gates} gates: {work} units of work at the bond the circuit has reached ({max_bond_used}), the most one job may take ({}); ask for a smaller max_bond", catalog::MPS_MAX_WORK)), + crate::quantum_mpsim::MpsRunError::OutOfWork { gate, gates, work, max_bond_used } => crate::engine::refusal::tag(crate::engine::refusal::METHOD_REFUSES, format!("stopped after {gate} of {gates} gates: {work} units of work at the bond the circuit has reached ({max_bond_used}), the most one job may take ({}); ask for a smaller max_bond", mps_budget())), })?; let rep = chain.report(); - if chain.work().saturating_add(catalog::mps_shots_work(r, rep.max_bond_used as u64)) > catalog::MPS_MAX_WORK { + if chain.work().saturating_add(catalog::mps_shots_work(r, rep.max_bond_used as u64)) > mps_budget() { return Err(crate::engine::refusal::tag(crate::engine::refusal::METHOD_REFUSES, format!("{} shots at the bond the circuit reached ({}) are more work than one job has left; ask for fewer shots", r.shots, rep.max_bond_used))); } out["accuracy"] = if rep.truncations == 0 { diff --git a/wai/wai-quantum/src/engine/schema.rs b/wai/wai-quantum/src/engine/schema.rs index 2b6625e33..005663e35 100644 --- a/wai/wai-quantum/src/engine/schema.rs +++ b/wai/wai-quantum/src/engine/schema.rs @@ -703,6 +703,7 @@ mod tests { json!({ "qasm": bell, "method": "exact", "shots": 100, "observables": ["Z0 Z1", { "pauli": "X0 X1", "coeff": 0.5 }], "amplitudes": ["00", "11"] }), // A gate held whole, the phase the method drops, an angle below its table and one it moved. json!({ "qasm": "OPENQASM 3.0;\nqubit[4] q;\nh q;\nctrl(3) @ z q[0], q[1], q[2], q[3];\nrz(pi / 4) q[0];\np(2 * pi / 2**50) q[1];\np(pi / 2 + 2 * pi / 2**48) q[2];\n", "method": "exact", "shots": 8 }), + json!({ "qasm": "OPENQASM 3.0;\nqubit[4] q;\nh q;\nctrl(3) @ z q[0], q[1], q[2], q[3];\nrz(pi / 4) q[0];\n", "method": "exact", "shots": 8, "options": { "controls": "whole" } }), json!({ "qasm": "OPENQASM 3.0;\nqubit[4] q;\nh q;\nctrl(3) @ x q[0], q[1], q[2], q[3];\n", "method": "statevector", "shots": 8 }), json!({ "qasm": rot, "method": "statevector", "shots": 100, "observables": ["Z0"], "amplitudes": ["000"], "seed": 3 }), json!({ "qasm": bell, "shots": 100, "observables": ["Z0 Z1"] }), diff --git a/wai/wai-quantum/src/engine/sets.rs b/wai/wai-quantum/src/engine/sets.rs index 969a67a10..34bb76140 100644 --- a/wai/wai-quantum/src/engine/sets.rs +++ b/wai/wai-quantum/src/engine/sets.rs @@ -236,6 +236,7 @@ pub fn summary(plans: &[catalog::Plan]) -> catalog::Plan { work: plans.iter().fold(0u64, |a, p| a.saturating_add(p.work)), qubits: plans.iter().map(|p| p.qubits).max().unwrap_or(0), target: None, + metered: false, } } diff --git a/wai/wai-quantum/src/engine/targets/job.rs b/wai/wai-quantum/src/engine/targets/job.rs index 7c462d43f..a4cd6b435 100644 --- a/wai/wai-quantum/src/engine/targets/job.rs +++ b/wai/wai-quantum/src/engine/targets/job.rs @@ -164,7 +164,7 @@ pub fn plan(v: &Value, job_bytes: u64) -> Result { if !pl.native.exact { why.push_str("; each gate costed as the target's own, equal up to one-qubit gates"); } - Ok(Plan { method, why, memory_bytes, work, qubits: p.noise.physical.len() as u32, target: Some(target_json(&p)) }) + Ok(Plan { method, why, memory_bytes, work, qubits: p.noise.physical.len() as u32, target: Some(target_json(&p)), metered: false }) } /// The bit string a simulated basis state reads as: logical qubit `i` read diff --git a/wai/wai-quantum/src/qasm/whole_tests.rs b/wai/wai-quantum/src/qasm/whole_tests.rs index 625243ef6..4ee27580e 100644 --- a/wai/wai-quantum/src/qasm/whole_tests.rs +++ b/wai/wai-quantum/src/qasm/whole_tests.rs @@ -27,6 +27,8 @@ const WHOLE: &[&str] = &[ "qubit[4] q;\nh q;\nctrl(2) @ sxdg q[0], q[1], q[2];\n", "qubit[4] q;\nh q;\nctrl @ cu(0.3, 0.4, 0.5, 0.6) q[0], q[1], q[2];\n", "qubit[5] q;\nh q;\nctrl(2) @ cu(0.3, 0.4, 0.5, pi) q[0], q[1], q[2], q[3];\n", + "qubit[5] q;\nh q;\nctrl(2) @ cu(0.3, 0.4, 0.5, 0.6) q[0], q[1], q[2], q[3];\n", + "qubit[4] q;\nh q;\nctrl(3) @ gphase(0.3) q[0], q[1], q[2];\n", "qubit[4] q;\nh q;\nctrl(2) @ swap q[0], q[1], q[2], q[3];\n", "qubit[4] q;\nh q;\nctrl(2) @ iswap q[0], q[1], q[2], q[3];\n", "qubit[4] q;\nh q;\nctrl(2) @ rzz(0.3) q[0], q[1], q[2], q[3];\n", @@ -141,7 +143,7 @@ fn past_what_standard_gates_hold_a_gate_still_reads_whole() { let qs: Vec = (0..21).map(|i| format!("q[{i}]")).collect(); let src = format!("qubit[21] q;\nctrl(20) @ z {};\n", qs.join(", ")); let d = read(&src).unwrap_err(); - assert!(d.code == diag::TOO_MANY_CONTROLS && d.message.contains("at most 16 controls") && d.message.contains("as many as 255"), "{d}"); + assert!(d.code == diag::TOO_MANY_CONTROLS && d.message.contains("at most 16 controls") && d.message.contains("as many as 255") && d.message.contains("\"controls\": \"whole\""), "{d}"); let p = read_whole(&src).unwrap().program; assert_eq!((p.ops.len(), p.standard_gates()), (1, (1 << 22) - 3)); let d = p.lowered().unwrap_err(); @@ -364,3 +366,18 @@ fn the_bit_exact_report_states_what_the_lowering_did() { assert_eq!((moved.moved, moved.below_table), (1, 0)); assert!(moved.largest_moved > 0.0); } + +/// A gate held whole carries its qubits: what a program may hold counts them, +/// so a loop of wide gates is refused where it would have taken gigabytes, and +/// nothing the standard form could hold is. +#[test] +fn a_loop_of_wide_whole_gates_is_held_to_what_a_program_may_hold() { + let qs: Vec = (0..255).map(|i| format!("q[{i}]")).collect(); + let src = format!("qubit[255] q;\nfor int i in [1:100000] {{\n ctrl(254) @ p(0.1) {};\n}}\n", qs.join(", ")); + let t = std::time::Instant::now(); + let d = read_whole(&src).err().unwrap(); + assert!(d.code == diag::TOO_MANY_GATES && d.line() == Some(3), "{d}"); + assert!(t.elapsed() < std::time::Duration::from_secs(20), "{:?}", t.elapsed()); + let src = format!("qubit[255] q;\nfor int i in [1:1000] {{\n ctrl(254) @ p(0.1) {};\n}}\n", qs.join(", ")); + assert_eq!(read_whole(&src).unwrap().program.ops.len(), 1000); +} diff --git a/wai/wai-quantum/src/quantum_frame.rs b/wai/wai-quantum/src/quantum_frame.rs index 954c37d1a..f9edda91e 100644 --- a/wai/wai-quantum/src/quantum_frame.rs +++ b/wai/wai-quantum/src/quantum_frame.rs @@ -1630,6 +1630,18 @@ mod tests { } } + /// The instructions this reader added are in the page that lists the text + /// forms and in the conformance set that says it holds each one. + #[test] + fn the_qec_page_and_conformance_set_name_these_forms() { + let page = include_str!("../docs/qec.md"); + let set = include_str!("../../quantum-conformance/qec-text/README.md"); + for form in ["C_XYZ", "C_ZYX", "CORRELATED_ERROR", "PAULI_CHANNEL_1"] { + assert!(page.contains(form) && set.contains(form), "{form}"); + } + assert!(page.contains("one qubit more") && page.contains("PAULI_CHANNEL_1(0.1, 0.1, 0)")); + } + /// `C_XYZ` and `C_ZYX` take no arguments, and are refused with one, as the /// reference tool refuses them. #[test] diff --git a/wai/wai-quantum/src/quantum_mpsim.rs b/wai/wai-quantum/src/quantum_mpsim.rs index 4c1a6e3f6..d3e7a951d 100644 --- a/wai/wai-quantum/src/quantum_mpsim.rs +++ b/wai/wai-quantum/src/quantum_mpsim.rs @@ -779,6 +779,23 @@ mod tests { assert!(hop > 20 * 16u64.pow(3), "{hop} units for two crossings of a chain at bond 16 or more"); } + /// An update is charged at the bond it spans: with the center already in + /// place, what a gate adds to the meter is `(2χ)³` of the bonds it finds, + /// not of a bond of one. + #[test] + fn an_update_is_priced_at_the_bond_it_spans() { + let n = 16u32; + let mut c = Chain::run(n, &saturating(n, 10), MpsConfig { max_bond: 32, cutoff: 1e-12 }).unwrap(); + let m = n as usize / 2; + c.apply(&Gate::cx(m as u32 - 1, m as u32)).unwrap(); + assert_eq!(c.center, m); + let chi = c.dl[m].max(c.dr[m + 1]) as u64; + assert!(chi >= 8, "{:?}", c.report()); + let before = c.work(); + c.apply(&Gate::cx(m as u32, m as u32 + 1)).unwrap(); + assert_eq!(c.work() - before, (2 * chi).pow(3)); + } + /// The walk a plan bounds the work on holds the meter from above, on /// circuits whose gates jump across the chain and at bonds it fills. #[test] @@ -823,7 +840,8 @@ mod tests { /// budget stops at the gate that passed it. #[test] fn the_meter_counts_the_bonds_reached_and_changes_nothing() { - // The 24-qubit QFT's entanglement stays low, far below the bond asked. + // The QFT from |0…0⟩ is a product state at every step: each `cp` finds + // its other qubit in |0⟩, so it runs at bond 1, far below the bond asked. let n = 24; let mut gates = Vec::new(); for q in 0..n { @@ -838,7 +856,7 @@ mod tests { assert_eq!(plain.report(), metered.report()); assert_eq!(plain.amplitude(&[0; 24]).unwrap(), metered.amplitude(&[0; 24]).unwrap()); let r = plain.report(); - assert!(r.max_bond_used < 64, "reached {}", r.max_bond_used); + assert_eq!(r.max_bond_used, 1); // Below the bound at the bond asked, which is (2·256)³ an update. assert_eq!(plain.work(), metered.work()); assert!(plain.work() > 0 && plain.work() < r.updates * 512u64.pow(3) / 100, "{} over {} updates", plain.work(), r.updates); -- 2.54.0 (Apple Git-157) From 55208351c3a0dbeae89f89e37c2ba56c898c2fb8 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Sat, 7 Nov 2026 01:44:51 -0500 Subject: [PATCH 09/14] wai-quantum: the rest of the review's fixes on the reader-scaling branch - A named method that needs standard gates reads them, so a program they cannot hold is refused as the reader refuses it: on its line, with Q208 or Q210 and no J011. Both refusals past 16 controls say how a job holds the gate, and no longer say the bit-exact method does so by default. - A verdict with no intent reads the program as it ran, so a gate past 16 controls runs over MCP, as the docs say; an intent is checked in standard gates, and a job with one is refused there, on its line. - lint's dynamic_steps counts standard steps, beside gates. - options.controls is read: another value, or "whole" on a job that runs standard gates, is refused (J003), and the schema, methods list, API description, README and both MCP servers name it. - accuracy.global_phase is stated against method statevector's state, not the language's, whose U and gphase differ from it; below_table and moved_angles say they count phase gates, at 1e-14 of a turn. - operations is an engine member. - Gates held whole may take 2,000,000 qubits in all (Q210), which holds nothing the standard form holds. - A metered plan says `metered`, its work what the meter allows, and such a job does not set the method's measured rate. - The refusal, service and QEC pages and the corpus say what changed; the tests are named in CI; the conformance set holds the new text forms; the service snapshot and the agent docs are regenerated. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/wai-quantum-lang.yml | 14 + .github/workflows/wai-quantum-qec.yml | 5 + .github/workflows/wai-quantum-registry.yml | 40 + ...-11-05-many-controlled-gates-stay-whole.md | 10 +- wai/quantum-conformance/qec-text/README.md | 6 + .../qec-text/circuits/correlated.circuit | 10 + .../qec-text/models/correlated.dem | 2 + .../refuse/no_independent_flips.circuit | 4 + wai/quantum-conformance/qec-text/vectors.json | 26 + wai/quantum-cross-simulator/README.md | 6 +- wai/quantum-cross-simulator/tools/compare.py | 5 +- wai/quantum-cross-simulator/tools/report.py | 4 +- wai/wai-quantum-cli/docs/llms-full.txt | 16 +- wai/wai-quantum-cli/docs/local-mcp.json | 115 ++- wai/wai-quantum-cli/docs/service-mcp.json | 691 +++++++++++++++++- wai/wai-quantum-cli/src/mcp.rs | 2 +- wai/wai-quantum-service/README.md | 4 +- wai/wai-quantum-service/src/discovery.rs | 2 +- wai/wai-quantum-service/src/jobs.rs | 5 +- wai/wai-quantum-service/src/mcp.rs | 2 +- wai/wai-quantum/docs/job-refusals.md | 2 +- wai/wai-quantum/docs/qasm-feature-matrix.md | 2 +- wai/wai-quantum/docs/qec.md | 16 +- wai/wai-quantum/schemas/job-request.v1.json | 8 +- wai/wai-quantum/schemas/job-result.v1.json | 6 +- wai/wai-quantum/schemas/plan.v1.json | 7 +- wai/wai-quantum/src/engine/catalog.rs | 43 +- wai/wai-quantum/src/engine/job.rs | 2 +- wai/wai-quantum/src/engine/refusal.rs | 2 +- wai/wai-quantum/src/engine/registry/mod.rs | 2 +- wai/wai-quantum/src/engine/run.rs | 12 +- wai/wai-quantum/src/engine/verdict.rs | 4 +- wai/wai-quantum/src/qasm.rs | 29 +- wai/wai-quantum/src/qasm/elab.rs | 22 +- wai/wai-quantum/tests/qec_text_conformance.rs | 5 +- 35 files changed, 1014 insertions(+), 117 deletions(-) create mode 100644 wai/quantum-conformance/qec-text/circuits/correlated.circuit create mode 100644 wai/quantum-conformance/qec-text/models/correlated.dem create mode 100644 wai/quantum-conformance/qec-text/refuse/no_independent_flips.circuit diff --git a/.github/workflows/wai-quantum-lang.yml b/.github/workflows/wai-quantum-lang.yml index 4d8104261..3dd9e95ba 100644 --- a/.github/workflows/wai-quantum-lang.yml +++ b/.github/workflows/wai-quantum-lang.yml @@ -82,6 +82,20 @@ jobs: for m in qasm::diag qasm::lex qasm::parse qasm::value qasm::lang_tests qasm::whole_tests qasm::tests quantum_toolchain::tests::qasm_round_trip; do grep -q "^test $m.* \.\.\. ok$" "$RUNNER_TEMP/qasm.log" || { echo "::error::no test of $m ran"; exit 1; } done + # A gate held whole, each test by name. + for t in qasm::whole_tests::a_whole_program_lowers_to_what_the_reader_writes \ + qasm::whole_tests::every_program_of_the_reader_s_corpus_reads_alike_both_ways \ + qasm::whole_tests::only_what_would_double_stands_whole \ + qasm::whole_tests::past_what_standard_gates_hold_a_gate_still_reads_whole \ + qasm::whole_tests::the_bit_exact_circuit_holds_a_whole_gate_under_its_controls \ + qasm::whole_tests::the_whole_gate_is_nearer_the_ideal_state_than_its_expansion \ + qasm::whole_tests::the_state_vector_of_a_whole_gate_is_its_expansion_s_within_rounding \ + qasm::whole_tests::a_run_without_a_whole_gate_is_the_run_it_was \ + qasm::whole_tests::a_lowering_that_needs_standard_gates_writes_them \ + qasm::whole_tests::the_bit_exact_report_states_what_the_lowering_did \ + qasm::whole_tests::a_loop_of_wide_whole_gates_is_held_to_what_a_program_may_hold; do + grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/qasm.log" || { echo "::error::$t did not run and pass"; exit 1; } + done - name: The conformance corpus shell: bash working-directory: wai/wai-quantum diff --git a/.github/workflows/wai-quantum-qec.yml b/.github/workflows/wai-quantum-qec.yml index 0addffc1d..10aa8a43b 100644 --- a/.github/workflows/wai-quantum-qec.yml +++ b/.github/workflows/wai-quantum-qec.yml @@ -117,6 +117,11 @@ jobs: quantum_frame::tests::a_pauli_channel_samples_its_law \ quantum_frame::tests::the_cycling_gates_cycle_the_axes \ quantum_frame::tests::a_correlated_error_flips_its_targets_together \ + quantum_frame::tests::a_pauli_channel_with_independent_rates_above_one_half_is_taken \ + quantum_frame::tests::the_carrier_s_index_is_refused_in_text \ + quantum_frame::tests::a_correlated_error_with_no_index_left_for_its_carrier_is_refused \ + quantum_frame::tests::the_cycling_gates_take_no_arguments \ + quantum_frame::tests::the_qec_page_and_conformance_set_name_these_forms \ quantum_frame::tests::the_reference_colour_code_has_the_reference_s_model \ engine::mitigate::tests::pauli_channels_round_trip_through_rates_and_fidelities \ engine::mitigate::tests::the_twirled_circuit_is_the_job_where_the_noise_is_pauli \ diff --git a/.github/workflows/wai-quantum-registry.yml b/.github/workflows/wai-quantum-registry.yml index bc35f272f..44c8b611d 100644 --- a/.github/workflows/wai-quantum-registry.yml +++ b/.github/workflows/wai-quantum-registry.yml @@ -108,6 +108,46 @@ jobs: engine::refusal::tests::the_documented_table_is_the_table; do grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/engine.log" || { echo "::error::$t did not run"; exit 1; } done + # A gate held whole through a job, and the meter that holds a matrix + # product job, each test by name. + for t in engine::catalog::whole_tests::what_takes_standard_gates_gives_what_it_gave \ + engine::catalog::whole_tests::a_job_on_the_state_vectors_holds_the_gate_whole \ + engine::catalog::whole_tests::the_bit_exact_method_keeps_its_bits_unless_asked \ + engine::catalog::whole_tests::a_job_can_ask_for_standard_gates \ + engine::catalog::whole_tests::every_other_method_takes_standard_gates \ + engine::catalog::whole_tests::past_the_standard_form_only_the_state_vectors_take_it \ + engine::catalog::whole_tests::a_gate_in_a_program_that_measures_runs_whole \ + engine::catalog::whole_tests::a_verdict_holds_a_whole_run_to_its_intent \ + engine::catalog::whole_tests::a_registered_method_sees_standard_gates \ + engine::catalog::whole_tests::a_bit_exact_result_states_its_global_phase \ + engine::catalog::whole_tests::an_angle_below_the_table_is_stated \ + engine::catalog::whole_tests::a_named_matrix_product_job_is_held_to_the_bond_it_reaches \ + engine::catalog::whole_tests::a_gate_too_large_for_standard_gates_is_refused_before_they_are_written \ + engine::catalog::whole_tests::a_tiny_phase_under_many_controls_is_not_read_as_clifford \ + engine::catalog::whole_tests::a_verdict_with_no_intent_holds_a_run_past_the_standard_form \ + engine::catalog::whole_tests::a_named_method_on_standard_gates_refuses_as_the_reader_does \ + engine::catalog::whole_tests::lint_counts_a_program_s_steps_in_standard_gates \ + engine::catalog::whole_tests::the_refusal_past_16_controls_names_the_option \ + engine::catalog::whole_tests::options_controls_is_read_and_not_ignored \ + engine::catalog::whole_tests::the_stated_phase_is_relative_to_the_state_vector \ + engine::catalog::whole_tests::the_bit_exact_whole_form_gives_the_state_vector_s_amplitudes \ + engine::catalog::whole_tests::a_bit_exact_result_s_accuracy_members_hold_what_they_say \ + engine::catalog::whole_tests::the_meter_stops_a_job_that_passes_its_budget \ + engine::catalog::whole_tests::a_metered_plan_states_the_work_its_meter_allows \ + engine::catalog::tests::the_mps_plan_bounds_its_run; do + grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/engine.log" || { echo "::error::$t did not run"; exit 1; } + done + cargo test --locked --release --features full --lib -- quantum_mpsim:: quantum_sv::tests::a_gate_under_controls quantum::tests::the_walk_under_controls 2>&1 | tee "$RUNNER_TEMP/meter.log" + for t in quantum_mpsim::tests::the_meter_counts_the_bonds_reached_and_changes_nothing \ + quantum_mpsim::tests::the_meter_charges_each_move_of_the_center \ + quantum_mpsim::tests::a_far_gate_stops_at_the_update_that_passes_the_budget \ + quantum_mpsim::tests::an_update_is_priced_at_the_bond_it_spans \ + quantum_mpsim::tests::the_bound_holds_the_meter \ + quantum_sv::tests::a_gate_under_controls_is_its_dense_gate_on_any_thread_count \ + quantum_sv::tests::a_gate_under_controls_must_fit_the_register \ + quantum::tests::the_walk_under_controls_gives_the_scan_s_bits; do + grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/meter.log" || { echo "::error::$t did not run"; exit 1; } + done - name: The example, tested and run shell: bash working-directory: wai/wai-quantum diff --git a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md index c808cf32d..4086f7500 100644 --- a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md +++ b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md @@ -1,12 +1,12 @@ ### wai-quantum: a gate under many controls stays one operation on the state vector, the bit-exact method says what its lowering did, and the error-correction reader takes `C_XYZ`, `E` and `PAULI_CHANNEL_1` -**What a result gives.** A job on `statevector` whose program holds a gate under controls that used to be written through a phase polynomial (`x`, `y`, `z` or `h` under three or more controls; `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` or `sxdg` under two or more) runs that gate as one operation; its amplitudes move by double-precision rounding, within the method's bound, and `"options": {"controls": "standard"}` gives the old bits. A job on `exact` gives the bits it gave, by default: the bit-exact method's bits are the rounding of each gate it applies, so it runs the standard gates unless the job asks for `"options": {"controls": "whole"}`, which holds such a gate whole under its controls, nearer the ideal state by no more than the extension's published bound and with another `state_hash`. A result on `exact` also says, in `accuracy`, the global phase its lowering drops and any angle it ran as no phase or moved (below), so a job whose program holds `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` or `u`, or such an angle, gives the same bits and hash in a result whose JSON, and so whose receipt, holds those members too. Every other method and request gives what it gave. +**What a result gives.** A job on `statevector` whose program holds a gate under controls that used to be written through a phase polynomial (`x`, `y`, `z` or `h` under three or more controls; `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` or `sxdg` under two or more) runs that gate as one operation; its amplitudes and expectation values move by double-precision rounding, within the method's bound, its plan's and estimate's `work` fall with the gates it runs, and `"options": {"controls": "standard"}` gives the old bits. A job on `exact` gives the bits it gave, by default: the bit-exact method's bits are the rounding of each gate it applies, so it runs the standard gates unless the job asks for `"options": {"controls": "whole"}`, which holds such a gate whole under its controls, nearer the ideal state by no more than the extension's published bound and with another `state_hash`. `controls` is read: another value is refused, and so is `"whole"` on a job that runs standard gates (`J003`). A result on `exact` also says, in `accuracy`, the global phase its lowering drops and any angle it ran as no phase or moved (below), so a job whose program holds `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` or `u`, or such an angle, gives the same bits and hash in a result whose JSON, and so whose receipt, holds those members too. Every other method and request gives what it gave. - **The reader.** `qasm::read_whole` keeps a gate whose standard gates would double as one operation (`Op::is_whole`), under as many as 255 controls. `Program::lowered` writes it in standard gates: exactly what `qasm::read` gives of the same text, its steps, timing and records moved with it, one lowering behind both. `read` and `parse` give standard gates as they did, and refuse past 16 controls and past `MAX_OPS` as they did. The Clifford check of a program holding a gate whole counts its standard gates first and refuses what `read` refuses, with `Q208` or `Q210`, before writing any; it reads those gates' phases exactly, so a phase under many controls too small for the reader's tolerance (`ctrl(16) @ p(1e-7)`) is not taken for none. A method's plan makes only the circuit it reads: the bit-exact circuit for `exact`, the Clifford gates for `stabilizer`. - **The state vector.** `StateVector::run_ops` applies such a gate as one (`Controlled`), visiting only the `2^(n − c)` amplitudes its controls leave on; a run without one is `run`, to the bit. Two Grover iterations on 14 qubits run as 130 operations, not 131,186 gates. Asked for, the bit-exact simulator holds the gate under its controls and walks only those indices too; a gate under two or more controls in standard gates (a Toffoli) takes the same walk, to the bit of the scan it replaces. -- **What a job counts.** `gates` counts standard gates however the method ran them, as it always has, so a receipt's provenance carries the count it carried; `operations`, a new optional member of a result and of `lint_qasm`, says what a method holding gates whole ran. A job with `compile`, `noise`, `mitigate`, `target`, `provider` or a named `fabric` place runs standard gates as it did, as do the other methods, a registered method among them. Methods that need standard gates refuse what those cannot hold with `Q208` or `Q210`, and `auto` passes over them. +- **What a job counts.** `gates` counts standard gates however the method ran them, as it always has, so a receipt's provenance carries the count it carried, and `lint_qasm`'s `dynamic_steps` counts steps the same way; `operations`, a new optional member of a result and of `lint_qasm`, says what a method holding gates whole ran. A provenance's `plan.work` follows what the method ran. A job with `compile`, `noise`, `mitigate`, `target`, `provider` or a named `fabric` place runs standard gates as it did, as do the other methods, a registered method among them. Methods that need standard gates, named, refuse what those cannot hold as the reader does, on its line, with `Q208` or `Q210`, saying how a job holds such a gate; `auto` passes over them. A job with an `intent` is held to standard gates, since the intent is checked in them; a verdict with none, which both MCP servers ask for on every run, reads the program as it ran. Gates held whole may take 2,000,000 qubits in all (`Q210`), which holds no program the standard form holds. - **What depended on the expansion** did not change: the reader's standard gates, the bit-exact method's hash, a compile, the QIR and jeff exports and the resource estimate's counts, each checked against this engine's output before the change, and the expected hashes of `quantum-conformance/`. -- **The bit-exact method says what its lowering did** (`accuracy`, each only when there is something to say). `global_phase`: `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `u` become phase gates, so OpenQASM's state is `e^(i·radians)` times the amplitudes given; the phase is exact, in 2^33rds of a turn, whole turns counted. `below_table`: an angle of `2π/2^47` or less ran as no phase, as the table's arithmetic has it, and now says so here and in the plan's `why`. `moved_angles`: an angle within the reader's tolerance of a dyadic one, by more than a double's rounding of it. -- **The matrix-product job.** A job that names `mps` is no longer refused on an estimate at the bond it asks for: it runs under a meter of the bonds it holds (`Chain::run_within`, `Chain::work`), which changes no number, and stops with `J011`, saying where, if those pass one job's work. The meter counts each two-site update, each move of the orthogonality center and each one-qubit gate, and holds the budget at each update, inside a gate that crosses the chain too. The 30-qubit QFT at `max_bond` 256 runs, and reaches far less. A job with `auto` is held to the estimate, and told what naming the method does. The estimate now walks the same steps at the bond asked for (`WorkBound`), so it bounds the meter: a plan's `work` for `mps` is larger than before where gates move the center far, and `auto` passes over `mps` for a few circuits it took before. +- **The bit-exact method says what its lowering did** (`accuracy`, each only when there is something to say). `global_phase`: `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `u` become phase gates, so method statevector's state of the program that ran is `e^(i·radians)` times the amplitudes given; the phase is exact, in 2^33rds of a turn, whole turns counted. The language's own state can differ from both: its `U` is `e^(iθ/2)` times the matrix both take as `u`, the reader drops an uncontrolled `gphase`, and a compiled job's program is the compile's. `below_table`: a phase gate within the reader's tolerance, 1e-14 of a turn, of a whole turn ran as no phase, as the table's arithmetic has it, and now says so here and in the plan's `why`. `moved_angles`: a phase gate within that tolerance of a dyadic angle, by more than a double's rounding of it. Their `angles` count the lowering's phase gates, so one angle written may be several. +- **The matrix-product job.** A job that names `mps` is no longer refused on an estimate at the bond it asks for: it runs under a meter of the bonds it holds (`Chain::run_within`, `Chain::work`), which changes no number, and stops with `J011`, saying where, if those pass one job's work. The meter counts each two-site update, each move of the orthogonality center and each one-qubit gate, and holds the budget at each update, inside a gate that crosses the chain too. The 30-qubit QFT of a basis state at `max_bond` 256 runs, a product state at every step, at bond 1. Its plan says `metered`, and its `work` is then what the meter allows, so a dry run's time is the meter's and such a job does not set the method's measured rate. A job with `auto` is held to the estimate, and told what naming the method does. The estimate now walks the same steps at the bond asked for (`WorkBound`), so it bounds the meter: a plan's `work` for `mps` is larger than before where gates move the center far, and `auto` passes over `mps` for a few circuits it took before. - **The error-correction text.** `C_XYZ` and `C_ZYX`; `E` (or `CORRELATED_ERROR`), a flip on a qubit of its own handed to its Pauli targets, so a circuit with one holds one qubit more than its text names; and `PAULI_CHANNEL_1`, as the independent flips with its law, a rate above 1/2 among them where the law needs one (`(0.6, 0.3, 0.05)`). A channel with no such flips (`PAULI_CHANNEL_1(0.1, 0.1, 0)`) is refused with its line. `C_XYZ` and `C_ZYX` take no arguments and refuse one. A text may not name qubit 4294967295, the index the carrier is read under, nor leave a correlated error no index for its carrier (qubit 4294967294 named); both are refused with their line. -- **The corpus** ([quantum-cross-simulator/](quantum-cross-simulator/README.md)): rerun, with the bit-exact method's amplitudes held to OpenQASM's with the phase its result states, and before-and-after timings on one host. +- **The corpus** ([quantum-cross-simulator/](quantum-cross-simulator/README.md)): rerun, with the bit-exact method's amplitudes held to the reference's with the phase its result states, and before-and-after timings on one host. diff --git a/wai/quantum-conformance/qec-text/README.md b/wai/quantum-conformance/qec-text/README.md index 5501a23c3..1dcbbfdfc 100644 --- a/wai/quantum-conformance/qec-text/README.md +++ b/wai/quantum-conformance/qec-text/README.md @@ -35,6 +35,12 @@ The files: coordinates shifted by `SHIFT_COORDS`. A tag on a noise instruction is the tag of every mechanism it makes, and mechanisms with one symptom set but different tags stay apart. +- `correlated`: written by hand. `C_XYZ` and `C_ZYX` on a qubit that a + detector reads through them; `E` and `CORRELATED_ERROR` on Pauli targets, so + the circuit holds one qubit more than its text names; `PAULI_CHANNEL_1`, as + the independent flips with its law, one rate above 1/2. +- `refuse/no_independent_flips.circuit`: `PAULI_CHANNEL_1(0.1, 0.1, 0)`, which + no independent flips give. - `models/decomposed.dem`: written by hand. Decomposed errors, a tagged one, a `repeat` block with `shift_detectors`, detector coordinates and a declared observable no error flips. diff --git a/wai/quantum-conformance/qec-text/circuits/correlated.circuit b/wai/quantum-conformance/qec-text/circuits/correlated.circuit new file mode 100644 index 000000000..c21209036 --- /dev/null +++ b/wai/quantum-conformance/qec-text/circuits/correlated.circuit @@ -0,0 +1,10 @@ +R 0 1 2 +C_XYZ 0 +C_ZYX 0 +E(0.01) X0 Y1 +CORRELATED_ERROR(0.02) Z1 X2 +PAULI_CHANNEL_1(0.6, 0.3, 0.05) 2 +M 0 1 2 +DETECTOR rec[-3] +DETECTOR rec[-2] +OBSERVABLE_INCLUDE(0) rec[-1] diff --git a/wai/quantum-conformance/qec-text/models/correlated.dem b/wai/quantum-conformance/qec-text/models/correlated.dem new file mode 100644 index 000000000..e26e45fbe --- /dev/null +++ b/wai/quantum-conformance/qec-text/models/correlated.dem @@ -0,0 +1,2 @@ +error(0.8839999999999999) L0 +error(0.01) D0 D1 diff --git a/wai/quantum-conformance/qec-text/refuse/no_independent_flips.circuit b/wai/quantum-conformance/qec-text/refuse/no_independent_flips.circuit new file mode 100644 index 000000000..8ba79fc25 --- /dev/null +++ b/wai/quantum-conformance/qec-text/refuse/no_independent_flips.circuit @@ -0,0 +1,4 @@ +R 0 +PAULI_CHANNEL_1(0.1, 0.1, 0) 0 +M 0 +DETECTOR rec[-1] diff --git a/wai/quantum-conformance/qec-text/vectors.json b/wai/quantum-conformance/qec-text/vectors.json index a87d4384e..cfa69a9b7 100644 --- a/wai/quantum-conformance/qec-text/vectors.json +++ b/wai/quantum-conformance/qec-text/vectors.json @@ -69,6 +69,18 @@ "model": "models/tagged.dem", "model_blake3": "eb62f2e8d90f4f9a121314949852929d390112ef82cef91979ae7bd73182a95f", "mechanisms": 10 + }, + { + "file": "circuits/correlated.circuit", + "qubits": 4, + "measurements": 3, + "detectors": 2, + "observables": 1, + "tags": [], + "text_blake3": "04ecd1c77c5e22ff4570985e360731fc2a3d4eb2a3dad4c6cdda1c44ecb014c9", + "model": "models/correlated.dem", + "model_blake3": "5610664e2dde57ba866720afe009cc26fb11af8e511a2f31e477577a2a5e623f", + "mechanisms": 2 } ], "models": [ @@ -117,6 +129,15 @@ "tagged": 6, "text_blake3": "eb62f2e8d90f4f9a121314949852929d390112ef82cef91979ae7bd73182a95f" }, + { + "file": "models/correlated.dem", + "detectors": 2, + "observables": 1, + "mechanisms": 2, + "decomposed": 0, + "tagged": 0, + "text_blake3": "5610664e2dde57ba866720afe009cc26fb11af8e511a2f31e477577a2a5e623f" + }, { "file": "models/decomposed.dem", "detectors": 7, @@ -128,6 +149,11 @@ } ], "refuse": [ + { + "file": "refuse/no_independent_flips.circuit", + "line": 2, + "contains": "no form as independent" + }, { "file": "refuse/unsupported.circuit", "line": 3, diff --git a/wai/quantum-cross-simulator/README.md b/wai/quantum-cross-simulator/README.md index acbfa210a..9790aa782 100644 --- a/wai/quantum-cross-simulator/README.md +++ b/wai/quantum-cross-simulator/README.md @@ -199,7 +199,7 @@ extension states modulus 1.0000189 and within 10^-5 rad. These are integers, the matrices by a global phase (a `strict` distance of up to 1.97 on a rotation by a whole turn). No measurement sees it, and under a control the method is right (`controlled_rz_full_turn`, `gate_crz`, `gate_cu`). A result on this method states the phase (`accuracy.global_phase`, - exactly, in 2^33rds of a turn), and the corpus holds the method's state to OpenQASM's with that + exactly, in 2^33rds of a turn), and the corpus holds the method's state to the reference's with that phase, nothing fitted. - **Angles below the table.** The bit-exact method reads an angle within 10^-14 of a turn of a dyadic one as that dyadic. A phase of 2π/2^k is therefore refused for k = 33 … 46 (`[Q500]`), @@ -634,7 +634,9 @@ Host: Apple M3 Ultra, macOS 27.2, 32 logical CPUs, 256 GiB, arm64. Each figure i Host: Apple M3 Ultra, macOS 27.2, 32 logical CPUs, 256 GiB, arm64. The same harness and circuits, with the engine under test built before and after a gate under many controls stood whole on its state vector, one build straight after the other: each figure is the engine's own call, the median of 5 runs (the minimum in brackets), and ops are the operations it ran. -| case | engine | threads | before: ops | before: seconds, median (min) | after: ops | after: seconds, median (min) | load average before → after | +`wai.exact_whole`'s before rows ran a build with no such option, so they are standard gates, as their ops show. The last column is the one-minute load as each build's row began. + +| case | engine | threads | before: ops | before: seconds, median (min) | after: ops | after: seconds, median (min) | load average, before build → after build | |---|---|---|---|---|---|---|---| | qft_n20 | `wai.statevector` | all (32) | 230 | 0.0227 (0.0223) | 230 | 0.0326 (0.0307) | 30.9 → 84.8 | | qft_n20 | `aer.statevector` | 32 | 231 | 0.0708 (0.0672) | 231 | 0.0841 (0.0824) | 30.9 → 84.9 | diff --git a/wai/quantum-cross-simulator/tools/compare.py b/wai/quantum-cross-simulator/tools/compare.py index 351b35b3c..6bfc3f3e6 100644 --- a/wai/quantum-cross-simulator/tools/compare.py +++ b/wai/quantum-cross-simulator/tools/compare.py @@ -551,7 +551,8 @@ def check_state_entry(e, runner, rep, engines): c = rep.add(e["id"], eng, quantity, measured, bound, measured <= bound, note=why) c["strict"] = d c["global_phase"] = phase - # The phase the method's result states: with it, the state is OpenQASM's, nothing fitted. + # The phase the method's result states: with it, the state is the reference's, which writes + # each gate as method statevector does, nothing fitted. turn = complex(math.cos(ans.get("global_phase", 0.0)), math.sin(ans.get("global_phase", 0.0))) stated = exact.distance(ref.re, ref.im, *[exact.ints_from_floats([float(x) for x in part]) for part in ((vec * turn).real, (vec * turn).imag)])[0] rep.add(e["id"], eng, "distance from the exact state, with the global phase its result states", stated, bound + 8 * tol.U_DOUBLE, stated <= bound + 8 * tol.U_DOUBLE) @@ -582,7 +583,7 @@ def check_state_entry(e, runner, rep, engines): return planned = ans.get("planned") # The bit-exact method lowers rz to a phase gate, and so on; its result states the phase that - # drops, and its amplitudes are held to OpenQASM's with that phase, nothing fitted. + # drops, and its amplitudes are held to the reference's with that phase, nothing fitted. turn = 1 if planned == "exact": stated_phase = ((ans.get("accuracy") or {}).get("global_phase") or {}).get("radians", 0.0) diff --git a/wai/quantum-cross-simulator/tools/report.py b/wai/quantum-cross-simulator/tools/report.py index 8a6fc5ef9..fffd14fd4 100644 --- a/wai/quantum-cross-simulator/tools/report.py +++ b/wai/quantum-cross-simulator/tools/report.py @@ -172,7 +172,9 @@ def results_section(): out.append("") out.append("Host: %s. The same harness and circuits, with the engine under test built before and after a gate under many controls stood whole on its state vector, one build straight after the other: each figure is the engine's own call, the median of %d runs (the minimum in brackets), and ops are the operations it ran." % (host_line(p), p["repeat"])) out.append("") - out.append("| case | engine | threads | before: ops | before: seconds, median (min) | after: ops | after: seconds, median (min) | load average before → after |") + out.append("`wai.exact_whole`'s before rows ran a build with no such option, so they are standard gates, as their ops show. The last column is the one-minute load as each build's row began.") + out.append("") + out.append("| case | engine | threads | before: ops | before: seconds, median (min) | after: ops | after: seconds, median (min) | load average, before build → after build |") out.append("|---|---|---|---|---|---|---|---|") for row in p["rows"]: cell = lambda r: ("not run: %s" % r["not_run"][:90]) if r.get("not_run") else "%s (%s)" % (fmt_seconds(r["seconds_median"]), fmt_seconds(r["seconds_min"])) diff --git a/wai/wai-quantum-cli/docs/llms-full.txt b/wai/wai-quantum-cli/docs/llms-full.txt index 96e6d7075..2ba31b410 100644 --- a/wai/wai-quantum-cli/docs/llms-full.txt +++ b/wai/wai-quantum-cli/docs/llms-full.txt @@ -55,7 +55,7 @@ Parameters: - `observables` (array): Pauli observables, as "Z0 Z1" or "0.5 X2". - `amplitudes` (array): Basis states whose amplitudes to return, as bit strings with the highest qubit first. - `noise` (object): Channel probabilities -- `options` (object): Method options: max_bond, fusion, trajectories, threshold, memory_gb. +- `options` (object): Method options: max_bond, fusion, controls, trajectories, threshold, memory_gb. - `compile` (object): Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's "compiled" states its distance from the program. - `target` (any): A device target: its name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to the target's gates, placed where it is most likely to succeed and simulated under the target's noise, the target's hash in the receipt; noise may not be given beside it. - `fabric` (any): Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than this host's CPU for the job's size and fusion, otherwise the CPU; list_fabric states the rule and its numbers), cpu, accelerator (the first certified accelerator member that holds the state, the next taking over if it fails during the run), a member's id or key (list_fabric), or a list of members, a power of two of them, the state split by its top qubits into one partition on each; a pauli job's sum of terms runs on the member accelerator or its id or key names. Every member placed is certified bit-exact against the CPU, so the answers are the CPU's; the result's "fabric" names where the state ran, sealed by the receipt. A placement this host cannot honour is refused (J013). @@ -79,7 +79,7 @@ Parameters: - `observables` (array): Pauli observables, as "Z0 Z1" or "0.5 X2". - `amplitudes` (array): Basis states whose amplitudes to return, as bit strings with the highest qubit first. - `noise` (object): Channel probabilities -- `options` (object): Method options: max_bond, fusion, trajectories, threshold, memory_gb. +- `options` (object): Method options: max_bond, fusion, controls, trajectories, threshold, memory_gb. - `compile` (object): Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's "compiled" states its distance from the program. - `target` (any): A device target: its name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to the target's gates, placed where it is most likely to succeed and simulated under the target's noise, the target's hash in the receipt; noise may not be given beside it. - `fabric` (any): Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than this host's CPU for the job's size and fusion, otherwise the CPU; list_fabric states the rule and its numbers), cpu, accelerator (the first certified accelerator member that holds the state, the next taking over if it fails during the run), a member's id or key (list_fabric), or a list of members, a power of two of them, the state split by its top qubits into one partition on each; a pauli job's sum of terms runs on the member accelerator or its id or key names. Every member placed is certified bit-exact against the CPU, so the answers are the CPU's; the result's "fabric" names where the state ran, sealed by the receipt. A placement this host cannot honour is refused (J013). @@ -431,7 +431,7 @@ Parameters: - `observables` (array): Pauli observables, as "Z0 Z1" or "0.5 X2". - `amplitudes` (array): Basis states whose amplitudes to return, as bit strings with the highest qubit first. - `noise` (object): Channel probabilities -- `options` (object): Method options: max_bond, fusion, trajectories, threshold, memory_gb. +- `options` (object): Method options: max_bond, fusion, controls, trajectories, threshold, memory_gb. - `compile` (object): Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's "compiled" states its distance from the program. - `target` (any, required): A device target: its name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to the target's gates, placed where it is most likely to succeed and simulated under the target's noise, the target's hash in the receipt; noise may not be given beside it. - `fabric` (any): Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than this host's CPU for the job's size and fusion, otherwise the CPU; list_fabric states the rule and its numbers), cpu, accelerator (the first certified accelerator member that holds the state, the next taking over if it fails during the run), a member's id or key (list_fabric), or a list of members, a power of two of them, the state split by its top qubits into one partition on each; a pauli job's sum of terms runs on the member accelerator or its id or key names. Every member placed is certified bit-exact against the CPU, so the answers are the CPU's; the result's "fabric" names where the state ran, sealed by the receipt. A placement this host cannot honour is refused (J013). @@ -632,7 +632,7 @@ Parameters: - `noise` (object): Optional noise, each a probability: depolarizing_1q, depolarizing_2q, amplitude_damping, dephasing (after each gate on its qubits), readout (each measured bit). - `method` (string, one of auto, exact, statevector, statevector_single, stabilizer, pauli, mps, tensor_network, cutrank, cutrank_single, stabilizer_rank, density_matrix, trajectories, pulse): Leave as auto unless you need a particular method; pulse runs a pulse program (OpenPulse calibrations on physical qubits, see pulse_schedule) under the pulse options, its error bounded. - `seed` (integer): Sampling seed (default 1); the same job and seed give the same counts. -- `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories. +- `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories. - `compile` (object): Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's `compiled` states its distance from the program. - `target` (any): A device target: a built-in target's name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to its gates, placed where it is most likely to succeed and simulated under its noise, its hash in the receipt; not with noise or amplitudes. The service reads the document given and fetches nothing. - `fabric` (any): Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than the host's CPU for the job's size and fusion, otherwise the CPU), cpu, accelerator (any certified accelerator member), a member's id or key, or a list of members, a power of two of them, the state split by its top qubits into one partition on each; a pauli job's sum of terms runs on the member accelerator or its id or key names. Every member placed is certified bit-exact against the CPU, so the answers are the CPU's; the result's `fabric` names where the state ran, sealed by the receipt. A placement the service cannot honour is refused (J013): it places only on its CPU. @@ -656,7 +656,7 @@ Parameters: - `noise` (object): Optional noise, each a probability: depolarizing_1q, depolarizing_2q, amplitude_damping, dephasing (after each gate on its qubits), readout (each measured bit). - `method` (string, one of auto, exact, statevector, statevector_single, stabilizer, pauli, mps, tensor_network, cutrank, cutrank_single, stabilizer_rank, density_matrix, trajectories, pulse): Leave as auto unless you need a particular method; pulse runs a pulse program (OpenPulse calibrations on physical qubits, see pulse_schedule) under the pulse options, its error bounded. - `seed` (integer): Sampling seed (default 1); the same job and seed give the same counts. -- `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories. +- `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories. - `compile` (object): Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's `compiled` states its distance from the program. - `target` (any): A device target: a built-in target's name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to its gates, placed where it is most likely to succeed and simulated under its noise, its hash in the receipt; not with noise or amplitudes. The service reads the document given and fetches nothing. - `fabric` (any): Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than the host's CPU for the job's size and fusion, otherwise the CPU), cpu, accelerator (any certified accelerator member), a member's id or key, or a list of members, a power of two of them, the state split by its top qubits into one partition on each; a pauli job's sum of terms runs on the member accelerator or its id or key names. Every member placed is certified bit-exact against the CPU, so the answers are the CPU's; the result's `fabric` names where the state ran, sealed by the receipt. A placement the service cannot honour is refused (J013): it places only on its CPU. @@ -681,7 +681,7 @@ Parameters: - `noise` (object): Optional noise, each a probability: depolarizing_1q, depolarizing_2q, amplitude_damping, dephasing (after each gate on its qubits), readout (each measured bit). - `method` (string, one of auto, exact, statevector, statevector_single, stabilizer, pauli, mps, tensor_network, cutrank, cutrank_single, stabilizer_rank, density_matrix, trajectories, pulse): Leave as auto unless you need a particular method; pulse runs a pulse program (OpenPulse calibrations on physical qubits, see pulse_schedule) under the pulse options, its error bounded. - `seed` (integer): Sampling seed (default 1); the same job and seed give the same counts. -- `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories. +- `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories. - `compile` (object): Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's `compiled` states its distance from the program. - `target` (any): A device target: a built-in target's name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to its gates, placed where it is most likely to succeed and simulated under its noise, its hash in the receipt; not with noise or amplitudes. The service reads the document given and fetches nothing. - `fabric` (any): Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than the host's CPU for the job's size and fusion, otherwise the CPU), cpu, accelerator (any certified accelerator member), a member's id or key, or a list of members, a power of two of them, the state split by its top qubits into one partition on each; a pauli job's sum of terms runs on the member accelerator or its id or key names. Every member placed is certified bit-exact against the CPU, so the answers are the CPU's; the result's `fabric` names where the state ran, sealed by the receipt. A placement the service cannot honour is refused (J013): it places only on its CPU. @@ -828,7 +828,7 @@ Parameters: - `noise` (object): Optional noise, each a probability: depolarizing_1q, depolarizing_2q, amplitude_damping, dephasing (after each gate on its qubits), readout (each measured bit). - `params` (object): A value for each of the program's parameters (input float theta;, input angle phi;), as {"theta": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes. - `seed` (integer): Sampling seed (default 1); the same job and seed give the same counts. -- `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories. +- `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories. - `compile` (object): Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's `compiled` states its distance from the program. - `target` (any, required): A device target: a built-in target's name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to its gates, placed where it is most likely to succeed and simulated under its noise, its hash in the receipt; not with noise or amplitudes. The service reads the document given and fetches nothing. - `fabric` (any): Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than the host's CPU for the job's size and fusion, otherwise the CPU), cpu, accelerator (any certified accelerator member), a member's id or key, or a list of members, a power of two of them, the state split by its top qubits into one partition on each; a pauli job's sum of terms runs on the member accelerator or its id or key names. Every member placed is certified bit-exact against the CPU, so the answers are the CPU's; the result's `fabric` names where the state ran, sealed by the receipt. A placement the service cannot honour is refused (J013): it places only on its CPU. @@ -1068,7 +1068,7 @@ Each construct below is supported (read as the language defines it), lowered (re | Construct | Status | Codes | |---|---|---| -| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`); `exact` does so only when asked (`"options": {"controls": "whole"}`), since its bits are those of the gates it applies | Q201, Q207, Q208 | +| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`); `exact` does so only when asked (`"options": {"controls": "whole"}`), since its bits are those of the gates it applies. Those gates are `x`, `y`, `z` and `h` under three or more controls and `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` and `sxdg` under two or more, each lowered to the method's gates under its controls (`sx` as `h s h`, `ry` as `sdg h rz h s`), and not `p(pi)`, which is `z`. A job with an `intent` is held to 16: an intent is checked in standard gates, while a verdict with none reads the program as it ran | Q201, Q207, Q208 | | `inv @` on any gate | lowered exactly: each gate's inverse, in reverse order | Q202 | | `pow(k) @`, `k` a whole number | lowered exactly: angles scaled or the gate repeated; negative `k` repeats the inverse | Q203 | | `pow(r) @`, `r` fractional | lowered where an exact principal root exists (`pow(1/2) @ x` is `sx`; rotations by less than 2π; phases; controlled forms); refused otherwise (`u`, `cu`, user gates) | Q204, Q205 | diff --git a/wai/wai-quantum-cli/docs/local-mcp.json b/wai/wai-quantum-cli/docs/local-mcp.json index 87a45d098..7abb0b230 100644 --- a/wai/wai-quantum-cli/docs/local-mcp.json +++ b/wai/wai-quantum-cli/docs/local-mcp.json @@ -119,7 +119,7 @@ }, "options": { "type": "object", - "description": "Method options: max_bond, fusion, trajectories, threshold, memory_gb." + "description": "Method options: max_bond, fusion, controls, trajectories, threshold, memory_gb." }, "compile": { "type": "object", @@ -727,7 +727,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -1479,7 +1488,7 @@ }, "global_phase": { "type": "object", - "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", "required": [ "turns_over_2_33", "radians", @@ -1502,7 +1511,7 @@ }, "below_table": { "type": "object", - "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", "required": [ "angles", "largest_radians", @@ -1523,7 +1532,7 @@ }, "moved_angles": { "type": "object", - "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", "required": [ "angles", "largest_radians", @@ -4563,7 +4572,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -5313,7 +5331,7 @@ }, "global_phase": { "type": "object", - "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", "required": [ "turns_over_2_33", "radians", @@ -5336,7 +5354,7 @@ }, "below_table": { "type": "object", - "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", "required": [ "angles", "largest_radians", @@ -5357,7 +5375,7 @@ }, "moved_angles": { "type": "object", - "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", "required": [ "angles", "largest_radians", @@ -8993,7 +9011,7 @@ }, "options": { "type": "object", - "description": "Method options: max_bond, fusion, trajectories, threshold, memory_gb." + "description": "Method options: max_bond, fusion, controls, trajectories, threshold, memory_gb." }, "compile": { "type": "object", @@ -9437,7 +9455,8 @@ }, "work": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The method's own unit: an upper bound on what the run takes where the method's cost is known beforehand, and with `metered` what the meter holds it to." }, "qubits": { "type": "integer", @@ -9492,6 +9511,10 @@ } } }, + "metered": { + "type": "boolean", + "description": "True when a job naming method mps would pass one job's work at the bond it asks for: it runs under a meter of the bonds it reaches, may take far less than `work`, and stops with J011 if it passes `work`." + }, "verdict": { "title": "wai.quantum.verdict/1", "description": "How far the engine checked an answer about a program, as one level of an ordered ladder (wai-quantum://docs/verdicts): refused, parsed, executed, evidence, proof. A level says how far the engine checked, not that the answer is good: holds says whether the intents held (true, false, or null when none was decided). A job's result carries one under verdict when the job gives an intent or asks for one, and the receipt seals it; both MCP servers state one beside every answer about a program.", @@ -30428,7 +30451,7 @@ }, "options": { "type": "object", - "description": "Method options: max_bond, fusion, trajectories, threshold, memory_gb." + "description": "Method options: max_bond, fusion, controls, trajectories, threshold, memory_gb." }, "compile": { "type": "object", @@ -31039,7 +31062,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -31791,7 +31823,7 @@ }, "global_phase": { "type": "object", - "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", "required": [ "turns_over_2_33", "radians", @@ -31814,7 +31846,7 @@ }, "below_table": { "type": "object", - "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", "required": [ "angles", "largest_radians", @@ -31835,7 +31867,7 @@ }, "moved_angles": { "type": "object", - "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", "required": [ "angles", "largest_radians", @@ -34875,7 +34907,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -35625,7 +35666,7 @@ }, "global_phase": { "type": "object", - "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", "required": [ "turns_over_2_33", "radians", @@ -35648,7 +35689,7 @@ }, "below_table": { "type": "object", - "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", "required": [ "angles", "largest_radians", @@ -35669,7 +35710,7 @@ }, "moved_angles": { "type": "object", - "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", "required": [ "angles", "largest_radians", @@ -51068,7 +51109,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -51820,7 +51870,7 @@ }, "global_phase": { "type": "object", - "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", "required": [ "turns_over_2_33", "radians", @@ -51843,7 +51893,7 @@ }, "below_table": { "type": "object", - "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", "required": [ "angles", "largest_radians", @@ -51864,7 +51914,7 @@ }, "moved_angles": { "type": "object", - "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", "required": [ "angles", "largest_radians", @@ -54904,7 +54954,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -55654,7 +55713,7 @@ }, "global_phase": { "type": "object", - "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", "required": [ "turns_over_2_33", "radians", @@ -55677,7 +55736,7 @@ }, "below_table": { "type": "object", - "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", "required": [ "angles", "largest_radians", @@ -55698,7 +55757,7 @@ }, "moved_angles": { "type": "object", - "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", "required": [ "angles", "largest_radians", diff --git a/wai/wai-quantum-cli/docs/service-mcp.json b/wai/wai-quantum-cli/docs/service-mcp.json index d58babf6e..1f639af23 100644 --- a/wai/wai-quantum-cli/docs/service-mcp.json +++ b/wai/wai-quantum-cli/docs/service-mcp.json @@ -91,7 +91,7 @@ }, "options": { "type": "object", - "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories." + "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories." }, "compile": { "type": "object", @@ -743,7 +743,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -1458,7 +1467,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -1487,6 +1502,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -4508,7 +4588,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -5221,7 +5310,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -5250,6 +5345,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -10183,7 +10343,7 @@ }, "options": { "type": "object", - "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories." + "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories." }, "compile": { "type": "object", @@ -10839,7 +10999,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -11554,7 +11723,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -11583,6 +11758,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -14604,7 +14844,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -15317,7 +15566,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -15346,6 +15601,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -20279,7 +20599,7 @@ }, "options": { "type": "object", - "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories." + "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories." }, "compile": { "type": "object", @@ -21955,7 +22275,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -22670,7 +22999,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -22699,6 +23034,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -25720,7 +26120,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -26433,7 +26842,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -26462,6 +26877,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -44042,7 +44522,7 @@ }, "options": { "type": "object", - "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories." + "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories." }, "compile": { "type": "object", @@ -44687,7 +45167,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -45402,7 +45891,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -45431,6 +45926,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -48452,7 +49012,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", @@ -49165,7 +49734,13 @@ }, "gates": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." }, "accuracy": { "type": "object", @@ -49194,6 +49769,71 @@ "note": { "type": "string" }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, "fusion": { "type": "integer" }, @@ -52401,7 +53041,16 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), and memory_gb." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "type": "object", diff --git a/wai/wai-quantum-cli/src/mcp.rs b/wai/wai-quantum-cli/src/mcp.rs index 70b0d8144..d92532e9e 100644 --- a/wai/wai-quantum-cli/src/mcp.rs +++ b/wai/wai-quantum-cli/src/mcp.rs @@ -123,7 +123,7 @@ fn job_schema() -> Value { "observables": { "type": "array", "items": { "type": "string" }, "description": "Pauli observables, as \"Z0 Z1\" or \"0.5 X2\"." }, "amplitudes": { "type": "array", "items": { "type": "string" }, "description": "Basis states whose amplitudes to return, as bit strings with the highest qubit first." }, "noise": { "type": "object", "description": "Channel probabilities", "properties": catalog::NOISE_CHANNELS.iter().map(|k| (k.to_string(), json!({ "type": "number", "minimum": 0, "maximum": 1 }))).collect::>(), "additionalProperties": false }, - "options": { "type": "object", "description": "Method options: max_bond, fusion, trajectories, threshold, memory_gb." }, + "options": { "type": "object", "description": "Method options: max_bond, fusion, controls, trajectories, threshold, memory_gb." }, "compile": compile_options_schema("Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's \"compiled\" states its distance from the program."), "target": { "description": "A device target: its name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to the target's gates, placed where it is most likely to succeed and simulated under the target's noise, the target's hash in the receipt; noise may not be given beside it." }, "fabric": fabric_schema(), diff --git a/wai/wai-quantum-service/README.md b/wai/wai-quantum-service/README.md index db996b0c9..27fde1a4c 100644 --- a/wai/wai-quantum-service/README.md +++ b/wai/wai-quantum-service/README.md @@ -27,7 +27,7 @@ A job is JSON: | `observables` | Pauli strings such as `"Z0 Z1"`, or `{"pauli": "X3 Y4", "coeff": 0.5}` | | `amplitudes` | bit strings, one character per qubit, qubit `n − 1` first | | `noise` | `{"depolarizing_1q", "depolarizing_2q", "amplitude_damping", "dephasing", "readout"}`, each a probability | -| `options` | per method: `threshold`, `max_weight` and `ladder` (pauli), `max_bond` and `cutoff` (mps), `fusion` (statevector), `trajectories`, `memory_gb` | +| `options` | per method: `threshold`, `max_weight` and `ladder` (pauli), `max_bond` and `cutoff` (mps), `fusion` (statevector), `controls` (statevector and exact: `"standard"` or `"whole"`, a gate under many controls in standard gates or as one), `trajectories`, `memory_gb` | | `compile` | `{"epsilon", "level", "basis"}`: compile the program first (as `POST /v1/compile` does) and run the compiled circuit. With `basis` `clifford_t` (the default) it runs on the bit-exact method, and the result's `compiled` states its distance from the program | | `intent` | what the program must do: `{"distribution": {...}}`, `{"equivalent": ""}`, `{"prepares": ""}`, or a list. The result's `verdict` states the level the engine checked to (refused, parsed, executed, evidence, proof) and whether the intents hold, sealed by the receipt ([the verdict page](../wai-quantum/docs/verdicts.md)). A reference's check is held to the equivalence bound below | | `verdict` | `true`: the verdict with no intent | @@ -81,7 +81,7 @@ curl -s https://wai.transaction.science/quantum-jobs/v1/run -H 'content-type: ap | `statevector_single` | any circuit with gates on at most four qubits, up to 33 qubits, where the host has a GPU | counts, expectations, amplitudes | single | | `stabilizer` | Clifford circuits (rotations by whole quarter turns), up to 32768 qubits, optionally with depolarizing, dephasing and readout noise | counts, expectations | exact; with noise, an estimate | | `pauli` | any circuit, up to 1024 qubits | expectations | bounded | -| `mps` | any circuit, up to 4096 qubits, at bond dimension up to 256; best when entanglement stays low | counts, expectations, amplitudes | exact when nothing is truncated, otherwise heuristic | +| `mps` | any circuit, up to 4096 qubits, at bond dimension up to 256; best when entanglement stays low. Named, a job past one job's work at the bond it asks for runs under a meter of the bonds it reaches (`metered` in its plan, whose `work` is then what the meter allows) and stops with `J011` if it passes it | counts, expectations, amplitudes | exact when nothing is truncated, otherwise heuristic | | `tensor_network` | any circuit | amplitudes | exact | | `cutrank` | a Clifford circuit, then one layer of one-qubit gates at any angles, up to 4096 qubits, as wide as the state's cut-rank allows | counts, amplitudes | exact; single when only a single-precision table fits | | `cutrank_single` | as `cutrank`, with the table on the host's GPU, where it has one; only when asked for | counts, amplitudes | single | diff --git a/wai/wai-quantum-service/src/discovery.rs b/wai/wai-quantum-service/src/discovery.rs index b40b44a91..e51f1dc9b 100644 --- a/wai/wai-quantum-service/src/discovery.rs +++ b/wai/wai-quantum-service/src/discovery.rs @@ -127,7 +127,7 @@ pub fn openapi(server: &str) -> Value { "dephasing": { "type": "number", "minimum": 0, "maximum": 1 }, "readout": { "type": "number", "minimum": 0, "maximum": 1 } }, "description": "Each a probability, applied after every gate on the qubits it touched (readout: each measured bit)." }, - "options": { "type": "object", "description": "Per method: threshold, max_weight, ladder, max_terms (pauli); max_bond, cutoff (mps); fusion (statevector); trajectories; memory_gb." }, + "options": { "type": "object", "description": "Per method: threshold, max_weight, ladder, max_terms (pauli); max_bond, cutoff (mps); fusion, controls (statevector); controls (exact); trajectories; memory_gb." }, "compile": { "$ref": "#/components/schemas/CompileOptions", "description": "Compile the program first (as POST /v1/compile does) and run the compiled circuit; with basis clifford_t it runs on the bit-exact method, and the result's `compiled` states its distance from the program and the certificate's hash." }, "target": { "oneOf": [ diff --git a/wai/wai-quantum-service/src/jobs.rs b/wai/wai-quantum-service/src/jobs.rs index 57978a23b..5fceb7394 100644 --- a/wai/wai-quantum-service/src/jobs.rs +++ b/wai/wai-quantum-service/src/jobs.rs @@ -844,12 +844,15 @@ impl Service { q.pop_front(); } }; + // A metered job was planned at what its meter allows, not at what it + // took: its time says nothing of the method's rate. match &job.work { + Work::One if job.plan.metered => {} Work::One => push(&job.plan.method, job.plan.work, r, &r["energy"]), // A set's items are timed one by one; the set's energy covers them all. Work::Set { plans, .. } => { for (it, p) in r["items"].as_array().into_iter().flatten().zip(plans) { - if it["status"] == "done" { + if it["status"] == "done" && !p.metered { push(&p.method, p.work, &it["result"], &Value::Null); } } diff --git a/wai/wai-quantum-service/src/mcp.rs b/wai/wai-quantum-service/src/mcp.rs index 2f2b3fc37..6c3265fce 100644 --- a/wai/wai-quantum-service/src/mcp.rs +++ b/wai/wai-quantum-service/src/mcp.rs @@ -225,7 +225,7 @@ fn tool_list() -> Value { } }, "method": { "type": "string", "enum": ["auto", "exact", "statevector", "statevector_single", "stabilizer", "pauli", "mps", "tensor_network", "cutrank", "cutrank_single", "stabilizer_rank", "density_matrix", "trajectories", "pulse"], "description": "Leave as auto unless you need a particular method; pulse runs a pulse program (OpenPulse calibrations on physical qubits, see pulse_schedule) under the pulse options, its error bounded." }, "seed": { "type": "integer", "description": "Sampling seed (default 1); the same job and seed give the same counts." }, - "options": { "type": "object", "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), trajectories." }, + "options": { "type": "object", "description": "Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories." }, "compile": { "type": "object", "description": "Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's `compiled` states its distance from the program.", "properties": compile_props() }, "target": { "description": "A device target: a built-in target's name (list_targets) or a target document (wai.quantum.target/1). The program is then compiled to its gates, placed where it is most likely to succeed and simulated under its noise, its hash in the receipt; not with noise or amplitudes. The service reads the document given and fetches nothing." }, "fabric": { "description": "Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than the host's CPU for the job's size and fusion, otherwise the CPU), cpu, accelerator (any certified accelerator member), a member's id or key, or a list of members, a power of two of them, the state split by its top qubits into one partition on each; a pauli job's sum of terms runs on the member accelerator or its id or key names. Every member placed is certified bit-exact against the CPU, so the answers are the CPU's; the result's `fabric` names where the state ran, sealed by the receipt. A placement the service cannot honour is refused (J013): it places only on its CPU.", "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "array", "minItems": 2, "maxItems": 64, "items": { "type": "string", "minLength": 1 } }] }, diff --git a/wai/wai-quantum/docs/job-refusals.md b/wai/wai-quantum/docs/job-refusals.md index 87384a3d3..07210d108 100644 --- a/wai/wai-quantum/docs/job-refusals.md +++ b/wai/wai-quantum/docs/job-refusals.md @@ -62,7 +62,7 @@ browser engine. A test holds this page to the code's table. | `J008` | refused | The mitigation the job asked for does not read or cannot be done: no noise model, no observables (no shots, for readout), a program that measures in the middle, more qubits or work than it takes, a device target beside it, or options that do not read (the message says which). | | `J009` | refused | An error-correction request that does not read or cannot be done: an unknown code or decoder, a decoder the code does not admit, a syndrome or an error that does not fit the code, circuit text or a model that does not read, or sizes past the limits (the message says which). | | `J010` | refused | A method that does not exist: the methods list names them. | -| `J011` | refused | The method named cannot take this job: a gate it does not hold, more qubits, memory or work than it takes here, or an answer it does not give (noise it cannot take is `J061`); the message says which, and `auto` picks a method that can. | +| `J011` | refused | The method named cannot take this job: a gate it does not hold, more qubits, memory or work than it takes here, or an answer it does not give (noise it cannot take is `J061`); the message says which, and `auto` picks a method that can. A job on `mps` runs under a meter of the bonds it reaches, so this can also come from a job that has started: it stopped where its work passed what a job may take. | | `J012` | refused | No method takes this job: each method's reason is listed, so the job can be changed to suit one. | | `J013` | refused | A placement on the fabric (`fabric`) this host cannot honour: no member by that name, no certified accelerator member here, a state or a partition larger than a member holds, a partition count that is not a power of two, or a method or program the fabric's members do not run (the message says which, and what is here). | | `J020` | refused | An intent that does not read: not one of `distribution`, `equivalent` or `prepares`, a distribution whose outcomes are not the program's bits or whose probabilities do not sum to 1, or a reference program that does not read. | diff --git a/wai/wai-quantum/docs/qasm-feature-matrix.md b/wai/wai-quantum/docs/qasm-feature-matrix.md index f96e26e91..29d82836a 100644 --- a/wai/wai-quantum/docs/qasm-feature-matrix.md +++ b/wai/wai-quantum/docs/qasm-feature-matrix.md @@ -109,7 +109,7 @@ and in the browser build. | Construct | Status | Codes | |---|---|---| -| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`); `exact` does so only when asked (`"options": {"controls": "whole"}`), since its bits are those of the gates it applies | Q201, Q207, Q208 | +| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls in standard gates. A job on `statevector` holds a gate whose standard gates would double as one operation, under as many as 255, and lowers it only where a method needs standard gates (`qasm::read_whole`); `exact` does so only when asked (`"options": {"controls": "whole"}`), since its bits are those of the gates it applies. Those gates are `x`, `y`, `z` and `h` under three or more controls and `s`, `sdg`, `t`, `tdg`, `p`, `rx`, `ry`, `rz`, `u`, `sx` and `sxdg` under two or more, each lowered to the method's gates under its controls (`sx` as `h s h`, `ry` as `sdg h rz h s`), and not `p(pi)`, which is `z`. A job with an `intent` is held to 16: an intent is checked in standard gates, while a verdict with none reads the program as it ran | Q201, Q207, Q208 | | `inv @` on any gate | lowered exactly: each gate's inverse, in reverse order | Q202 | | `pow(k) @`, `k` a whole number | lowered exactly: angles scaled or the gate repeated; negative `k` repeats the inverse | Q203 | | `pow(r) @`, `r` fractional | lowered where an exact principal root exists (`pow(1/2) @ x` is `sx`; rotations by less than 2π; phases; controlled forms); refused otherwise (`u`, `cu`, user gates) | Q204, Q205 | diff --git a/wai/wai-quantum/docs/qec.md b/wai/wai-quantum/docs/qec.md index 7ce59abce..81295b3c4 100644 --- a/wai/wai-quantum/docs/qec.md +++ b/wai/wai-quantum/docs/qec.md @@ -120,10 +120,18 @@ their errors. error model text, the subset the crate's circuits use and more: tags on instructions (`DEPOLARIZE1[leak](0.01) 0`), Pauli-target observables (`OBSERVABLE_INCLUDE(0) X0 Z3`), detector coordinates, `REPEAT` blocks, -`SHIFT_COORDS`, and in models `^`-separated decompositions, `detector` and -`logical_observable` declarations, `repeat` and `shift_detectors`. A -circuit's model written back keeps its tags and coordinates. What the reader -does not take it refuses with the line, never skipping it. The +`SHIFT_COORDS`, the axis-cycling gates `C_XYZ` and `C_ZYX`, correlated errors +(`E(p) X1 Y2 Z3`, also `CORRELATED_ERROR`) and one-qubit Pauli channels +(`PAULI_CHANNEL_1(px, py, pz)`), and in models `^`-separated decompositions, +`detector` and `logical_observable` declarations, `repeat` and +`shift_detectors`. A correlated error is a flip on a qubit of its own, handed +to its targets, so a circuit with one holds one qubit more than its text +names. A Pauli channel becomes the independent X, Y and Z flips with its law, +a rate above 1/2 among them where the law needs one; a channel with no such +flips (`PAULI_CHANNEL_1(0.1, 0.1, 0)`) is refused, since a model of +independent mechanisms cannot state it. A circuit's model written back keeps +its tags and coordinates. What the reader does not take it refuses with the +line, never skipping it. The [conformance vectors](../../quantum-conformance/qec-text/) hold each form, the model each circuit gives, and each refusal. diff --git a/wai/wai-quantum/schemas/job-request.v1.json b/wai/wai-quantum/schemas/job-request.v1.json index 774f108ab..0fa8a0a23 100644 --- a/wai/wai-quantum/schemas/job-request.v1.json +++ b/wai/wai-quantum/schemas/job-request.v1.json @@ -137,7 +137,13 @@ }, "options": { "type": "object", - "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts), memory_gb, and controls: a gate under many controls runs as one on statevector and in standard gates on exact; \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit, and \"whole\" holds the gate whole on exact too, which gives other bits than its default." + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "properties": { + "controls": { + "enum": ["whole", "standard"], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } }, "compile": { "$ref": "compile-result.v1.json#/$defs/options" diff --git a/wai/wai-quantum/schemas/job-result.v1.json b/wai/wai-quantum/schemas/job-result.v1.json index 068e70bdf..facf3d5ad 100644 --- a/wai/wai-quantum/schemas/job-result.v1.json +++ b/wai/wai-quantum/schemas/job-result.v1.json @@ -773,7 +773,7 @@ }, "global_phase": { "type": "object", - "description": "The bit-exact method: OpenQASM's state is e^(i radians) times the amplitudes given, since its lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1.", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", "required": ["turns_over_2_33", "radians", "note"], "properties": { "turns_over_2_33": { "type": "integer", "minimum": 0, "description": "The phase exactly, in 2^33rds of a turn." }, @@ -783,7 +783,7 @@ }, "below_table": { "type": "object", - "description": "The bit-exact method: angles that are not zero and ran as no phase, within the reader's tolerance of a whole turn.", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", "required": ["angles", "largest_radians", "note"], "properties": { "angles": { "type": "integer", "minimum": 1 }, @@ -793,7 +793,7 @@ }, "moved_angles": { "type": "object", - "description": "The bit-exact method: angles within the reader's tolerance of a dyadic angle, by more than a double's rounding of it, that ran as it.", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", "required": ["angles", "largest_radians", "note"], "properties": { "angles": { "type": "integer", "minimum": 1 }, diff --git a/wai/wai-quantum/schemas/plan.v1.json b/wai/wai-quantum/schemas/plan.v1.json index b5107e3ae..4642b5a8d 100644 --- a/wai/wai-quantum/schemas/plan.v1.json +++ b/wai/wai-quantum/schemas/plan.v1.json @@ -24,7 +24,8 @@ }, "work": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "The method's own unit: an upper bound on what the run takes where the method's cost is known beforehand, and with `metered` what the meter holds it to." }, "qubits": { "type": "integer", @@ -32,6 +33,10 @@ }, "target": { "$ref": "job-result.v1.json#/$defs/target_placement" + }, + "metered": { + "type": "boolean", + "description": "True when a job naming method mps would pass one job's work at the bond it asks for: it runs under a meter of the bonds it reaches, may take far less than `work`, and stops with J011 if it passes `work`." } } } diff --git a/wai/wai-quantum/src/engine/catalog.rs b/wai/wai-quantum/src/engine/catalog.rs index 1e8abc608..ff79cdb12 100644 --- a/wai/wai-quantum/src/engine/catalog.rs +++ b/wai/wai-quantum/src/engine/catalog.rs @@ -165,8 +165,8 @@ pub fn describe(job_bytes: u64) -> Value { /// hashed into its identity). pub(crate) fn method_text(method: &str) -> Value { match method { - "exact" => json!({ "accuracy": "bit-exact", "circuits": "every angle a dyadic multiple of 2π (2πm/2^k, k ≤ 32)", "answers": ["counts", "expectations", "amplitudes", "state_hash"] }), - "statevector" => json!({ "accuracy": "exact", "circuits": "any", "answers": ["counts", "expectations", "amplitudes"] }), + "exact" => json!({ "accuracy": "bit-exact", "circuits": "every angle a dyadic multiple of 2π (2πm/2^k, k ≤ 32)", "answers": ["counts", "expectations", "amplitudes", "state_hash"], "options": { "controls": "whole: a gate whose standard gates would double runs as one, under as many as 255 controls, with other bits than the default (standard)" } }), + "statevector" => json!({ "accuracy": "exact", "circuits": "any", "answers": ["counts", "expectations", "amplitudes"], "options": { "controls": "standard: a gate under many controls runs in standard gates, reproducing a result made that way bit for bit (default whole: it runs as one, under as many as 255 controls)" } }), "statevector_single" => json!({ "accuracy": "single", "circuits": "any, gates on at most four qubits", "answers": ["counts", "expectations", "amplitudes"], "options": { "fusion": "the widest fused gate (default 3, at most 3)" } }), "stabilizer" => json!({ "accuracy": "exact; with Pauli noise, counts are noisy samples and expectations estimates", "circuits": "Clifford (rotations by whole quarter turns, controlled phases by whole half turns), optionally with depolarizing, dephasing and readout noise", "answers": ["counts", "expectations"], "options": { "trajectories": "with noise: the shots expectation values are estimated from (default: the shots, at least 10000)" } }), "pauli" => json!({ "accuracy": "bounded", "circuits": "any", "answers": ["expectations"], "options": { "threshold": "coefficients below it are dropped (default 1e-5); the bound covers what was dropped", "max_weight": "Pauli strings heavier than this are dropped", "ladder": "also report the value at up to three thresholds a decade apart above it, to show it settling (default true)", "max_terms": "the most Pauli terms to hold (default: what the job's memory holds); past it the threshold rises, and the bound covers what drops" } }), @@ -386,6 +386,24 @@ pub(crate) fn may_run_whole(v: &Value) -> bool { && v.pointer("/options/controls").and_then(Value::as_str) != Some("standard") } +/// `options.controls` read: `"standard"`, or `"whole"` on a job that can hold a +/// gate whole, on a method that does ([`runs_whole`]; `auto` takes it where it +/// lands on one). A value left unread would give another result in silence. +fn read_controls(v: &Value) -> Result<(), String> { + let Some(c) = v.pointer("/options/controls").filter(|c| !c.is_null()) else { + return Ok(()); + }; + match c.as_str() { + Some("standard") => Ok(()), + Some("whole") if !may_run_whole(v) => Err(tag(refusal::BAD_FIELD, "options.controls \"whole\": this job runs standard gates, as one with a compile, noise, mitigation, a device target or a named place on the fabric does; leave it out")), + Some("whole") => match v.get("method").and_then(Value::as_str).unwrap_or("auto") { + "auto" | "exact" | "statevector" => Ok(()), + m => Err(tag(refusal::BAD_FIELD, format!("options.controls \"whole\": {m} runs standard gates; exact and statevector hold a gate whole"))), + }, + _ => Err(tag(refusal::BAD_FIELD, format!("options.controls is \"whole\" or \"standard\", not {c}"))), + } +} + fn observable(v: &Value, n: u32) -> Result { let (text, coeff) = match v { Value::String(s) => (s.clone(), 1.0), @@ -563,6 +581,7 @@ pub(crate) fn read_form(reg: &Registry, v: &Value, whole: bool) -> Result<(Reque if is_set(v) { return Err(tag(refusal::BAD_SET, "this request is a set (\"programs\" or \"sweep\"): it runs as a set, one item at a time, where sets are taken (the job service, or wai-quantum run and submit)")); } + read_controls(v)?; // A provider job runs on the person's own device, through a host that // holds their credentials (engine::provider); the engine's methods never // stand in for it. @@ -590,9 +609,11 @@ pub(crate) fn read_form(reg: &Registry, v: &Value, whole: bool) -> Result<(Reque }; let reading = if whole && may_run_whole(v) { qasm::read_whole(&src)? } else { qasm::read(&src)? }; let (program, diagnostics) = (reading.program, reading.diagnostics); - // A verdict reads the program in standard gates, whichever way it runs. - if program.has_whole() && super::verdict::asked(v) { - program.lowered()?; + // An intent is checked in standard gates, whichever way the job runs: one + // they cannot hold is refused as the reader refuses it, on its line. A + // verdict with no intent reads the program as it ran. + if program.has_whole() && v.get("intent").is_some_and(|i| !i.is_null()) { + qasm::read(&src)?; } // "intent": what the program must do, checked with its result // (super::verdict); refused here when it does not read. @@ -1073,8 +1094,11 @@ pub(crate) fn try_method(method: &str, r: &Request, dyadic: &Result MPS_MAX_WORK { format!("; its work at that bond would pass one job's ({work}, at most {MPS_MAX_WORK}), so it runs metered on the bond it reaches and stops [{}] if that passes it", refusal::METHOD_REFUSES) } else { String::new() }; - Ok(plan(memory, work, format!("matrix product state of {n} qubits at bond dimension {chi}{metered}"))) + // Past what a job may take at that bond, the meter holds the run to + // what a job may take: all that can be said of its work beforehand. + let metered = work > MPS_MAX_WORK; + let said = if metered { format!("; its work at that bond would pass one job's ({work}, at most {MPS_MAX_WORK}), so it runs metered on the bond it reaches and stops [{}] if that passes it", refusal::METHOD_REFUSES) } else { String::new() }; + Ok(Plan { metered, ..plan(memory, work.min(MPS_MAX_WORK), format!("matrix product state of {n} qubits at bond dimension {chi}{said}")) }) } "cutrank" => { use crate::quantum_cutrank::Precision; @@ -1250,7 +1274,10 @@ pub(crate) fn plan_in(reg: &Registry, v: &Value, job_bytes: u64) -> Result Value { "gates": p.ops.len(), "bits": p.n_bits, "measured": p.measured.len(), - "dynamic_steps": p.dynamic.as_ref().map(Vec::len), + "dynamic_steps": p.standard_steps().map(|n| n.min((1u128 << 53) - 1) as u64), }); if p.has_whole() { v["gates"] = json!(p.standard_gates().min((1u128 << 53) - 1) as u64); diff --git a/wai/wai-quantum/src/engine/refusal.rs b/wai/wai-quantum/src/engine/refusal.rs index 08b760a5a..6331965ed 100644 --- a/wai/wai-quantum/src/engine/refusal.rs +++ b/wai/wai-quantum/src/engine/refusal.rs @@ -85,7 +85,7 @@ table! { // The method. UNKNOWN_METHOD = "J010", Refused, "A method that does not exist: the methods list names them."; - METHOD_REFUSES = "J011", Refused, "The method named cannot take this job: a gate it does not hold, more qubits, memory or work than it takes here, or an answer it does not give (noise it cannot take is `J061`); the message says which, and `auto` picks a method that can."; + METHOD_REFUSES = "J011", Refused, "The method named cannot take this job: a gate it does not hold, more qubits, memory or work than it takes here, or an answer it does not give (noise it cannot take is `J061`); the message says which, and `auto` picks a method that can. A job on `mps` runs under a meter of the bonds it reaches, so this can also come from a job that has started: it stopped where its work passed what a job may take."; NO_METHOD = "J012", Refused, "No method takes this job: each method's reason is listed, so the job can be changed to suit one."; FABRIC = "J013", Refused, "A placement on the fabric (`fabric`) this host cannot honour: no member by that name, no certified accelerator member here, a state or a partition larger than a member holds, a partition count that is not a power of two, or a method or program the fabric's members do not run (the message says which, and what is here)."; diff --git a/wai/wai-quantum/src/engine/registry/mod.rs b/wai/wai-quantum/src/engine/registry/mod.rs index 713da91ed..92db0ceed 100644 --- a/wai/wai-quantum/src/engine/registry/mod.rs +++ b/wai/wai-quantum/src/engine/registry/mod.rs @@ -72,7 +72,7 @@ pub const ACCURACY_CLASSES: [&str; 6] = ["bit-exact", "exact", "single", "bounde /// The members of a job's result the engine writes; a registered method's /// run leaves them as they are. -pub const ENGINE_MEMBERS: [&str; 13] = ["method", "qubits", "gates", "compiled", "repaired", "engine", "schema", "components", "receipt", "verdict", "provenance", "energy", "elapsed_ms"]; +pub const ENGINE_MEMBERS: [&str; 14] = ["method", "qubits", "gates", "operations", "compiled", "repaired", "engine", "schema", "components", "receipt", "verdict", "provenance", "energy", "elapsed_ms"]; /// What a component is. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/wai/wai-quantum/src/engine/run.rs b/wai/wai-quantum/src/engine/run.rs index eaf6d36e8..9c77bc063 100644 --- a/wai/wai-quantum/src/engine/run.rs +++ b/wai/wai-quantum/src/engine/run.rs @@ -62,29 +62,29 @@ fn mps_budget() -> u64 { /// What the bit-exact method promises of a result, and what the lowering to /// its gates did to the program, so that neither is silent: the global phase -/// by which its amplitudes differ from OpenQASM's, and the angles below its -/// table that ran as no phase. +/// by which its amplitudes differ from method statevector's, and the angles +/// below its table that ran as no phase. fn exact_accuracy(report: &crate::qasm::DyadicReport) -> Value { let mut a = json!({ "class": "bit-exact" }); if report.global_phase != 0 { a["global_phase"] = json!({ "turns_over_2_33": report.global_phase, "radians": report.global_phase_radians(), - "note": "OpenQASM's state is e^(i·radians) times these amplitudes: this method lowers rz, rx, ry, rxx, ryy, rzz and u to phase gates, each without the standard's e^(−iθ/2). No measurement sees it; a gate under a control keeps its phase.", + "note": "method statevector's state of the program that ran is e^(i·radians) times these amplitudes: this method lowers rz, rx, ry, rxx, ryy, rzz and u to phase gates, each without that method's e^(−iθ/2). No measurement sees it; a gate under a control keeps its phase. Neither method holds the language's own phase where it differs: its U is e^(iθ/2) times the matrix both take as u, and the reader drops an uncontrolled gphase.", }); } if report.below_table > 0 { a["below_table"] = json!({ "angles": report.below_table, "largest_radians": report.largest_below_table, - "note": "angles this close to a whole turn are below every entry of the phase table and ran as no phase; this method's bound holds, and method statevector applies them", + "note": "phase gates of the lowering (one angle written may be several) within 1e-14 of a turn of a whole turn are below every entry of the phase table and ran as no phase; this method's bound holds, and method statevector applies them", }); } if report.moved > 0 { a["moved_angles"] = json!({ "angles": report.moved, "largest_radians": report.largest_moved, - "note": "angles within the reader's tolerance of a dyadic one, by more than a double's rounding, ran as that dyadic angle", + "note": "phase gates of the lowering within the reader's tolerance, 1e-14 of a turn, of a dyadic angle, by more than a double's rounding, ran as that dyadic angle", }); } a @@ -621,7 +621,7 @@ pub(crate) fn run_builtin(method: &str, job: &Job<'_>, plan: &Plan, out: &mut Va // the run is held to the bond it reaches. let mut chain = Chain::run_within(n, &gates, MpsConfig { max_bond: chi, cutoff }, mps_budget().saturating_sub(catalog::mps_shots_work(r, 1))).map_err(|e| match e { crate::quantum_mpsim::MpsRunError::Chain(e) => e.to_string(), - crate::quantum_mpsim::MpsRunError::OutOfWork { gate, gates, work, max_bond_used } => crate::engine::refusal::tag(crate::engine::refusal::METHOD_REFUSES, format!("stopped after {gate} of {gates} gates: {work} units of work at the bond the circuit has reached ({max_bond_used}), the most one job may take ({}); ask for a smaller max_bond", mps_budget())), + crate::quantum_mpsim::MpsRunError::OutOfWork { gate, gates, work, max_bond_used } => crate::engine::refusal::tag(crate::engine::refusal::METHOD_REFUSES, format!("stopped in gate {gate} of {gates}: {work} units of work at the bond the circuit has reached ({max_bond_used}), the most one job may take ({}); ask for a smaller max_bond", mps_budget())), })?; let rep = chain.report(); if chain.work().saturating_add(catalog::mps_shots_work(r, rep.max_bond_used as u64)) > mps_budget() { diff --git a/wai/wai-quantum/src/engine/verdict.rs b/wai/wai-quantum/src/engine/verdict.rs index 200635c0f..0e9f4d626 100644 --- a/wai/wai-quantum/src/engine/verdict.rs +++ b/wai/wai-quantum/src/engine/verdict.rs @@ -538,7 +538,9 @@ fn distribution(o: &Map, p: &Program, noise: Option<&crate::quant /// What the reader said of `src`: `{"ok": true, "diagnostics": […]}`, or /// `{"ok": false}` with its refusal as a diagnostic's JSON; and the program. fn parsed(src: &str) -> (Value, Option) { - match qasm::read(src) { + // A gate past what standard gates hold still reads: a job can hold it whole. + let read = qasm::read(src).or_else(|d| if d.code == qasm::diag::TOO_MANY_CONTROLS || d.code == qasm::diag::TOO_MANY_GATES { qasm::read_whole(src) } else { Err(d) }); + match read { Ok(r) => (json!({ "ok": true, "diagnostics": r.diagnostics.iter().map(|d| d.to_json()).collect::>() }), Some(r)), Err(d) => { let mut v = d.to_json(); diff --git a/wai/wai-quantum/src/qasm.rs b/wai/wai-quantum/src/qasm.rs index cbc2e1a3d..5d5ce46e5 100644 --- a/wai/wai-quantum/src/qasm.rs +++ b/wai/wai-quantum/src/qasm.rs @@ -798,18 +798,22 @@ pub(crate) fn dyadic(angle: f64) -> Option { /// gates: what a result on that method states ([`Program::dyadic_with_report`]). #[derive(Clone, Debug, Default, PartialEq)] pub struct DyadicReport { - /// The global phase the lowering drops, in `2^33`rds of a turn: OpenQASM's - /// state is `e^{2πi·g/2^33}` times the circuit's. `rz`, `rx`, `ry`, `rxx`, - /// `ryy`, `rzz` and `u` become phase gates, each `e^{iθ/2}` from the - /// standard's matrix; a gate under a control keeps its phase. + /// The global phase the lowering drops, in `2^33`rds of a turn: the state + /// method statevector gives of the same program is `e^{2πi·g/2^33}` times + /// the circuit's. `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `u` become phase + /// gates, each `e^{iθ/2}` from the matrix that method applies; a gate under + /// a control keeps its phase. That is not the language's own state where + /// the two differ: its `U` is `e^{iθ/2}` times the matrix both methods take + /// as `u`, and the reader drops an uncontrolled `gphase` on every method. pub global_phase: u64, - /// Angles that are not zero and ran as no phase: within the reader's - /// tolerance of a whole turn, below every entry of the table. + /// Phase gates of the lowering (one angle written may be several) that are + /// not zero and ran as no phase: within the reader's tolerance, 1e-14 of a + /// turn, of a whole turn, below every entry of the table. pub below_table: u64, /// The largest of them, in radians from a whole turn. pub largest_below_table: f64, - /// Angles moved to the dyadic one within the reader's tolerance by more - /// than a double's rounding of it. + /// Phase gates whose angle moved to the dyadic one within the reader's + /// tolerance by more than a double's rounding of it. pub moved: u64, /// The largest such move, in radians. pub largest_moved: f64, @@ -1378,6 +1382,13 @@ impl Program { Self::standard_count(&self.ops) } + /// How many steps a dynamic program is written in in standard gates, without + /// writing them; `None` for a program with no steps. + pub fn standard_steps(&self) -> Option { + let len = |o: &Op| if o.is_whole() { controls::whole_len(o.kind, &o.params, o.controls().len()) } else { 1 }; + self.dynamic.as_ref().map(|steps| steps.iter().fold(0u128, |n, s| n.saturating_add(if let Instr::Gate(i) = s { len(&self.ops[*i]) } else { 1 }))) + } + fn standard_count(ops: &[Op]) -> u128 { ops.iter().fold(0u128, |n, o| n.saturating_add(if o.is_whole() { controls::whole_len(o.kind, &o.params, o.controls().len()) } else { 1 })) } @@ -1396,7 +1407,7 @@ impl Program { /// than a program may hold: counted without writing them. fn standard_within(ops: &[Op]) -> Result { if ops.iter().any(|o| o.controls().len() > elab::MAX_CONTROLS as usize) { - return Err(Diagnostic::new(diag::TOO_MANY_CONTROLS, None, format!("written in standard gates, modifiers add at most {} controls", elab::MAX_CONTROLS))); + return Err(Diagnostic::new(diag::TOO_MANY_CONTROLS, None, format!("written in standard gates, modifiers add at most {} controls; {}", elab::MAX_CONTROLS, elab::HELD_WHOLE))); } let total = Self::standard_count(ops); if total > MAX_OPS as u128 { diff --git a/wai/wai-quantum/src/qasm/elab.rs b/wai/wai-quantum/src/qasm/elab.rs index 3d077eca1..77a20dbe8 100644 --- a/wai/wai-quantum/src/qasm/elab.rs +++ b/wai/wai-quantum/src/qasm/elab.rs @@ -33,6 +33,8 @@ pub(crate) const MAX_CONTROLS: u32 = 16; /// The most controls modifiers may add where a gate stays one op /// ([`super::read_whole`]): as many as the bit-exact circuit's op-log counts. pub(crate) const MAX_WHOLE_CONTROLS: u32 = 255; +/// What a refusal past the standard form tells a job it can do. +pub(crate) const HELD_WHOLE: &str = "a job on the state vector holds a gate under as many as 255 as one, and on the bit-exact method with \"options\": {\"controls\": \"whole\"}"; /// The most statements and loop iterations a program may run on reading. pub(crate) const MAX_STEPS: u64 = 20_000_000; /// The most times one `while` may run on reading. @@ -243,6 +245,8 @@ pub(crate) struct Elab<'a> { tan: Option, /// Whether a gate whose standard form would double stays one op. whole: bool, + /// The qubits of the gates held whole so far. + held: usize, } /// The program `stmts` (read from `src`, its tokens `toks`) run into the @@ -308,6 +312,7 @@ fn elaborate_form(src: &str, toks: &[Token], stmts: &[Stmt], version: Version, i written: BTreeSet::new(), tan, whole, + held: 0, }; e.prescan(toks, stmts)?; e.block(stmts)?; @@ -479,14 +484,23 @@ impl<'a> Elab<'a> { if self.ops.len() >= MAX_OPS { return self.fail(diag::TOO_MANY_GATES, at, format!("more than {MAX_OPS} gates")); } - for &q in &qubits { + let op = Op { kind, qubits, params }; + // A gate held whole carries its qubits. Its standard gates are at least + // as many, so whatever the standard form holds is within this. + if op.is_whole() { + self.held += op.qubits.len(); + if self.held > MAX_OPS { + return self.fail(diag::TOO_MANY_GATES, at, format!("gates held whole on more than {MAX_OPS} qubits in all")); + } + } + for &q in &op.qubits { self.touched[q as usize] = true; } if let Some(t) = self.tan.as_mut() { - let next = t.next.take().unwrap_or_else(|| vec![t.zero(); params.len()]); + let next = t.next.take().unwrap_or_else(|| vec![t.zero(); op.params.len()]); t.ops.push(next); } - self.ops.push(Op { kind, qubits, params }); + self.ops.push(op); self.lines.push(self.top); self.steps.push(Instr::Gate(self.ops.len() - 1)); Ok(()) @@ -1652,7 +1666,7 @@ impl<'a> Elab<'a> { }; let most = if self.whole { MAX_WHOLE_CONTROLS } else { MAX_CONTROLS }; if polarity.len() as i128 + n > most as i128 { - return self.fail(diag::TOO_MANY_CONTROLS, *mat, format!("modifiers add at most {most} controls here{}", if self.whole { "" } else { ", written in standard gates; a job on the state vector or the bit-exact method holds a gate under as many as 255 as one" })); + return self.fail(diag::TOO_MANY_CONTROLS, *mat, format!("modifiers add at most {most} controls here{}", if self.whole { String::new() } else { format!(", written in standard gates; {HELD_WHOLE}") })); } polarity.extend(std::iter::repeat_n(*on, n as usize)); } diff --git a/wai/wai-quantum/tests/qec_text_conformance.rs b/wai/wai-quantum/tests/qec_text_conformance.rs index b8512c973..7dc3179db 100644 --- a/wai/wai-quantum/tests/qec_text_conformance.rs +++ b/wai/wai-quantum/tests/qec_text_conformance.rs @@ -36,11 +36,12 @@ fn generated() -> Vec<(&'static str, &'static str, String)> { } /// The hand-written circuits and models, kept as committed. -const WRITTEN_CIRCUITS: [&str; 1] = ["circuits/tagged.circuit"]; +const WRITTEN_CIRCUITS: [&str; 2] = ["circuits/tagged.circuit", "circuits/correlated.circuit"]; const WRITTEN_MODELS: [&str; 1] = ["models/decomposed.dem"]; /// What each refused file must be refused for: (file, line, words). -const REFUSED: [(&str, usize, &str); 7] = [ +const REFUSED: [(&str, usize, &str); 8] = [ + ("refuse/no_independent_flips.circuit", 2, "no form as independent"), ("refuse/unsupported.circuit", 3, "unsupported instruction 'T'"), ("refuse/random_observable.circuit", 0, "not deterministic"), ("refuse/record.circuit", 3, "measurement record out of range"), -- 2.54.0 (Apple Git-157) From 0051cdeb1919732ac474e969db8fa190961e1b54 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Sat, 7 Nov 2026 01:46:05 -0500 Subject: [PATCH 10/14] wai-quantum: Q210 says what else it refuses, and the state vector's gate under controls is tested under wasm Co-Authored-By: Claude Opus 5.5 --- .github/workflows/wai-quantum-registry.yml | 6 ++++++ wai/wai-quantum-cli/docs/llms-full.txt | 2 +- wai/wai-quantum/docs/qasm-diagnostics.md | 2 +- wai/wai-quantum/src/qasm/diag.rs | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wai-quantum-registry.yml b/.github/workflows/wai-quantum-registry.yml index 44c8b611d..c4cfd673f 100644 --- a/.github/workflows/wai-quantum-registry.yml +++ b/.github/workflows/wai-quantum-registry.yml @@ -215,3 +215,9 @@ jobs: set -euo pipefail cargo test --locked --target wasm32-wasip2 --features full --lib engine::registry:: 2>&1 | tee "$RUNNER_TEMP/wasip2.log" grep -qE '^test result: ok\. 12 passed; 0 failed' "$RUNNER_TEMP/wasip2.log" || { echo "::error::the registry's tests did not all pass under wasip2"; exit 1; } + # The browser's engine runs a gate under controls by this path too. + cargo test --locked --target wasm32-wasip2 --features full --lib quantum_sv::tests::a_gate_under_controls 2>&1 | tee "$RUNNER_TEMP/wasip2-sv.log" + for t in quantum_sv::tests::a_gate_under_controls_is_its_dense_gate_on_any_thread_count \ + quantum_sv::tests::a_gate_under_controls_must_fit_the_register; do + grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/wasip2-sv.log" || { echo "::error::$t did not run under wasip2"; exit 1; } + done diff --git a/wai/wai-quantum-cli/docs/llms-full.txt b/wai/wai-quantum-cli/docs/llms-full.txt index 2ba31b410..03d6b8fb2 100644 --- a/wai/wai-quantum-cli/docs/llms-full.txt +++ b/wai/wai-quantum-cli/docs/llms-full.txt @@ -1237,7 +1237,7 @@ Every code: | `Q207` | refused | A control modifier that adds no control: `ctrl(0) @`. | | `Q208` | refused | Modifiers that add more controls than the reader lowers (16 written in standard gates, 255 on a gate a method holds whole). | | `Q209` | refused | Gate definitions or subroutine calls nested deeper than 32. | -| `Q210` | refused | A program that expands to more gates than the reader holds (2 000 000). | +| `Q210` | refused | A program that expands to more gates than the reader holds (2 000 000), or that holds gates whole on more qubits than that in all. | | `Q211` | refused | A modifier on something that is not a gate. | | `Q212` | refused | A statement a gate's body may not hold: a gate holds gate calls, `gphase`, `barrier`, loops and conditions known on reading. | | `Q300` | lowered | An `if`, `while` or `switch` whose condition is known on reading: decided then. | diff --git a/wai/wai-quantum/docs/qasm-diagnostics.md b/wai/wai-quantum/docs/qasm-diagnostics.md index 60a6153f3..defaf3611 100644 --- a/wai/wai-quantum/docs/qasm-diagnostics.md +++ b/wai/wai-quantum/docs/qasm-diagnostics.md @@ -89,7 +89,7 @@ engine. A test holds this page to the code's table. | `Q207` | refused | A control modifier that adds no control: `ctrl(0) @`. | | `Q208` | refused | Modifiers that add more controls than the reader lowers (16 written in standard gates, 255 on a gate a method holds whole). | | `Q209` | refused | Gate definitions or subroutine calls nested deeper than 32. | -| `Q210` | refused | A program that expands to more gates than the reader holds (2 000 000). | +| `Q210` | refused | A program that expands to more gates than the reader holds (2 000 000), or that holds gates whole on more qubits than that in all. | | `Q211` | refused | A modifier on something that is not a gate. | | `Q212` | refused | A statement a gate's body may not hold: a gate holds gate calls, `gphase`, `barrier`, loops and conditions known on reading. | | `Q300` | lowered | An `if`, `while` or `switch` whose condition is known on reading: decided then. | diff --git a/wai/wai-quantum/src/qasm/diag.rs b/wai/wai-quantum/src/qasm/diag.rs index 6dd165719..579bbf021 100644 --- a/wai/wai-quantum/src/qasm/diag.rs +++ b/wai/wai-quantum/src/qasm/diag.rs @@ -213,7 +213,7 @@ table! { NO_CONTROLS = "Q207", Refused, "A control modifier that adds no control: `ctrl(0) @`."; TOO_MANY_CONTROLS = "Q208", Refused, "Modifiers that add more controls than the reader lowers (16 written in standard gates, 255 on a gate a method holds whole)."; TOO_DEEP = "Q209", Refused, "Gate definitions or subroutine calls nested deeper than 32."; - TOO_MANY_GATES = "Q210", Refused, "A program that expands to more gates than the reader holds (2 000 000)."; + TOO_MANY_GATES = "Q210", Refused, "A program that expands to more gates than the reader holds (2 000 000), or that holds gates whole on more qubits than that in all."; MODIFIER_PLACE = "Q211", Refused, "A modifier on something that is not a gate."; GATE_BODY = "Q212", Refused, "A statement a gate's body may not hold: a gate holds gate calls, `gphase`, `barrier`, loops and conditions known on reading."; -- 2.54.0 (Apple Git-157) From 572d0d27b91b7b1cd18495793f71189c61dea1d3 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Sat, 7 Nov 2026 01:53:13 -0500 Subject: [PATCH 11/14] wai-quantum: the example's plan, a comment for a macro, and a type for the walk's step Co-Authored-By: Claude Opus 5.5 --- wai/wai-quantum/examples/extension_points.rs | 2 +- wai/wai-quantum/src/engine/run.rs | 2 +- wai/wai-quantum/src/qasm.rs | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/wai/wai-quantum/examples/extension_points.rs b/wai/wai-quantum/examples/extension_points.rs index 3b400b9d7..e82b4206a 100644 --- a/wai/wai-quantum/examples/extension_points.rs +++ b/wai/wai-quantum/examples/extension_points.rs @@ -80,7 +80,7 @@ impl Method for BasisTable { return Err("basis_table answers counts and amplitudes".into()); } let n = r.program.n_qubits; - Ok(Plan { method: "basis_table".into(), why: format!("a permutation of basis states on {n} qubits, followed bit by bit"), memory_bytes: 1 << 20, work: r.program.ops.len() as u64, qubits: n, target: None }) + Ok(Plan { method: "basis_table".into(), why: format!("a permutation of basis states on {n} qubits, followed bit by bit"), memory_bytes: 1 << 20, work: r.program.ops.len() as u64, qubits: n, target: None, metered: false }) } fn run(&self, job: &Job<'_>, _: &Plan, out: &mut Value) -> Result<(), String> { let r = job.request()?; diff --git a/wai/wai-quantum/src/engine/run.rs b/wai/wai-quantum/src/engine/run.rs index 9c77bc063..6415272bc 100644 --- a/wai/wai-quantum/src/engine/run.rs +++ b/wai/wai-quantum/src/engine/run.rs @@ -45,7 +45,7 @@ fn index_of(bits: &str, n: u32, pos: impl Fn(u32) -> u32) -> usize { x } -/// A test's budget for an `mps` run, in place of [`catalog::MPS_MAX_WORK`]. +// A test's budget for an `mps` run, in place of `catalog::MPS_MAX_WORK`. #[cfg(test)] thread_local! { pub(crate) static MPS_BUDGET: std::cell::Cell> = const { std::cell::Cell::new(None) }; diff --git a/wai/wai-quantum/src/qasm.rs b/wai/wai-quantum/src/qasm.rs index 5d5ce46e5..910a886c5 100644 --- a/wai/wai-quantum/src/qasm.rs +++ b/wai/wai-quantum/src/qasm.rs @@ -1305,7 +1305,8 @@ impl Program { (H, &[2]), (Cx, &[1, 2]), (Tdg, &[2]), (Cx, &[0, 2]), (T, &[2]), (Cx, &[1, 2]), (Tdg, &[2]), (Cx, &[0, 2]), (T, &[1]), (T, &[2]), (H, &[2]), (Cx, &[0, 1]), (T, &[0]), (Tdg, &[1]), (Cx, &[0, 1]), ]; - let ccx = |each: &mut dyn FnMut(Kind, &[u32], &[f64]), abc: [u32; 3]| { + type Step<'a> = dyn FnMut(Kind, &[u32], &[f64]) + 'a; + let ccx = |each: &mut Step<'_>, abc: [u32; 3]| { let mut q = [0u32; 2]; for (k, at) in CCX { for (j, &i) in at.iter().enumerate() { -- 2.54.0 (Apple Git-157) From 9324f1fab007aa87770c7847db47b8078abb5c21 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Sat, 7 Nov 2026 02:18:10 -0500 Subject: [PATCH 12/14] wai-quantum: a request's options keep the members the methods list names Naming `controls` in the schema made the strict check refuse the others. Co-Authored-By: Claude Opus 5.5 --- wai/wai-quantum-cli/docs/local-mcp.json | 6 ++++++ wai/wai-quantum-cli/docs/service-mcp.json | 9 +++++++++ wai/wai-quantum/schemas/job-request.v1.json | 1 + 3 files changed, 16 insertions(+) diff --git a/wai/wai-quantum-cli/docs/local-mcp.json b/wai/wai-quantum-cli/docs/local-mcp.json index 7abb0b230..b4c691083 100644 --- a/wai/wai-quantum-cli/docs/local-mcp.json +++ b/wai/wai-quantum-cli/docs/local-mcp.json @@ -728,6 +728,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -4573,6 +4574,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -31063,6 +31065,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -34908,6 +34911,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -51110,6 +51114,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -54955,6 +54960,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ diff --git a/wai/wai-quantum-cli/docs/service-mcp.json b/wai/wai-quantum-cli/docs/service-mcp.json index 1f639af23..98e4a5cc6 100644 --- a/wai/wai-quantum-cli/docs/service-mcp.json +++ b/wai/wai-quantum-cli/docs/service-mcp.json @@ -744,6 +744,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -4589,6 +4590,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -11000,6 +11002,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -14845,6 +14848,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -22276,6 +22280,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -26121,6 +26126,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -45168,6 +45174,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -49013,6 +49020,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ @@ -53042,6 +53050,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": [ diff --git a/wai/wai-quantum/schemas/job-request.v1.json b/wai/wai-quantum/schemas/job-request.v1.json index 0fa8a0a23..697d35c2c 100644 --- a/wai/wai-quantum/schemas/job-request.v1.json +++ b/wai/wai-quantum/schemas/job-request.v1.json @@ -138,6 +138,7 @@ "options": { "type": "object", "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, "properties": { "controls": { "enum": ["whole", "standard"], -- 2.54.0 (Apple Git-157) From 3d948f6d8fb54867efe344b2f920b4957fcd3fdf Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Sat, 7 Nov 2026 02:19:33 -0500 Subject: [PATCH 13/14] wai-quantum: the new tests take no time bound a loaded host could pass Co-Authored-By: Claude Opus 5.5 --- wai/wai-quantum/src/engine/catalog/whole_tests.rs | 3 ++- wai/wai-quantum/src/qasm/whole_tests.rs | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/wai/wai-quantum/src/engine/catalog/whole_tests.rs b/wai/wai-quantum/src/engine/catalog/whole_tests.rs index eaffa8aa4..f4355c45f 100644 --- a/wai/wai-quantum/src/engine/catalog/whole_tests.rs +++ b/wai/wai-quantum/src/engine/catalog/whole_tests.rs @@ -426,7 +426,8 @@ fn a_gate_too_large_for_standard_gates_is_refused_before_they_are_written() { let _ = plan(&json!({ "qasm": src, "method": method, "shots": 16 }), CAP); } let _ = plan(&json!({ "qasm": src, "method": "statevector", "shots": 16, "dry_run": true }), CAP); - assert!(t.elapsed() < std::time::Duration::from_secs(10), "{src}: {:?}", t.elapsed()); + // A bound far past any host's load, and far below what writing them takes. + assert!(t.elapsed() < std::time::Duration::from_secs(120), "{src}: {:?}", t.elapsed()); } } diff --git a/wai/wai-quantum/src/qasm/whole_tests.rs b/wai/wai-quantum/src/qasm/whole_tests.rs index 4ee27580e..6948cf565 100644 --- a/wai/wai-quantum/src/qasm/whole_tests.rs +++ b/wai/wai-quantum/src/qasm/whole_tests.rs @@ -374,10 +374,8 @@ fn the_bit_exact_report_states_what_the_lowering_did() { fn a_loop_of_wide_whole_gates_is_held_to_what_a_program_may_hold() { let qs: Vec = (0..255).map(|i| format!("q[{i}]")).collect(); let src = format!("qubit[255] q;\nfor int i in [1:100000] {{\n ctrl(254) @ p(0.1) {};\n}}\n", qs.join(", ")); - let t = std::time::Instant::now(); let d = read_whole(&src).err().unwrap(); assert!(d.code == diag::TOO_MANY_GATES && d.line() == Some(3), "{d}"); - assert!(t.elapsed() < std::time::Duration::from_secs(20), "{:?}", t.elapsed()); let src = format!("qubit[255] q;\nfor int i in [1:1000] {{\n ctrl(254) @ p(0.1) {};\n}}\n", qs.join(", ")); assert_eq!(read_whole(&src).unwrap().program.ops.len(), 1000); } -- 2.54.0 (Apple Git-157) From caece6677e4b4bd5243835e609d51e4a94a1ad94 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Sat, 7 Nov 2026 03:31:54 -0500 Subject: [PATCH 14/14] wai-quantum: the corpus rerun at the review's fixes, on both hosts The same counts as before them: 1743 pass on macOS arm64, 1738 on Linux x86_64, none failing; the self-test catches its 23 faults on each. Co-Authored-By: Claude Opus 5.5 --- ...-11-05-many-controlled-gates-stay-whole.md | 2 +- wai/quantum-cross-simulator/README.md | 38 +- .../results/conformance-linux-x86_64.json | 1912 ++++++++-------- .../results/conformance-macos-arm64.json | 1914 ++++++++--------- 4 files changed, 1933 insertions(+), 1933 deletions(-) diff --git a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md index 4086f7500..ca2c46a17 100644 --- a/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md +++ b/wai/changes/2026-11-05-many-controlled-gates-stay-whole.md @@ -7,6 +7,6 @@ - **What a job counts.** `gates` counts standard gates however the method ran them, as it always has, so a receipt's provenance carries the count it carried, and `lint_qasm`'s `dynamic_steps` counts steps the same way; `operations`, a new optional member of a result and of `lint_qasm`, says what a method holding gates whole ran. A provenance's `plan.work` follows what the method ran. A job with `compile`, `noise`, `mitigate`, `target`, `provider` or a named `fabric` place runs standard gates as it did, as do the other methods, a registered method among them. Methods that need standard gates, named, refuse what those cannot hold as the reader does, on its line, with `Q208` or `Q210`, saying how a job holds such a gate; `auto` passes over them. A job with an `intent` is held to standard gates, since the intent is checked in them; a verdict with none, which both MCP servers ask for on every run, reads the program as it ran. Gates held whole may take 2,000,000 qubits in all (`Q210`), which holds no program the standard form holds. - **What depended on the expansion** did not change: the reader's standard gates, the bit-exact method's hash, a compile, the QIR and jeff exports and the resource estimate's counts, each checked against this engine's output before the change, and the expected hashes of `quantum-conformance/`. - **The bit-exact method says what its lowering did** (`accuracy`, each only when there is something to say). `global_phase`: `rz`, `rx`, `ry`, `rxx`, `ryy`, `rzz` and `u` become phase gates, so method statevector's state of the program that ran is `e^(i·radians)` times the amplitudes given; the phase is exact, in 2^33rds of a turn, whole turns counted. The language's own state can differ from both: its `U` is `e^(iθ/2)` times the matrix both take as `u`, the reader drops an uncontrolled `gphase`, and a compiled job's program is the compile's. `below_table`: a phase gate within the reader's tolerance, 1e-14 of a turn, of a whole turn ran as no phase, as the table's arithmetic has it, and now says so here and in the plan's `why`. `moved_angles`: a phase gate within that tolerance of a dyadic angle, by more than a double's rounding of it. Their `angles` count the lowering's phase gates, so one angle written may be several. -- **The matrix-product job.** A job that names `mps` is no longer refused on an estimate at the bond it asks for: it runs under a meter of the bonds it holds (`Chain::run_within`, `Chain::work`), which changes no number, and stops with `J011`, saying where, if those pass one job's work. The meter counts each two-site update, each move of the orthogonality center and each one-qubit gate, and holds the budget at each update, inside a gate that crosses the chain too. The 30-qubit QFT of a basis state at `max_bond` 256 runs, a product state at every step, at bond 1. Its plan says `metered`, and its `work` is then what the meter allows, so a dry run's time is the meter's and such a job does not set the method's measured rate. A job with `auto` is held to the estimate, and told what naming the method does. The estimate now walks the same steps at the bond asked for (`WorkBound`), so it bounds the meter: a plan's `work` for `mps` is larger than before where gates move the center far, and `auto` passes over `mps` for a few circuits it took before. +- **The matrix-product job.** A job that names `mps` is no longer refused on an estimate at the bond it asks for: it runs under a meter of the bonds it holds (`Chain::run_within`, `Chain::work`), which changes no number, and stops with `J011`, saying where, if those pass one job's work. The meter counts each two-site update, each move of the orthogonality center and each one-qubit gate, and holds the budget at each update, inside a gate that crosses the chain too. The 30-qubit QFT of a basis state at `max_bond` 256 runs, a product state at every step, at bond 1. Its plan says `metered`, and its `work` is then what the meter allows, so a dry run's time is the meter's and such a job does not set the method's measured rate. A job with `auto` is held to the estimate, and told what naming the method does. The estimate now walks the same steps at the bond asked for (`WorkBound`), so it bounds the meter: a plan's `work` for `mps` now counts those moves and its one-qubit gates, so it is larger than before, and `auto` passes over `mps` where they take it past one job's work. - **The error-correction text.** `C_XYZ` and `C_ZYX`; `E` (or `CORRELATED_ERROR`), a flip on a qubit of its own handed to its Pauli targets, so a circuit with one holds one qubit more than its text names; and `PAULI_CHANNEL_1`, as the independent flips with its law, a rate above 1/2 among them where the law needs one (`(0.6, 0.3, 0.05)`). A channel with no such flips (`PAULI_CHANNEL_1(0.1, 0.1, 0)`) is refused with its line. `C_XYZ` and `C_ZYX` take no arguments and refuse one. A text may not name qubit 4294967295, the index the carrier is read under, nor leave a correlated error no index for its carrier (qubit 4294967294 named); both are refused with their line. - **The corpus** ([quantum-cross-simulator/](quantum-cross-simulator/README.md)): rerun, with the bit-exact method's amplitudes held to the reference's with the phase its result states, and before-and-after timings on one host. diff --git a/wai/quantum-cross-simulator/README.md b/wai/quantum-cross-simulator/README.md index 9790aa782..49587fcfa 100644 --- a/wai/quantum-cross-simulator/README.md +++ b/wai/quantum-cross-simulator/README.md @@ -5,7 +5,7 @@ held to a reference within a tolerance derived from the arithmetic that produced command regenerates every result here on a clean machine. ```sh -bash wai/quantum-cross-simulator/reproduce.sh --tier full # the whole corpus: 35 to 45 minutes on the hosts below +bash wai/quantum-cross-simulator/reproduce.sh --tier full # the whole corpus: 35 to 50 minutes on the hosts below bash wai/quantum-cross-simulator/reproduce.sh # the CI tier, a few minutes bash wai/quantum-cross-simulator/reproduce.sh --self-test # every injected fault must be caught bash wai/quantum-cross-simulator/reproduce.sh --perf --out perf.json @@ -250,25 +250,25 @@ controls the standard form refuses (`[Q208]`), so `grover_n20` has no "before". ### `conformance-linux-x86_64.json` -Host: AMD RYZEN AI MAX+ 395 w/ Radeon 8060S, Ubuntu 26.04.1 LTS, 32 logical CPUs, 123 GiB, x86_64. Tier full, 2758.8 s. Checks: info 12, known 11, not run 14, pass 1738, refused 10. +Host: AMD RYZEN AI MAX+ 395 w/ Radeon 8060S, Ubuntu 26.04.1 LTS, 32 logical CPUs, 123 GiB, x86_64. Tier full, 2911.3 s. Checks: info 12, known 11, not run 14, pass 1738, refused 10. | family | `wai.exact` | `wai.statevector` | `wai.stabilizer` | `wai.auto` | `wai.mps` | `wai.tensor_network` | `wai.density_matrix` | `wai.qec` | `aer.statevector` | `aer.qasm_import` | `aer.stabilizer` | `aer.mps` | `aer.density_matrix` | `stim.tableau` | `quimb.dense` | `quimb.tensor_network` | `quimb.mps` | `ddsim.statevector` | `qsim.statevector` | `pairs and references` | `references` | |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| | bit_order | 24/24 (0.068) | 8/8 (0.015) | 12/12 | 8/8 (0.0069) | | | | | 8/8 (0.016) | 6/6 (0.016) | 5/5 | | | 7/7 | 6/6 (0.019) | 6/6 (0.031) | | 8/8 (0.00015) | 8/8 (0.013) | 15/15 (0.0084) | 5/5 | -| clifford_large | 4/4 (0.012) | 1/1 (0.00077) | 34/34 (0.43) | 1/1 (7.8e-05) | | | | | 1/1 (0.00084) | 1/1 (0.00084) | 16/16 (0.51) | | | 19/19 (0.3) | 1/1 (0.0017) | 1/1 (4.4e-08) | | 1/1 (2.4e-07) | 1/1 (0.00052) | | 15/15 | -| dynamic | | 12/12 (0.29) | 8/8 (0.21) | 12/12 (0.29) | | | | | 12/12 (0.36) | | | | | 8/8 (0.29) | | | | 8/8 (0.29) · 11 known | 6 not run | | | +| clifford_large | 4/4 (0.012) | 1/1 (0.00077) | 34/34 (0.43) | 1/1 (7.8e-05) | | | | | 1/1 (0.00084) | 1/1 (0.00084) | 16/16 (0.51) | | | 19/19 (0.3) | 1/1 (0.0017) | 1/1 (4.5e-08) | | 1/1 (2.4e-07) | 1/1 (0.00052) | | 15/15 | +| dynamic | | 12/12 (0.29) | 8/8 (0.21) | 12/12 (0.29) | | | | | 12/12 (0.36) | | | | | 8/8 (0.29) | | | | 8/8 (0.36) · 11 known | 6 not run | | | | gate_conventions | 188/188 (0.069) | 47/47 (0.017) | | 47/47 (0.066) | | | | | 47/47 (0.018) | 47/47 (0.018) | | | | | 46/46 (0.017) · 1 not run | 46/46 (0.032) · 1 not run | | 47/47 (0.00015) | 46/46 (0.026) · 1 not run | | | -| ghz | 20/20 (0.042) | 7/7 (0.21) | 2/2 (0.022) | 7/7 (0.022) | | | | | 7/7 (0.059) | 5/5 (0.011) | | | | 2/2 (0.29) | 5/5 (0.0094) | 5/5 (0.041) | | 7/7 (0.38) | 7/7 (0.14) | | 5/5 | -| grover | 16/16 (0.029) | 6/6 (0.12) | | 6/6 (0.14) | | | | | 6/6 (0.25) | 4/4 (0.0043) | | | | | 4/4 (0.0079) | 4/4 (0.0003) | | 6/6 (0.12) | 6/6 (0.27) | | 4/4 | +| ghz | 20/20 (0.042) | 7/7 (0.21) | 2/2 (0.022) | 7/7 (0.022) | | | | | 7/7 (0.059) | 5/5 (0.011) | | | | 2/2 (0.29) | 5/5 (0.0094) | 5/5 (0.041) | | 7/7 (0.082) | 7/7 (0.14) | | 5/5 | +| grover | 16/16 (0.029) | 6/6 (0.12) | | 6/6 (0.14) | | | | | 6/6 (0.25) | 4/4 (0.0043) | | | | | 4/4 (0.0079) | 4/4 (0.00034) | | 6/6 (0.21) | 6/6 (0.27) | | 4/4 | | mirror | 7/7 (0.007) | 3/3 (0.00036) | | | | | | | 3/3 (0.00068) | | | | | | 3/3 (0.00036) | | | 2/2 (7e-05) · 1 not run | 3/3 (0.00057) | | | | noise | | | | | | | 3/3 (0.00093) | | | | | | 3/3 (0.00093) | | | | | | | | | | other | | | | | | | | | | | | | | | | | | | | | 3/3 | | qec | | | | | | | | 29/29 (0.61) · 2 refused as listed | | | | | | 22/22 (0.53) · 2 not run | | | | | | 44/44 (0.016) | | -| qft | 25/25 (0.042) | 9/9 (0.58) | | 8/8 (0.66) | | | | | 9/9 (0.61) | 6/6 (0.009) | | | | | 7/7 (0.0062) | 5/5 (0.0057) | | 9/9 (0.61) | 9/9 (0.63) | 15/15 (0.0027) | 5/5 | +| qft | 25/25 (0.042) | 9/9 (0.58) | | 8/8 (0.66) | | | | | 9/9 (0.61) | 6/6 (0.009) | | | | | 7/7 (0.0062) | 5/5 (0.0057) | | 9/9 (0.63) | 9/9 (0.63) | 15/15 (0.0027) | 5/5 | | qpe | 12/12 (0.017) · 2 refused as listed | 5/5 (0.0091) | | 5/5 (0.013) | | | | | 5/5 (0.0058) | 5/5 (0.0075) | | | | | 5/5 (0.0071) | 4/4 (0.0014) | | 5/5 (4.8e-06) | 5/5 (0.0034) | | 5/5 | -| random_clifford_t | 12/12 (0.039) | 3/3 (0.0047) | | 3/3 (0.017) | | | | | 3/3 (0.0042) | 3/3 (0.0042) | | | | | 3/3 (0.003) | 3/3 (0.00025) | | 3/3 (3e-05) | 3/3 (0.001) | | | +| random_clifford_t | 12/12 (0.039) | 3/3 (0.0047) | | 3/3 (0.017) | | | | | 3/3 (0.0042) | 3/3 (0.0042) | | | | | 3/3 (0.003) | 3/3 (0.00024) | | 3/3 (3e-05) | 3/3 (0.001) | | | | random_dyadic | 8/8 (0.0067) | 2/2 (0.0018) | | 2/2 (0.0016) | | | | | 2/2 (0.0027) | 2/2 (0.0036) | | | | | 2/2 (0.0019) | 2/2 (0.00015) | | 2/2 (6.8e-06) | 2/2 (0.004) | | | -| random_rotations | 3 refused as listed | 5/5 (0.48) | | 5/5 (0.48) | | | | | 5/5 (0.5) | 3/3 (0.0034) | | | | | 3/3 (0.0018) | 3/3 (0.00014) | | 5/5 (0.44) · 1 not run | 5/5 (0.4) | 6/6 (0.0017) | | +| random_rotations | 3 refused as listed | 5/5 (0.48) | | 5/5 (0.48) | | | | | 5/5 (0.5) | 3/3 (0.0034) | | | | | 3/3 (0.0018) | 3/3 (0.00014) | | 5/5 (0.4) · 1 not run | 5/5 (0.4) | 6/6 (0.0017) | | | small_angle | 62/62 (0.9) · 3 refused as listed | 32/32 (0.016) | 2/2 | 18/18 (0.098) | | | | | 32/32 (0.018) | 29/29 (0.016) | 1/1 | | | 1/1 | 30/30 (0.019) | 29/29 (0.016) | | 29/29 (0.15) | 33/33 (0.0075) | | 1/1 | | wide_mps | | | | | 6/6 (0.00017) | 5/5 (0.00057) | | | | | | 4/4 (0.00023) · 1 not run | | | | 5/5 (0.043) | 5/5 (7.3e-05) | | | | | | wide_tn | | | | | 1/1 (0.00093) | 1/1 (6.4e-07) | | | | | | 1/1 (0.0021) | | | | 1/1 (0.02) | 1/1 (0.0011) | | | 21/21 (0.02) | | @@ -276,7 +276,7 @@ Host: AMD RYZEN AI MAX+ 395 w/ Radeon 8060S, Ubuntu 26.04.1 LTS, 32 logical CPUs Known disagreements of other engines with the exact reference (`corpus/known-disagreements.json`): - `repeat_until_success`, `ddsim.statevector`: ValueError: [changePermutation] Target must be an injective mapping using only keys and logical qubits from the source permutation. | known: MQT DDSIM 2.7.0's qasm_simulator raises ValueError [changePermutation] on this program (two qubits; qubit 1 measured three times in the middle, with gates between and an x conditioned on each reading; four classical bits) and gives no counts. It raises the same without the conditioned x, and on qubit 1 measured, h, measured again, then qubit 0 measured into a third bit; with no third bit it gives counts. Each is a case of the reproducer. -- `measure_twice`, `ddsim.statevector`: 10: 49867 shots, probability 0; 11: 0 shots, expected 50000.0 ± 1084.8 | known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2. +- `measure_twice`, `ddsim.statevector`: 10: 50067 shots, probability 0; 11: 0 shots, expected 50000.0 ± 1084.8 | known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2. - `measure_twice`, `ddsim.statevector`: known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2. - `measure_twice`, `ddsim.statevector`, reproducer (corpus/reproducers/ddsim_repeated_measurement.py): h, then c[0] and c[1] measured from the qubit with nothing between: only 00 and 10 come — saw ['00', '10'] - `measure_twice`, `ddsim.statevector`, reproducer (corpus/reproducers/ddsim_repeated_measurement.py): x, then the same two measurements: 10 on every shot — saw ['10'] @@ -339,25 +339,25 @@ Versions: cirq-core 1.7.0, mqt.core 3.11.0, mqt.ddsim 2.7.0, numpy 2.5.4, python ### `conformance-macos-arm64.json` -Host: Apple M3 Ultra, macOS 27.2, 32 logical CPUs, 256 GiB, arm64. Tier full, 2316.4 s. Checks: info 12, known 11, not run 12, pass 1743, refused 10. +Host: Apple M3 Ultra, macOS 27.2, 32 logical CPUs, 256 GiB, arm64. Tier full, 2092.6 s. Checks: info 12, known 11, not run 12, pass 1743, refused 10. | family | `wai.exact` | `wai.statevector` | `wai.stabilizer` | `wai.auto` | `wai.mps` | `wai.tensor_network` | `wai.density_matrix` | `wai.qec` | `aer.statevector` | `aer.qasm_import` | `aer.stabilizer` | `aer.mps` | `aer.density_matrix` | `stim.tableau` | `quimb.dense` | `quimb.tensor_network` | `quimb.mps` | `ddsim.statevector` | `qsim.statevector` | `pairs and references` | `references` | |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| | bit_order | 24/24 (0.068) | 8/8 (0.015) | 12/12 | 8/8 (0.0069) | | | | | 8/8 (0.016) | 6/6 (0.016) | 5/5 | | | 7/7 | 6/6 (0.019) | 6/6 (0.031) | | 8/8 (0.00015) | 8/8 (0.013) | 15/15 (0.0084) | 5/5 | -| clifford_large | 4/4 (0.012) | 1/1 (0.00077) | 34/34 (0.43) | 1/1 (7.8e-05) | | | | | 1/1 (0.00084) | 1/1 (0.00084) | 16/16 (0.51) | | | 19/19 (0.34) | 1/1 (0.0017) | 1/1 (4.9e-08) | | 1/1 (2.4e-07) | 1/1 (0.0024) | | 15/15 | -| dynamic | | 12/12 (0.29) | 8/8 (0.21) | 12/12 (0.29) | | | | | 12/12 (0.36) | | | | | 8/8 (0.32) | | | | 8/8 (0.26) · 11 known | 6 not run | | | +| clifford_large | 4/4 (0.012) | 1/1 (0.00077) | 34/34 (0.43) | 1/1 (7.8e-05) | | | | | 1/1 (0.00084) | 1/1 (0.00084) | 16/16 (0.51) | | | 19/19 (0.34) | 1/1 (0.0017) | 1/1 (5e-08) | | 1/1 (2.4e-07) | 1/1 (0.0024) | | 15/15 | +| dynamic | | 12/12 (0.29) | 8/8 (0.21) | 12/12 (0.29) | | | | | 12/12 (0.36) | | | | | 8/8 (0.32) | | | | 8/8 (0.25) · 11 known | 6 not run | | | | gate_conventions | 188/188 (0.069) | 47/47 (0.017) | | 47/47 (0.066) | | | | | 47/47 (0.018) | 47/47 (0.018) | | | | | 46/46 (0.017) · 1 not run | 46/46 (0.032) · 1 not run | | 47/47 (0.00015) | 46/46 (0.026) · 1 not run | | | -| ghz | 20/20 (0.042) | 7/7 (0.21) | 2/2 (0.022) | 7/7 (0.022) | | | | | 7/7 (0.059) | 5/5 (0.011) | | | | 2/2 (0.29) | 5/5 (0.0094) | 5/5 (0.041) | | 7/7 (0.1) | 7/7 (0.14) | | 5/5 | -| grover | 16/16 (0.029) | 6/6 (0.12) | | 6/6 (0.14) | | | | | 6/6 (0.25) | 4/4 (0.0043) | | | | | 4/4 (0.0079) | 4/4 (0.0003) | | 6/6 (0.16) | 6/6 (0.27) | | 4/4 | +| ghz | 20/20 (0.042) | 7/7 (0.21) | 2/2 (0.022) | 7/7 (0.022) | | | | | 7/7 (0.059) | 5/5 (0.011) | | | | 2/2 (0.29) | 5/5 (0.0094) | 5/5 (0.041) | | 7/7 (0.21) | 7/7 (0.14) | | 5/5 | +| grover | 16/16 (0.029) | 6/6 (0.12) | | 6/6 (0.14) | | | | | 6/6 (0.25) | 4/4 (0.0043) | | | | | 4/4 (0.0079) | 4/4 (0.0003) | | 6/6 (0.21) | 6/6 (0.27) | | 4/4 | | mirror | 7/7 (0.007) | 3/3 (0.00036) | | | | | | | 3/3 (0.0011) | | | | | | 3/3 (0.00049) | | | 3/3 (0.00079) | 3/3 (0.00059) | | | | noise | | | | | | | 3/3 (0.00093) | | | | | | 3/3 (0.00093) | | | | | | | | | | other | | | | | | | | | | | | | | | | | | | | | 3/3 | | qec | | | | | | | | 29/29 (0.61) · 2 refused as listed | | | | | | 22/22 (0.52) · 2 not run | | | | | | 44/44 (0.016) | | -| qft | 25/25 (0.042) | 9/9 (0.58) | | 8/8 (0.66) | | | | | 9/9 (0.61) | 6/6 (0.009) | | | | | 7/7 (0.0062) | 5/5 (0.0093) | | 9/9 (0.6) | 9/9 (0.63) | 15/15 (0.0027) | 5/5 | +| qft | 25/25 (0.042) | 9/9 (0.58) | | 8/8 (0.66) | | | | | 9/9 (0.61) | 6/6 (0.009) | | | | | 7/7 (0.0062) | 5/5 (0.0093) | | 9/9 (0.67) | 9/9 (0.63) | 15/15 (0.0027) | 5/5 | | qpe | 12/12 (0.017) · 2 refused as listed | 5/5 (0.0091) | | 5/5 (0.013) | | | | | 5/5 (0.005) | 5/5 (0.0074) | | | | | 5/5 (0.0068) | 4/4 (0.0011) | | 5/5 (7e-06) | 5/5 (0.0037) | | 5/5 | -| random_clifford_t | 12/12 (0.039) | 3/3 (0.0047) | | 3/3 (0.017) | | | | | 3/3 (0.0042) | 3/3 (0.0042) | | | | | 3/3 (0.003) | 3/3 (0.0002) | | 3/3 (3.7e-05) | 3/3 (0.0012) | | | +| random_clifford_t | 12/12 (0.039) | 3/3 (0.0047) | | 3/3 (0.017) | | | | | 3/3 (0.0042) | 3/3 (0.0042) | | | | | 3/3 (0.003) | 3/3 (0.00021) | | 3/3 (3.7e-05) | 3/3 (0.0012) | | | | random_dyadic | 8/8 (0.0067) | 2/2 (0.0018) | | 2/2 (0.0016) | | | | | 2/2 (0.0031) | 2/2 (0.0038) | | | | | 2/2 (0.0014) | 2/2 (0.00016) | | 2/2 (8e-06) | 2/2 (0.004) | | | -| random_rotations | 3 refused as listed | 5/5 (0.48) | | 5/5 (0.48) | | | | | 5/5 (0.5) | 3/3 (0.0039) | | | | | 3/3 (0.0019) | 3/3 (0.00014) | | 5/5 (0.4) | 5/5 (0.4) | 10/10 (0.067) | | +| random_rotations | 3 refused as listed | 5/5 (0.48) | | 5/5 (0.48) | | | | | 5/5 (0.5) | 3/3 (0.0039) | | | | | 3/3 (0.0019) | 3/3 (0.00014) | | 5/5 (0.49) | 5/5 (0.4) | 10/10 (0.067) | | | small_angle | 62/62 (0.9) · 3 refused as listed | 32/32 (0.016) | 2/2 | 18/18 (0.098) | | | | | 32/32 (0.018) | 29/29 (0.016) | 1/1 | | | 1/1 | 30/30 (0.019) | 29/29 (0.016) | | 29/29 (0.15) | 33/33 (0.0075) | | 1/1 | | wide_mps | | | | | 6/6 (0.00017) | 5/5 (0.00057) | | | | | | 4/4 (0.00023) · 1 not run | | | | 5/5 (0.043) | 5/5 (7.3e-05) | | | | | | wide_tn | | | | | 1/1 (0.00093) | 1/1 (6.4e-07) | | | | | | 1/1 (0.0033) | | | | 1/1 (0.019) | 1/1 (0.0006) | | | 21/21 (0.015) | | @@ -365,7 +365,7 @@ Host: Apple M3 Ultra, macOS 27.2, 32 logical CPUs, 256 GiB, arm64. Tier full, 23 Known disagreements of other engines with the exact reference (`corpus/known-disagreements.json`): - `repeat_until_success`, `ddsim.statevector`: ValueError: [changePermutation] Target must be an injective mapping using only keys and logical qubits from the source permutation. | known: MQT DDSIM 2.7.0's qasm_simulator raises ValueError [changePermutation] on this program (two qubits; qubit 1 measured three times in the middle, with gates between and an x conditioned on each reading; four classical bits) and gives no counts. It raises the same without the conditioned x, and on qubit 1 measured, h, measured again, then qubit 0 measured into a third bit; with no third bit it gives counts. Each is a case of the reproducer. -- `measure_twice`, `ddsim.statevector`: 10: 50246 shots, probability 0; 11: 0 shots, expected 50000.0 ± 1084.8 | known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2. +- `measure_twice`, `ddsim.statevector`: 10: 49689 shots, probability 0; 11: 0 shots, expected 50000.0 ± 1084.8 | known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2. - `measure_twice`, `ddsim.statevector`: known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2. - `measure_twice`, `ddsim.statevector`, reproducer (corpus/reproducers/ddsim_repeated_measurement.py): h, then c[0] and c[1] measured from the qubit with nothing between: only 00 and 10 come — saw ['00', '10'] - `measure_twice`, `ddsim.statevector`, reproducer (corpus/reproducers/ddsim_repeated_measurement.py): x, then the same two measurements: 10 on every shot — saw ['10'] diff --git a/wai/quantum-cross-simulator/results/conformance-linux-x86_64.json b/wai/quantum-cross-simulator/results/conformance-linux-x86_64.json index d18afba3a..8ac3ec34f 100644 --- a/wai/quantum-cross-simulator/results/conformance-linux-x86_64.json +++ b/wai/quantum-cross-simulator/results/conformance-linux-x86_64.json @@ -11,9 +11,9 @@ "os": "Ubuntu 26.04.1 LTS", "logical_cpus": 32, "load_average": [ - 15.34716796875, - 18.3154296875, - 20.51806640625 + 21.2060546875, + 29.57958984375, + 39.220703125 ] }, "versions": { @@ -31,9 +31,9 @@ }, "engine_under_test": { "driver": "cross_simulator", - "build": "wai/wai-quantum 0cd14ae3d7845da8d8a1782565781b8a54bb141b, wai/wai-quantum-qpu c1031872aac2c4d2bcf134af80b9dc454954a2de, wai/wai-quantum-cli d3407ee21f3de60a94f4aad561c3dd5c94d47905, wai/quantum-cross-simulator/tools 4f8a83407e5d84edb64017508ab2833879a58bec, wai/quantum-cross-simulator/corpus 1bac9494b3e2e021b99e84fb39b0b046cc970198; rustc 1.99.1 (58cf8f9c3 2026-10-13)" + "build": "wai/wai-quantum 9e64fd1f2b4999ac354c41f5c81ebf04fd8f0269, wai/wai-quantum-qpu 6c2ad362552acb790e81959369680cff5f6fe038, wai/wai-quantum-cli d9d32f1cd4d67f83f58a248ea83d92a6f14cc51f, wai/quantum-cross-simulator/tools 137bbf3854af843e597329bee150489d80f6a93d, wai/quantum-cross-simulator/corpus c648944451c6bc843d5645a384e396324fb617cd; rustc 1.99.1 (58cf8f9c3 2026-10-13)" }, - "seconds": 2758.8, + "seconds": 2911.3, "summary": { "pass": 1738, "refused": 10, @@ -103,7 +103,7 @@ "note": "double precision, fusion width 3", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.002355921 + "seconds": 0.000154332 }, { "entry": "bit_order_x_low", @@ -115,7 +115,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000139895 + "seconds": 0.000136407 }, { "entry": "bit_order_x_low", @@ -127,7 +127,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000141106, + "seconds": 0.000141688, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -142,7 +142,7 @@ "note": "double precision, gate by gate", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.8091795619111508 + "seconds": 0.9349293599370867 }, { "entry": "bit_order_x_low", @@ -154,7 +154,7 @@ "note": "double precision, a contraction of width 5.0", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.002163947792723775 + "seconds": 0.002035345882177353 }, { "entry": "bit_order_x_low", @@ -166,7 +166,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.006068774964660406 + "seconds": 0.010332814883440733 }, { "entry": "bit_order_x_low", @@ -178,7 +178,7 @@ "note": "single precision, fusion width 2", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0005227180663496256 + "seconds": 0.0005162549205124378 }, { "entry": "bit_order_x_low", @@ -195,7 +195,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 4.567601718008518e-05 + "seconds": 4.717893898487091e-05 }, { "entry": "bit_order_x_low", @@ -204,7 +204,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 1.453e-06 + "seconds": 6.402e-06 }, { "entry": "bit_order_x_low", @@ -221,7 +221,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 9.1432e-05 + "seconds": 0.000107814 }, { "entry": "bit_order_x_low", @@ -277,7 +277,7 @@ "note": "double precision, fusion width 3", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000155043 + "seconds": 0.002749235 }, { "entry": "bit_order_x_high", @@ -289,7 +289,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000134193 + "seconds": 0.000142209 }, { "entry": "bit_order_x_high", @@ -301,7 +301,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000129034, + "seconds": 0.000137991, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -316,7 +316,7 @@ "note": "double precision, gate by gate", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.9358811981510371 + "seconds": 0.8945470110047609 }, { "entry": "bit_order_x_high", @@ -328,7 +328,7 @@ "note": "double precision, a contraction of width 5.0", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0016758558340370655 + "seconds": 0.0020862428937107325 }, { "entry": "bit_order_x_high", @@ -340,7 +340,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.008693352807313204 + "seconds": 0.009399872971698642 }, { "entry": "bit_order_x_high", @@ -352,7 +352,7 @@ "note": "single precision, fusion width 2", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0007507179398089647 + "seconds": 0.00048209098167717457 }, { "entry": "bit_order_x_high", @@ -369,7 +369,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 5.113682709634304e-05 + "seconds": 3.478606231510639e-05 }, { "entry": "bit_order_x_high", @@ -378,7 +378,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 4.879e-06 + "seconds": 4.449e-06 }, { "entry": "bit_order_x_high", @@ -395,7 +395,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000117912 + "seconds": 8.3358e-05 }, { "entry": "bit_order_x_high", @@ -451,7 +451,7 @@ "note": "double precision, fusion width 3", "strict": 2.853028722211445e-16, "global_phase": -5.504485103160786e-17, - "seconds": 0.000208234 + "seconds": 0.000193125 }, { "entry": "bit_order_product", @@ -463,7 +463,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.7214193512736154e-16, "global_phase": -7.54854054484019e-17, - "seconds": 0.000156526 + "seconds": 0.000135085 }, { "entry": "bit_order_product", @@ -475,7 +475,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.7214193512736154e-16, "global_phase": -7.54854054484019e-17, - "seconds": 0.000166885, + "seconds": 0.000156286, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -490,7 +490,7 @@ "note": "double precision, gate by gate", "strict": 3.964222321740644e-16, "global_phase": -3.4093253995171833e-17, - "seconds": 1.035651037003845 + "seconds": 0.6794167838525027 }, { "entry": "bit_order_product", @@ -502,7 +502,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 2.773703885184681e-16, "global_phase": -5.510528309801803e-17, - "seconds": 0.002997633069753647 + "seconds": 0.002350941998884082 }, { "entry": "bit_order_product", @@ -514,7 +514,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.011275315895486e-17, "global_phase": 9.959077994004481e-18, - "seconds": 0.007254354888573289 + "seconds": 0.007930726045742631 }, { "entry": "bit_order_product", @@ -526,7 +526,7 @@ "note": "single precision, fusion width 2", "strict": 3.518581035832407e-08, "global_phase": 1.33385189244294e-08, - "seconds": 0.0006025789771229029 + "seconds": 0.0005366241093724966 }, { "entry": "bit_order_product", @@ -582,7 +582,7 @@ "note": "double precision, fusion width 3", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000156225 + "seconds": 0.000151637 }, { "entry": "bit_order_control", @@ -594,7 +594,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 8.997e-05 + "seconds": 0.000110058 }, { "entry": "bit_order_control", @@ -606,7 +606,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000141026, + "seconds": 0.000117332, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -621,7 +621,7 @@ "note": "double precision, gate by gate", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.8137311202008277 + "seconds": 0.5324786899145693 }, { "entry": "bit_order_control", @@ -633,7 +633,7 @@ "note": "double precision, a contraction of width 4.0", "strict": 3.3306690738754696e-16, "global_phase": 0.0, - "seconds": 0.0017638118006289005 + "seconds": 0.0020953600760549307 }, { "entry": "bit_order_control", @@ -645,7 +645,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.00802221498452127 + "seconds": 0.007282420992851257 }, { "entry": "bit_order_control", @@ -657,7 +657,7 @@ "note": "single precision, fusion width 2", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0005257232114672661 + "seconds": 0.0005370250437408686 }, { "entry": "bit_order_control", @@ -674,7 +674,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 3.8322992622852325e-05 + "seconds": 3.308197483420372e-05 }, { "entry": "bit_order_control", @@ -683,7 +683,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 6.102e-06 + "seconds": 4.97e-06 }, { "entry": "bit_order_control", @@ -700,7 +700,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 9.7254e-05 + "seconds": 9.0621e-05 }, { "entry": "bit_order_control", @@ -756,7 +756,7 @@ "note": "double precision, fusion width 3", "strict": 0.0, "global_phase": 0.0, - "seconds": 3.71e-07 + "seconds": 3.507e-06 }, { "entry": "empty_register", @@ -768,7 +768,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000102082 + "seconds": 0.000108635 }, { "entry": "empty_register", @@ -780,7 +780,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000129986, + "seconds": 0.000133662, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -795,7 +795,7 @@ "note": "double precision, gate by gate", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.7339987740851939 + "seconds": 0.6725205229595304 }, { "entry": "empty_register", @@ -807,7 +807,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.001609800849109888 + "seconds": 0.001236937940120697 }, { "entry": "empty_register", @@ -819,7 +819,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.008620506152510643 + "seconds": 0.0060624058824032545 }, { "entry": "empty_register", @@ -831,7 +831,7 @@ "note": "single precision, fusion width 2", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0004139421507716179 + "seconds": 0.0003917301073670387 }, { "entry": "empty_register", @@ -848,7 +848,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 4.427391104400158e-05 + "seconds": 4.0526967495679855e-05 }, { "entry": "empty_register", @@ -857,7 +857,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 8.22e-07 + "seconds": 3.757e-06 }, { "entry": "empty_register", @@ -874,7 +874,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 9.4138e-05 + "seconds": 8.1815e-05 }, { "entry": "empty_register", @@ -930,7 +930,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.00014319 + "seconds": 0.000171384 }, { "entry": "one_qubit", @@ -942,7 +942,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000133121 + "seconds": 0.000138362 }, { "entry": "one_qubit", @@ -954,7 +954,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000134254, + "seconds": 0.000124085, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -969,7 +969,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.7388546278234571 + "seconds": 0.7622498217970133 }, { "entry": "one_qubit", @@ -981,7 +981,7 @@ "note": "double precision, a contraction of width 1.0", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.0008224239572882652 + "seconds": 0.0008135479874908924 }, { "entry": "one_qubit", @@ -993,7 +993,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.005901037948206067 + "seconds": 0.00693305185995996 }, { "entry": "one_qubit", @@ -1005,7 +1005,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0004487780388444662 + "seconds": 0.0005470339674502611 }, { "entry": "one_qubit", @@ -1022,7 +1022,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 6.398092955350876e-05 + "seconds": 3.372388891875744e-05 }, { "entry": "one_qubit", @@ -1031,7 +1031,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 7.665e-06 + "seconds": 5.039e-06 }, { "entry": "one_qubit", @@ -1048,7 +1048,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000107643 + "seconds": 8.7095e-05 }, { "entry": "one_qubit", @@ -1232,7 +1232,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.000168087 + "seconds": 0.000133382 }, { "entry": "ghz_n2", @@ -1244,7 +1244,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000135826 + "seconds": 0.000149472 }, { "entry": "ghz_n2", @@ -1256,7 +1256,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000141918, + "seconds": 0.000153941, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1271,7 +1271,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.713551415828988 + "seconds": 0.8130771189462394 }, { "entry": "ghz_n2", @@ -1283,7 +1283,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 4.026696510285133e-16, "global_phase": 0.0, - "seconds": 0.0013712409418076277 + "seconds": 0.0013601998798549175 }, { "entry": "ghz_n2", @@ -1295,7 +1295,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.008008940145373344 + "seconds": 0.00847629806958139 }, { "entry": "ghz_n2", @@ -1307,7 +1307,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0005433058831840754 + "seconds": 0.0006000041030347347 }, { "entry": "ghz_n2", @@ -1371,7 +1371,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.000163219 + "seconds": 0.000165613 }, { "entry": "ghz_n3", @@ -1383,7 +1383,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000146146 + "seconds": 0.000141528 }, { "entry": "ghz_n3", @@ -1395,7 +1395,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.0001484, + "seconds": 0.000136568, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1410,7 +1410,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.6600238259416074 + "seconds": 0.8011018999386579 }, { "entry": "ghz_n3", @@ -1422,7 +1422,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 7.166881427652682e-16, "global_phase": 0.0, - "seconds": 0.002045754808932543 + "seconds": 0.0015426049940288067 }, { "entry": "ghz_n3", @@ -1434,7 +1434,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.008277998073026538 + "seconds": 0.006387049099430442 }, { "entry": "ghz_n3", @@ -1446,7 +1446,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0004952459130436182 + "seconds": 0.0005108749028295279 }, { "entry": "ghz_n3", @@ -1510,7 +1510,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.000213433 + "seconds": 0.000224965 }, { "entry": "ghz_n5", @@ -1522,7 +1522,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000133903 + "seconds": 0.000140375 }, { "entry": "ghz_n5", @@ -1534,7 +1534,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000144002, + "seconds": 0.000152769, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1549,7 +1549,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.6070356038399041 + "seconds": 0.6857008000370115 }, { "entry": "ghz_n5", @@ -1561,7 +1561,7 @@ "note": "double precision, a contraction of width 5.0", "strict": 1.1877158803704008e-15, "global_phase": 0.0, - "seconds": 0.0025526119861751795 + "seconds": 0.002261002082377672 }, { "entry": "ghz_n5", @@ -1573,7 +1573,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.013378764037042856 + "seconds": 0.007307407911866903 }, { "entry": "ghz_n5", @@ -1585,7 +1585,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.000584794906899333 + "seconds": 0.0005306929815560579 }, { "entry": "ghz_n5", @@ -1649,7 +1649,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.000233421 + "seconds": 0.000271473 }, { "entry": "ghz_n8", @@ -1661,7 +1661,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000167706 + "seconds": 0.000118113 }, { "entry": "ghz_n8", @@ -1673,7 +1673,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000145545, + "seconds": 0.000130386, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1688,7 +1688,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.8728732368908823 + "seconds": 0.6354408948682249 }, { "entry": "ghz_n8", @@ -1700,7 +1700,7 @@ "note": "double precision, a contraction of width 8.0", "strict": 2.757808339054176e-15, "global_phase": 0.0, - "seconds": 0.0043983489740639925 + "seconds": 0.0028000911697745323 }, { "entry": "ghz_n8", @@ -1712,7 +1712,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.00821344694122672 + "seconds": 0.005791893927380443 }, { "entry": "ghz_n8", @@ -1724,7 +1724,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0008158811833709478 + "seconds": 0.0005170379299670458 }, { "entry": "ghz_n8", @@ -1788,7 +1788,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.000473965 + "seconds": 0.000494524 }, { "entry": "ghz_n12", @@ -1800,7 +1800,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000266844 + "seconds": 0.000254461 }, { "entry": "ghz_n12", @@ -1812,7 +1812,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000297352, + "seconds": 0.000246256, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1827,7 +1827,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.9556462268810719 + "seconds": 0.5724717429839075 }, { "entry": "ghz_n12", @@ -1839,7 +1839,7 @@ "note": "double precision, a contraction of width 12.0", "strict": 3.071826830790931e-15, "global_phase": 0.0, - "seconds": 0.008892529178410769 + "seconds": 0.005226255860179663 }, { "entry": "ghz_n12", @@ -1851,7 +1851,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.009456194005906582 + "seconds": 0.006585625000298023 }, { "entry": "ghz_n12", @@ -1863,7 +1863,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0005821199156343937 + "seconds": 0.0005745359230786562 }, { "entry": "ghz_n12", @@ -1927,7 +1927,7 @@ "note": "double precision, fusion width 3", "strict": 2.257974101246671e-16, "global_phase": 1.5308084989341915e-17, - "seconds": 0.000184859 + "seconds": 0.000146246 }, { "entry": "qft_n3_x5", @@ -1939,7 +1939,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.3884324549296737e-16, "global_phase": 3.806340515408302e-16, - "seconds": 0.000174039 + "seconds": 0.000133463 }, { "entry": "qft_n3_x5", @@ -1951,7 +1951,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.3884324549296737e-16, "global_phase": 3.806340515408302e-16, - "seconds": 0.00016953, + "seconds": 0.000123073, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1966,7 +1966,7 @@ "note": "double precision, gate by gate", "strict": 2.6677932835798804e-16, "global_phase": 4.306366060497084e-17, - "seconds": 0.9689505510032177 + "seconds": 0.7196352640166879 }, { "entry": "qft_n3_x5", @@ -1978,7 +1978,7 @@ "note": "double precision, a contraction of width 4.0", "strict": 7.524080403774347e-16, "global_phase": -2.765095852147809e-16, - "seconds": 0.0027986071072518826 + "seconds": 0.002207542071118951 }, { "entry": "qft_n3_x5", @@ -1990,7 +1990,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.237121377012062e-16, "global_phase": 0.0, - "seconds": 0.008258281042799354 + "seconds": 0.005557871889322996 }, { "entry": "qft_n3_x5", @@ -2002,7 +2002,7 @@ "note": "single precision, fusion width 2", "strict": 3.268347795371965e-08, "global_phase": -1.8378428171781463e-08, - "seconds": 0.0006425241008400917 + "seconds": 0.0005777720361948013 }, { "entry": "qft_n3_x5", @@ -2066,7 +2066,7 @@ "note": "double precision, fusion width 3", "strict": 3.506724345492627e-16, "global_phase": 1.283897907660248e-16, - "seconds": 0.000406979 + "seconds": 0.000312611 }, { "entry": "qft_n5_x19", @@ -2078,7 +2078,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.303815859586128e-16, "global_phase": 4.630671312859982e-16, - "seconds": 0.000172696 + "seconds": 0.000140625 }, { "entry": "qft_n5_x19", @@ -2090,7 +2090,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.303815859586128e-16, "global_phase": 4.630671312859982e-16, - "seconds": 0.000173198, + "seconds": 0.000160052, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2105,7 +2105,7 @@ "note": "double precision, gate by gate", "strict": 5.057824840498477e-16, "global_phase": 1.4612721318054353e-16, - "seconds": 0.669324005022645 + "seconds": 0.7029365189373493 }, { "entry": "qft_n5_x19", @@ -2117,7 +2117,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 9.059602036814133e-16, "global_phase": 8.074243513517871e-17, - "seconds": 0.09386956202797592 + "seconds": 0.09331040596589446 }, { "entry": "qft_n5_x19", @@ -2129,7 +2129,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.9241850975309797e-16, "global_phase": 4.6098944822979383e-17, - "seconds": 0.005827319109812379 + "seconds": 0.008152705850079656 }, { "entry": "qft_n5_x19", @@ -2141,7 +2141,7 @@ "note": "single precision, fusion width 2", "strict": 1.2543028130092563e-07, "global_phase": -7.144875201754854e-08, - "seconds": 0.0007222539279609919 + "seconds": 0.0007104817777872086 }, { "entry": "qft_n5_x19", @@ -2205,7 +2205,7 @@ "note": "double precision, fusion width 3", "strict": 8.320669916157845e-16, "global_phase": 3.306698650009266e-16, - "seconds": 0.000625973 + "seconds": 0.00088379 }, { "entry": "qft_n8_x173", @@ -2217,7 +2217,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.996490609257424e-16, "global_phase": 9.084158885110515e-16, - "seconds": 0.000167126 + "seconds": 0.000208884 }, { "entry": "qft_n8_x173", @@ -2229,7 +2229,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.996490609257424e-16, "global_phase": 9.084158885110515e-16, - "seconds": 0.000180842, + "seconds": 0.000210778, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2244,19 +2244,19 @@ "note": "double precision, gate by gate", "strict": 7.763478117220366e-16, "global_phase": 3.0372576170693494e-16, - "seconds": 0.6458048839122057 + "seconds": 0.7517462440300733 }, { "entry": "qft_n8_x173", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 8.889677839653127e-15, + "measured": 8.985416523784293e-15, "tolerance": 5.472132013758785e-10, "status": "pass", "note": "double precision, a contraction of width 11.0", - "strict": 8.895168328369591e-15, - "global_phase": -3.1248599522154173e-16, - "seconds": 0.10698625212535262 + "strict": 8.986590769910576e-15, + "global_phase": -1.4527064378643825e-16, + "seconds": 0.12861927784979343 }, { "entry": "qft_n8_x173", @@ -2268,7 +2268,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.6777798095682838e-16, "global_phase": 4.766451331749067e-17, - "seconds": 0.007089011836796999 + "seconds": 0.015808593947440386 }, { "entry": "qft_n8_x173", @@ -2280,7 +2280,7 @@ "note": "single precision, fusion width 2", "strict": 2.1361092843437718e-07, "global_phase": -1.5870936099867787e-07, - "seconds": 0.0010094668250530958 + "seconds": 0.0010555949993431568 }, { "entry": "qft_n8_x173", @@ -2344,7 +2344,7 @@ "note": "double precision, fusion width 3", "strict": 1.05735130271346e-15, "global_phase": 4.856407661367594e-16, - "seconds": 0.001460048 + "seconds": 0.088320477 }, { "entry": "qft_n12_x2741", @@ -2356,7 +2356,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4235804381409074e-15, "global_phase": 1.3445091043436557e-15, - "seconds": 0.001086753 + "seconds": 0.001126288 }, { "entry": "qft_n12_x2741", @@ -2368,7 +2368,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4235804381409074e-15, "global_phase": 1.3445091043436557e-15, - "seconds": 0.001091702, + "seconds": 0.001168758, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2383,19 +2383,19 @@ "note": "double precision, gate by gate", "strict": 1.2719000340925913e-15, "global_phase": 4.81426406762063e-16, - "seconds": 0.657696760026738 + "seconds": 0.7360440820921212 }, { "entry": "qft_n12_x2741", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.0241086531956606e-14, + "measured": 1.0317417579829573e-14, "tolerance": 1.22787892058417e-05, "status": "pass", "note": "double precision, a contraction of width 20.0", - "strict": 1.0241221200867061e-14, - "global_phase": 5.2519806415824354e-17, - "seconds": 0.3440058440901339 + "strict": 1.0318523311105159e-14, + "global_phase": 1.5105563625452084e-16, + "seconds": 0.7565001070033759 }, { "entry": "qft_n12_x2741", @@ -2407,7 +2407,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.468256033541478e-16, "global_phase": -1.0198722492404313e-18, - "seconds": 0.008348862174898386 + "seconds": 0.011779679916799068 }, { "entry": "qft_n12_x2741", @@ -2419,7 +2419,7 @@ "note": "single precision, fusion width 2", "strict": 2.930851582105311e-07, "global_phase": -2.336473764348756e-07, - "seconds": 0.0014230089727789164 + "seconds": 0.001911963103339076 }, { "entry": "qft_n12_x2741", @@ -2483,7 +2483,7 @@ "note": "double precision, fusion width 3", "strict": 1.3611349762871244e-15, "global_phase": 5.292345204732061e-16, - "seconds": 0.003259598 + "seconds": 0.004065492 }, { "entry": "qft_n14_x10923", @@ -2495,7 +2495,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4337352821423908e-15, "global_phase": 1.310803683777888e-15, - "seconds": 0.005217727 + "seconds": 0.006136206 }, { "entry": "qft_n14_x10923", @@ -2507,7 +2507,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4337352821423908e-15, "global_phase": 1.310803683777888e-15, - "seconds": 0.004989195, + "seconds": 0.005237707, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2522,7 +2522,7 @@ "note": "double precision, gate by gate", "strict": 1.4189542437976667e-15, "global_phase": 4.717268824830606e-16, - "seconds": 0.622086487011984 + "seconds": 0.6083897268399596 }, { "entry": "qft_n14_x10923", @@ -2534,7 +2534,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.017553738362537e-16, "global_phase": -1.617385543496028e-16, - "seconds": 0.014290696941316128 + "seconds": 0.014166960958391428 }, { "entry": "qft_n14_x10923", @@ -2546,7 +2546,7 @@ "note": "single precision, fusion width 2", "strict": 3.543161592552357e-07, "global_phase": -2.6790922427742024e-07, - "seconds": 0.002619087928906083 + "seconds": 0.0018842709250748158 }, { "entry": "qft_n14_x10923", @@ -2602,7 +2602,7 @@ "note": "double precision, fusion width 3", "strict": 1.101391650619332e-15, "global_phase": 1.9797940426470196e-16, - "seconds": 0.001846528 + "seconds": 0.008989026 }, { "entry": "qft_superposed_n10", @@ -2614,7 +2614,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0602512121224904e-15, "global_phase": 9.256274969002942e-16, - "seconds": 0.000394055 + "seconds": 0.000483043 }, { "entry": "qft_superposed_n10", @@ -2626,7 +2626,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0602512121224904e-15, "global_phase": 9.256274969002942e-16, - "seconds": 0.000506837, + "seconds": 0.000488182, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2641,19 +2641,19 @@ "note": "double precision, gate by gate", "strict": 1.279828475104203e-15, "global_phase": 7.391904992106145e-17, - "seconds": 0.8106321049854159 + "seconds": 0.7302031340077519 }, { "entry": "qft_superposed_n10", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 7.345255257079278e-15, + "measured": 7.031212712368057e-15, "tolerance": 5.015566805471182e-06, "status": "pass", "note": "double precision, a contraction of width 19.0", - "strict": 7.356661395949502e-15, - "global_phase": 4.0950226251255155e-16, - "seconds": 0.35940493596717715 + "strict": 7.0356473722990305e-15, + "global_phase": 2.4976336955624e-16, + "seconds": 0.6504162838682532 }, { "entry": "qft_superposed_n10", @@ -2665,7 +2665,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.5872082553212343e-15, "global_phase": -3.8342807661503016e-17, - "seconds": 0.01745840208604932 + "seconds": 0.01427947380580008 }, { "entry": "qft_superposed_n10", @@ -2677,7 +2677,7 @@ "note": "single precision, fusion width 2", "strict": 1.5658919686253052e-07, "global_phase": -6.317885380118834e-08, - "seconds": 0.0014647969510406256 + "seconds": 0.0018519090954214334 }, { "entry": "qft_superposed_n10", @@ -2909,7 +2909,7 @@ "note": "double precision, fusion width 3", "strict": 1.0198506246188093e-15, "global_phase": 0.0, - "seconds": 0.000163729 + "seconds": 0.000188376 }, { "entry": "grover_n3", @@ -2921,7 +2921,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.82855567997045e-16, "global_phase": 7.11825952004399e-16, - "seconds": 9.7494e-05 + "seconds": 0.000162407 }, { "entry": "grover_n3", @@ -2933,7 +2933,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.82855567997045e-16, "global_phase": 7.11825952004399e-16, - "seconds": 0.000170222, + "seconds": 0.00015375, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2948,7 +2948,7 @@ "note": "double precision, gate by gate", "strict": 1.1870146619100088e-15, "global_phase": 0.0, - "seconds": 0.5668590939603746 + "seconds": 0.7377703140955418 }, { "entry": "grover_n3", @@ -2960,7 +2960,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 5.966650663593933e-16, "global_phase": 0.0, - "seconds": 0.0029824241064488888 + "seconds": 0.0029380719643086195 }, { "entry": "grover_n3", @@ -2972,7 +2972,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.322204543158198e-16, "global_phase": 0.0, - "seconds": 0.005772144068032503 + "seconds": 0.008088665083050728 }, { "entry": "grover_n3", @@ -2984,7 +2984,7 @@ "note": "single precision, fusion width 2", "strict": 1.712509627811334e-07, "global_phase": 0.0, - "seconds": 0.0008025558199733496 + "seconds": 0.0012311069294810295 }, { "entry": "grover_n3", @@ -3048,7 +3048,7 @@ "note": "double precision, fusion width 3", "strict": 3.926196862092386e-15, "global_phase": 0.0, - "seconds": 0.000888519 + "seconds": 0.00939314 }, { "entry": "grover_n5", @@ -3060,7 +3060,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.554278208317962e-15, "global_phase": 3.3051253236443238e-15, - "seconds": 0.000160613 + "seconds": 0.000182234 }, { "entry": "grover_n5", @@ -3072,7 +3072,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.554278208317962e-15, "global_phase": 3.3051253236443238e-15, - "seconds": 0.000209696, + "seconds": 0.000225756, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3087,19 +3087,19 @@ "note": "double precision, gate by gate", "strict": 3.979364197199202e-15, "global_phase": 0.0, - "seconds": 0.5394958320539445 + "seconds": 0.7601337530650198 }, { "entry": "grover_n5", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 5.707920859394904e-15, + "measured": 6.6223351559130934e-15, "tolerance": 1.9326685410829237e-11, "status": "pass", "note": "double precision, a contraction of width 7.0", - "strict": 5.707920859394904e-15, + "strict": 6.6223351559130934e-15, "global_phase": 0.0, - "seconds": 0.11723517393693328 + "seconds": 0.1316526299342513 }, { "entry": "grover_n5", @@ -3111,7 +3111,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.063150391861205e-17, "global_phase": 0.0, - "seconds": 0.0051896239165216684 + "seconds": 0.00699318409897387 }, { "entry": "grover_n5", @@ -3123,7 +3123,7 @@ "note": "single precision, fusion width 2", "strict": 1.475046831785649e-07, "global_phase": 0.0, - "seconds": 0.0014350709971040487 + "seconds": 0.002171332947909832 }, { "entry": "grover_n5", @@ -3187,7 +3187,7 @@ "note": "double precision, fusion width 3", "strict": 1.6055183209665808e-14, "global_phase": 0.0, - "seconds": 0.003299163 + "seconds": 0.004205497 }, { "entry": "grover_n8", @@ -3199,7 +3199,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3818998850279718e-14, "global_phase": 1.3333198341892727e-14, - "seconds": 0.000551211 + "seconds": 0.000667882 }, { "entry": "grover_n8", @@ -3211,7 +3211,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3818998850279718e-14, "global_phase": 1.3333198341892727e-14, - "seconds": 0.000527577, + "seconds": 0.000536103, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3226,19 +3226,19 @@ "note": "double precision, gate by gate", "strict": 1.8051945192911557e-14, "global_phase": 0.0, - "seconds": 0.5686874189414084 + "seconds": 0.9000320550985634 }, { "entry": "grover_n8", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 7.156317977481662e-14, + "measured": 6.967561028670812e-14, "tolerance": 1.4460064500364516e-08, "status": "pass", "note": "double precision, a contraction of width 12.0", - "strict": 7.156317977481662e-14, + "strict": 6.967561028670812e-14, "global_phase": 0.0, - "seconds": 0.515175678068772 + "seconds": 2.1085380548611283 }, { "entry": "grover_n8", @@ -3250,7 +3250,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.0522346859459808e-15, "global_phase": 0.0, - "seconds": 0.017741206102073193 + "seconds": 0.022867111954838037 }, { "entry": "grover_n8", @@ -3262,7 +3262,7 @@ "note": "single precision, fusion width 2", "strict": 2.7917667985836753e-07, "global_phase": 0.0, - "seconds": 0.007252280134707689 + "seconds": 0.043900176882743835 }, { "entry": "grover_n8", @@ -3326,7 +3326,7 @@ "note": "double precision, fusion width 3", "strict": 3.7861950351453296e-14, "global_phase": 0.0, - "seconds": 0.008483085 + "seconds": 0.085250245 }, { "entry": "grover_n10", @@ -3338,7 +3338,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.3673609522423125e-14, "global_phase": 3.2463955134398285e-14, - "seconds": 0.002094437 + "seconds": 0.002338479 }, { "entry": "grover_n10", @@ -3350,7 +3350,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.3673609522423125e-14, "global_phase": 3.2463955134398285e-14, - "seconds": 0.002991741, + "seconds": 0.003550159, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3365,19 +3365,19 @@ "note": "double precision, gate by gate", "strict": 4.53350780910714e-14, "global_phase": 0.0, - "seconds": 0.7879055209923536 + "seconds": 1.008445812156424 }, { "entry": "grover_n10", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.282331798902906e-13, + "measured": 1.2448171736998097e-13, "tolerance": 1.892533604466189e-05, "status": "pass", "note": "double precision, a contraction of width 18.0", - "strict": 1.282331798902906e-13, + "strict": 1.2448171736998097e-13, "global_phase": 0.0, - "seconds": 2.7516728481277823 + "seconds": 3.153706369921565 }, { "entry": "grover_n10", @@ -3389,7 +3389,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.2520782731179646e-15, "global_phase": 0.0, - "seconds": 0.015344498213380575 + "seconds": 0.019052081974223256 }, { "entry": "grover_n10", @@ -3401,7 +3401,7 @@ "note": "single precision, fusion width 2", "strict": 3.9603425553760547e-07, "global_phase": 0.0, - "seconds": 0.07239893195219338 + "seconds": 0.018152743112295866 }, { "entry": "grover_n10", @@ -3465,7 +3465,7 @@ "note": "double precision, fusion width 3", "strict": 8.969588494495959e-16, "global_phase": 1.2447490626286985e-17, - "seconds": 0.000307281 + "seconds": 0.000447195 }, { "entry": "qpe_t4_m5", @@ -3477,7 +3477,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.950557577583702e-16, "global_phase": 3.063604932067729e-16, - "seconds": 0.000156005 + "seconds": 0.000170152 }, { "entry": "qpe_t4_m5", @@ -3489,7 +3489,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.950557577583702e-16, "global_phase": 3.063604932067729e-16, - "seconds": 0.000155805, + "seconds": 0.000154612, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3504,7 +3504,7 @@ "note": "double precision, gate by gate", "strict": 6.897806972913936e-16, "global_phase": 1.2445605710183747e-16, - "seconds": 0.681786848930642 + "seconds": 0.954243266955018 }, { "entry": "qpe_t4_m5", @@ -3516,7 +3516,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 2.261831872770116e-15, "global_phase": 2.7622468976838543e-16, - "seconds": 0.08536671008914709 + "seconds": 0.13123415899462998 }, { "entry": "qpe_t4_m5", @@ -3528,7 +3528,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.132622887710837e-76, "global_phase": 8.636168555094445e-78, - "seconds": 0.006311323028057814 + "seconds": 0.00937630794942379 }, { "entry": "qpe_t4_m5", @@ -3540,7 +3540,7 @@ "note": "single precision, fusion width 2", "strict": 9.809987558646393e-08, "global_phase": -6.2842104853189e-08, - "seconds": 0.0009238249622285366 + "seconds": 0.0010337140411138535 }, { "entry": "qpe_t4_m5", @@ -3604,7 +3604,7 @@ "note": "double precision, fusion width 3", "strict": 1.4100014542159497e-15, "global_phase": -1.6968573694255317e-16, - "seconds": 0.000718096 + "seconds": 0.036192582 }, { "entry": "qpe_t8_m173", @@ -3616,7 +3616,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.461694205298591e-16, "global_phase": 4.545696251957764e-16, - "seconds": 0.00029621 + "seconds": 0.000299285 }, { "entry": "qpe_t8_m173", @@ -3628,7 +3628,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.461694205298591e-16, "global_phase": 4.545696251957764e-16, - "seconds": 0.000225927, + "seconds": 0.000286822, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3643,19 +3643,19 @@ "note": "double precision, gate by gate", "strict": 1.3787192988274878e-15, "global_phase": -1.1712366921111296e-16, - "seconds": 0.5726143370848149 + "seconds": 0.9082774410489947 }, { "entry": "qpe_t8_m173", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 7.2083489839097e-15, + "measured": 7.712521632522422e-15, "tolerance": 1.5373360013432097e-08, "status": "pass", "note": "double precision, a contraction of width 14.0", - "strict": 7.213043986309759e-15, - "global_phase": 2.602085213965229e-16, - "seconds": 0.31377014494501054 + "strict": 7.714545732165125e-15, + "global_phase": 1.7670857800574282e-16, + "seconds": 0.6500995769165456 }, { "entry": "qpe_t8_m173", @@ -3667,7 +3667,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.607656667869935e-76, "global_phase": -1.727233711018889e-77, - "seconds": 0.006697952980175614 + "seconds": 0.01840951107442379 }, { "entry": "qpe_t8_m173", @@ -3679,7 +3679,7 @@ "note": "single precision, fusion width 2", "strict": 2.876291632867958e-07, "global_phase": -2.3313432961912926e-07, - "seconds": 0.0010788990184664726 + "seconds": 0.0015708699356764555 }, { "entry": "qpe_t8_m173", @@ -3743,7 +3743,7 @@ "note": "double precision, fusion width 3", "strict": 1.882816968641882e-15, "global_phase": 3.7724122817685328e-16, - "seconds": 0.002496737 + "seconds": 0.192926434 }, { "entry": "qpe_t12_m2741", @@ -3755,7 +3755,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.839500472473385e-16, "global_phase": 5.640957091605201e-16, - "seconds": 0.002547353 + "seconds": 0.003085252 }, { "entry": "qpe_t12_m2741", @@ -3767,7 +3767,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4625597378806557e-15, "global_phase": 1.2545156525992895e-15, - "seconds": 0.002564164, + "seconds": 0.003865497, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3782,7 +3782,7 @@ "note": "double precision, gate by gate", "strict": 2.156472537645196e-15, "global_phase": -1.663867892004838e-16, - "seconds": 0.5730251029599458 + "seconds": 0.8729030711110681 }, { "entry": "qpe_t12_m2741", @@ -3794,7 +3794,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.21584525039295e-75, "global_phase": 1.727233711018889e-76, - "seconds": 0.006369883893057704 + "seconds": 0.009275814983993769 }, { "entry": "qpe_t12_m2741", @@ -3806,7 +3806,7 @@ "note": "single precision, fusion width 2", "strict": 3.842768069606236e-07, "global_phase": -2.680624504591769e-07, - "seconds": 0.0016155121847987175 + "seconds": 0.0024462840519845486 }, { "entry": "qpe_t12_m2741", @@ -3843,7 +3843,7 @@ "note": "double precision, fusion width 3", "strict": 1.4189449206665662e-15, "global_phase": 9.228121731687924e-16, - "seconds": 0.000474096 + "seconds": 0.000664186 }, { "entry": "qpe_t6_third", @@ -3855,7 +3855,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.014150468655927e-15, "global_phase": -8.611717972347723e-16, - "seconds": 0.00015924 + "seconds": 0.000193386 }, { "entry": "qpe_t6_third", @@ -3867,7 +3867,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3989903050203014e-15, "global_phase": 1.2165404969299746e-15, - "seconds": 0.000147349, + "seconds": 0.000197122, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3882,19 +3882,19 @@ "note": "double precision, gate by gate", "strict": 1.7012647607988397e-15, "global_phase": -1.1616003785718901e-15, - "seconds": 0.5867704001720995 + "seconds": 0.6715273240115494 }, { "entry": "qpe_t6_third", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.355517830463208e-15, + "measured": 3.2659034408605568e-15, "tolerance": 4.542902048736096e-10, "status": "pass", "note": "double precision, a contraction of width 11.0", - "strict": 3.5442174439603333e-15, - "global_phase": -1.1410422338880405e-15, - "seconds": 0.10206977394409478 + "strict": 3.3700203413193007e-15, + "global_phase": -8.312110537529174e-16, + "seconds": 0.1839573299512267 }, { "entry": "qpe_t6_third", @@ -3906,7 +3906,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.2134194796667104e-16, "global_phase": -1.517261646831866e-17, - "seconds": 0.005539344856515527 + "seconds": 0.006013578036800027 }, { "entry": "qpe_t6_third", @@ -3918,7 +3918,7 @@ "note": "single precision, fusion width 2", "strict": 1.9800979111404798e-07, "global_phase": -1.1358480392540512e-07, - "seconds": 0.0008513280190527439 + "seconds": 0.0010759239085018635 }, { "entry": "qpe_t6_third", @@ -3955,7 +3955,7 @@ "note": "double precision, fusion width 3", "strict": 2.278811280653084e-15, "global_phase": 1.4018513039698793e-15, - "seconds": 0.001194737 + "seconds": 0.021571067 }, { "entry": "qpe_t10_third", @@ -3967,7 +3967,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.6713352516360588e-15, "global_phase": -1.5006345758409982e-15, - "seconds": 0.000600144 + "seconds": 0.00073009 }, { "entry": "qpe_t10_third", @@ -3979,7 +3979,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.231826808090807e-15, "global_phase": 2.048181826171667e-15, - "seconds": 0.001988226, + "seconds": 0.000661891, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3994,19 +3994,19 @@ "note": "double precision, gate by gate", "strict": 3.080042516876848e-15, "global_phase": -1.964037958916231e-15, - "seconds": 0.5931423369329423 + "seconds": 0.7243918271269649 }, { "entry": "qpe_t10_third", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.119206924199239e-15, + "measured": 3.265114379449417e-15, "tolerance": 8.774588089962489e-05, "status": "pass", "note": "double precision, a contraction of width 22.0", - "strict": 3.815773100545302e-15, - "global_phase": -2.197879095599353e-15, - "seconds": 0.23734905500896275 + "strict": 3.736302713563119e-15, + "global_phase": -1.816311112252462e-15, + "seconds": 0.34309028182178736 }, { "entry": "qpe_t10_third", @@ -4018,7 +4018,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.653228779622703e-16, "global_phase": -3.000212530738417e-17, - "seconds": 0.011942410143092275 + "seconds": 0.014241441851481795 }, { "entry": "qpe_t10_third", @@ -4030,7 +4030,7 @@ "note": "single precision, fusion width 2", "strict": 3.283191717293934e-07, "global_phase": -2.492874103907835e-07, - "seconds": 0.0012861799914389849 + "seconds": 0.0014166280161589384 }, { "entry": "qpe_t10_third", @@ -4086,7 +4086,7 @@ "note": "double precision, fusion width 3", "strict": 2.1287684798629586e-15, "global_phase": 4.054496842783867e-17, - "seconds": 0.000814559 + "seconds": 0.007167659 }, { "entry": "clifford_t_n4_d20", @@ -4098,7 +4098,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3114612183423928e-15, "global_phase": 8.36946064770723e-16, - "seconds": 0.000220396 + "seconds": 0.000216389 }, { "entry": "clifford_t_n4_d20", @@ -4110,7 +4110,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3114612183423928e-15, "global_phase": 8.36946064770723e-16, - "seconds": 0.000170842, + "seconds": 0.000210778, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4125,19 +4125,19 @@ "note": "double precision, gate by gate", "strict": 1.390711969694405e-15, "global_phase": -2.1877291266863018e-16, - "seconds": 0.5434361959341913 + "seconds": 1.0319226789288223 }, { "entry": "clifford_t_n4_d20", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.5852604453922125e-15, + "measured": 1.5463132922437171e-15, "tolerance": 6.366438041334249e-12, "status": "pass", "note": "double precision, a contraction of width 6.0", - "strict": 1.6300751652267495e-15, - "global_phase": -3.7959763508733615e-16, - "seconds": 0.15803172416053712 + "strict": 1.577358000519889e-15, + "global_phase": -3.114056262088067e-16, + "seconds": 0.34522227197885513 }, { "entry": "clifford_t_n4_d20", @@ -4149,7 +4149,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.726554759573411e-16, "global_phase": -1.6183299128189006e-16, - "seconds": 0.005929852835834026 + "seconds": 0.005987649085000157 }, { "entry": "clifford_t_n4_d20", @@ -4161,7 +4161,7 @@ "note": "single precision, fusion width 2", "strict": 2.652872169893507e-07, "global_phase": 2.3009207451654658e-07, - "seconds": 0.0013331680092960596 + "seconds": 0.002077037002891302 }, { "entry": "clifford_t_n4_d20", @@ -4217,7 +4217,7 @@ "note": "double precision, fusion width 3", "strict": 5.622384485102909e-15, "global_phase": 3.829288436678506e-17, - "seconds": 0.004434256 + "seconds": 0.006558999 }, { "entry": "clifford_t_n8_d40", @@ -4229,7 +4229,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.882352168215574e-15, "global_phase": 2.215740359183579e-15, - "seconds": 0.000474747 + "seconds": 0.000553547 }, { "entry": "clifford_t_n8_d40", @@ -4241,7 +4241,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.882352168215574e-15, "global_phase": 2.215740359183579e-15, - "seconds": 0.000465509, + "seconds": 0.000578964, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4256,19 +4256,19 @@ "note": "double precision, gate by gate", "strict": 4.036090676030125e-15, "global_phase": 3.1340158216307306e-16, - "seconds": 0.5980893231462687 + "seconds": 1.965204177191481 }, { "entry": "clifford_t_n8_d40", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.740257725746665e-13, + "measured": 3.7405761658731626e-13, "tolerance": 3.14722561000377e-08, "status": "pass", "note": "double precision, a contraction of width 13.0", - "strict": 3.7402578033872476e-13, - "global_phase": 7.620968322013595e-17, - "seconds": 0.5186840759124607 + "strict": 3.740577804970068e-13, + "global_phase": 3.501761888590552e-16, + "seconds": 1.5400365570094436 }, { "entry": "clifford_t_n8_d40", @@ -4280,7 +4280,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.6764911083077484e-15, "global_phase": -3.4525471909877264e-16, - "seconds": 0.03184275608509779 + "seconds": 0.030396400950849056 }, { "entry": "clifford_t_n8_d40", @@ -4292,7 +4292,7 @@ "note": "single precision, fusion width 2", "strict": 8.085724621375064e-07, "global_phase": 7.298004917524249e-07, - "seconds": 0.005220161052420735 + "seconds": 0.007940921001136303 }, { "entry": "clifford_t_n8_d40", @@ -4348,7 +4348,7 @@ "note": "double precision, fusion width 3", "strict": 7.23755922358584e-15, "global_phase": 1.7960187025050173e-17, - "seconds": 0.011356525 + "seconds": 0.011712641 }, { "entry": "clifford_t_n12_d40", @@ -4360,7 +4360,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.465338738445407e-15, "global_phase": 2.891942735534964e-15, - "seconds": 0.003517244 + "seconds": 0.00475057 }, { "entry": "clifford_t_n12_d40", @@ -4372,7 +4372,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.465338738445407e-15, "global_phase": 2.891942735534964e-15, - "seconds": 0.006773266, + "seconds": 0.008402855, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4387,19 +4387,19 @@ "note": "double precision, gate by gate", "strict": 5.220686102560184e-15, "global_phase": -3.371275496591598e-16, - "seconds": 0.7157717009540647 + "seconds": 1.2555564320646226 }, { "entry": "clifford_t_n12_d40", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.1077070588377518e-12, + "measured": 3.1076966645830333e-12, "tolerance": 0.00018851685818136647, "status": "pass", "note": "double precision, a contraction of width 21.0", - "strict": 3.107707062595376e-12, - "global_phase": -1.5282405784289468e-16, - "seconds": 3.0983387872111052 + "strict": 3.1076966782447503e-12, + "global_phase": -2.913982588178931e-16, + "seconds": 8.592591682914644 }, { "entry": "clifford_t_n12_d40", @@ -4411,7 +4411,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.9354181978940125e-14, "global_phase": 1.994345757944291e-15, - "seconds": 0.39312908495776355 + "seconds": 0.8490567519329488 }, { "entry": "clifford_t_n12_d40", @@ -4423,7 +4423,7 @@ "note": "single precision, fusion width 2", "strict": 1.5783814202752789e-06, "global_phase": 1.519563935349324e-06, - "seconds": 0.007883613929152489 + "seconds": 0.0075857199262827635 }, { "entry": "clifford_t_n12_d40", @@ -4479,7 +4479,7 @@ "note": "double precision, fusion width 3", "strict": 1.5858100500850096e-15, "global_phase": -7.098047794018468e-16, - "seconds": 0.001660677 + "seconds": 0.049427066 }, { "entry": "dyadic_n6_k20", @@ -4491,7 +4491,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.322932786265629e-15, "global_phase": 7.127777235625039e-16, - "seconds": 0.000277695 + "seconds": 0.000308583 }, { "entry": "dyadic_n6_k20", @@ -4503,7 +4503,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.6337180633325466e-15, "global_phase": -6.476132559055545e-16, - "seconds": 0.000271062, + "seconds": 0.000315857, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4518,19 +4518,19 @@ "note": "double precision, gate by gate", "strict": 1.6025540997944576e-15, "global_phase": 5.678243661967013e-16, - "seconds": 0.6365398210473359 + "seconds": 2.1417154320515692 }, { "entry": "dyadic_n6_k20", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.2408248722573055e-14, + "measured": 1.2513682890603532e-14, "tolerance": 8.221463240828132e-11, "status": "pass", "note": "double precision, a contraction of width 8.0", - "strict": 1.246194130081694e-14, - "global_phase": 1.1555711244969611e-15, - "seconds": 0.23937811818905175 + "strict": 1.254599757658374e-14, + "global_phase": 8.998864956545942e-16, + "seconds": 0.3704212170559913 }, { "entry": "dyadic_n6_k20", @@ -4542,7 +4542,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.8755756033629022e-15, "global_phase": 3.4753803450446e-16, - "seconds": 0.013474664883688092 + "seconds": 0.013780530076473951 }, { "entry": "dyadic_n6_k20", @@ -4554,7 +4554,7 @@ "note": "single precision, fusion width 2", "strict": 9.574301253659594e-07, "global_phase": 3.252635195781324e-07, - "seconds": 0.0019101379439234734 + "seconds": 0.02111254003830254 }, { "entry": "dyadic_n6_k20", @@ -4610,7 +4610,7 @@ "note": "double precision, fusion width 3", "strict": 2.144929701446449e-15, "global_phase": -5.597427605381909e-16, - "seconds": 0.004751706 + "seconds": 0.011007278 }, { "entry": "dyadic_n10_k30", @@ -4622,7 +4622,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.323331428935808e-15, "global_phase": 7.27716649695331e-16, - "seconds": 0.001387351 + "seconds": 0.001645862 }, { "entry": "dyadic_n10_k30", @@ -4634,7 +4634,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.248944686135354e-15, "global_phase": -1.1791422134167121e-16, - "seconds": 0.001228671, + "seconds": 0.001670277, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4649,19 +4649,19 @@ "note": "double precision, gate by gate", "strict": 2.1819492426391685e-15, "global_phase": 6.145819600733233e-16, - "seconds": 0.6100535851437598 + "seconds": 0.8247093961108476 }, { "entry": "dyadic_n10_k30", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.6416616371921406e-14, + "measured": 3.6801144307066973e-14, "tolerance": 2.931147265744985e-07, "status": "pass", "note": "double precision, a contraction of width 15.0", - "strict": 3.6416626214183573e-14, - "global_phase": 2.677394008695518e-17, - "seconds": 0.8340093679726124 + "strict": 3.6802131037866775e-14, + "global_phase": 2.6949326290196986e-16, + "seconds": 1.5739126368425786 }, { "entry": "dyadic_n10_k30", @@ -4673,7 +4673,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.667266135266657e-15, "global_phase": 1.52357175780466e-15, - "seconds": 0.1314345169812441 + "seconds": 0.2839310180861503 }, { "entry": "dyadic_n10_k30", @@ -4685,7 +4685,7 @@ "note": "single precision, fusion width 2", "strict": 1.337290611147161e-06, "global_phase": 1.5824854839615882e-07, - "seconds": 0.0038522679824382067 + "seconds": 0.004032833036035299 }, { "entry": "dyadic_n10_k30", @@ -4714,7 +4714,7 @@ "note": "double precision, fusion width 3", "strict": 1.72086804212411e-15, "global_phase": -8.152710389464119e-16, - "seconds": 0.001604682 + "seconds": 0.041245019 }, { "entry": "rotations_n6", @@ -4726,7 +4726,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.730542936658874e-15, "global_phase": -9.88707548857764e-16, - "seconds": 0.000235415 + "seconds": 0.000316118 }, { "entry": "rotations_n6", @@ -4738,7 +4738,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.730542936658874e-15, "global_phase": -9.88707548857764e-16, - "seconds": 0.000230286, + "seconds": 0.000334984, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4753,19 +4753,19 @@ "note": "double precision, gate by gate", "strict": 1.6882917775498031e-15, "global_phase": -8.224972569253662e-16, - "seconds": 0.5667941318824887 + "seconds": 0.8276130550075322 }, { "entry": "rotations_n6", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.1860881763502593e-14, + "measured": 1.1774553037021259e-14, "tolerance": 8.221463240828132e-11, "status": "pass", "note": "double precision, a contraction of width 8.0", - "strict": 1.1983039757816626e-14, - "global_phase": -1.7066709201323853e-15, - "seconds": 0.22709469287656248 + "strict": 1.1873100441907809e-14, + "global_phase": -1.5265696453175127e-15, + "seconds": 0.5314007501583546 }, { "entry": "rotations_n6", @@ -4777,7 +4777,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.7183138212342367e-15, "global_phase": -8.1098885205021715e-16, - "seconds": 0.012781785801053047 + "seconds": 0.012334737926721573 }, { "entry": "rotations_n6", @@ -4789,7 +4789,7 @@ "note": "single precision, fusion width 2", "strict": 5.124601652408091e-07, "global_phase": -3.100974919087481e-08, - "seconds": 0.002288903808221221, + "seconds": 0.0033509249333292246, "adapter": [ "U as a matrix" ] @@ -4821,7 +4821,7 @@ "note": "double precision, fusion width 3", "strict": 2.9061712219412836e-15, "global_phase": -1.5401496063733773e-15, - "seconds": 0.005216064 + "seconds": 0.006571213 }, { "entry": "rotations_n10", @@ -4833,7 +4833,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.808390973035661e-15, "global_phase": -1.3153526089958304e-15, - "seconds": 0.001404203 + "seconds": 0.002095912 }, { "entry": "rotations_n10", @@ -4845,7 +4845,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.808390973035661e-15, "global_phase": -1.3153526089958304e-15, - "seconds": 0.001119635, + "seconds": 0.001760679, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4860,19 +4860,19 @@ "note": "double precision, gate by gate", "strict": 2.788521275555992e-15, "global_phase": -1.3351207658040794e-15, - "seconds": 0.7453696459997445 + "seconds": 1.530550095019862 }, { "entry": "rotations_n10", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.622449837606657e-14, + "measured": 3.5993579947513025e-14, "tolerance": 2.931147265744985e-07, "status": "pass", "note": "double precision, a contraction of width 15.0", - "strict": 3.6242936482230905e-14, - "global_phase": -1.1559248493627473e-15, - "seconds": 0.5295749199576676 + "strict": 3.601818422424288e-14, + "global_phase": -1.3310887924879225e-15, + "seconds": 2.2433785430621356 }, { "entry": "rotations_n10", @@ -4884,7 +4884,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.450057187920476e-15, "global_phase": -3.6224310278193606e-16, - "seconds": 0.42816399107687175 + "seconds": 0.492728355107829 }, { "entry": "rotations_n10", @@ -4896,7 +4896,7 @@ "note": "single precision, fusion width 2", "strict": 7.591580684621947e-07, "global_phase": -3.729936028107713e-08, - "seconds": 0.004000297049060464, + "seconds": 0.08001646096818149, "adapter": [ "U as a matrix" ] @@ -4928,7 +4928,7 @@ "note": "double precision, fusion width 3", "strict": 3.898968578999015e-15, "global_phase": -2.3527803658438282e-15, - "seconds": 0.009036923 + "seconds": 0.040579921 }, { "entry": "rotations_n12", @@ -4940,7 +4940,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.902351393327043e-15, "global_phase": -2.439223789273524e-15, - "seconds": 0.007893131 + "seconds": 0.008897239 }, { "entry": "rotations_n12", @@ -4952,7 +4952,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.902351393327043e-15, "global_phase": -2.439223789273524e-15, - "seconds": 0.00858082, + "seconds": 0.005471263, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4967,19 +4967,19 @@ "note": "double precision, gate by gate", "strict": 3.8278999440208364e-15, "global_phase": -2.3806449616021136e-15, - "seconds": 0.77993448311463 + "seconds": 0.7795569410081953 }, { "entry": "rotations_n12", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 2.670974497614059e-12, + "measured": 2.6705976099795316e-12, "tolerance": 1.3263461525542181e-06, "status": "pass", "note": "double precision, a contraction of width 16.0", - "strict": 2.6709753033837003e-12, - "global_phase": -2.0747002134010112e-15, - "seconds": 2.3266282798722386 + "strict": 2.670598811306482e-12, + "global_phase": -2.5330857086201887e-15, + "seconds": 2.543737977044657 }, { "entry": "rotations_n12", @@ -4991,7 +4991,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.0205168483494635e-14, "global_phase": -1.3857867779226801e-15, - "seconds": 3.4476725980639458 + "seconds": 2.171901292866096 }, { "entry": "rotations_n12", @@ -5003,7 +5003,7 @@ "note": "single precision, fusion width 2", "strict": 1.0176647613122722e-06, "global_phase": 2.1775337559876202e-07, - "seconds": 0.011063721030950546, + "seconds": 0.09308301215060055, "adapter": [ "U as a matrix" ] @@ -5083,7 +5083,7 @@ "status": "pass", "note": "the extension's published bound (quantum-sim.md section 5), summed over the op-log the engine ran", "strict": 1.5188537817569304e-06, - "seconds": 0.118241144 + "seconds": 0.112520737 }, { "entry": "mirror_n10", @@ -5110,7 +5110,7 @@ "status": "pass", "note": "double precision, fusion width 3", "strict": 1.984140267936255e-15, - "seconds": 0.015947116 + "seconds": 0.0144204 }, { "entry": "mirror_n10", @@ -5121,7 +5121,7 @@ "status": "pass", "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9420360610175412e-15, - "seconds": 0.004359007 + "seconds": 0.00297333 }, { "entry": "mirror_n10", @@ -5132,7 +5132,7 @@ "status": "pass", "note": "double precision, gate by gate", "strict": 1.9850192843430372e-15, - "seconds": 1.2322948011569679 + "seconds": 0.8844628329388797 }, { "entry": "mirror_n10", @@ -5143,7 +5143,7 @@ "status": "pass", "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, - "seconds": 0.37245202297344804 + "seconds": 0.3208372760564089 }, { "entry": "mirror_n10", @@ -5154,7 +5154,7 @@ "status": "pass", "note": "single precision, fusion width 2", "strict": 8.626889824960075e-07, - "seconds": 0.014901499031111598 + "seconds": 0.009853586787357926 }, { "entry": "mirror_n16", @@ -5165,7 +5165,7 @@ "status": "pass", "note": "the extension's published bound (quantum-sim.md section 5), summed over the op-log the engine ran", "strict": 1.5097785874851365e-05, - "seconds": 1.770442944 + "seconds": 1.394228254 }, { "entry": "mirror_n16", @@ -5184,7 +5184,7 @@ "status": "pass", "note": "double precision, fusion width 3", "strict": 2.238789057608218e-15, - "seconds": 0.465222564 + "seconds": 0.343061387 }, { "entry": "mirror_n16", @@ -5195,7 +5195,7 @@ "status": "pass", "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.848208265600261e-15, - "seconds": 0.271898905 + "seconds": 0.135122222 }, { "entry": "mirror_n16", @@ -5206,7 +5206,7 @@ "status": "pass", "note": "double precision, gate by gate", "strict": 2.200259822259795e-15, - "seconds": 2.2321852010209113 + "seconds": 2.053697933908552 }, { "entry": "mirror_n16", @@ -5217,7 +5217,7 @@ "status": "pass", "note": "decision-diagram edge weights merged within 2^-42", "strict": 5.367485032355598e-13, - "seconds": 78.0326703269966 + "seconds": 77.147202340886 }, { "entry": "mirror_n16", @@ -5228,7 +5228,7 @@ "status": "pass", "note": "single precision, fusion width 2", "strict": 9.717400499111354e-07, - "seconds": 0.024692772887647152 + "seconds": 0.01644881395623088 }, { "entry": "mirror_n20", @@ -5239,7 +5239,7 @@ "status": "pass", "note": "the extension's published bound (quantum-sim.md section 5), summed over the op-log the engine ran", "strict": 4.738962099310268e-05, - "seconds": 32.836955815 + "seconds": 40.32995814 }, { "entry": "mirror_n20", @@ -5258,7 +5258,7 @@ "status": "pass", "note": "double precision, fusion width 3", "strict": 1.783666617688025e-15, - "seconds": 0.405718888 + "seconds": 0.445616931 }, { "entry": "mirror_n20", @@ -5269,7 +5269,7 @@ "status": "pass", "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.7208726785094627e-15, - "seconds": 2.997210681 + "seconds": 3.767106777 }, { "entry": "mirror_n20", @@ -5280,7 +5280,7 @@ "status": "pass", "note": "double precision, gate by gate", "strict": 1.816462945258661e-15, - "seconds": 73.14944432792254 + "seconds": 78.6269969609566 }, { "entry": "mirror_n20", @@ -5300,7 +5300,7 @@ "status": "pass", "note": "single precision, fusion width 2", "strict": 8.583169738309598e-07, - "seconds": 0.1425629248842597 + "seconds": 0.40705790487118065 }, { "entry": "small_angle_k8", @@ -5347,7 +5347,7 @@ "note": "double precision, fusion width 3", "strict": 1.85959557341835e-16, "global_phase": -5.1513497497288096e-20, - "seconds": 0.000127581 + "seconds": 0.000191492 }, { "entry": "small_angle_k8", @@ -5372,7 +5372,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.718539386259611e-17, "global_phase": 6.207071732258519e-17, - "seconds": 0.000165824 + "seconds": 0.000156295 }, { "entry": "small_angle_k8", @@ -5397,7 +5397,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.718539386259611e-17, "global_phase": 6.207071732258519e-17, - "seconds": 0.000151005, + "seconds": 0.000155474, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -5425,7 +5425,7 @@ "note": "double precision, gate by gate", "strict": 2.630646413577557e-16, "global_phase": -1.3512029458769615e-18, - "seconds": 0.5239672048483044 + "seconds": 0.7633466699626297 }, { "entry": "small_angle_k8", @@ -5450,7 +5450,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.5162704195682586e-16, "global_phase": -1.6716237491675073e-19, - "seconds": 0.0009646830148994923 + "seconds": 0.0013536568731069565 }, { "entry": "small_angle_k8", @@ -5475,7 +5475,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.065562305172074e-17, "global_phase": 1.1904931336954907e-18, - "seconds": 0.006873050006106496 + "seconds": 0.011116119101643562 }, { "entry": "small_angle_k8", @@ -5500,7 +5500,7 @@ "note": "single precision, fusion width 2", "strict": 2.9370438261224258e-08, "global_phase": -8.206690548754471e-10, - "seconds": 0.0006404900923371315 + "seconds": 0.0005562999285757542 }, { "entry": "small_angle_k8", @@ -5569,7 +5569,7 @@ "note": "double precision, fusion width 3", "strict": 1.82547570059512e-16, "global_phase": 6.91366666472064e-21, - "seconds": 0.000141077 + "seconds": 0.000178828 }, { "entry": "small_angle_k16", @@ -5594,7 +5594,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0927932505288209e-16, "global_phase": 6.124134630745771e-17, - "seconds": 0.000156566 + "seconds": 0.000167326 }, { "entry": "small_angle_k16", @@ -5619,7 +5619,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0927932505288209e-16, "global_phase": 6.124134630745771e-17, - "seconds": 0.000135867, + "seconds": 0.000155264, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -5647,7 +5647,7 @@ "note": "double precision, gate by gate", "strict": 1.565389992262524e-16, "global_phase": 3.847678097819925e-22, - "seconds": 0.8196503189392388 + "seconds": 0.7786808670498431 }, { "entry": "small_angle_k16", @@ -5672,7 +5672,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.5619800335560763e-16, "global_phase": 6.686554175722784e-21, - "seconds": 0.0011509950272738934 + "seconds": 0.0011718440800905228 }, { "entry": "small_angle_k16", @@ -5697,7 +5697,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.584721728060106e-17, "global_phase": 3.757155249022045e-21, - "seconds": 0.008372372016310692 + "seconds": 0.007908520055934787 }, { "entry": "small_angle_k16", @@ -5722,7 +5722,7 @@ "note": "single precision, fusion width 2", "strict": 3.2498100863323152e-09, "global_phase": -8.463048083580325e-12, - "seconds": 0.000574205070734024 + "seconds": 0.0005937321111559868 }, { "entry": "small_angle_k16", @@ -5791,7 +5791,7 @@ "note": "double precision, fusion width 3", "strict": 2.1618425343289958e-16, "global_phase": -4.874625787480407e-24, - "seconds": 0.000139804 + "seconds": 0.000156285 }, { "entry": "small_angle_k24", @@ -5816,7 +5816,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.073974588850753e-17, "global_phase": 6.123234627532328e-17, - "seconds": 0.000147339 + "seconds": 0.000145404 }, { "entry": "small_angle_k24", @@ -5841,7 +5841,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.073974588850753e-17, "global_phase": 6.123234627532328e-17, - "seconds": 0.000116931, + "seconds": 0.000124506, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -5869,7 +5869,7 @@ "note": "double precision, gate by gate", "strict": 2.4197409606121436e-16, "global_phase": -2.4697673580566565e-23, - "seconds": 0.5589711859356612 + "seconds": 1.5295793309342116 }, { "entry": "small_angle_k24", @@ -5894,7 +5894,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.3310296492947388e-16, "global_phase": -5.503546281709894e-24, - "seconds": 0.0010174629278481007 + "seconds": 0.0011986440513283014 }, { "entry": "small_angle_k24", @@ -5919,7 +5919,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.5063878560100614e-14, "global_phase": 1.3154399712170649e-20, - "seconds": 0.005638725822791457 + "seconds": 0.0068358429707586765 }, { "entry": "small_angle_k24", @@ -5944,7 +5944,7 @@ "note": "single precision, fusion width 2", "strict": 6.871130644612338e-14, "global_phase": -3.3632504423353635e-14, - "seconds": 0.0005348911508917809 + "seconds": 0.000593861099332571 }, { "entry": "small_angle_k24", @@ -6013,7 +6013,7 @@ "note": "double precision, fusion width 3", "strict": 1.9524967158251372e-16, "global_phase": 6.71583667849561e-25, - "seconds": 0.000168889 + "seconds": 0.001200117 }, { "entry": "small_angle_k26", @@ -6038,7 +6038,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.578845626274399e-17, "global_phase": 6.123235275851835e-17, - "seconds": 0.000138381 + "seconds": 0.000164872 }, { "entry": "small_angle_k26", @@ -6063,7 +6063,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.578845626274399e-17, "global_phase": 6.123235275851835e-17, - "seconds": 0.000125968, + "seconds": 0.000329602, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6091,7 +6091,7 @@ "note": "double precision, gate by gate", "strict": 2.5239932650251915e-16, "global_phase": 2.3332666200026874e-24, - "seconds": 0.830411515198648 + "seconds": 1.9288277961313725 }, { "entry": "small_angle_k26", @@ -6116,7 +6116,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.4013320253395263e-16, "global_phase": -6.407979693356206e-25, - "seconds": 0.0012882850132882595 + "seconds": 0.0011730659753084183 }, { "entry": "small_angle_k26", @@ -6141,7 +6141,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.1914924100062395e-15, "global_phase": 2.014580430297663e-22, - "seconds": 0.005393852945417166 + "seconds": 0.0319674180354923 }, { "entry": "small_angle_k26", @@ -6166,7 +6166,7 @@ "note": "single precision, fusion width 2", "strict": 1.2288145633023052e-14, "global_phase": -8.408128157662514e-15, - "seconds": 0.0005562009755522013 + "seconds": 0.0011881538666784763 }, { "entry": "small_angle_k26", @@ -6235,7 +6235,7 @@ "note": "double precision, fusion width 3", "strict": 1.3940409624957706e-16, "global_phase": -3.6016109745977435e-25, - "seconds": 0.000171704 + "seconds": 0.000179399 }, { "entry": "small_angle_k28", @@ -6260,7 +6260,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.6411063727342416e-16, "global_phase": 6.123234392345849e-17, - "seconds": 0.000152899 + "seconds": 0.000155654 }, { "entry": "small_angle_k28", @@ -6285,7 +6285,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.6411063727342416e-16, "global_phase": 6.123234392345849e-17, - "seconds": 0.000143862, + "seconds": 0.000150875, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6313,7 +6313,7 @@ "note": "double precision, gate by gate", "strict": 1.1778473976565107e-16, "global_phase": 2.6539241761670182e-24, - "seconds": 0.7825873750261962 + "seconds": 0.8932855888269842 }, { "entry": "small_angle_k28", @@ -6338,7 +6338,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.0322780871983296e-16, "global_phase": 7.304624273862791e-25, - "seconds": 0.0009445548057556152 + "seconds": 0.0012798381503671408 }, { "entry": "small_angle_k28", @@ -6363,7 +6363,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.3696827562538982e-16, "global_phase": 2.6449066869591424e-24, - "seconds": 0.008472621906548738 + "seconds": 0.584981590975076 }, { "entry": "small_angle_k28", @@ -6388,7 +6388,7 @@ "note": "single precision, fusion width 2", "strict": 2.9790264018692395e-15, "global_phase": -2.10203207147538e-15, - "seconds": 0.0004781039897352457 + "seconds": 0.0005686639342457056 }, { "entry": "small_angle_k28", @@ -6457,7 +6457,7 @@ "note": "double precision, fusion width 3", "strict": 2.30763959096193e-16, "global_phase": 3.8352550973466707e-25, - "seconds": 0.000151947 + "seconds": 0.000163559 }, { "entry": "small_angle_k30", @@ -6482,7 +6482,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.743777155297435e-17, "global_phase": 6.123234070875654e-17, - "seconds": 0.000139384 + "seconds": 0.00015391 }, { "entry": "small_angle_k30", @@ -6507,7 +6507,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.743777155297435e-17, "global_phase": 6.123234070875654e-17, - "seconds": 0.000128472, + "seconds": 0.000144523, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6535,7 +6535,7 @@ "note": "double precision, gate by gate", "strict": 2.1365565322645643e-16, "global_phase": -8.86261455065536e-26, - "seconds": 0.5515901679173112 + "seconds": 1.0348957560490817 }, { "entry": "small_angle_k30", @@ -6560,7 +6560,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.0281877206483399e-16, "global_phase": -1.7738338483450532e-25, - "seconds": 0.0009473999962210655 + "seconds": 0.0012194840237498283 }, { "entry": "small_angle_k30", @@ -6585,7 +6585,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.560517226586893e-18, "global_phase": 5.359933175532669e-25, - "seconds": 0.00901298294775188 + "seconds": 0.008595275925472379 }, { "entry": "small_angle_k30", @@ -6610,7 +6610,7 @@ "note": "single precision, fusion width 2", "strict": 7.432791667721722e-16, "global_phase": -5.255080183697786e-16, - "seconds": 0.00042570498771965504 + "seconds": 0.0006382360588759184 }, { "entry": "small_angle_k30", @@ -6679,7 +6679,7 @@ "note": "double precision, fusion width 3", "strict": 2.2258028030058234e-16, "global_phase": 8.805429279700935e-26, - "seconds": 0.000115257 + "seconds": 0.000159982 }, { "entry": "small_angle_k32", @@ -6704,7 +6704,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659891128289178e-17, "global_phase": 6.123234007335431e-17, - "seconds": 0.00012715 + "seconds": 0.000147719 }, { "entry": "small_angle_k32", @@ -6729,7 +6729,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659891128289178e-17, "global_phase": 6.123234007335431e-17, - "seconds": 0.000135526, + "seconds": 0.000128593, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6757,7 +6757,7 @@ "note": "double precision, gate by gate", "strict": 2.2151021875367953e-16, "global_phase": -2.998362101329583e-26, - "seconds": 0.512606143951416 + "seconds": 1.6039311741478741 }, { "entry": "small_angle_k32", @@ -6782,7 +6782,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1048856556976266e-16, "global_phase": -5.217293084528376e-26, - "seconds": 0.0008442460093647242 + "seconds": 0.0021670639980584383 }, { "entry": "small_angle_k32", @@ -6807,7 +6807,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 5.350323266617113e-19, "global_phase": 1.3204155822915235e-25, - "seconds": 0.004587428877130151 + "seconds": 0.007776980986818671 }, { "entry": "small_angle_k32", @@ -6832,7 +6832,7 @@ "note": "single precision, fusion width 2", "strict": 1.8579668241137169e-16, "global_phase": -1.3137700460027175e-16, - "seconds": 0.0004178390372544527 + "seconds": 0.0005906261503696442 }, { "entry": "small_angle_k32", @@ -6874,7 +6874,7 @@ "note": "double precision, fusion width 3", "strict": 2.221784032698946e-16, "global_phase": 4.3831469282588235e-26, - "seconds": 0.000159261 + "seconds": 0.000166805 }, { "entry": "below_grid_k33", @@ -6899,7 +6899,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.65958122267691e-17, "global_phase": 6.123234000694218e-17, - "seconds": 0.000139483 + "seconds": 0.000143281 }, { "entry": "below_grid_k33", @@ -6924,7 +6924,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.65958122267691e-17, "global_phase": 6.123234000694218e-17, - "seconds": 0.00015379, + "seconds": 0.000146557, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6952,7 +6952,7 @@ "note": "double precision, gate by gate", "strict": 2.2191088715510154e-16, "global_phase": -1.518748762256435e-26, - "seconds": 0.4906055668834597 + "seconds": 1.0631785232108086 }, { "entry": "below_grid_k33", @@ -6977,7 +6977,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1088862505292507e-16, "global_phase": -2.628214253855832e-26, - "seconds": 0.0008642231114208698 + "seconds": 0.0011689080856740475 }, { "entry": "below_grid_k33", @@ -7002,7 +7002,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.3375808166545222e-19, "global_phase": 6.597185983559708e-26, - "seconds": 0.004626563983038068 + "seconds": 0.008928315015509725 }, { "entry": "below_grid_k33", @@ -7027,7 +7027,7 @@ "note": "single precision, fusion width 2", "strict": 9.28977634359184e-17, "global_phase": -6.568850230033155e-17, - "seconds": 0.0004285599570721388 + "seconds": 0.0006028290372341871 }, { "entry": "below_grid_k33", @@ -7069,7 +7069,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446130889769e-16, "global_phase": 3.419238090495615e-28, - "seconds": 0.000113004 + "seconds": 0.000170452 }, { "entry": "below_grid_k40", @@ -7094,7 +7094,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562386814e-17, "global_phase": 6.123233995799644e-17, - "seconds": 0.000136748 + "seconds": 0.000149472 }, { "entry": "below_grid_k40", @@ -7119,7 +7119,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562386814e-17, "global_phase": 6.123233995799644e-17, - "seconds": 0.000133312, + "seconds": 0.000154983, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -7147,7 +7147,7 @@ "note": "double precision, gate by gate", "strict": 2.2204459676108604e-16, "global_phase": -1.1916179177194308e-28, - "seconds": 0.4640534471254796 + "seconds": 1.1677657719701529 }, { "entry": "below_grid_k40", @@ -7172,7 +7172,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102229429857054e-16, "global_phase": -2.0583878330314597e-28, - "seconds": 0.0009777280502021313 + "seconds": 0.0012202451471239328 }, { "entry": "below_grid_k40", @@ -7197,7 +7197,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.16394544667156e-24, "global_phase": 5.152777687854373e-28, - "seconds": 0.006569165037944913 + "seconds": 0.008545032003894448 }, { "entry": "below_grid_k40", @@ -7222,7 +7222,7 @@ "note": "single precision, fusion width 2", "strict": 7.25762272319939e-19, "global_phase": -5.1319142422184975e-19, - "seconds": 0.0004382289480417967 + "seconds": 0.0005812780000269413 }, { "entry": "below_grid_k40", @@ -7292,7 +7292,7 @@ "note": "double precision, fusion width 3", "strict": 2.2204460492552957e-16, "global_phase": 2.6712795152298427e-30, - "seconds": 0.000119646 + "seconds": 0.000152478 }, { "entry": "below_grid_k47", @@ -7317,7 +7317,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562355044e-17, "global_phase": 6.12323399573716e-17, - "seconds": 0.000143341 + "seconds": 0.000149292 }, { "entry": "below_grid_k47", @@ -7342,7 +7342,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562355044e-17, "global_phase": 6.12323399573716e-17, - "seconds": 0.000140555, + "seconds": 0.000150024, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -7370,7 +7370,7 @@ "note": "double precision, gate by gate", "strict": 2.2204460492453302e-16, "global_phase": -9.309517411881617e-31, - "seconds": 0.5966388520319015 + "seconds": 1.1097540461923927 }, { "entry": "below_grid_k47", @@ -7395,7 +7395,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230246201737e-16, "global_phase": -1.6081157375256844e-30, - "seconds": 0.0010387529619038105 + "seconds": 0.0011843971442431211 }, { "entry": "below_grid_k47", @@ -7420,7 +7420,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.1568581975409175e-14, "global_phase": 2.2322358387255243e-14, - "seconds": 0.005599773023277521 + "seconds": 0.012427516048774123 }, { "entry": "below_grid_k47", @@ -7445,7 +7445,7 @@ "note": "single precision, fusion width 2", "strict": 5.67001775178211e-21, "global_phase": -4.009308001733202e-21, - "seconds": 0.0005594571121037006 + "seconds": 0.0005793650634586811 }, { "entry": "below_grid_k47", @@ -7515,7 +7515,7 @@ "note": "double precision, fusion width 3", "strict": 2.2204460492515585e-16, "global_phase": 1.3356397576093598e-30, - "seconds": 0.000118654 + "seconds": 0.000153901 }, { "entry": "below_grid_k48", @@ -7540,7 +7540,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354982e-17, "global_phase": 6.123233995736958e-17, - "seconds": 0.00013739 + "seconds": 0.000149482 }, { "entry": "below_grid_k48", @@ -7565,7 +7565,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354982e-17, "global_phase": 6.123233995736958e-17, - "seconds": 0.00010612, + "seconds": 0.00014806, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -7593,7 +7593,7 @@ "note": "double precision, gate by gate", "strict": 2.2204460492490674e-16, "global_phase": -4.654758705996424e-31, - "seconds": 0.4815827750135213 + "seconds": 1.038887957809493 }, { "entry": "below_grid_k48", @@ -7618,7 +7618,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230246239108e-16, "global_phase": -8.040578687684036e-31, - "seconds": 0.0008706650696694851 + "seconds": 0.0012053069658577442 }, { "entry": "below_grid_k48", @@ -7643,7 +7643,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.5784290987704587e-14, "global_phase": 1.1161179193627622e-14, - "seconds": 0.005710252095013857 + "seconds": 0.009912926005199552 }, { "entry": "below_grid_k48", @@ -7668,7 +7668,7 @@ "note": "single precision, fusion width 2", "strict": 2.8350088758910386e-21, "global_phase": -2.004654000866601e-21, - "seconds": 0.00041252002120018005 + "seconds": 0.0005960362032055855 }, { "entry": "below_grid_k48", @@ -7738,7 +7738,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446049250318e-16, "global_phase": 8.347748485046958e-32, - "seconds": 0.000115669 + "seconds": 0.000159522 }, { "entry": "below_grid_k52", @@ -7763,7 +7763,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354938e-17, "global_phase": 6.12323399573678e-17, - "seconds": 0.000134004 + "seconds": 0.000145946 }, { "entry": "below_grid_k52", @@ -7788,7 +7788,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354938e-17, "global_phase": 6.12323399573678e-17, - "seconds": 0.000110839, + "seconds": 0.000155884, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -7816,7 +7816,7 @@ "note": "double precision, gate by gate", "strict": 2.2204460492503082e-16, "global_phase": -2.9092241912593063e-32, - "seconds": 0.5119252169970423 + "seconds": 1.0584673639386892 }, { "entry": "below_grid_k52", @@ -7841,7 +7841,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230246251516e-16, "global_phase": -5.025361679814063e-32, - "seconds": 0.0009874270763248205 + "seconds": 0.0011556930840015411 }, { "entry": "below_grid_k52", @@ -7866,7 +7866,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 9.865181867315367e-16, "global_phase": 6.975736996017264e-16, - "seconds": 0.006357064004987478 + "seconds": 0.019237961154431105 }, { "entry": "below_grid_k52", @@ -7891,7 +7891,7 @@ "note": "single precision, fusion width 2", "strict": 1.7718805474318958e-22, "global_phase": -1.2529087505416256e-22, - "seconds": 0.0004090119618922472 + "seconds": 0.0006495171692222357 }, { "entry": "below_grid_k52", @@ -7961,7 +7961,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446049250313e-16, "global_phase": 3.2608392519714503e-34, - "seconds": 0.000128754 + "seconds": 0.000167958 }, { "entry": "below_grid_k60", @@ -7986,7 +7986,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354932e-17, "global_phase": 6.123233995736765e-17, - "seconds": 0.00014277 + "seconds": 0.000149071 }, { "entry": "below_grid_k60", @@ -8011,7 +8011,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354932e-17, "global_phase": 6.123233995736765e-17, - "seconds": 0.000138521, + "seconds": 0.000140977, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -8039,7 +8039,7 @@ "note": "double precision, gate by gate", "strict": 2.220446049250313e-16, "global_phase": -1.136415699710684e-34, - "seconds": 0.4894634070806205 + "seconds": 1.2461148570291698 }, { "entry": "below_grid_k60", @@ -8064,7 +8064,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230246251565e-16, "global_phase": -1.9630319061773865e-34, - "seconds": 0.0009723280090838671 + "seconds": 0.0012525059282779694 }, { "entry": "below_grid_k60", @@ -8089,7 +8089,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.853586666920065e-18, "global_phase": 2.7248972640692436e-18, - "seconds": 0.006605122936889529 + "seconds": 0.007413574028760195 }, { "entry": "below_grid_k60", @@ -8114,7 +8114,7 @@ "note": "single precision, fusion width 2", "strict": 6.921408388405842e-25, "global_phase": -4.894174806803225e-25, - "seconds": 0.00041604600846767426 + "seconds": 0.0006558289751410484 }, { "entry": "below_grid_k60", @@ -8156,7 +8156,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446050500313e-16, "global_phase": -8.636168555094445e-78, - "seconds": 0.000114065 + "seconds": 0.000164181 }, { "entry": "tiny_radians", @@ -8181,7 +8181,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562364557e-17, "global_phase": 6.123233995748117e-17, - "seconds": 0.000150204 + "seconds": 0.000175221 }, { "entry": "tiny_radians", @@ -8206,7 +8206,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562364557e-17, "global_phase": 6.123233995748117e-17, - "seconds": 0.00014265, + "seconds": 0.000154812, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -8234,7 +8234,7 @@ "note": "double precision, gate by gate", "strict": 2.220446048000313e-16, "global_phase": -8.636168555094445e-78, - "seconds": 0.5032982227858156 + "seconds": 0.8880720508750528 }, { "entry": "tiny_radians", @@ -8259,7 +8259,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230233751565e-16, "global_phase": -8.636168555094445e-78, - "seconds": 0.0009115030989050865 + "seconds": 0.0011204169131815434 }, { "entry": "tiny_radians", @@ -8284,7 +8284,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.0710678118654759e-13, "global_phase": -8.636168555094445e-78, - "seconds": 0.005645979894325137 + "seconds": 0.030869803857058287 }, { "entry": "tiny_radians", @@ -8309,7 +8309,7 @@ "note": "single precision, fusion width 2", "strict": 5.2212207224549863e-20, "global_phase": -8.636168555094445e-78, - "seconds": 0.0004946750123053789 + "seconds": 0.0007075460162013769 }, { "entry": "tiny_radians", @@ -8378,7 +8378,7 @@ "note": "double precision, fusion width 3", "strict": 2.264462534400411e-16, "global_phase": 1.9176275486733354e-25, - "seconds": 0.000186172 + "seconds": 0.000154752 }, { "entry": "controlled_small_angle_k30", @@ -8403,7 +8403,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.5107736123526882e-16, "global_phase": 1.6248208038498013e-25, - "seconds": 0.000170101 + "seconds": 0.000154041 }, { "entry": "controlled_small_angle_k30", @@ -8428,7 +8428,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.5107736123526882e-16, "global_phase": 1.6248208038498013e-25, - "seconds": 0.000156606, + "seconds": 0.000162447, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -8456,7 +8456,7 @@ "note": "double precision, gate by gate", "strict": 2.1789050545163395e-16, "global_phase": -4.43130727532768e-26, - "seconds": 0.6040103428531438 + "seconds": 1.2360023439396173 }, { "entry": "controlled_small_angle_k30", @@ -8481,7 +8481,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.2442154962177805e-16, "global_phase": 9.621203981595483e-27, - "seconds": 0.0011019830126315355 + "seconds": 0.0014827910345047712 }, { "entry": "controlled_small_angle_k30", @@ -8506,7 +8506,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.264462534400411e-16, "global_phase": 1.9176275486733354e-25, - "seconds": 0.0054118570405989885 + "seconds": 0.06754703796468675 }, { "entry": "controlled_small_angle_k30", @@ -8531,7 +8531,7 @@ "note": "single precision, fusion width 2", "strict": 3.035841329600863e-16, "global_phase": -1.5173170672237367e-16, - "seconds": 0.0005057158414274454 + "seconds": 0.0005638850852847099 }, { "entry": "controlled_small_angle_k30", @@ -8619,7 +8619,7 @@ "note": "double precision, fusion width 3", "strict": 1.1478380657970898e-11, "global_phase": 1.2540980081523036e-14, - "seconds": 0.037610739 + "seconds": 0.076399391 }, { "entry": "repeated_phase_k19", @@ -8631,7 +8631,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1478380657970898e-11, "global_phase": 1.2540980081523036e-14, - "seconds": 0.21767977 + "seconds": 0.285771809 }, { "entry": "repeated_phase_k19", @@ -8643,7 +8643,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.1472378602661593e-11, "global_phase": 1.8012456755360483e-73, - "seconds": 0.9876863299869001 + "seconds": 1.3364316138904542 }, { "entry": "repeated_phase_k19", @@ -8655,7 +8655,7 @@ "note": "single precision, fusion width 2", "strict": 3.567080057109706e-06, "global_phase": -3.567080057094577e-06, - "seconds": 2.4592813597992063 + "seconds": 3.696880143834278 }, { "entry": "repeated_phase_k19", @@ -8711,7 +8711,7 @@ "note": "double precision, fusion width 3", "strict": 5.74251759013435e-12, "global_phase": -4.491256677518576e-16, - "seconds": 0.017287721 + "seconds": 0.022429463 }, { "entry": "repeated_phase_k19_quarter", @@ -8723,7 +8723,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.74251759013435e-12, "global_phase": -4.491256677518576e-16, - "seconds": 0.081371409 + "seconds": 0.095569817 }, { "entry": "repeated_phase_k19_quarter", @@ -8735,7 +8735,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 5.740297126521909e-12, "global_phase": -2.703379842801214e-73, - "seconds": 0.37705205800011754 + "seconds": 0.661482198163867 }, { "entry": "repeated_phase_k19_quarter", @@ -8747,7 +8747,7 @@ "note": "single precision, fusion width 2", "strict": 1.6820540622575209e-06, "global_phase": -1.6820540622559346e-06, - "seconds": 1.2846732579637319 + "seconds": 2.0897612748667598 }, { "entry": "repeated_phase_k19_quarter", @@ -8803,7 +8803,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446049250313e-16, "global_phase": 0.0, - "seconds": 0.001064632 + "seconds": 0.001786638 }, { "entry": "h_squared_chain", @@ -8815,7 +8815,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.7734780031702986e-13, "global_phase": 1.2540383223268955e-13, - "seconds": 0.001977818 + "seconds": 0.003060887 }, { "entry": "h_squared_chain", @@ -8827,7 +8827,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.268858116783184e-74, "global_phase": 0.0, - "seconds": 0.03533276286907494 + "seconds": 0.02561213099397719 }, { "entry": "h_squared_chain", @@ -8839,7 +8839,7 @@ "note": "single precision, fusion width 2", "strict": 4.268858116783184e-74, "global_phase": 0.0, - "seconds": 0.031277890084311366 + "seconds": 0.051019754027947783 }, { "entry": "h_squared_chain", @@ -8851,7 +8851,7 @@ "note": "double precision, gate by gate", "strict": 3.2152058793144533e-13, "global_phase": 0.0, - "seconds": 1.3477782858535647 + "seconds": 1.9802141329273582 }, { "entry": "h_squared_chain", @@ -8868,7 +8868,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 5.778903141617775e-05 + "seconds": 6.934092380106449e-05 }, { "entry": "h_squared_chain", @@ -8877,7 +8877,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 1.059e-05 + "seconds": 2.8373e-05 }, { "entry": "h_squared_chain", @@ -8894,7 +8894,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00155033 + "seconds": 0.001804672 }, { "entry": "h_squared_chain", @@ -8950,7 +8950,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000155774 + "seconds": 0.000191532 }, { "entry": "gate_id", @@ -8962,7 +8962,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000115378 + "seconds": 0.000159932 }, { "entry": "gate_id", @@ -8974,7 +8974,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000131699, + "seconds": 0.000159071, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -8989,7 +8989,7 @@ "note": "double precision, gate by gate", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.6160517998505384 + "seconds": 0.8638838229235262 }, { "entry": "gate_id", @@ -9001,7 +9001,7 @@ "note": "double precision, a contraction of width 1.0", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.0006877589039504528 + "seconds": 0.0008340768981724977 }, { "entry": "gate_id", @@ -9013,7 +9013,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.005686716875061393 + "seconds": 0.012509840074926615 }, { "entry": "gate_id", @@ -9025,7 +9025,7 @@ "note": "single precision, fusion width 2", "strict": 4.024089473196959e-08, "global_phase": -6.396748512344255e-09, - "seconds": 0.0004612321499735117 + "seconds": 0.0005610408261418343 }, { "entry": "gate_id", @@ -9081,7 +9081,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000138322 + "seconds": 0.00017415 }, { "entry": "gate_x", @@ -9093,7 +9093,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000124385 + "seconds": 0.000153611 }, { "entry": "gate_x", @@ -9105,7 +9105,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000130216, + "seconds": 0.000151547, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9120,7 +9120,7 @@ "note": "double precision, gate by gate", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.49857682012952864 + "seconds": 1.2120440187864006 }, { "entry": "gate_x", @@ -9132,7 +9132,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.612115705267018e-16, "global_phase": 2.3791499247742048e-17, - "seconds": 0.0009764160495251417 + "seconds": 0.00116033386439085 }, { "entry": "gate_x", @@ -9144,7 +9144,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.005067806923761964 + "seconds": 0.011998333968222141 }, { "entry": "gate_x", @@ -9156,7 +9156,7 @@ "note": "single precision, fusion width 2", "strict": 4.024089473196959e-08, "global_phase": -6.396748512344255e-09, - "seconds": 0.00045124301686882973 + "seconds": 0.0005161359440535307 }, { "entry": "gate_x", @@ -9212,7 +9212,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000125918 + "seconds": 0.000166585 }, { "entry": "gate_y", @@ -9224,7 +9224,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000161576 + "seconds": 0.00015869 }, { "entry": "gate_y", @@ -9236,7 +9236,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000143942, + "seconds": 0.00015895, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9251,7 +9251,7 @@ "note": "double precision, gate by gate", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.5646501379087567 + "seconds": 0.7125941070262343 }, { "entry": "gate_y", @@ -9263,7 +9263,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.612115705267018e-16, "global_phase": 2.3791499247742048e-17, - "seconds": 0.0009366800077259541 + "seconds": 0.0010586921125650406 }, { "entry": "gate_y", @@ -9275,7 +9275,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.004713087109848857 + "seconds": 0.006773335160687566 }, { "entry": "gate_y", @@ -9287,7 +9287,7 @@ "note": "single precision, fusion width 2", "strict": 4.024089473196959e-08, "global_phase": -6.396748512344255e-09, - "seconds": 0.0004722718149423599 + "seconds": 0.0005435580387711525 }, { "entry": "gate_y", @@ -9343,7 +9343,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 9.7956e-05 + "seconds": 0.000145876 }, { "entry": "gate_z", @@ -9355,7 +9355,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000136448 + "seconds": 0.000166936 }, { "entry": "gate_z", @@ -9367,7 +9367,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000154232, + "seconds": 0.000168238, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9382,7 +9382,7 @@ "note": "double precision, gate by gate", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.49886358296498656 + "seconds": 0.8109020399861038 }, { "entry": "gate_z", @@ -9394,7 +9394,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.612115705267018e-16, "global_phase": 2.3791499247742048e-17, - "seconds": 0.0009604350198060274 + "seconds": 0.0011017019860446453 }, { "entry": "gate_z", @@ -9406,7 +9406,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006320253945887089 + "seconds": 0.006779456045478582 }, { "entry": "gate_z", @@ -9418,7 +9418,7 @@ "note": "single precision, fusion width 2", "strict": 4.024089473196959e-08, "global_phase": -6.396748512344255e-09, - "seconds": 0.0004337499849498272 + "seconds": 0.0007418019231408834 }, { "entry": "gate_z", @@ -9474,7 +9474,7 @@ "note": "double precision, fusion width 3", "strict": 1.2276852703978877e-16, "global_phase": -1.6687439983489124e-17, - "seconds": 0.000154802 + "seconds": 0.000180912 }, { "entry": "gate_h", @@ -9486,7 +9486,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.3023652669763116e-17, "global_phase": -6.214105046513707e-20, - "seconds": 0.000136448 + "seconds": 0.000153511 }, { "entry": "gate_h", @@ -9498,7 +9498,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.3023652669763116e-17, "global_phase": -6.214105046513707e-20, - "seconds": 0.000140035, + "seconds": 0.000160885, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9513,7 +9513,7 @@ "note": "double precision, gate by gate", "strict": 1.0613476464155822e-16, "global_phase": -1.3839838747142408e-17, - "seconds": 0.5050084560643882 + "seconds": 0.7016189580317587 }, { "entry": "gate_h", @@ -9525,7 +9525,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.0446975334341954e-16, "global_phase": -1.7627270019922646e-17, - "seconds": 0.0009062821045517921 + "seconds": 0.0011314991861581802 }, { "entry": "gate_h", @@ -9537,7 +9537,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.0263238454550441e-16, "global_phase": 2.0454135602798455e-17, - "seconds": 0.012196579948067665 + "seconds": 0.007663968950510025 }, { "entry": "gate_h", @@ -9549,7 +9549,7 @@ "note": "single precision, fusion width 2", "strict": 5.98957996981961e-08, "global_phase": -5.1987446891852715e-09, - "seconds": 0.00040527619421482086 + "seconds": 0.0006675219628959894 }, { "entry": "gate_h", @@ -9605,7 +9605,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000145876 + "seconds": 0.000145665 }, { "entry": "gate_s", @@ -9617,7 +9617,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000147549 + "seconds": 0.000168849 }, { "entry": "gate_s", @@ -9629,7 +9629,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000139754, + "seconds": 0.000174509, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9644,7 +9644,7 @@ "note": "double precision, gate by gate", "strict": 7.941848649409825e-17, "global_phase": -2.2006940457149062e-17, - "seconds": 0.5377752089407295 + "seconds": 0.7643932551145554 }, { "entry": "gate_s", @@ -9656,7 +9656,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.615108259473306e-16, "global_phase": 2.51305584158725e-17, - "seconds": 0.0009637919720262289 + "seconds": 0.0011042070109397173 }, { "entry": "gate_s", @@ -9668,7 +9668,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.0054317861795425415 + "seconds": 0.007649200968444347 }, { "entry": "gate_s", @@ -9680,7 +9680,7 @@ "note": "single precision, fusion width 2", "strict": 4.024089473196959e-08, "global_phase": -6.396748512344255e-09, - "seconds": 0.00042303907684981823 + "seconds": 0.0007111949380487204 }, { "entry": "gate_s", @@ -9736,7 +9736,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.00011642 + "seconds": 0.000159571 }, { "entry": "gate_sdg", @@ -9748,7 +9748,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000126278 + "seconds": 0.000162778 }, { "entry": "gate_sdg", @@ -9760,7 +9760,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000134835, + "seconds": 0.000141668, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9775,7 +9775,7 @@ "note": "double precision, gate by gate", "strict": 7.827453581328017e-17, "global_phase": -2.6024117961540415e-17, - "seconds": 0.462912391172722 + "seconds": 0.7314945589751005 }, { "entry": "gate_sdg", @@ -9787,7 +9787,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.6116569270757267e-16, "global_phase": 2.1113380911481146e-17, - "seconds": 0.001037621172145009 + "seconds": 0.0009334951173514128 }, { "entry": "gate_sdg", @@ -9799,7 +9799,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.004844555165618658 + "seconds": 0.02304405509494245 }, { "entry": "gate_sdg", @@ -9811,7 +9811,7 @@ "note": "single precision, fusion width 2", "strict": 3.970085749751892e-08, "global_phase": -4.599493655358549e-09, - "seconds": 0.0004047041293233633 + "seconds": 0.0006083000916987658 }, { "entry": "gate_sdg", @@ -9867,7 +9867,7 @@ "note": "double precision, fusion width 3", "strict": 7.853716323280881e-17, "global_phase": -2.312587473280089e-17, - "seconds": 0.000114436 + "seconds": 0.000175872 }, { "entry": "gate_t", @@ -9879,7 +9879,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.992952424721852e-17, "global_phase": -2.2074877633532985e-17, - "seconds": 0.000155354 + "seconds": 0.000149753 }, { "entry": "gate_t", @@ -9891,7 +9891,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.992952424721852e-17, "global_phase": -2.2074877633532985e-17, - "seconds": 0.000126188, + "seconds": 0.000150755, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9906,7 +9906,7 @@ "note": "double precision, gate by gate", "strict": 8.897950494461851e-17, "global_phase": -1.7725634002671274e-17, - "seconds": 0.46133273490704596 + "seconds": 0.7612508931197226 }, { "entry": "gate_t", @@ -9918,7 +9918,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.583379157683397e-16, "global_phase": 2.4806146796528305e-17, - "seconds": 0.0010850110556930304 + "seconds": 0.0010064418893307447 }, { "entry": "gate_t", @@ -9930,7 +9930,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.726175410066437e-17, "global_phase": -2.7402490746767553e-17, - "seconds": 0.014500122051686049 + "seconds": 0.006908070063218474 }, { "entry": "gate_t", @@ -9942,7 +9942,7 @@ "note": "single precision, fusion width 2", "strict": 3.9294051504657585e-08, "global_phase": -5.440896726885419e-09, - "seconds": 0.0004045639652758837 + "seconds": 0.0006007049232721329 }, { "entry": "gate_t", @@ -9998,7 +9998,7 @@ "note": "double precision, fusion width 3", "strict": 7.853716323280881e-17, "global_phase": -2.312587473280089e-17, - "seconds": 0.00011093 + "seconds": 0.000165372 }, { "entry": "gate_tdg", @@ -10010,7 +10010,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.992952424721852e-17, "global_phase": -2.2074877633532985e-17, - "seconds": 0.000188146 + "seconds": 0.000163409 }, { "entry": "gate_tdg", @@ -10022,7 +10022,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.992952424721852e-17, "global_phase": -2.2074877633532985e-17, - "seconds": 0.000147038, + "seconds": 0.000163599, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10037,7 +10037,7 @@ "note": "double precision, gate by gate", "strict": 8.431147619128386e-17, "global_phase": -2.74751183636626e-17, - "seconds": 0.576440610922873 + "seconds": 0.8400632108096033 }, { "entry": "gate_tdg", @@ -10049,7 +10049,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.621579032190157e-16, "global_phase": 1.8282281350235733e-17, - "seconds": 0.0010396349243819714 + "seconds": 0.0014820219948887825 }, { "entry": "gate_tdg", @@ -10061,7 +10061,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.726175410066437e-17, "global_phase": -2.7402490746767553e-17, - "seconds": 0.005514802178367972 + "seconds": 0.008479922078549862 }, { "entry": "gate_tdg", @@ -10073,7 +10073,7 @@ "note": "single precision, fusion width 2", "strict": 3.9294051504657585e-08, "global_phase": -5.440896726885419e-09, - "seconds": 0.0006007449701428413 + "seconds": 0.0009287961293011904 }, { "entry": "gate_tdg", @@ -10129,7 +10129,7 @@ "note": "double precision, fusion width 3", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 0.000113575 + "seconds": 0.000175943 }, { "entry": "gate_sx", @@ -10141,7 +10141,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 0.000148541 + "seconds": 0.000148191 }, { "entry": "gate_sx", @@ -10153,7 +10153,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 0.000143592, + "seconds": 0.000171204, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10168,7 +10168,7 @@ "note": "double precision, gate by gate", "strict": 9.961413598330114e-17, "global_phase": 2.0591289991867726e-17, - "seconds": 0.6280007511377335 + "seconds": 1.0763617081101984 }, { "entry": "gate_sx", @@ -10180,7 +10180,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.3610312764631958e-16, "global_phase": 6.038780769123827e-17, - "seconds": 0.0009208801202476025 + "seconds": 0.0011713949497789145 }, { "entry": "gate_sx", @@ -10192,7 +10192,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.110604477631002e-17, "global_phase": 2.0920862582516193e-17, - "seconds": 0.007007122039794922 + "seconds": 0.01593183004297316 }, { "entry": "gate_sx", @@ -10204,7 +10204,7 @@ "note": "single precision, fusion width 2", "strict": 6.78300679413258e-08, "global_phase": 1.3427146129244078e-08, - "seconds": 0.0005101249553263187 + "seconds": 0.0006257831119000912 }, { "entry": "gate_sx", @@ -10260,7 +10260,7 @@ "note": "double precision, fusion width 3", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 0.000121499 + "seconds": 0.000159121 }, { "entry": "gate_sxdg", @@ -10272,7 +10272,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 0.00014333 + "seconds": 0.000165192 }, { "entry": "gate_sxdg", @@ -10284,7 +10284,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 0.00011608, + "seconds": 0.000161615, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10299,7 +10299,7 @@ "note": "double precision, gate by gate", "strict": 1.9663515787631043e-16, "global_phase": -1.395101005575933e-16, - "seconds": 0.7648752420209348 + "seconds": 0.8969830889254808 }, { "entry": "gate_sxdg", @@ -10311,7 +10311,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.6741400176489413e-16, "global_phase": -1.3098476345895072e-17, - "seconds": 0.0009887078776955605 + "seconds": 0.001161054940894246 }, { "entry": "gate_sxdg", @@ -10323,7 +10323,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.110604477631002e-17, "global_phase": 2.0920862582516193e-17, - "seconds": 0.006407558917999268 + "seconds": 0.031893155071884394 }, { "entry": "gate_sxdg", @@ -10335,7 +10335,7 @@ "note": "single precision, fusion width 2", "strict": 6.78300679413258e-08, "global_phase": 1.3427146129244078e-08, - "seconds": 0.000538448104634881 + "seconds": 0.0004891050048172474 }, { "entry": "gate_sxdg", @@ -10391,7 +10391,7 @@ "note": "double precision, fusion width 3", "strict": 7.704220013563471e-17, "global_phase": -2.4223802756456756e-17, - "seconds": 0.000133813 + "seconds": 0.000161997 }, { "entry": "gate_p", @@ -10403,7 +10403,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.704220013563471e-17, "global_phase": -2.4223802756456756e-17, - "seconds": 0.000118964 + "seconds": 0.000158289 }, { "entry": "gate_p", @@ -10415,7 +10415,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.704220013563471e-17, "global_phase": -2.4223802756456756e-17, - "seconds": 0.000130858, + "seconds": 0.00012195, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10430,7 +10430,7 @@ "note": "double precision, gate by gate", "strict": 7.704220013563471e-17, "global_phase": -2.4223802756456756e-17, - "seconds": 0.8084728547837585 + "seconds": 0.6901257699355483 }, { "entry": "gate_p", @@ -10442,7 +10442,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.603191180512201e-16, "global_phase": 2.4727213882336242e-17, - "seconds": 0.0009593728464096785 + "seconds": 0.0011018929071724415 }, { "entry": "gate_p", @@ -10454,7 +10454,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.7124430933596e-17, "global_phase": -2.551922345944299e-17, - "seconds": 0.007254129042848945 + "seconds": 0.007051871856674552 }, { "entry": "gate_p", @@ -10466,7 +10466,7 @@ "note": "single precision, fusion width 2", "strict": 4.100365323443884e-08, "global_phase": -5.595173160877515e-09, - "seconds": 0.0005202628672122955 + "seconds": 0.0004946249537169933 }, { "entry": "gate_p", @@ -10522,7 +10522,7 @@ "note": "double precision, fusion width 3", "strict": 8.906935906670267e-17, "global_phase": -2.0163293299049675e-17, - "seconds": 0.000134204 + "seconds": 0.000151917 }, { "entry": "gate_rz", @@ -10534,7 +10534,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.906935906670267e-17, "global_phase": -2.0163293299049675e-17, - "seconds": 0.000146356 + "seconds": 0.000162096 }, { "entry": "gate_rz", @@ -10546,7 +10546,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.906935906670267e-17, "global_phase": -2.0163293299049675e-17, - "seconds": 0.000129675, + "seconds": 0.000146116, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10561,7 +10561,7 @@ "note": "double precision, gate by gate", "strict": 8.906935906670267e-17, "global_phase": -2.0163293299049675e-17, - "seconds": 0.7295955589506775 + "seconds": 0.6528139610309154 }, { "entry": "gate_rz", @@ -10573,7 +10573,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.423352576881746e-17, "global_phase": 3.694430415771201e-18, - "seconds": 0.0009588520042598248 + "seconds": 0.0011983958538621664 }, { "entry": "gate_rz", @@ -10585,7 +10585,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.4301320525273574e-17, "global_phase": 2.3736116645869262e-18, - "seconds": 0.007193434983491898 + "seconds": 0.0074052889831364155 }, { "entry": "gate_rz", @@ -10597,7 +10597,7 @@ "note": "single precision, fusion width 2", "strict": 4.94410319513861e-08, "global_phase": -6.618135859134059e-09, - "seconds": 0.0004998650401830673 + "seconds": 0.0006390481721609831 }, { "entry": "gate_rz", @@ -10653,7 +10653,7 @@ "note": "double precision, fusion width 3", "strict": 8.351343419056392e-17, "global_phase": -3.476965240722211e-17, - "seconds": 0.000154583 + "seconds": 0.0001591 }, { "entry": "gate_rx", @@ -10665,7 +10665,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.351343419056392e-17, "global_phase": -3.476965240722211e-17, - "seconds": 0.000162878 + "seconds": 0.000157979 }, { "entry": "gate_rx", @@ -10677,7 +10677,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.351343419056392e-17, "global_phase": -3.476965240722211e-17, - "seconds": 0.000144162, + "seconds": 0.000102994, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10692,7 +10692,7 @@ "note": "double precision, gate by gate", "strict": 8.351343419056392e-17, "global_phase": -3.476965240722211e-17, - "seconds": 0.6461693581659347 + "seconds": 0.7792739158030599 }, { "entry": "gate_rx", @@ -10704,7 +10704,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.9392622051601065e-17, "global_phase": 9.65362097176489e-18, - "seconds": 0.0010594420600682497 + "seconds": 0.0011065921280533075 }, { "entry": "gate_rx", @@ -10716,7 +10716,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.9052959352986414e-16, "global_phase": -9.775449483214286e-19, - "seconds": 0.006378344027325511 + "seconds": 0.006917888065800071 }, { "entry": "gate_rx", @@ -10728,7 +10728,7 @@ "note": "single precision, fusion width 2", "strict": 7.14538418283606e-08, "global_phase": -3.942499283618367e-09, - "seconds": 0.0005515820812433958 + "seconds": 0.0006230780854821205 }, { "entry": "gate_rx", @@ -10784,7 +10784,7 @@ "note": "double precision, fusion width 3", "strict": 6.842613937384835e-17, "global_phase": -3.969624109223988e-17, - "seconds": 0.000165814 + "seconds": 0.000144773 }, { "entry": "gate_ry", @@ -10796,7 +10796,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 6.842613937384835e-17, "global_phase": -3.969624109223988e-17, - "seconds": 0.000127501 + "seconds": 0.000155715 }, { "entry": "gate_ry", @@ -10808,7 +10808,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 6.842613937384835e-17, "global_phase": -3.969624109223988e-17, - "seconds": 0.000145255, + "seconds": 0.000153991, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10823,7 +10823,7 @@ "note": "double precision, gate by gate", "strict": 6.842613937384835e-17, "global_phase": -3.969624109223988e-17, - "seconds": 0.7901482740417123 + "seconds": 0.950372913852334 }, { "entry": "gate_ry", @@ -10835,7 +10835,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.6948196926025085e-16, "global_phase": -3.031878606224255e-17, - "seconds": 0.001095019979402423 + "seconds": 0.0012946969363838434 }, { "entry": "gate_ry", @@ -10847,7 +10847,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.076873167985705e-16, "global_phase": -9.487130142598933e-19, - "seconds": 0.01606759591959417 + "seconds": 0.013509560143575072 }, { "entry": "gate_ry", @@ -10859,7 +10859,7 @@ "note": "single precision, fusion width 2", "strict": 6.646933669056669e-08, "global_phase": -7.563115743658391e-09, - "seconds": 0.0005971279460936785 + "seconds": 0.0008372431620955467 }, { "entry": "gate_ry", @@ -10915,7 +10915,7 @@ "note": "double precision, fusion width 3", "strict": 8.691864484222037e-17, "global_phase": -2.533016296550929e-17, - "seconds": 0.000146808 + "seconds": 0.0001638 }, { "entry": "gate_u", @@ -10927,7 +10927,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.691864484222037e-17, "global_phase": -2.533016296550929e-17, - "seconds": 0.000156535 + "seconds": 0.000164852 }, { "entry": "gate_u", @@ -10939,7 +10939,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.691864484222037e-17, "global_phase": -2.533016296550929e-17, - "seconds": 0.000154873, + "seconds": 0.000161806, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10954,7 +10954,7 @@ "note": "double precision, gate by gate", "strict": 8.691864484222037e-17, "global_phase": -2.533016296550929e-17, - "seconds": 0.8953445188235492 + "seconds": 0.6328724110499024 }, { "entry": "gate_u", @@ -10966,7 +10966,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 4.01615510436094e-17, "global_phase": -1.2559845816239341e-17, - "seconds": 0.001277415081858635 + "seconds": 0.0011528600007295609 }, { "entry": "gate_u", @@ -10978,7 +10978,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 9.242975907293169e-17, "global_phase": -3.9457728612879396e-17, - "seconds": 0.007864413084462285 + "seconds": 0.02001568116247654 }, { "entry": "gate_u", @@ -10990,7 +10990,7 @@ "note": "single precision, fusion width 2", "strict": 5.756340185722096e-08, "global_phase": 3.221397862402741e-09, - "seconds": 0.0005922189448028803, + "seconds": 0.0005976299289613962, "adapter": [ "U as a matrix" ] @@ -11049,7 +11049,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.000153711 + "seconds": 0.000150284 }, { "entry": "gate_cx", @@ -11061,7 +11061,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000155704 + "seconds": 0.00016403 }, { "entry": "gate_cx", @@ -11073,7 +11073,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000155404, + "seconds": 0.000162027, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11088,7 +11088,7 @@ "note": "double precision, gate by gate", "strict": 8.857402632175859e-17, "global_phase": -9.647844174701355e-18, - "seconds": 0.8930106980260462 + "seconds": 0.6010669718962163 }, { "entry": "gate_cx", @@ -11100,7 +11100,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 3.760226996469289e-16, "global_phase": 6.2882856822035484e-18, - "seconds": 0.0019370811060070992 + "seconds": 0.0018972069956362247 }, { "entry": "gate_cx", @@ -11112,7 +11112,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.424447715313029e-17, "global_phase": -1.260889585891152e-17, - "seconds": 0.007696615997701883 + "seconds": 0.008332181954756379 }, { "entry": "gate_cx", @@ -11124,7 +11124,7 @@ "note": "single precision, fusion width 2", "strict": 4.3725610219115716e-08, "global_phase": -1.8036046965337988e-09, - "seconds": 0.0006059650331735611 + "seconds": 0.0005156651604920626 }, { "entry": "gate_cx", @@ -11180,7 +11180,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.000187404 + "seconds": 0.000160103 }, { "entry": "gate_cy", @@ -11192,7 +11192,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000159371 + "seconds": 0.000161806 }, { "entry": "gate_cy", @@ -11204,7 +11204,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000164181, + "seconds": 0.000175622, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11219,7 +11219,7 @@ "note": "double precision, gate by gate", "strict": 8.770551865339345e-17, "global_phase": -8.915536074191195e-18, - "seconds": 0.8051477409899235 + "seconds": 0.848699556896463 }, { "entry": "gate_cy", @@ -11231,7 +11231,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 4.88014002929309e-16, "global_phase": 2.9887434152964544e-17, - "seconds": 0.001303102821111679 + "seconds": 0.001684343907982111 }, { "entry": "gate_cy", @@ -11243,7 +11243,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.801829443895296e-17, "global_phase": -1.2344437959503701e-17, - "seconds": 0.006964451866224408 + "seconds": 0.007800055900588632 }, { "entry": "gate_cy", @@ -11255,7 +11255,7 @@ "note": "single precision, fusion width 2", "strict": 5.6825705358055105e-08, "global_phase": -2.1986460052579153e-09, - "seconds": 0.0007462399080395699 + "seconds": 0.0005278280004858971 }, { "entry": "gate_cy", @@ -11311,7 +11311,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.00017467 + "seconds": 0.000185561 }, { "entry": "gate_cz", @@ -11323,7 +11323,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000170392 + "seconds": 0.000177536 }, { "entry": "gate_cz", @@ -11335,7 +11335,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000154011, + "seconds": 0.000166024, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11350,7 +11350,7 @@ "note": "double precision, gate by gate", "strict": 8.857402632175859e-17, "global_phase": -9.647844174701355e-18, - "seconds": 0.677235416835174 + "seconds": 0.7755721278954297 }, { "entry": "gate_cz", @@ -11362,7 +11362,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 5.749743207707539e-17, "global_phase": -3.7846341003276924e-17, - "seconds": 0.0012669551651924849 + "seconds": 0.0016995531041175127 }, { "entry": "gate_cz", @@ -11374,7 +11374,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.2301684670985136e-17, "global_phase": 1.4944812019014365e-17, - "seconds": 0.021235962165519595 + "seconds": 0.0070811668410897255 }, { "entry": "gate_cz", @@ -11386,7 +11386,7 @@ "note": "single precision, fusion width 2", "strict": 4.3725610219115716e-08, "global_phase": -1.8036046965337988e-09, - "seconds": 0.0007802147883921862 + "seconds": 0.0006782819982618093 }, { "entry": "gate_cz", @@ -11442,7 +11442,7 @@ "note": "double precision, fusion width 3", "strict": 9.011893242098248e-17, "global_phase": -3.534699716199192e-17, - "seconds": 0.000126048 + "seconds": 0.000171444 }, { "entry": "gate_ch", @@ -11454,7 +11454,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0533633233600722e-16, "global_phase": -6.049332165550436e-17, - "seconds": 0.000169951 + "seconds": 0.000175592 }, { "entry": "gate_ch", @@ -11466,7 +11466,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0533633233600722e-16, "global_phase": -6.049332165550436e-17, - "seconds": 0.000170803, + "seconds": 0.000183568, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11481,7 +11481,7 @@ "note": "double precision, gate by gate", "strict": 8.84074282147305e-17, "global_phase": -9.864105534567055e-18, - "seconds": 0.770113862818107 + "seconds": 0.8023670839611441 }, { "entry": "gate_ch", @@ -11493,7 +11493,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 8.84664545257197e-17, "global_phase": -9.305934782451324e-18, - "seconds": 0.0015178481116890907 + "seconds": 0.0015489580109715462 }, { "entry": "gate_ch", @@ -11505,7 +11505,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.1310339669549782e-16, "global_phase": -9.561523159884953e-18, - "seconds": 0.04572232812643051 + "seconds": 0.007594838039949536 }, { "entry": "gate_ch", @@ -11517,7 +11517,7 @@ "note": "single precision, fusion width 2", "strict": 3.887514690754156e-08, "global_phase": -1.7132622630867782e-09, - "seconds": 0.0006310818716883659 + "seconds": 0.0006828410550951958 }, { "entry": "gate_ch", @@ -11573,7 +11573,7 @@ "note": "double precision, fusion width 3", "strict": 1.0208510354511309e-16, "global_phase": -3.1023325683456925e-17, - "seconds": 0.00016956 + "seconds": 0.000154752 }, { "entry": "gate_csx", @@ -11585,7 +11585,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9841132369045797e-16, "global_phase": -6.062903440956213e-17, - "seconds": 0.000123593 + "seconds": 0.000161245 }, { "entry": "gate_csx", @@ -11597,7 +11597,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9841132369045797e-16, "global_phase": -6.062903440956213e-17, - "seconds": 0.000163619, + "seconds": 0.000164431, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11612,7 +11612,7 @@ "note": "double precision, gate by gate", "strict": 9.125317820124742e-17, "global_phase": -6.878497463590267e-18, - "seconds": 0.6918904429767281 + "seconds": 0.8272385150194168 }, { "entry": "gate_csx", @@ -11624,7 +11624,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 1.066563277494779e-16, "global_phase": -5.85827326053431e-17, - "seconds": 0.0010776459239423275 + "seconds": 0.0014055469073355198 }, { "entry": "gate_csx", @@ -11636,7 +11636,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.011375504119853e-17, "global_phase": 1.07165993949384e-17, - "seconds": 0.005421485984697938 + "seconds": 0.008845261996611953 }, { "entry": "gate_csx", @@ -11648,7 +11648,7 @@ "note": "single precision, fusion width 2", "strict": 9.135192126279703e-08, "global_phase": -4.1025140345377066e-09, - "seconds": 0.0006550080142915249 + "seconds": 0.0005972788203507662 }, { "entry": "gate_csx", @@ -11704,7 +11704,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.0001798 + "seconds": 0.000170753 }, { "entry": "gate_swap", @@ -11716,7 +11716,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000140065 + "seconds": 0.000167788 }, { "entry": "gate_swap", @@ -11728,7 +11728,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000146477, + "seconds": 0.000162447, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11743,7 +11743,7 @@ "note": "double precision, gate by gate", "strict": 8.857402632175859e-17, "global_phase": -9.647844174701355e-18, - "seconds": 0.662757967133075 + "seconds": 0.5297612070571631 }, { "entry": "gate_swap", @@ -11755,7 +11755,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 9.01323343579344e-17, "global_phase": -3.574487808951742e-17, - "seconds": 0.0013583668041974306 + "seconds": 0.0013281709980219603 }, { "entry": "gate_swap", @@ -11767,7 +11767,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.929333588180882e-17, "global_phase": 1.4669463408880753e-17, - "seconds": 0.006923343986272812 + "seconds": 0.013757719192653894 }, { "entry": "gate_swap", @@ -11779,7 +11779,7 @@ "note": "single precision, fusion width 2", "strict": 4.3725610219115716e-08, "global_phase": -1.8036046965337988e-09, - "seconds": 0.0005522030405700207 + "seconds": 0.0006916280835866928 }, { "entry": "gate_swap", @@ -11835,7 +11835,7 @@ "note": "double precision, fusion width 3", "strict": 8.915186535406673e-17, "global_phase": -3.5692466279524444e-17, - "seconds": 0.000120869 + "seconds": 0.000151787 }, { "entry": "gate_cp", @@ -11847,7 +11847,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9817542452890808e-16, "global_phase": -5.941143185791318e-17, - "seconds": 0.000162667 + "seconds": 0.000139213 }, { "entry": "gate_cp", @@ -11859,7 +11859,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9817542452890808e-16, "global_phase": -5.941143185791318e-17, - "seconds": 0.000128573, + "seconds": 0.000180481, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11874,7 +11874,7 @@ "note": "double precision, gate by gate", "strict": 8.858980833816434e-17, "global_phase": -9.655969324789357e-18, - "seconds": 0.569846339058131 + "seconds": 0.6911670889239758 }, { "entry": "gate_cp", @@ -11886,7 +11886,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 4.994363711516718e-16, "global_phase": -2.1811258359976394e-17, - "seconds": 0.0012398529797792435 + "seconds": 0.0017265339847654104 }, { "entry": "gate_cp", @@ -11898,7 +11898,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.235558624947136e-17, "global_phase": 1.496056354469242e-17, - "seconds": 0.005791113944724202 + "seconds": 0.01394448196515441 }, { "entry": "gate_cp", @@ -11910,7 +11910,7 @@ "note": "single precision, fusion width 2", "strict": 4.378062298540436e-08, "global_phase": -1.7982195301532557e-09, - "seconds": 0.0005897639784961939 + "seconds": 0.00051728799007833 }, { "entry": "gate_cp", @@ -11966,7 +11966,7 @@ "note": "double precision, fusion width 3", "strict": 9.698821067454252e-17, "global_phase": -3.59045673273073e-17, - "seconds": 0.000124215 + "seconds": 0.000156085 }, { "entry": "gate_crx", @@ -11978,7 +11978,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9851544823524085e-16, "global_phase": -5.956982339748994e-17, - "seconds": 7.6635e-05 + "seconds": 0.000170202 }, { "entry": "gate_crx", @@ -11990,7 +11990,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9851544823524085e-16, "global_phase": -5.956982339748994e-17, - "seconds": 0.0001324, + "seconds": 0.000154132, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12005,7 +12005,7 @@ "note": "double precision, gate by gate", "strict": 8.786005079066397e-17, "global_phase": -9.114394956161993e-18, - "seconds": 0.5505139040760696 + "seconds": 0.7780839470215142 }, { "entry": "gate_crx", @@ -12017,7 +12017,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 1.1082744485265874e-16, "global_phase": -6.387456569465732e-17, - "seconds": 0.0013504319358617067 + "seconds": 0.0013070611748844385 }, { "entry": "gate_crx", @@ -12029,7 +12029,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.765720863933407e-17, "global_phase": -9.482197611873177e-18, - "seconds": 0.005537515040487051 + "seconds": 0.007938988972455263 }, { "entry": "gate_crx", @@ -12041,7 +12041,7 @@ "note": "single precision, fusion width 2", "strict": 4.2026073233097646e-08, "global_phase": -1.4462017472784202e-09, - "seconds": 0.0005854959599673748 + "seconds": 0.000693941954523325 }, { "entry": "gate_crx", @@ -12097,7 +12097,7 @@ "note": "double precision, fusion width 3", "strict": 1.0024255523485516e-16, "global_phase": -3.6054244168158195e-17, - "seconds": 0.000118073 + "seconds": 0.000173938 }, { "entry": "gate_cry", @@ -12109,7 +12109,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.980659682132769e-16, "global_phase": -5.968868788740983e-17, - "seconds": 0.000159191 + "seconds": 0.000165353 }, { "entry": "gate_cry", @@ -12121,7 +12121,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.980659682132769e-16, "global_phase": -5.968868788740983e-17, - "seconds": 0.000139784, + "seconds": 0.000163149, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12136,7 +12136,7 @@ "note": "double precision, gate by gate", "strict": 8.917742241711794e-17, "global_phase": -9.23453091197496e-18, - "seconds": 0.561909870011732 + "seconds": 0.5257747499272227 }, { "entry": "gate_cry", @@ -12148,7 +12148,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 2.0679924065344703e-16, "global_phase": -8.678784647247017e-17, - "seconds": 0.0013575858902186155 + "seconds": 0.001605986151844263 }, { "entry": "gate_cry", @@ -12160,7 +12160,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 9.707217474362964e-17, "global_phase": -8.644535780344246e-18, - "seconds": 0.006457444047555327 + "seconds": 0.014785652980208397 }, { "entry": "gate_cry", @@ -12172,7 +12172,7 @@ "note": "single precision, fusion width 2", "strict": 4.314382574241824e-08, "global_phase": -1.4672102648496911e-09, - "seconds": 0.0005828919820487499 + "seconds": 0.000514493091031909 }, { "entry": "gate_cry", @@ -12228,7 +12228,7 @@ "note": "double precision, fusion width 3", "strict": 9.947118394848183e-17, "global_phase": -3.5386121754067354e-17, - "seconds": 0.000164952 + "seconds": 0.000154602 }, { "entry": "gate_crz", @@ -12240,7 +12240,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9815193236339522e-16, "global_phase": -5.946576214758588e-17, - "seconds": 0.000159391 + "seconds": 0.000163088 }, { "entry": "gate_crz", @@ -12252,7 +12252,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9815193236339522e-16, "global_phase": -5.946576214758588e-17, - "seconds": 0.000149222, + "seconds": 0.000163229, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12267,7 +12267,7 @@ "note": "double precision, gate by gate", "strict": 8.880395942884383e-17, "global_phase": -8.995939846703679e-18, - "seconds": 0.6917760970536619 + "seconds": 0.7200218590442091 }, { "entry": "gate_crz", @@ -12279,7 +12279,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 5.010747716875595e-16, "global_phase": 3.348621880571692e-18, - "seconds": 0.001451331889256835 + "seconds": 0.0014978819526731968 }, { "entry": "gate_crz", @@ -12291,7 +12291,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.2365718473423015e-17, "global_phase": 1.4328304100354705e-17, - "seconds": 0.01619239104911685 + "seconds": 0.006997368996962905 }, { "entry": "gate_crz", @@ -12303,7 +12303,7 @@ "note": "single precision, fusion width 2", "strict": 4.102382026084183e-08, "global_phase": -1.3283904116881511e-09, - "seconds": 0.0006654271855950356 + "seconds": 0.000728757819160819 }, { "entry": "gate_crz", @@ -12359,7 +12359,7 @@ "note": "double precision, fusion width 3", "strict": 8.902240780164087e-17, "global_phase": -3.5454719336911746e-17, - "seconds": 0.000177526 + "seconds": 0.000156125 }, { "entry": "gate_cu", @@ -12371,7 +12371,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9900977238579004e-16, "global_phase": -5.778302861011668e-17, - "seconds": 0.0001642 + "seconds": 0.000413592 }, { "entry": "gate_cu", @@ -12383,7 +12383,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9900977238579004e-16, "global_phase": -5.778302861011668e-17, - "seconds": 0.000161465, + "seconds": 0.000168098, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12398,7 +12398,7 @@ "note": "double precision, gate by gate", "strict": 9.162380364018188e-17, "global_phase": -5.063428604904715e-18, - "seconds": 0.7442252880427986 + "seconds": 0.7649018350057304 }, { "entry": "gate_cu", @@ -12410,7 +12410,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 2.497052173396658e-16, "global_phase": 3.779122463256467e-17, - "seconds": 0.0011513559147715569 + "seconds": 0.0013769939541816711 }, { "entry": "gate_cu", @@ -12422,7 +12422,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.0045300706224988e-16, "global_phase": -3.793081001973975e-17, - "seconds": 0.008020899025723338 + "seconds": 0.008243223885074258 }, { "entry": "gate_cu", @@ -12434,7 +12434,7 @@ "note": "single precision, fusion width 2", "strict": 3.8943857071260265e-08, "global_phase": -2.3195076395136797e-09, - "seconds": 0.0006536948494613171, + "seconds": 0.0006516620051115751, "adapter": [ "U as a matrix" ] @@ -12493,7 +12493,7 @@ "note": "double precision, fusion width 3", "strict": 8.114732548118926e-17, "global_phase": -3.46438477984978e-17, - "seconds": 0.000145805 + "seconds": 0.00016366 }, { "entry": "gate_rzz", @@ -12505,7 +12505,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.875523507253141e-16, "global_phase": -6.500887442050855e-17, - "seconds": 0.000182635 + "seconds": 0.000167998 }, { "entry": "gate_rzz", @@ -12517,7 +12517,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.875523507253141e-16, "global_phase": -6.500887442050855e-17, - "seconds": 0.000151987, + "seconds": 0.000159642, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12532,7 +12532,7 @@ "note": "double precision, gate by gate", "strict": 7.6084808223538e-17, "global_phase": -3.382745883856216e-17, - "seconds": 0.6443465929478407 + "seconds": 0.5427632268983871 }, { "entry": "gate_rzz", @@ -12544,7 +12544,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 3.2602942662321956e-16, "global_phase": -4.5457681816075216e-17, - "seconds": 0.0013273379299789667 + "seconds": 0.0014458941295742989 }, { "entry": "gate_rzz", @@ -12556,7 +12556,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.865470546336336e-17, "global_phase": 1.650644909206721e-17, - "seconds": 0.00738117890432477 + "seconds": 0.011576255084946752 }, { "entry": "gate_rzz", @@ -12568,7 +12568,7 @@ "note": "single precision, fusion width 2", "strict": 3.731200351689503e-08, "global_phase": -2.11081839962072e-08, - "seconds": 0.0005317151080816984 + "seconds": 0.0005655589047819376 }, { "entry": "gate_rzz", @@ -12624,7 +12624,7 @@ "note": "double precision, fusion width 3", "strict": 1.203844925257312e-16, "global_phase": -3.9846685910587735e-17, - "seconds": 0.000124806 + "seconds": 0.005180424 }, { "entry": "gate_rxx", @@ -12636,7 +12636,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2266091037362635e-16, "global_phase": -6.390672161584823e-17, - "seconds": 0.000160584 + "seconds": 0.000143081 }, { "entry": "gate_rxx", @@ -12648,7 +12648,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2266091037362635e-16, "global_phase": -6.390672161584823e-17, - "seconds": 0.000136158, + "seconds": 0.000173798, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12663,7 +12663,7 @@ "note": "double precision, gate by gate", "strict": 1.1225432227990271e-16, "global_phase": -1.3277241177965651e-17, - "seconds": 0.6892354749143124 + "seconds": 0.6573530419263989 }, { "entry": "gate_rxx", @@ -12675,7 +12675,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 4.698141079668197e-16, "global_phase": 4.031288652513078e-18, - "seconds": 0.0014404819812625647 + "seconds": 0.0013054378796368837 }, { "entry": "gate_rxx", @@ -12687,7 +12687,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.5088529315976045e-16, "global_phase": 1.755149544000275e-17, - "seconds": 0.008760376134887338 + "seconds": 0.005889214109629393 }, { "entry": "gate_rxx", @@ -12699,7 +12699,7 @@ "note": "single precision, fusion width 2", "strict": 3.031567173987386e-08, "global_phase": 8.362221574148164e-09, - "seconds": 0.0005347009282559156 + "seconds": 0.0005486670415848494 }, { "entry": "gate_rxx", @@ -12755,7 +12755,7 @@ "note": "double precision, fusion width 3", "strict": 1.288187406182432e-16, "global_phase": -5.957428546725693e-17, - "seconds": 0.000167066 + "seconds": 0.000139875 }, { "entry": "gate_ryy", @@ -12767,7 +12767,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2962602289809404e-16, "global_phase": -8.332955701122513e-17, - "seconds": 0.000152759 + "seconds": 0.000168328 }, { "entry": "gate_ryy", @@ -12779,7 +12779,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2962602289809404e-16, "global_phase": -8.332955701122513e-17, - "seconds": 0.000168829, + "seconds": 0.000173708, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12794,7 +12794,7 @@ "note": "double precision, gate by gate", "strict": 1.1671980311662524e-16, "global_phase": -3.302195000488207e-17, - "seconds": 0.7084285670425743 + "seconds": 0.7914362498559058 }, { "entry": "gate_ryy", @@ -12806,7 +12806,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 5.901040528879488e-16, "global_phase": -2.2226657774544426e-17, - "seconds": 0.0018383839633315802 + "seconds": 0.0016745459288358688 }, { "entry": "gate_ryy", @@ -12818,7 +12818,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.2181771912564385e-16, "global_phase": -3.182350774689283e-17, - "seconds": 0.005542043829336762 + "seconds": 0.0124274049885571 }, { "entry": "gate_ryy", @@ -12830,7 +12830,7 @@ "note": "single precision, fusion width 2", "strict": 3.511769130076908e-08, "global_phase": 1.855369759389716e-08, - "seconds": 0.0005512009374797344 + "seconds": 0.0008133470546454191 }, { "entry": "gate_ryy", @@ -12886,7 +12886,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.000168238 + "seconds": 0.000180642 }, { "entry": "gate_negcx", @@ -12898,7 +12898,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000155083 + "seconds": 0.000165994 }, { "entry": "gate_negcx", @@ -12910,7 +12910,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000143411, + "seconds": 0.000173247, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12925,7 +12925,7 @@ "note": "double precision, gate by gate", "strict": 8.857402632175859e-17, "global_phase": -9.647844174701355e-18, - "seconds": 0.6635926440358162, + "seconds": 1.3796109179966152, "adapter": [ "negcx as x, cx, x" ] @@ -12940,7 +12940,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 6.023587187968749e-16, "global_phase": 2.7895844644493254e-17, - "seconds": 0.002049884060397744, + "seconds": 0.0023097170051187277, "adapter": [ "negcx as x, cx, x" ] @@ -12955,7 +12955,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.424447715313029e-17, "global_phase": -1.260889585891152e-17, - "seconds": 0.010875422973185778 + "seconds": 0.015579673927277327 }, { "entry": "gate_negcx", @@ -12967,7 +12967,7 @@ "note": "single precision, fusion width 2", "strict": 4.337439164317688e-08, "global_phase": -1.5235511753926034e-09, - "seconds": 0.0005989109631627798 + "seconds": 0.0008374939206987619 }, { "entry": "gate_negcx", @@ -13023,7 +13023,7 @@ "note": "double precision, fusion width 3", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 0.000160533 + "seconds": 0.000162617 }, { "entry": "gate_ccx", @@ -13035,7 +13035,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.000145114 + "seconds": 0.000184048 }, { "entry": "gate_ccx", @@ -13047,7 +13047,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.000138371, + "seconds": 0.000185591, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13062,7 +13062,7 @@ "note": "double precision, gate by gate", "strict": 1.4013366226977055e-16, "global_phase": -2.5373511133172645e-18, - "seconds": 0.6037390411365777 + "seconds": 0.9991447480861098 }, { "entry": "gate_ccx", @@ -13074,7 +13074,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 1.4013059000063044e-16, "global_phase": -2.784644461915488e-17, - "seconds": 0.001203384017571807 + "seconds": 0.0015405919402837753 }, { "entry": "gate_ccx", @@ -13086,7 +13086,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.6170785510676706e-16, "global_phase": -2.4539622958386736e-18, - "seconds": 0.006061495048925281 + "seconds": 0.01359469210729003 }, { "entry": "gate_ccx", @@ -13098,7 +13098,7 @@ "note": "single precision, fusion width 2", "strict": 2.553695652880276e-08, "global_phase": 1.452549941361316e-09, - "seconds": 0.0005829911679029465 + "seconds": 0.0006121678743511438 }, { "entry": "gate_ccx", @@ -13154,7 +13154,7 @@ "note": "double precision, fusion width 3", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 0.000123824 + "seconds": 0.000160073 }, { "entry": "gate_ccz", @@ -13166,7 +13166,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.000166465 + "seconds": 0.000167606 }, { "entry": "gate_ccz", @@ -13178,7 +13178,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.000127922, + "seconds": 0.000173788, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13193,7 +13193,7 @@ "note": "double precision, gate by gate", "strict": 1.4013366226977055e-16, "global_phase": -2.5373511133172645e-18, - "seconds": 0.734755540965125 + "seconds": 1.002932989038527 }, { "entry": "gate_ccz", @@ -13205,7 +13205,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 1.4013059000063044e-16, "global_phase": -2.784644461915488e-17, - "seconds": 0.0017379638738930225 + "seconds": 0.0021035769023001194 }, { "entry": "gate_ccz", @@ -13217,7 +13217,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.4495985349309682e-17, "global_phase": 1.7289083146586244e-19, - "seconds": 0.01011457503773272 + "seconds": 0.009285214124247432 }, { "entry": "gate_ccz", @@ -13229,7 +13229,7 @@ "note": "single precision, fusion width 2", "strict": 2.553695652880276e-08, "global_phase": 1.452549941361316e-09, - "seconds": 0.0005050748586654663 + "seconds": 0.0008768679108470678 }, { "entry": "gate_ccz", @@ -13285,7 +13285,7 @@ "note": "double precision, fusion width 3", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 0.000128924 + "seconds": 0.000178498 }, { "entry": "gate_cswap", @@ -13297,7 +13297,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.000119877 + "seconds": 0.000179509 }, { "entry": "gate_cswap", @@ -13309,7 +13309,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.000167076, + "seconds": 0.000182756, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13324,7 +13324,7 @@ "note": "double precision, gate by gate", "strict": 1.4013366226977055e-16, "global_phase": -2.5373511133172645e-18, - "seconds": 0.5806664668489248 + "seconds": 0.9549928670749068 }, { "entry": "gate_cswap", @@ -13336,7 +13336,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 1.4013059000063044e-16, "global_phase": -2.784644461915488e-17, - "seconds": 0.0013941051438450813 + "seconds": 0.0020531010814011097 }, { "entry": "gate_cswap", @@ -13348,7 +13348,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.0254124592450465e-17, "global_phase": 8.866276048486312e-20, - "seconds": 0.005872847978025675 + "seconds": 0.007788866059854627 }, { "entry": "gate_cswap", @@ -13360,7 +13360,7 @@ "note": "single precision, fusion width 2", "strict": 2.553695652880276e-08, "global_phase": 1.452549941361316e-09, - "seconds": 0.0005331479478627443 + "seconds": 0.0007971471641212702 }, { "entry": "gate_cswap", @@ -13416,7 +13416,7 @@ "note": "double precision, fusion width 3", "strict": 1.3855069357692387e-16, "global_phase": -2.8088848837941315e-17, - "seconds": 0.000162016 + "seconds": 0.000218382 }, { "entry": "gate_c2p", @@ -13428,7 +13428,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470249484123369e-16, "global_phase": -5.5331649595364525e-17, - "seconds": 0.000140115 + "seconds": 0.00018016 }, { "entry": "gate_c2p", @@ -13440,7 +13440,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470249484123369e-16, "global_phase": -5.5331649595364525e-17, - "seconds": 0.000148471, + "seconds": 0.000170582, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13455,7 +13455,7 @@ "note": "double precision, gate by gate", "strict": 1.4013378258698447e-16, "global_phase": -2.5373362654207204e-18, - "seconds": 0.5763238910585642 + "seconds": 1.2081175858620554 }, { "entry": "gate_c2p", @@ -13467,7 +13467,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 1.352664922370875e-16, "global_phase": -2.928086575644102e-17, - "seconds": 0.0016980699729174376 + "seconds": 0.0022093569859862328 }, { "entry": "gate_c2p", @@ -13479,7 +13479,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.4494944356881143e-17, "global_phase": 1.7280707492796442e-19, - "seconds": 0.006105427863076329 + "seconds": 0.008134699193760753 }, { "entry": "gate_c2p", @@ -13491,7 +13491,7 @@ "note": "single precision, fusion width 2", "strict": 2.5537054944531005e-08, "global_phase": 1.4525418475928885e-09, - "seconds": 0.000594473909586668 + "seconds": 0.0006741238757967949 }, { "entry": "gate_c2p", @@ -13547,7 +13547,7 @@ "note": "double precision, fusion width 3", "strict": 1.385638179882964e-16, "global_phase": -2.8091482637843886e-17, - "seconds": 0.000138302 + "seconds": 0.000210087 }, { "entry": "gate_c2rz", @@ -13559,7 +13559,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.4470597500024585e-16, "global_phase": -5.569630515112943e-17, - "seconds": 0.000162647 + "seconds": 0.000166494 }, { "entry": "gate_c2rz", @@ -13571,7 +13571,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.4470597500024585e-16, "global_phase": -5.569630515112943e-17, - "seconds": 0.000126339, + "seconds": 0.000158039, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13586,7 +13586,7 @@ "note": "double precision, gate by gate", "strict": 1.401338580384328e-16, "global_phase": -2.5350650652912525e-18, - "seconds": 0.7321718391031027 + "seconds": 0.9438813920132816 }, { "entry": "gate_c2rz", @@ -13598,7 +13598,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 1.3898649867130245e-16, "global_phase": -2.183005071623825e-18, - "seconds": 0.002658153884112835 + "seconds": 0.0028002739418298006 }, { "entry": "gate_c2rz", @@ -13610,7 +13610,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.4794165255085104e-17, "global_phase": 1.6610444227779503e-19, - "seconds": 0.00578857003711164 + "seconds": 0.007755761966109276 }, { "entry": "gate_c2rz", @@ -13622,7 +13622,7 @@ "note": "single precision, fusion width 2", "strict": 3.462165651149508e-08, "global_phase": 1.3836998209989688e-09, - "seconds": 0.0005954259540885687 + "seconds": 0.000667802058160305 }, { "entry": "gate_c2rz", @@ -13678,7 +13678,7 @@ "note": "double precision, fusion width 3", "strict": 1.385606040263293e-16, "global_phase": -2.8089793690612016e-17, - "seconds": 0.00018488 + "seconds": 0.000191302 }, { "entry": "gate_c2ry", @@ -13690,7 +13690,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.4813348680394973e-16, "global_phase": -5.532178000472185e-17, - "seconds": 0.000171905 + "seconds": 0.000181693 }, { "entry": "gate_c2ry", @@ -13702,7 +13702,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.4813348680394973e-16, "global_phase": -5.532178000472185e-17, - "seconds": 0.000156525, + "seconds": 0.000165853, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13717,7 +13717,7 @@ "note": "double precision, gate by gate", "strict": 1.401730153381778e-16, "global_phase": -2.541868486490896e-18, - "seconds": 0.9408812660258263 + "seconds": 0.8184536269400269 }, { "entry": "gate_c2ry", @@ -13729,7 +13729,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 1.381511581476646e-16, "global_phase": -2.2156764705053963e-18, - "seconds": 0.0019831990357488394 + "seconds": 0.001749326940625906 }, { "entry": "gate_c2ry", @@ -13741,7 +13741,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.140218574169683e-17, "global_phase": -5.414054055847395e-17, - "seconds": 0.006854083156213164 + "seconds": 0.00793608301319182 }, { "entry": "gate_c2ry", @@ -13753,7 +13753,7 @@ "note": "single precision, fusion width 2", "strict": 3.46410246490762e-08, "global_phase": 1.3849956703601621e-09, - "seconds": 0.0006026590708643198 + "seconds": 0.0007222858257591724 }, { "entry": "gate_c2ry", @@ -13809,7 +13809,7 @@ "note": "double precision, fusion width 3", "strict": 1.1418412035005258e-16, "global_phase": -9.306014224130332e-18, - "seconds": 0.000208283 + "seconds": 0.000239763 }, { "entry": "gate_c3x", @@ -13821,7 +13821,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2057454549202864e-16, "global_phase": -3.850320092070849e-17, - "seconds": 0.000140475 + "seconds": 0.000172396 }, { "entry": "gate_c3x", @@ -13833,7 +13833,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2057454549202864e-16, "global_phase": -3.850320092070849e-17, - "seconds": 0.000171394, + "seconds": 0.000207242, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13848,7 +13848,7 @@ "note": "double precision, gate by gate", "strict": 2.2850088420415793e-16, "global_phase": 1.2992703127221225e-17, - "seconds": 0.6806608298793435 + "seconds": 0.7528841369785368 }, { "entry": "gate_c3x", @@ -13860,7 +13860,7 @@ "note": "double precision, a contraction of width 4.0", "strict": 1.0734769178841271e-16, "global_phase": -9.403586273589279e-18, - "seconds": 0.0024981109891086817 + "seconds": 0.0025589580181986094 }, { "entry": "gate_c3x", @@ -13872,7 +13872,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.112211140817646e-16, "global_phase": -6.344245552251684e-17, - "seconds": 0.005902155069634318 + "seconds": 0.007352990098297596 }, { "entry": "gate_c3x", @@ -13884,7 +13884,7 @@ "note": "single precision, fusion width 2", "strict": 7.642205600447223e-08, "global_phase": 1.5249555543893608e-08, - "seconds": 0.0006263540126383305 + "seconds": 0.0008793231099843979 }, { "entry": "gate_c3x", @@ -13940,7 +13940,7 @@ "note": "double precision, fusion width 3", "strict": 1.1418412035005258e-16, "global_phase": -9.306014224130332e-18, - "seconds": 0.000172787 + "seconds": 0.000239603 }, { "entry": "gate_c3z", @@ -13952,7 +13952,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.599966217654964e-16, "global_phase": 1.4446076422946466e-17, - "seconds": 0.00015333 + "seconds": 0.000183597 }, { "entry": "gate_c3z", @@ -13964,7 +13964,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.599966217654964e-16, "global_phase": 1.4446076422946466e-17, - "seconds": 0.000138722, + "seconds": 0.000193095, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13979,7 +13979,7 @@ "note": "double precision, gate by gate", "strict": 2.2850089960147827e-16, "global_phase": 1.299270222922428e-17, - "seconds": 0.5690983049571514 + "seconds": 0.9252639138139784 }, { "entry": "gate_c3z", @@ -13991,7 +13991,7 @@ "note": "double precision, a contraction of width 4.0", "strict": 3.3768940600253865e-16, "global_phase": -1.609024639425753e-17, - "seconds": 0.0021034060046076775 + "seconds": 0.002693100832402706 }, { "entry": "gate_c3z", @@ -14003,7 +14003,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.070586436385354e-17, "global_phase": -3.264981576007027e-17, - "seconds": 0.005551822017878294 + "seconds": 0.0078543690033257 }, { "entry": "gate_c3z", @@ -14015,7 +14015,7 @@ "note": "single precision, fusion width 2", "strict": 7.642205600447223e-08, "global_phase": 1.5249555543893608e-08, - "seconds": 0.0006285780109465122 + "seconds": 0.0007361718453466892 }, { "entry": "gate_c3z", @@ -14071,7 +14071,7 @@ "note": "double precision, fusion width 3", "strict": 1.4948344912607779e-16, "global_phase": -1.2703930273265457e-16, - "seconds": 0.000127692 + "seconds": 0.000150064 }, { "entry": "full_turn_rz_t1_0", @@ -14083,7 +14083,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4948344912607779e-16, "global_phase": -1.2703930273265457e-16, - "seconds": 0.000115939 + "seconds": 0.00014236 }, { "entry": "full_turn_rz_t1_0", @@ -14095,7 +14095,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4948344912607779e-16, "global_phase": -1.2703930273265457e-16, - "seconds": 0.000143691, + "seconds": 0.000162216, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14110,7 +14110,7 @@ "note": "double precision, gate by gate", "strict": 1.4948344912607779e-16, "global_phase": -1.2703930273265457e-16, - "seconds": 0.5107016549445689 + "seconds": 0.8489981819875538 }, { "entry": "full_turn_rz_t1_0", @@ -14122,7 +14122,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.9056138362361657e-16, "global_phase": -7.990180385963304e-17, - "seconds": 0.0009188458789139986 + "seconds": 0.0014253449626266956 }, { "entry": "full_turn_rz_t1_0", @@ -14134,7 +14134,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006299806060269475 + "seconds": 0.03799460013397038 }, { "entry": "full_turn_rz_t1_0", @@ -14146,7 +14146,7 @@ "note": "single precision, fusion width 2", "strict": 9.037682710149867e-08, "global_phase": 7.710813084434486e-08, - "seconds": 0.0004882519133388996 + "seconds": 0.0007225458975881338 }, { "entry": "full_turn_rz_t1_0", @@ -14202,7 +14202,7 @@ "note": "double precision, fusion width 3", "strict": 1.4345679644901053e-16, "global_phase": -7.291263256419637e-17, - "seconds": 0.000113565 + "seconds": 0.000187394 }, { "entry": "full_turn_rx_t1_0", @@ -14214,7 +14214,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4345679644901053e-16, "global_phase": -7.291263256419637e-17, - "seconds": 0.000123383 + "seconds": 0.000165012 }, { "entry": "full_turn_rx_t1_0", @@ -14226,7 +14226,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4345679644901053e-16, "global_phase": -7.291263256419637e-17, - "seconds": 0.000128603, + "seconds": 0.000245264, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14241,7 +14241,7 @@ "note": "double precision, gate by gate", "strict": 1.4345679644901053e-16, "global_phase": -7.291263256419637e-17, - "seconds": 0.5771548009943217 + "seconds": 0.8059269250370562 }, { "entry": "full_turn_rx_t1_0", @@ -14253,7 +14253,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.847827009626881e-16, "global_phase": -2.523059717935201e-17, - "seconds": 0.0009049910586327314 + "seconds": 0.0014989641495049 }, { "entry": "full_turn_rx_t1_0", @@ -14265,7 +14265,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.01368123502470553 + "seconds": 0.018352315993979573 }, { "entry": "full_turn_rx_t1_0", @@ -14277,7 +14277,7 @@ "note": "single precision, fusion width 2", "strict": 8.782752682484874e-08, "global_phase": 2.4168096663117897e-08, - "seconds": 0.0005043330602347851 + "seconds": 0.0007657180540263653 }, { "entry": "full_turn_rx_t1_0", @@ -14333,7 +14333,7 @@ "note": "double precision, fusion width 3", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.000116641 + "seconds": 0.000200419 }, { "entry": "full_turn_ry_t1_0", @@ -14345,7 +14345,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.000137721 + "seconds": 0.000152097 }, { "entry": "full_turn_ry_t1_0", @@ -14357,7 +14357,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.000136337, + "seconds": 0.000161656, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14372,7 +14372,7 @@ "note": "double precision, gate by gate", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.675958793843165 + "seconds": 1.118330632103607 }, { "entry": "full_turn_ry_t1_0", @@ -14384,7 +14384,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.145218421465822e-16, "global_phase": 1.6471238045877752e-17, - "seconds": 0.0011074929498136044 + "seconds": 0.0013415259309113026 }, { "entry": "full_turn_ry_t1_0", @@ -14396,7 +14396,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006416406016796827 + "seconds": 0.04406964499503374 }, { "entry": "full_turn_ry_t1_0", @@ -14408,7 +14408,7 @@ "note": "single precision, fusion width 2", "strict": 1.0303836032604117e-07, "global_phase": -1.3212549757350479e-09, - "seconds": 0.0005131601355969906 + "seconds": 0.0008250400424003601 }, { "entry": "full_turn_ry_t1_0", @@ -14464,7 +14464,7 @@ "note": "double precision, fusion width 3", "strict": 9.42812133633664e-17, "global_phase": -1.4642115032431582e-17, - "seconds": 0.000121589 + "seconds": 0.00016887 }, { "entry": "full_turn_p_t1_0", @@ -14476,7 +14476,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.42812133633664e-17, "global_phase": -1.4642115032431582e-17, - "seconds": 0.000144844 + "seconds": 0.000149282 }, { "entry": "full_turn_p_t1_0", @@ -14488,7 +14488,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.42812133633664e-17, "global_phase": -1.4642115032431582e-17, - "seconds": 0.000150434, + "seconds": 0.000156135, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14503,7 +14503,7 @@ "note": "double precision, gate by gate", "strict": 9.42812133633664e-17, "global_phase": -1.4642115032431582e-17, - "seconds": 0.6021296789404005 + "seconds": 0.8226093640550971 }, { "entry": "full_turn_p_t1_0", @@ -14515,7 +14515,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.6640113228721536e-16, "global_phase": 3.249538384058998e-17, - "seconds": 0.0009654848836362362 + "seconds": 0.0013081030920147896 }, { "entry": "full_turn_p_t1_0", @@ -14527,7 +14527,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.005471550161018968 + "seconds": 0.009285544976592064 }, { "entry": "full_turn_p_t1_0", @@ -14539,7 +14539,7 @@ "note": "single precision, fusion width 2", "strict": 5.666655211839174e-08, "global_phase": -1.2866865989558174e-08, - "seconds": 0.0005774209275841713 + "seconds": 0.0006903351750224829 }, { "entry": "full_turn_p_t1_0", @@ -14595,7 +14595,7 @@ "note": "double precision, fusion width 3", "strict": 2.7979863037694193e-16, "global_phase": -2.5699069640890605e-16, - "seconds": 0.000129094 + "seconds": 0.000170964 }, { "entry": "full_turn_rz_t2_0", @@ -14607,7 +14607,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.7979863037694193e-16, "global_phase": -2.5699069640890605e-16, - "seconds": 0.00011658 + "seconds": 0.00015868 }, { "entry": "full_turn_rz_t2_0", @@ -14619,7 +14619,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.7979863037694193e-16, "global_phase": -2.5699069640890605e-16, - "seconds": 0.000154151, + "seconds": 0.000161635, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14634,7 +14634,7 @@ "note": "double precision, gate by gate", "strict": 2.7979863037694193e-16, "global_phase": -2.5699069640890605e-16, - "seconds": 0.5578112739603966 + "seconds": 0.8462102711200714 }, { "entry": "full_turn_rz_t2_0", @@ -14646,7 +14646,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.0608999734962266e-16, "global_phase": -2.249110223171109e-16, - "seconds": 0.0009432921651750803 + "seconds": 0.0011439730878919363 }, { "entry": "full_turn_rz_t2_0", @@ -14658,7 +14658,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.005483854096382856 + "seconds": 0.007187838898971677 }, { "entry": "full_turn_rz_t2_0", @@ -14670,7 +14670,7 @@ "note": "single precision, fusion width 2", "strict": 1.627436187799992e-07, "global_phase": 1.4615635214958267e-07, - "seconds": 0.0005027800798416138 + "seconds": 0.0005954061634838581 }, { "entry": "full_turn_rz_t2_0", @@ -14726,7 +14726,7 @@ "note": "double precision, fusion width 3", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.00012199 + "seconds": 0.000166996 }, { "entry": "full_turn_u_t1_0", @@ -14738,7 +14738,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.000154672 + "seconds": 0.000167667 }, { "entry": "full_turn_u_t1_0", @@ -14750,7 +14750,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.000122001, + "seconds": 0.000138292, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14765,7 +14765,7 @@ "note": "double precision, gate by gate", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.6006962000392377 + "seconds": 0.5875217339489609 }, { "entry": "full_turn_u_t1_0", @@ -14777,7 +14777,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.145218421465822e-16, "global_phase": 1.6471238045877752e-17, - "seconds": 0.0009284350089728832 + "seconds": 0.001281192060559988 }, { "entry": "full_turn_u_t1_0", @@ -14789,7 +14789,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.005104346899315715 + "seconds": 0.007734872866421938 }, { "entry": "full_turn_u_t1_0", @@ -14801,7 +14801,7 @@ "note": "single precision, fusion width 2", "strict": 4.024089473196959e-08, "global_phase": -6.396748512344255e-09, - "seconds": 0.0005718099419027567, + "seconds": 0.000523190014064312, "adapter": [ "U as a matrix" ] @@ -14860,7 +14860,7 @@ "note": "double precision, fusion width 3", "strict": 9.02558849753476e-17, "global_phase": -3.5446437687523536e-17, - "seconds": 0.0001217 + "seconds": 0.000152418 }, { "entry": "gate_gphase_controlled", @@ -14872,7 +14872,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9856040498679177e-16, "global_phase": -6.181819723743999e-17, - "seconds": 0.000128363 + "seconds": 0.000170081 }, { "entry": "gate_gphase_controlled", @@ -14884,7 +14884,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9856040498679177e-16, "global_phase": -6.181819723743999e-17, - "seconds": 0.000128984, + "seconds": 0.000158239, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14917,7 +14917,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.019615798246159e-17, "global_phase": 1.3818898041286565e-17, - "seconds": 0.016981201944872737 + "seconds": 0.010891070123761892 }, { "entry": "gate_gphase_controlled", @@ -14982,7 +14982,7 @@ "note": "double precision, fusion width 3", "strict": 2.383329718893769e-16, "global_phase": 0.0, - "seconds": 0.000175692 + "seconds": 0.000169691 }, { "entry": "controlled_rz_full_turn", @@ -14994,7 +14994,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.79306168888485e-16, "global_phase": -6.162975822039155e-33, - "seconds": 0.000171424 + "seconds": 0.000157037 }, { "entry": "controlled_rz_full_turn", @@ -15006,7 +15006,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.79306168888485e-16, "global_phase": -6.162975822039155e-33, - "seconds": 0.000152598, + "seconds": 0.000164581, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -15021,7 +15021,7 @@ "note": "double precision, gate by gate", "strict": 2.383329718893769e-16, "global_phase": 0.0, - "seconds": 0.8206533940974623 + "seconds": 0.6841625759843737 }, { "entry": "controlled_rz_full_turn", @@ -15033,7 +15033,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.051434889952961e-16, "global_phase": -6.162975822039156e-33, - "seconds": 0.001011932035908103 + "seconds": 0.0013677061069756746 }, { "entry": "controlled_rz_full_turn", @@ -15045,7 +15045,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.220446049250313e-16, "global_phase": 0.0, - "seconds": 0.0053974599577486515 + "seconds": 0.007371135056018829 }, { "entry": "controlled_rz_full_turn", @@ -15057,7 +15057,7 @@ "note": "single precision, fusion width 2", "strict": 6.181723814526122e-08, "global_phase": 0.0, - "seconds": 0.0005320250056684017 + "seconds": 0.0007053930312395096 }, { "entry": "controlled_rz_full_turn", @@ -15147,7 +15147,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 4.1729072108864784e-05 + "seconds": 4.504481330513954e-05 }, { "entry": "clifford_ghz_n100", @@ -15156,7 +15156,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 3.156e-06 + "seconds": 3.657e-06 }, { "entry": "clifford_ghz_n100", @@ -15173,7 +15173,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000262926 + "seconds": 0.000294086 }, { "entry": "clifford_ghz_n1000", @@ -15190,7 +15190,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0002678460441529751 + "seconds": 0.00019538914784789085 }, { "entry": "clifford_ghz_n1000", @@ -15199,7 +15199,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 3.0327e-05 + "seconds": 4.6007e-05 }, { "entry": "clifford_ghz_n1000", @@ -15216,7 +15216,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00717497 + "seconds": 0.011523095 }, { "entry": "clifford_ghz_n5000", @@ -15233,7 +15233,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0030303869862109423 + "seconds": 0.003534602001309395 }, { "entry": "clifford_ghz_n5000", @@ -15242,7 +15242,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.001630211 + "seconds": 0.00177707 }, { "entry": "clifford_ghz_n5000", @@ -15267,7 +15267,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 5.170796066522598e-05 + "seconds": 3.576790913939476e-05 }, { "entry": "clifford_cluster_n65", @@ -15276,7 +15276,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 7.464e-06 + "seconds": 7.294e-06 }, { "entry": "clifford_cluster_n65", @@ -15293,7 +15293,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000313082 + "seconds": 0.000204206 }, { "entry": "clifford_cluster_n1000", @@ -15310,7 +15310,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00024497206322848797 + "seconds": 0.00019752280786633492 }, { "entry": "clifford_cluster_n1000", @@ -15319,7 +15319,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.000109938 + "seconds": 6.5905e-05 }, { "entry": "clifford_cluster_n1000", @@ -15336,7 +15336,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.007919406 + "seconds": 0.007232463 }, { "entry": "clifford_cluster_n5000", @@ -15353,7 +15353,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.003309454070404172 + "seconds": 0.004687262000516057 }, { "entry": "clifford_cluster_n5000", @@ -15362,7 +15362,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.001444901 + "seconds": 0.001761791 }, { "entry": "clifford_cluster_n5000", @@ -15387,7 +15387,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 5.2558956667780876e-05 + "seconds": 5.66970556974411e-05 }, { "entry": "clifford_random_n63", @@ -15396,7 +15396,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 1.7623e-05 + "seconds": 1.4126e-05 }, { "entry": "clifford_random_n63", @@ -15413,7 +15413,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000712015 + "seconds": 0.000527547 }, { "entry": "clifford_random_n64", @@ -15430,7 +15430,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 5.378108471632004e-05 + "seconds": 5.829101428389549e-05 }, { "entry": "clifford_random_n64", @@ -15439,7 +15439,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 1.4848e-05 + "seconds": 1.7413e-05 }, { "entry": "clifford_random_n64", @@ -15456,7 +15456,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000506938 + "seconds": 0.00054992 }, { "entry": "clifford_random_n65", @@ -15473,7 +15473,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 5.300017073750496e-05 + "seconds": 6.374088115990162e-05 }, { "entry": "clifford_random_n65", @@ -15482,7 +15482,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 1.6822e-05 + "seconds": 1.8385e-05 }, { "entry": "clifford_random_n65", @@ -15499,7 +15499,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00079381 + "seconds": 0.000554688 }, { "entry": "clifford_random_n127", @@ -15516,7 +15516,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 9.078090079128742e-05 + "seconds": 8.147396147251129e-05 }, { "entry": "clifford_random_n127", @@ -15525,7 +15525,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 2.8484e-05 + "seconds": 3.2081e-05 }, { "entry": "clifford_random_n127", @@ -15542,7 +15542,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.001440842 + "seconds": 0.001331748 }, { "entry": "clifford_random_n128", @@ -15559,7 +15559,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 8.227513171732426e-05 + "seconds": 8.486001752316952e-05 }, { "entry": "clifford_random_n128", @@ -15568,7 +15568,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 2.8474e-05 + "seconds": 2.9777e-05 }, { "entry": "clifford_random_n128", @@ -15585,7 +15585,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00127554 + "seconds": 0.001273798 }, { "entry": "clifford_random_n129", @@ -15602,7 +15602,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 7.793703116476536e-05 + "seconds": 8.725491352379322e-05 }, { "entry": "clifford_random_n129", @@ -15611,7 +15611,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 4.0667e-05 + "seconds": 2.9866e-05 }, { "entry": "clifford_random_n129", @@ -15628,7 +15628,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.001222049 + "seconds": 0.001230376 }, { "entry": "clifford_random_n1000", @@ -15645,7 +15645,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0012512349057942629 + "seconds": 0.0012129629030823708 }, { "entry": "clifford_random_n1000", @@ -15654,7 +15654,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.000877598 + "seconds": 0.001213935 }, { "entry": "clifford_random_n1000", @@ -15671,7 +15671,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.058308448 + "seconds": 0.053752771 }, { "entry": "clifford_random_n2000", @@ -15688,7 +15688,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0027924960013478994 + "seconds": 0.0027415829245001078 }, { "entry": "clifford_random_n2000", @@ -15697,7 +15697,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.001975804 + "seconds": 0.002271775 }, { "entry": "clifford_random_n2000", @@ -15752,7 +15752,7 @@ "note": "double precision, fusion width 3", "strict": 1.3244320535236393e-15, "global_phase": -2.5571778398004984e-77, - "seconds": 0.006008293 + "seconds": 0.008212426 }, { "entry": "clifford_random_n10_as_state", @@ -15764,7 +15764,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.0439850796711554e-15, "global_phase": 1.900363860637374e-15, - "seconds": 0.001007734 + "seconds": 0.001210298 }, { "entry": "clifford_random_n10_as_state", @@ -15776,7 +15776,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.0439850796711554e-15, "global_phase": 1.900363860637374e-15, - "seconds": 0.001119235, + "seconds": 0.004207635, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -15791,19 +15791,19 @@ "note": "double precision, gate by gate", "strict": 4.3182725538710424e-15, "global_phase": 3.146394755705127e-15, - "seconds": 0.8057713718153536 + "seconds": 0.9863290898501873 }, { "entry": "clifford_random_n10_as_state", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.0678713780906063e-14, + "measured": 3.1685062560955955e-14, "tolerance": 7.041552439966656e-07, "status": "pass", "note": "double precision, a contraction of width 16.0", - "strict": 3.087105387727279e-14, - "global_phase": 3.440710427037386e-15, - "seconds": 1.1856781309470534 + "strict": 3.187117280836643e-14, + "global_phase": 3.439253798291533e-15, + "seconds": 1.6478121390100569 }, { "entry": "clifford_random_n10_as_state", @@ -15815,7 +15815,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.253673324449967e-16, "global_phase": -2.5571778398004988e-77, - "seconds": 0.018855358939617872 + "seconds": 0.019995892886072397 }, { "entry": "clifford_random_n10_as_state", @@ -15827,7 +15827,7 @@ "note": "single precision, fusion width 2", "strict": 7.598183428843805e-07, "global_phase": 7.171549827654089e-07, - "seconds": 0.005657400004565716 + "seconds": 0.027956231962889433 }, { "entry": "clifford_random_n10_as_state", @@ -15844,7 +15844,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 7.9029006883502e-05 + "seconds": 7.105409167706966e-05 }, { "entry": "clifford_random_n10_as_state", @@ -15853,7 +15853,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 8.406e-06 + "seconds": 1.3055e-05 }, { "entry": "clifford_random_n10_as_state", @@ -15870,7 +15870,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00027516 + "seconds": 0.000328832 }, { "entry": "clifford_random_n10_as_state", @@ -16057,7 +16057,7 @@ "tolerance": 2.76696570893817e-13, "status": "pass", "note": "29 two-site updates at bond 2; truncation from its reported discarded weight", - "seconds": 0.000702618, + "seconds": 0.000677772, "accuracy": { "class": "exact", "max_bond": 64, @@ -16073,7 +16073,7 @@ "tolerance": 8.450256244926496e-14, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.078773297, + "seconds": 0.046802061, "accuracy": { "class": "exact" } @@ -16086,7 +16086,7 @@ "tolerance": 2.76696570893817e-13, "status": "pass", "note": "29 two-site updates at bond 2, and 0 truncations, from its log", - "seconds": 0.000313903 + "seconds": 0.000291871 }, { "entry": "mps_ghz_n30", @@ -16096,7 +16096,7 @@ "tolerance": 8.566965708938169e-13, "status": "pass", "note": "29 two-site updates at bond 2; its cutoff drops at most 1e-28 of weight at each", - "seconds": 0.7247374821454287 + "seconds": 0.7189244439359754 }, { "entry": "mps_ghz_n30", @@ -16106,7 +16106,7 @@ "tolerance": 8.450256244926496e-14, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.6669374341145158 + "seconds": 0.7537474578712136 }, { "entry": "mps_ghz_n50", @@ -16116,7 +16116,7 @@ "tolerance": 4.67521792199987e-13, "status": "pass", "note": "49 two-site updates at bond 2; truncation from its reported discarded weight", - "seconds": 0.004099487, + "seconds": 0.000945598, "accuracy": { "class": "exact", "max_bond": 64, @@ -16132,7 +16132,7 @@ "tolerance": 1.4083760408211617e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.016979464, + "seconds": 0.002206681, "accuracy": { "class": "exact" } @@ -16145,7 +16145,7 @@ "tolerance": 4.67521792199987e-13, "status": "pass", "note": "49 two-site updates at bond 2, and 0 truncations, from its log", - "seconds": 0.000316207 + "seconds": 0.000318462 }, { "entry": "mps_ghz_n50", @@ -16155,7 +16155,7 @@ "tolerance": 1.447521792199987e-12, "status": "pass", "note": "49 two-site updates at bond 2; its cutoff drops at most 1e-28 of weight at each", - "seconds": 0.8698521771002561 + "seconds": 0.6187582779675722 }, { "entry": "mps_ghz_n50", @@ -16165,7 +16165,7 @@ "tolerance": 1.4083760408211617e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.7651352670509368 + "seconds": 0.722825980046764 }, { "entry": "mps_ghz_n100", @@ -16175,7 +16175,7 @@ "tolerance": 9.445848454657303e-13, "status": "pass", "note": "99 two-site updates at bond 2; truncation from its reported discarded weight", - "seconds": 0.000935868, + "seconds": 0.000998949, "accuracy": { "class": "exact", "max_bond": 64, @@ -16191,7 +16191,7 @@ "tolerance": 2.8167520816427206e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.018942754, + "seconds": 0.013741628, "accuracy": { "class": "exact" } @@ -16213,7 +16213,7 @@ "tolerance": 2.9245848454657303e-12, "status": "pass", "note": "99 two-site updates at bond 2; its cutoff drops at most 1e-28 of weight at each", - "seconds": 0.931437746156007 + "seconds": 0.6060133231803775 }, { "entry": "mps_ghz_n100", @@ -16223,7 +16223,7 @@ "tolerance": 2.8167520816427206e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.8245637910440564 + "seconds": 0.7550359040033072 }, { "entry": "mps_qft_n30", @@ -16233,7 +16233,7 @@ "tolerance": 5.3837041007541454e-11, "status": "pass", "note": "8990 two-site updates at bond 1; truncation from its reported discarded weight", - "seconds": 0.074539869, + "seconds": 0.017562523, "accuracy": { "class": "exact", "max_bond": 64, @@ -16249,7 +16249,7 @@ "tolerance": 7.408057974723756e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.223668607, + "seconds": 0.093128472, "accuracy": { "class": "exact" } @@ -16262,7 +16262,7 @@ "tolerance": 7.557546801821243e-12, "status": "pass", "note": "1262 two-site updates at bond 1, and 0 truncations, from its log", - "seconds": 0.002594282 + "seconds": 0.002753225 }, { "entry": "mps_qft_n30", @@ -16272,7 +16272,7 @@ "tolerance": 2.3363704100754143e-10, "status": "pass", "note": "8990 two-site updates at bond 1; its cutoff drops at most 1e-28 of weight at each", - "seconds": 1.7005217052064836 + "seconds": 1.27338236104697 }, { "entry": "mps_qft_n30", @@ -16282,7 +16282,7 @@ "tolerance": 7.408057974723756e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 1.1002529349643737 + "seconds": 0.8345614988356829 }, { "entry": "mps_qft_n40", @@ -16292,7 +16292,7 @@ "tolerance": 1.2767583029650018e-10, "status": "pass", "note": "21320 two-site updates at bond 1; truncation from its reported discarded weight", - "seconds": 0.040195412, + "seconds": 0.098822005, "accuracy": { "class": "exact", "max_bond": 64, @@ -16308,7 +16308,7 @@ "tolerance": 1.2675384367404737e-12, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.695740481, + "seconds": 0.388037845, "accuracy": { "class": "exact" } @@ -16321,7 +16321,7 @@ "tolerance": 1.3665865136181795e-11, "status": "pass", "note": "2282 two-site updates at bond 1, and 0 truncations, from its log", - "seconds": 0.008916719 + "seconds": 0.005938618 }, { "entry": "mps_qft_n40", @@ -16331,7 +16331,7 @@ "tolerance": 5.540758302965001e-10, "status": "pass", "note": "21320 two-site updates at bond 1; its cutoff drops at most 1e-28 of weight at each", - "seconds": 2.8177807428874075 + "seconds": 2.0974860701244324 }, { "entry": "mps_qft_n40", @@ -16341,7 +16341,7 @@ "tolerance": 1.2675384367404737e-12, "status": "pass", "note": "contraction of width 1.0", - "seconds": 1.4904490779154003 + "seconds": 1.4966158489696681 }, { "entry": "mps_qft_n30_bond256", @@ -16351,7 +16351,7 @@ "tolerance": 5.3837041007541454e-11, "status": "pass", "note": "8990 two-site updates at bond 1; truncation from its reported discarded weight", - "seconds": 0.009075378, + "seconds": 0.006104671, "accuracy": { "class": "exact", "max_bond": 256, @@ -16535,7 +16535,7 @@ "tolerance": 1.964309233906341e-12, "status": "pass", "note": "118 two-site updates at bond 4; truncation from its reported discarded weight", - "seconds": 0.0030908, + "seconds": 0.005172529, "accuracy": { "class": "exact", "max_bond": 64, @@ -16551,7 +16551,7 @@ "tolerance": 3.563571497430284e-09, "status": "pass", "note": "contraction of width 10.9", - "seconds": 0.470623066, + "seconds": 0.73703862, "accuracy": { "class": "exact" } @@ -16564,7 +16564,7 @@ "tolerance": 1.964309233906341e-12, "status": "pass", "note": "118 two-site updates at bond 4, and 0 truncations, from its log", - "seconds": 0.000631483 + "seconds": 0.000990643 }, { "entry": "tn_mirror_n40", @@ -16574,7 +16574,7 @@ "tolerance": 3.066648591607605e-12, "status": "pass", "note": "118 two-site updates at bond 1; its cutoff drops at most 1e-28 of weight at each", - "seconds": 0.6114467910956591 + "seconds": 0.8856923740822822 }, { "entry": "tn_mirror_n40", @@ -16584,7 +16584,7 @@ "tolerance": 5.605336642470576e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.7165519050322473 + "seconds": 1.151137094013393 }, { "entry": "bit_order_named_bits", @@ -16755,7 +16755,7 @@ "entry": "ghz_counts_n8", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.37611534349442094, + "measured": 0.08204476855638104, "tolerance": 1.0, "status": "pass" }, @@ -16763,7 +16763,7 @@ "entry": "ghz_counts_n8", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.008159999999999945, + "measured": 0.0017799999999999483, "tolerance": 0.02217450161929334, "status": "pass" }, @@ -16870,7 +16870,7 @@ "entry": "qft_counts_n8", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.4080160611981226, + "measured": 0.400436815479272, "tolerance": 1.0, "status": "pass" }, @@ -16878,7 +16878,7 @@ "entry": "qft_counts_n8", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.027339999999999996, + "measured": 0.028102499999999992, "tolerance": 0.04479339348223444, "status": "pass" }, @@ -16952,7 +16952,7 @@ "entry": "grover_counts_n5", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.12424073859545777, + "measured": 0.20547373810892686, "tolerance": 1.0, "status": "pass" }, @@ -16960,7 +16960,7 @@ "entry": "grover_counts_n5", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.0004240613746642782, + "measured": 0.00040869246125225546, "tolerance": 0.03012634777731961, "status": "pass" }, @@ -17034,7 +17034,7 @@ "entry": "rotations_counts_n6", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.3595111520927314, + "measured": 0.25061360099351476, "tolerance": 1.0, "status": "pass" }, @@ -17042,7 +17042,7 @@ "entry": "rotations_counts_n6", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.011398388775943253, + "measured": 0.010505537121383541, "tolerance": 0.025992412604050198, "status": "pass" }, @@ -17116,7 +17116,7 @@ "entry": "teleport", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.18874762938510276, + "measured": 0.29762652926120947, "tolerance": 1.0, "status": "pass" }, @@ -17124,7 +17124,7 @@ "entry": "teleport", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.003203679899192402, + "measured": 0.006150000000000014, "tolerance": 0.016954146745431286, "status": "pass" }, @@ -17182,7 +17182,7 @@ "entry": "reset_after_superposition", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.29499242627013406, + "measured": 0.01751517530978921, "tolerance": 1.0, "status": "pass" }, @@ -17190,7 +17190,7 @@ "entry": "reset_after_superposition", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.006399999999999961, + "measured": 0.00038000000000004697, "tolerance": 0.02217450161929334, "status": "pass" }, @@ -17284,14 +17284,14 @@ "measured": 46.092566604708445, "tolerance": 1.0, "status": "known", - "note": "10: 49867 shots, probability 0; 11: 0 shots, expected 50000.0 \u00b1 1084.8 | known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2.", + "note": "10: 50067 shots, probability 0; 11: 0 shots, expected 50000.0 \u00b1 1084.8 | known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2.", "right": "the exact reference: a second measurement of a qubit in the same basis repeats the first, so only 00 and 11 occur. Every other engine that ran this program met it (the results files)." }, { "entry": "measure_twice", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 1.0, + "measured": 1.00134, "tolerance": 0.02217450161929334, "status": "known", "note": "known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2.", @@ -17384,7 +17384,7 @@ "entry": "feedback_flip", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.04701441793680262, + "measured": 0.17607360442998626, "tolerance": 1.0, "status": "pass" }, @@ -17392,7 +17392,7 @@ "entry": "feedback_flip", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.0010200000000000209, + "measured": 0.00381999999999999, "tolerance": 0.02217450161929334, "status": "pass" }, @@ -17483,7 +17483,7 @@ "entry": "ghz_by_fusion", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.14673271672136112, + "measured": 0.1360999111618422, "tolerance": 1.0, "status": "pass" }, @@ -17491,7 +17491,7 @@ "entry": "ghz_by_fusion", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.0039000000000000146, + "measured": 0.0033800000000000496, "tolerance": 0.022791103731202682, "status": "pass" }, @@ -17612,8 +17612,8 @@ 219 ], "seconds": [ - 0.000374488, - 0.000481409952044487 + 0.000572012, + 0.0006277470383793116 ] }, { @@ -17658,8 +17658,8 @@ 1677 ], "seconds": [ - 0.001833124, - 0.003130214987322688 + 0.003358129, + 0.00474961893633008 ] }, { @@ -17704,8 +17704,8 @@ 5471 ], "seconds": [ - 0.005331033, - 0.011313447030261159 + 0.010661526, + 0.013134270906448364 ] }, { @@ -17750,8 +17750,8 @@ 12705 ], "seconds": [ - 0.011665603, - 0.023817474953830242 + 0.028993583, + 0.036961546866223216 ] }, { @@ -17796,8 +17796,8 @@ 24483 ], "seconds": [ - 0.041887519, - 0.047305366955697536 + 0.057554588, + 0.07804121891967952 ] }, { @@ -17842,8 +17842,8 @@ 66087 ], "seconds": [ - 0.10519866, - 0.14476526388898492 + 0.146920106, + 0.1627545019146055 ] }, { @@ -17888,8 +17888,8 @@ 221 ], "seconds": [ - 0.000382402, - 0.0005062969867140055 + 0.000382563, + 0.00044700480066239834 ] }, { @@ -17926,8 +17926,8 @@ 1679 ], "seconds": [ - 0.001848242, - 0.0032210659701377153 + 0.002812016, + 0.004489457933232188 ] }, { @@ -17964,8 +17964,8 @@ 5473 ], "seconds": [ - 0.005322888, - 0.010233757086098194 + 0.011311284, + 0.015677668852731586 ] }, { @@ -18002,8 +18002,8 @@ 423 ], "seconds": [ - 0.00057138, - 0.0007983287796378136 + 0.000998979, + 0.001291010994464159 ] }, { @@ -18040,8 +18040,8 @@ 3139 ], "seconds": [ - 0.003131017, - 0.005904216086491942 + 0.006629343, + 0.008975017117336392 ] }, { @@ -18078,8 +18078,8 @@ 21 ], "seconds": [ - 7.8498e-05, - 8.619297295808792e-05 + 0.000108816, + 0.0001162700355052948 ] }, { @@ -18116,8 +18116,8 @@ 225 ], "seconds": [ - 0.000464097, - 0.0006566110532730818 + 0.000458747, + 0.0006853060331195593 ] }, { @@ -18154,8 +18154,8 @@ 1825 ], "seconds": [ - 0.003280519, - 0.007462530862540007 + 0.004989282, + 0.010345948860049248 ] }, { @@ -18192,8 +18192,8 @@ 0 ], "seconds": [ - 5.283e-05, - 8.246512152254581e-05 + 6.2087e-05, + 8.22960864752531e-05 ] }, { @@ -18238,8 +18238,8 @@ 72 ], "seconds": [ - 0.000220216, - 0.00024213804863393307 + 0.000287183, + 0.0002572059165686369 ] }, { @@ -18268,8 +18268,8 @@ 1 ], "seconds": [ - 9.548e-06, - 4.1950028389692307e-05 + 6.532e-06, + 4.09269705414772e-05 ] }, { @@ -18298,8 +18298,8 @@ 2 ], "seconds": [ - 1.2554e-05, - 2.9044924303889275e-05 + 1.8134e-05, + 3.5236822441220284e-05 ] }, { @@ -18328,8 +18328,8 @@ 3 ], "seconds": [ - 2.4356e-05, - 5.516386590898037e-05 + 2.1481e-05, + 3.999494947493076e-05 ] }, { @@ -18358,8 +18358,8 @@ 1 ], "seconds": [ - 5.931e-06, - 3.490620292723179e-05 + 6.452e-06, + 3.414391539990902e-05 ] }, { @@ -18388,8 +18388,8 @@ 2 ], "seconds": [ - 1.8215e-05, - 3.3504096791148186e-05 + 2.1812e-05, + 4.080706275999546e-05 ] }, { @@ -18418,8 +18418,8 @@ 2 ], "seconds": [ - 1.9827e-05, - 3.3112941309809685e-05 + 1.8956e-05, + 3.827200271189213e-05 ] }, { @@ -18463,7 +18463,7 @@ "measured": 0.2304771050227863, "tolerance": 1.0, "status": "pass", - "seconds": 0.003615201 + "seconds": 0.004050197 }, { "entry": "surface_z_d3", @@ -18472,7 +18472,7 @@ "measured": 0.3592564596963066, "tolerance": 1.0, "status": "pass", - "seconds": 0.1075827251188457 + "seconds": 0.07694959500804543 }, { "entry": "surface_z_d5", @@ -18481,7 +18481,7 @@ "measured": 0.3987789919630123, "tolerance": 1.0, "status": "pass", - "seconds": 0.074976373 + "seconds": 0.091074638 }, { "entry": "surface_z_d5", @@ -18490,7 +18490,7 @@ "measured": 0.34883904623829703, "tolerance": 1.0, "status": "pass", - "seconds": 0.5974201168864965 + "seconds": 0.7251056500244886 }, { "entry": "surface_z_d7", @@ -18499,7 +18499,7 @@ "measured": 0.39835596383900373, "tolerance": 1.0, "status": "pass", - "seconds": 0.200314869 + "seconds": 0.243102982 }, { "entry": "surface_z_d7", @@ -18508,7 +18508,7 @@ "measured": 0.463022059775637, "tolerance": 1.0, "status": "pass", - "seconds": 2.7420738199725747 + "seconds": 3.3841843840200454 }, { "entry": "surface_z_d9", @@ -18517,7 +18517,7 @@ "measured": 0.4456060942390596, "tolerance": 1.0, "status": "pass", - "seconds": 0.445852029 + "seconds": 0.571808779 }, { "entry": "surface_z_d9", @@ -18526,7 +18526,7 @@ "measured": 0.49133700044087103, "tolerance": 1.0, "status": "pass", - "seconds": 5.983022558968514 + "seconds": 7.453695736126974 }, { "entry": "surface_z_d11", @@ -18535,7 +18535,7 @@ "measured": 0.4733064448042587, "tolerance": 1.0, "status": "pass", - "seconds": 0.816834926 + "seconds": 1.107420656 }, { "entry": "surface_z_d11", @@ -18544,7 +18544,7 @@ "measured": 0.494265729179998, "tolerance": 1.0, "status": "pass", - "seconds": 10.90659808809869 + "seconds": 12.671313090948388 }, { "entry": "surface_z_d15", @@ -18553,7 +18553,7 @@ "measured": 0.6057844326922145, "tolerance": 1.0, "status": "pass", - "seconds": 1.984449055 + "seconds": 2.041514554 }, { "entry": "surface_z_d15", @@ -18562,7 +18562,7 @@ "measured": 0.5310423100164744, "tolerance": 1.0, "status": "pass", - "seconds": 28.577561676036566 + "seconds": 31.782362492056563 }, { "entry": "surface_x_d3", @@ -18571,7 +18571,7 @@ "measured": 0.23096664789658297, "tolerance": 1.0, "status": "pass", - "seconds": 0.017592923 + "seconds": 0.016568994 }, { "entry": "surface_x_d3", @@ -18580,7 +18580,7 @@ "measured": 0.24836638793595103, "tolerance": 1.0, "status": "pass", - "seconds": 0.15404318599030375 + "seconds": 0.15703959786333144 }, { "entry": "surface_x_d5", @@ -18589,7 +18589,7 @@ "measured": 0.3987789919630123, "tolerance": 1.0, "status": "pass", - "seconds": 0.078944642 + "seconds": 0.139988101 }, { "entry": "surface_x_d5", @@ -18598,7 +18598,7 @@ "measured": 0.34883904623845396, "tolerance": 1.0, "status": "pass", - "seconds": 0.613441200228408 + "seconds": 0.8262862039264292 }, { "entry": "surface_x_d7", @@ -18607,7 +18607,7 @@ "measured": 0.39835596383900373, "tolerance": 1.0, "status": "pass", - "seconds": 0.204635163 + "seconds": 0.27716144 }, { "entry": "surface_x_d7", @@ -18616,7 +18616,7 @@ "measured": 0.4630220597752447, "tolerance": 1.0, "status": "pass", - "seconds": 2.6584641330409795 + "seconds": 3.4751031089108437 }, { "entry": "unrotated_z_d3", @@ -18625,7 +18625,7 @@ "measured": 0.44319045410204105, "tolerance": 1.0, "status": "pass", - "seconds": 0.031801932 + "seconds": 0.04556965 }, { "entry": "unrotated_z_d3", @@ -18634,7 +18634,7 @@ "measured": 0.29774037578775453, "tolerance": 1.0, "status": "pass", - "seconds": 0.16122648888267577 + "seconds": 0.2566289040260017 }, { "entry": "unrotated_z_d5", @@ -18643,7 +18643,7 @@ "measured": 0.3643716825843924, "tolerance": 1.0, "status": "pass", - "seconds": 0.170442994 + "seconds": 0.330153684 }, { "entry": "unrotated_z_d5", @@ -18652,7 +18652,7 @@ "measured": 0.3678447763016299, "tolerance": 1.0, "status": "pass", - "seconds": 1.6419036919251084 + "seconds": 2.1485130169894546 }, { "entry": "repetition_d3", @@ -18661,7 +18661,7 @@ "measured": 0.21696476647114454, "tolerance": 1.0, "status": "pass", - "seconds": 0.006531913 + "seconds": 0.009300783 }, { "entry": "repetition_d3", @@ -18670,7 +18670,7 @@ "measured": 0.16872752131474592, "tolerance": 1.0, "status": "pass", - "seconds": 0.12611794914118946 + "seconds": 0.1293325771111995 }, { "entry": "repetition_d9", @@ -18679,7 +18679,7 @@ "measured": 0.3716880031955475, "tolerance": 1.0, "status": "pass", - "seconds": 0.057521541 + "seconds": 0.082445856 }, { "entry": "repetition_d9", @@ -18688,7 +18688,7 @@ "measured": 0.3111734043866635, "tolerance": 1.0, "status": "pass", - "seconds": 0.34336660616099834 + "seconds": 0.3575381839182228 }, { "entry": "repetition_d25", @@ -18697,7 +18697,7 @@ "measured": 0.47629975805018154, "tolerance": 1.0, "status": "pass", - "seconds": 0.478221563 + "seconds": 0.503679038 }, { "entry": "repetition_d25", @@ -18706,7 +18706,7 @@ "measured": 0.42762159205521044, "tolerance": 1.0, "status": "pass", - "seconds": 5.078061601845548 + "seconds": 5.497613825136796 }, { "entry": "surface_z_d5_noiseless", @@ -18715,7 +18715,7 @@ "measured": 0.0, "tolerance": 1.0, "status": "pass", - "seconds": 0.002695083 + "seconds": 0.002809621 }, { "entry": "surface_z_d5_noiseless", @@ -18724,7 +18724,7 @@ "measured": 0.0, "tolerance": 1.0, "status": "pass", - "seconds": 0.13810348603874445 + "seconds": 0.1401000628247857 }, { "entry": "color_d3", @@ -18733,7 +18733,7 @@ "measured": 0.33316165193450636, "tolerance": 1.0, "status": "pass", - "seconds": 0.012118459 + "seconds": 0.013104544 }, { "entry": "color_d3", @@ -18742,7 +18742,7 @@ "measured": 0.1617011303366621, "tolerance": 1.0, "status": "pass", - "seconds": 0.1484940389636904 + "seconds": 0.1132697188295424 }, { "entry": "qec_inverted_and_tagged", @@ -18751,7 +18751,7 @@ "measured": 0.05174210467167158, "tolerance": 1.0, "status": "pass", - "seconds": 0.000399545 + "seconds": 0.000612157 }, { "entry": "qec_inverted_and_tagged", @@ -18760,7 +18760,7 @@ "measured": 0.2698980054494511, "tolerance": 1.0, "status": "pass", - "seconds": 0.06581712607294321 + "seconds": 0.13209326495416462 }, { "entry": "qec_measure_flip_noise", @@ -18769,7 +18769,7 @@ "measured": 0.16886264250373062, "tolerance": 1.0, "status": "pass", - "seconds": 0.000744827 + "seconds": 0.001246557 }, { "entry": "qec_measure_flip_noise", @@ -18778,7 +18778,7 @@ "measured": 0.17751966435281882, "tolerance": 1.0, "status": "pass", - "seconds": 0.05513338791206479 + "seconds": 0.13049713801592588 }, { "entry": "qec_depolarize_merge", @@ -18787,7 +18787,7 @@ "measured": 0.0989377295879301, "tolerance": 1.0, "status": "pass", - "seconds": 0.001355051 + "seconds": 0.001302843 }, { "entry": "qec_depolarize_merge", @@ -18796,7 +18796,7 @@ "measured": 0.10116104935395413, "tolerance": 1.0, "status": "pass", - "seconds": 0.11912886193022132 + "seconds": 0.1269107279367745 }, { "entry": "qec_pauli_observable", @@ -18805,7 +18805,7 @@ "measured": 0.21396059499360365, "tolerance": 1.0, "status": "pass", - "seconds": 0.000340002 + "seconds": 0.000560159 }, { "entry": "qec_pauli_observable", @@ -18814,7 +18814,7 @@ "measured": 0.07551550411540674, "tolerance": 1.0, "status": "pass", - "seconds": 0.0589367151260376 + "seconds": 0.0786837839987129 }, { "entry": "qec_correlated", @@ -18823,7 +18823,7 @@ "measured": 0.11269506781951577, "tolerance": 1.0, "status": "pass", - "seconds": 0.000676118 + "seconds": 0.001202594 }, { "entry": "qec_correlated", @@ -18832,7 +18832,7 @@ "measured": 0.08477062623592344, "tolerance": 1.0, "status": "pass", - "seconds": 0.11061062617227435 + "seconds": 0.13995271385647357 }, { "entry": "qec_pauli_channel", @@ -18841,7 +18841,7 @@ "measured": 0.08546188592769022, "tolerance": 1.0, "status": "pass", - "seconds": 0.001533918 + "seconds": 0.002666041 }, { "entry": "qec_pauli_channel", @@ -18850,7 +18850,7 @@ "measured": 0.11640046230839035, "tolerance": 1.0, "status": "pass", - "seconds": 0.12030320195481181 + "seconds": 0.11171974893659353 }, { "entry": "measure_twice", diff --git a/wai/quantum-cross-simulator/results/conformance-macos-arm64.json b/wai/quantum-cross-simulator/results/conformance-macos-arm64.json index 87a4d4d1d..d350a4174 100644 --- a/wai/quantum-cross-simulator/results/conformance-macos-arm64.json +++ b/wai/quantum-cross-simulator/results/conformance-macos-arm64.json @@ -11,9 +11,9 @@ "os": "macOS 27.2", "logical_cpus": 32, "load_average": [ - 122.14794921875, - 108.67236328125, - 99.5634765625 + 26.8955078125, + 59.8603515625, + 73.7744140625 ] }, "versions": { @@ -31,9 +31,9 @@ }, "engine_under_test": { "driver": "cross_simulator", - "build": "wai/wai-quantum 0cd14ae3d7845da8d8a1782565781b8a54bb141b, wai/wai-quantum-qpu c1031872aac2c4d2bcf134af80b9dc454954a2de, wai/wai-quantum-cli d3407ee21f3de60a94f4aad561c3dd5c94d47905, wai/quantum-cross-simulator/tools 4f8a83407e5d84edb64017508ab2833879a58bec, wai/quantum-cross-simulator/corpus 1bac9494b3e2e021b99e84fb39b0b046cc970198; rustc 1.99.1 (58cf8f9c3 2026-10-13)" + "build": "wai/wai-quantum 9e64fd1f2b4999ac354c41f5c81ebf04fd8f0269, wai/wai-quantum-qpu 6c2ad362552acb790e81959369680cff5f6fe038, wai/wai-quantum-cli d9d32f1cd4d67f83f58a248ea83d92a6f14cc51f, wai/quantum-cross-simulator/tools 137bbf3854af843e597329bee150489d80f6a93d, wai/quantum-cross-simulator/corpus c648944451c6bc843d5645a384e396324fb617cd; rustc 1.99.1 (58cf8f9c3 2026-10-13)" }, - "seconds": 2316.4, + "seconds": 2092.6, "summary": { "pass": 1743, "refused": 10, @@ -103,7 +103,7 @@ "note": "double precision, fusion width 3", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.000109792 + "seconds": 0.000102167 }, { "entry": "bit_order_x_low", @@ -115,7 +115,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 6.5209e-05 + "seconds": 0.000895292 }, { "entry": "bit_order_x_low", @@ -127,7 +127,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 9.775e-05, + "seconds": 8.0833e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -142,7 +142,7 @@ "note": "double precision, gate by gate", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.5283181250561029 + "seconds": 1.2724548330297694 }, { "entry": "bit_order_x_low", @@ -154,7 +154,7 @@ "note": "double precision, a contraction of width 5.0", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0019908329704776406 + "seconds": 0.002450832980684936 }, { "entry": "bit_order_x_low", @@ -166,7 +166,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.005292000016197562 + "seconds": 0.03037991700693965 }, { "entry": "bit_order_x_low", @@ -178,7 +178,7 @@ "note": "single precision, fusion width 2", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.00212508300319314 + "seconds": 0.005590916029177606 }, { "entry": "bit_order_x_low", @@ -195,7 +195,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 2.3957923986017704e-05 + "seconds": 0.0003566249506548047 }, { "entry": "bit_order_x_low", @@ -204,7 +204,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 2.2042e-05 + "seconds": 1.2042e-05 }, { "entry": "bit_order_x_low", @@ -221,7 +221,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 6.4959e-05 + "seconds": 0.000127125 }, { "entry": "bit_order_x_low", @@ -277,7 +277,7 @@ "note": "double precision, fusion width 3", "strict": 0.0, "global_phase": 0.0, - "seconds": 2.1958e-05 + "seconds": 1.25e-05 }, { "entry": "bit_order_x_high", @@ -289,7 +289,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 8.6917e-05 + "seconds": 6.1125e-05 }, { "entry": "bit_order_x_high", @@ -301,7 +301,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 8.425e-05, + "seconds": 6.9541e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -316,7 +316,7 @@ "note": "double precision, gate by gate", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.582494999980554 + "seconds": 0.5520729579729959 }, { "entry": "bit_order_x_high", @@ -328,7 +328,7 @@ "note": "double precision, a contraction of width 5.0", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0014127499889582396 + "seconds": 0.0010776659473776817 }, { "entry": "bit_order_x_high", @@ -340,7 +340,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.005813209107145667 + "seconds": 0.005311832996085286 }, { "entry": "bit_order_x_high", @@ -352,7 +352,7 @@ "note": "single precision, fusion width 2", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0016896669985726476 + "seconds": 0.0016571659361943603 }, { "entry": "bit_order_x_high", @@ -369,7 +369,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 2.2833002731204033e-05 + "seconds": 2.0292005501687527e-05 }, { "entry": "bit_order_x_high", @@ -378,7 +378,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 3.667e-06 + "seconds": 2.125e-06 }, { "entry": "bit_order_x_high", @@ -395,7 +395,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 7.2375e-05 + "seconds": 5.8166e-05 }, { "entry": "bit_order_x_high", @@ -451,7 +451,7 @@ "note": "double precision, fusion width 3", "strict": 2.853028722211445e-16, "global_phase": -5.504485103160786e-17, - "seconds": 3.3208e-05 + "seconds": 2.5917e-05 }, { "entry": "bit_order_product", @@ -463,7 +463,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.7214193512736154e-16, "global_phase": -7.54854054484019e-17, - "seconds": 8.8625e-05 + "seconds": 0.00038225 }, { "entry": "bit_order_product", @@ -475,7 +475,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.7214193512736154e-16, "global_phase": -7.54854054484019e-17, - "seconds": 8.5417e-05, + "seconds": 9.0958e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -490,7 +490,7 @@ "note": "double precision, gate by gate", "strict": 3.964222321740644e-16, "global_phase": -3.4093253995171833e-17, - "seconds": 0.5338773750700057 + "seconds": 0.5094864999409765 }, { "entry": "bit_order_product", @@ -502,7 +502,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 2.773703885184681e-16, "global_phase": -5.510528309801803e-17, - "seconds": 0.0016217919765040278 + "seconds": 0.0016322910087183118 }, { "entry": "bit_order_product", @@ -514,7 +514,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.011275315895486e-17, "global_phase": 9.959077994004481e-18, - "seconds": 0.006192459026351571 + "seconds": 0.005283833015710115 }, { "entry": "bit_order_product", @@ -526,7 +526,7 @@ "note": "single precision, fusion width 2", "strict": 1.8082357865143764e-07, "global_phase": -7.827618484916611e-09, - "seconds": 0.0018974998965859413 + "seconds": 0.0018136670114472508 }, { "entry": "bit_order_product", @@ -582,7 +582,7 @@ "note": "double precision, fusion width 3", "strict": 0.0, "global_phase": 0.0, - "seconds": 2.05e-05 + "seconds": 1.35e-05 }, { "entry": "bit_order_control", @@ -594,7 +594,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 6.5167e-05 + "seconds": 6.4958e-05 }, { "entry": "bit_order_control", @@ -606,7 +606,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 7.5417e-05, + "seconds": 6.8209e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -621,7 +621,7 @@ "note": "double precision, gate by gate", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.5522822909988463 + "seconds": 0.5971098749432713 }, { "entry": "bit_order_control", @@ -633,7 +633,7 @@ "note": "double precision, a contraction of width 4.0", "strict": 3.3306690738754696e-16, "global_phase": 0.0, - "seconds": 0.0015270001022145152 + "seconds": 0.0014071250334382057 }, { "entry": "bit_order_control", @@ -645,7 +645,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.005978291970677674 + "seconds": 0.009499917039647698 }, { "entry": "bit_order_control", @@ -657,7 +657,7 @@ "note": "single precision, fusion width 2", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.001998292049393058 + "seconds": 0.001700707944110036 }, { "entry": "bit_order_control", @@ -674,7 +674,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 2.5084009394049644e-05 + "seconds": 0.00019333302043378353 }, { "entry": "bit_order_control", @@ -683,7 +683,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 4e-06 + "seconds": 2.5e-06 }, { "entry": "bit_order_control", @@ -700,7 +700,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 6.0333e-05 + "seconds": 6.4208e-05 }, { "entry": "bit_order_control", @@ -756,7 +756,7 @@ "note": "double precision, fusion width 3", "strict": 0.0, "global_phase": 0.0, - "seconds": 5.83e-07 + "seconds": 8.3e-08 }, { "entry": "empty_register", @@ -768,7 +768,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 6.9709e-05 + "seconds": 6.6167e-05 }, { "entry": "empty_register", @@ -780,7 +780,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 0.0, "global_phase": 0.0, - "seconds": 7.2458e-05, + "seconds": 5.7208e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -795,7 +795,7 @@ "note": "double precision, gate by gate", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.5421683751046658 + "seconds": 0.6821287089260295 }, { "entry": "empty_register", @@ -807,7 +807,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.0010393329430371523 + "seconds": 0.0008486249716952443 }, { "entry": "empty_register", @@ -819,7 +819,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.005209457944147289 + "seconds": 0.011510250042192638 }, { "entry": "empty_register", @@ -831,7 +831,7 @@ "note": "single precision, fusion width 2", "strict": 0.0, "global_phase": 0.0, - "seconds": 0.002238291082903743 + "seconds": 0.0020651250379160047 }, { "entry": "empty_register", @@ -848,7 +848,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 2.662499900907278e-05 + "seconds": 6.620900239795446e-05 }, { "entry": "empty_register", @@ -857,7 +857,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 1.917e-06 + "seconds": 2.584e-06 }, { "entry": "empty_register", @@ -874,7 +874,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 5.5917e-05 + "seconds": 5.6959e-05 }, { "entry": "empty_register", @@ -930,7 +930,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 1.4792e-05 + "seconds": 1.6292e-05 }, { "entry": "one_qubit", @@ -942,7 +942,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 6.8125e-05 + "seconds": 0.000116875 }, { "entry": "one_qubit", @@ -954,7 +954,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 9.2125e-05, + "seconds": 0.00016425, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -969,7 +969,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.6267081249970943 + "seconds": 0.6644514170475304 }, { "entry": "one_qubit", @@ -981,7 +981,7 @@ "note": "double precision, a contraction of width 1.0", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.0005899999523535371 + "seconds": 0.0012067909119650722 }, { "entry": "one_qubit", @@ -993,7 +993,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.009133915998972952 + "seconds": 0.015370958019047976 }, { "entry": "one_qubit", @@ -1005,7 +1005,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0018729170551523566 + "seconds": 0.0023275839630514383 }, { "entry": "one_qubit", @@ -1022,7 +1022,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 3.3832970075309277e-05 + "seconds": 1.979200169444084e-05 }, { "entry": "one_qubit", @@ -1031,7 +1031,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 3.208e-06 + "seconds": 2.125e-06 }, { "entry": "one_qubit", @@ -1048,7 +1048,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 6.1042e-05 + "seconds": 6.7291e-05 }, { "entry": "one_qubit", @@ -1232,7 +1232,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 3.0833e-05 + "seconds": 1.5083e-05 }, { "entry": "ghz_n2", @@ -1244,7 +1244,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 7.1667e-05 + "seconds": 7.8083e-05 }, { "entry": "ghz_n2", @@ -1256,7 +1256,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 8.5e-05, + "seconds": 7.6333e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1271,7 +1271,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.6229680830147117 + "seconds": 0.6777353340294212 }, { "entry": "ghz_n2", @@ -1283,7 +1283,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 4.026696510285133e-16, "global_phase": 0.0, - "seconds": 0.0007222499698400497 + "seconds": 0.0006837910041213036 }, { "entry": "ghz_n2", @@ -1295,7 +1295,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.005574541981332004 + "seconds": 0.006391291972249746 }, { "entry": "ghz_n2", @@ -1307,7 +1307,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.00212658301461488 + "seconds": 0.0017528330208733678 }, { "entry": "ghz_n2", @@ -1371,7 +1371,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 2.1083e-05 + "seconds": 1.8333e-05 }, { "entry": "ghz_n3", @@ -1383,7 +1383,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 7.6583e-05 + "seconds": 9.5875e-05 }, { "entry": "ghz_n3", @@ -1395,7 +1395,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 8.3584e-05, + "seconds": 0.000133083, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1410,7 +1410,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.5732722498942167 + "seconds": 0.6321267500752583 }, { "entry": "ghz_n3", @@ -1422,7 +1422,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 7.166881427652682e-16, "global_phase": 0.0, - "seconds": 0.0010339999571442604 + "seconds": 0.000982958939857781 }, { "entry": "ghz_n3", @@ -1434,7 +1434,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.005886708968318999 + "seconds": 0.009034749935381114 }, { "entry": "ghz_n3", @@ -1446,7 +1446,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0017849169671535492 + "seconds": 0.0018633330473676324 }, { "entry": "ghz_n3", @@ -1510,7 +1510,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 3.1125e-05 + "seconds": 2.5208e-05 }, { "entry": "ghz_n5", @@ -1522,7 +1522,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 8.1708e-05 + "seconds": 0.000133542 }, { "entry": "ghz_n5", @@ -1534,7 +1534,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000106625, + "seconds": 8.5541e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1549,7 +1549,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.568273082957603 + "seconds": 0.6228610839461908 }, { "entry": "ghz_n5", @@ -1561,7 +1561,7 @@ "note": "double precision, a contraction of width 5.0", "strict": 1.1877158803704008e-15, "global_phase": 0.0, - "seconds": 0.00209199998062104 + "seconds": 0.0019512079888954759 }, { "entry": "ghz_n5", @@ -1573,7 +1573,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.005659832968376577 + "seconds": 0.010086958995088935 }, { "entry": "ghz_n5", @@ -1585,7 +1585,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0019978330237790942 + "seconds": 0.002714957925491035 }, { "entry": "ghz_n5", @@ -1649,7 +1649,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 3.7125e-05 + "seconds": 3.4583e-05 }, { "entry": "ghz_n8", @@ -1661,7 +1661,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 8.7791e-05 + "seconds": 0.000152541 }, { "entry": "ghz_n8", @@ -1673,7 +1673,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000102375, + "seconds": 8.9125e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1688,7 +1688,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.5598747920012102 + "seconds": 0.5963870000559837 }, { "entry": "ghz_n8", @@ -1700,7 +1700,7 @@ "note": "double precision, a contraction of width 8.0", "strict": 2.757808339054176e-15, "global_phase": 0.0, - "seconds": 0.0026188750052824616 + "seconds": 0.003984584007412195 }, { "entry": "ghz_n8", @@ -1712,7 +1712,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.0055234580067917705 + "seconds": 0.007234541000798345 }, { "entry": "ghz_n8", @@ -1724,7 +1724,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.0016756670083850622 + "seconds": 0.0022514580050483346 }, { "entry": "ghz_n8", @@ -1788,7 +1788,7 @@ "note": "double precision, fusion width 3", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.00015875 + "seconds": 0.000149958 }, { "entry": "ghz_n12", @@ -1800,7 +1800,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 9.9583e-05 + "seconds": 0.000123542 }, { "entry": "ghz_n12", @@ -1812,7 +1812,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.9157615060679e-17, "global_phase": 0.0, - "seconds": 0.000105791, + "seconds": 0.000105667, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1827,7 +1827,7 @@ "note": "double precision, gate by gate", "strict": 8.865115929175827e-17, "global_phase": 0.0, - "seconds": 0.551976791000925 + "seconds": 0.5795155829982832 }, { "entry": "ghz_n12", @@ -1839,7 +1839,7 @@ "note": "double precision, a contraction of width 12.0", "strict": 3.071826830790931e-15, "global_phase": 0.0, - "seconds": 0.005573874921537936 + "seconds": 0.0056274160742759705 }, { "entry": "ghz_n12", @@ -1851,7 +1851,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.835808657661923e-17, "global_phase": 0.0, - "seconds": 0.005518916994333267 + "seconds": 0.006806833087466657 }, { "entry": "ghz_n12", @@ -1863,7 +1863,7 @@ "note": "single precision, fusion width 2", "strict": 1.7114271035800384e-08, "global_phase": 0.0, - "seconds": 0.002095207921229303 + "seconds": 0.002230999991297722 }, { "entry": "ghz_n12", @@ -1927,7 +1927,7 @@ "note": "double precision, fusion width 3", "strict": 2.257974101246671e-16, "global_phase": 1.5308084989341915e-17, - "seconds": 3.0708e-05 + "seconds": 4.8834e-05 }, { "entry": "qft_n3_x5", @@ -1939,7 +1939,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.3884324549296737e-16, "global_phase": 3.806340515408302e-16, - "seconds": 8.5708e-05 + "seconds": 9.4458e-05 }, { "entry": "qft_n3_x5", @@ -1951,7 +1951,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.3884324549296737e-16, "global_phase": 3.806340515408302e-16, - "seconds": 0.000112834, + "seconds": 9.225e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -1966,7 +1966,7 @@ "note": "double precision, gate by gate", "strict": 2.6677932835798804e-16, "global_phase": 4.306366060497084e-17, - "seconds": 0.617375958012417 + "seconds": 0.5794969580601901 }, { "entry": "qft_n3_x5", @@ -1978,7 +1978,7 @@ "note": "double precision, a contraction of width 4.0", "strict": 1.139868629242718e-15, "global_phase": 9.45940395232614e-17, - "seconds": 0.0021312920143827796 + "seconds": 0.0020078750094398856 }, { "entry": "qft_n3_x5", @@ -1990,7 +1990,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.237121377012062e-16, "global_phase": 0.0, - "seconds": 0.005934457993134856 + "seconds": 0.006794541957788169 }, { "entry": "qft_n3_x5", @@ -2002,7 +2002,7 @@ "note": "single precision, fusion width 2", "strict": 3.268347795371965e-08, "global_phase": -1.8378428171781463e-08, - "seconds": 0.0024990420788526535 + "seconds": 0.0019206670112907887 }, { "entry": "qft_n3_x5", @@ -2066,7 +2066,7 @@ "note": "double precision, fusion width 3", "strict": 3.506724345492627e-16, "global_phase": 1.283897907660248e-16, - "seconds": 5.2458e-05 + "seconds": 4.575e-05 }, { "entry": "qft_n5_x19", @@ -2078,7 +2078,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.303815859586128e-16, "global_phase": 4.630671312859982e-16, - "seconds": 8.2667e-05 + "seconds": 8.3083e-05 }, { "entry": "qft_n5_x19", @@ -2090,7 +2090,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.303815859586128e-16, "global_phase": 4.630671312859982e-16, - "seconds": 8.6917e-05, + "seconds": 9.0791e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2105,7 +2105,7 @@ "note": "double precision, gate by gate", "strict": 5.057824840498477e-16, "global_phase": 1.4612721318054353e-16, - "seconds": 0.6702932080952451 + "seconds": 0.5543182078981772 }, { "entry": "qft_n5_x19", @@ -2117,7 +2117,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 3.568580925489774e-15, "global_phase": 8.068488653208091e-17, - "seconds": 0.09552408300805837 + "seconds": 0.09624054201412946 }, { "entry": "qft_n5_x19", @@ -2129,7 +2129,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.9241850975309797e-16, "global_phase": 4.6098944822979383e-17, - "seconds": 0.007966416073031723 + "seconds": 0.006334249977953732 }, { "entry": "qft_n5_x19", @@ -2141,7 +2141,7 @@ "note": "single precision, fusion width 2", "strict": 1.1451268568459642e-07, "global_phase": -9.183741409430032e-08, - "seconds": 0.0030155000276863575 + "seconds": 0.0019482920179143548 }, { "entry": "qft_n5_x19", @@ -2205,7 +2205,7 @@ "note": "double precision, fusion width 3", "strict": 8.320669916157845e-16, "global_phase": 3.306698650009266e-16, - "seconds": 8.7417e-05 + "seconds": 8.3917e-05 }, { "entry": "qft_n8_x173", @@ -2217,7 +2217,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.996490609257424e-16, "global_phase": 9.084158885110515e-16, - "seconds": 0.000110666 + "seconds": 9.9375e-05 }, { "entry": "qft_n8_x173", @@ -2229,7 +2229,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.996490609257424e-16, "global_phase": 9.084158885110515e-16, - "seconds": 0.000113041, + "seconds": 9.825e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2244,19 +2244,19 @@ "note": "double precision, gate by gate", "strict": 7.763478117220366e-16, "global_phase": 3.0372576170693494e-16, - "seconds": 0.5547251669922844 + "seconds": 0.5438018339918926 }, { "entry": "qft_n8_x173", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.0051664491917764e-14, + "measured": 9.848030529682785e-15, "tolerance": 5.472132013758785e-10, "status": "pass", "note": "double precision, a contraction of width 11.0", - "strict": 1.0053609958829422e-14, - "global_phase": 1.977729662864757e-16, - "seconds": 0.24192449997644871 + "strict": 9.848125769146424e-15, + "global_phase": -4.331109975139002e-17, + "seconds": 0.27633200003765523 }, { "entry": "qft_n8_x173", @@ -2268,7 +2268,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.6777798095682838e-16, "global_phase": 4.766451331749067e-17, - "seconds": 0.0058260830119252205 + "seconds": 0.00613179209176451 }, { "entry": "qft_n8_x173", @@ -2280,7 +2280,7 @@ "note": "single precision, fusion width 2", "strict": 2.0308642052851654e-07, "global_phase": -1.6779062518160655e-07, - "seconds": 0.002733458997681737 + "seconds": 0.0028070410480722785 }, { "entry": "qft_n8_x173", @@ -2344,7 +2344,7 @@ "note": "double precision, fusion width 3", "strict": 1.05735130271346e-15, "global_phase": 4.856407661367594e-16, - "seconds": 0.000605 + "seconds": 0.001414917 }, { "entry": "qft_n12_x2741", @@ -2356,7 +2356,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4235804381409074e-15, "global_phase": 1.3445091043436557e-15, - "seconds": 0.000311375 + "seconds": 0.000298375 }, { "entry": "qft_n12_x2741", @@ -2368,7 +2368,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4235804381409074e-15, "global_phase": 1.3445091043436557e-15, - "seconds": 0.000325958, + "seconds": 0.000297042, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2383,19 +2383,19 @@ "note": "double precision, gate by gate", "strict": 1.2719000340925913e-15, "global_phase": 4.81426406762063e-16, - "seconds": 0.540344416978769 + "seconds": 0.5937242090003565 }, { "entry": "qft_n12_x2741", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 8.070239452755685e-15, + "measured": 6.87323327670131e-15, "tolerance": 1.22787892058417e-05, "status": "pass", "note": "double precision, a contraction of width 20.0", - "strict": 8.08337988437695e-15, - "global_phase": 4.607228346148255e-16, - "seconds": 0.387097500031814 + "strict": 6.910350110378411e-15, + "global_phase": 7.152642672835587e-16, + "seconds": 0.5901354160159826 }, { "entry": "qft_n12_x2741", @@ -2407,7 +2407,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.468256033541478e-16, "global_phase": -1.0198722492404313e-18, - "seconds": 0.007495790952816606 + "seconds": 0.007201957982033491 }, { "entry": "qft_n12_x2741", @@ -2419,7 +2419,7 @@ "note": "single precision, fusion width 2", "strict": 3.14510201058313e-07, "global_phase": -2.6119155895849175e-07, - "seconds": 0.0027111669769510627 + "seconds": 0.006519375019706786 }, { "entry": "qft_n12_x2741", @@ -2483,7 +2483,7 @@ "note": "double precision, fusion width 3", "strict": 1.3611349762871244e-15, "global_phase": 5.292345204732061e-16, - "seconds": 0.00283725 + "seconds": 0.003609833 }, { "entry": "qft_n14_x10923", @@ -2495,7 +2495,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4337352821423908e-15, "global_phase": 1.310803683777888e-15, - "seconds": 0.001199666 + "seconds": 0.001168333 }, { "entry": "qft_n14_x10923", @@ -2507,7 +2507,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4337352821423908e-15, "global_phase": 1.310803683777888e-15, - "seconds": 0.001171334, + "seconds": 0.00278575, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2522,7 +2522,7 @@ "note": "double precision, gate by gate", "strict": 1.4189542437976667e-15, "global_phase": 4.717268824830606e-16, - "seconds": 0.5607975419843569 + "seconds": 0.6244191660080105 }, { "entry": "qft_n14_x10923", @@ -2534,7 +2534,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.017553738362537e-16, "global_phase": -1.617385543496028e-16, - "seconds": 0.00870245904661715 + "seconds": 0.01401091692969203 }, { "entry": "qft_n14_x10923", @@ -2546,7 +2546,7 @@ "note": "single precision, fusion width 2", "strict": 3.536286417090728e-07, "global_phase": -2.9389127543731344e-07, - "seconds": 0.004972334019839764 + "seconds": 0.005183667060919106 }, { "entry": "qft_n14_x10923", @@ -2602,7 +2602,7 @@ "note": "double precision, fusion width 3", "strict": 1.101391650619332e-15, "global_phase": 1.9797940426470196e-16, - "seconds": 0.000230458 + "seconds": 0.000492584 }, { "entry": "qft_superposed_n10", @@ -2614,7 +2614,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0602512121224904e-15, "global_phase": 9.256274969002942e-16, - "seconds": 0.00016825 + "seconds": 0.000203625 }, { "entry": "qft_superposed_n10", @@ -2626,7 +2626,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0602512121224904e-15, "global_phase": 9.256274969002942e-16, - "seconds": 0.0001695, + "seconds": 0.000202708, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2641,19 +2641,19 @@ "note": "double precision, gate by gate", "strict": 1.279828475104203e-15, "global_phase": 7.391904992106145e-17, - "seconds": 0.5638268750626594 + "seconds": 0.720531833008863 }, { "entry": "qft_superposed_n10", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 9.354519588303098e-15, + "measured": 9.363648828098785e-15, "tolerance": 5.015566805471182e-06, "status": "pass", "note": "double precision, a contraction of width 19.0", - "strict": 9.354877743079331e-15, - "global_phase": -8.18587809259666e-17, - "seconds": 0.40733466704841703 + "strict": 9.368605969253075e-15, + "global_phase": 3.0472681399675506e-16, + "seconds": 0.40823275002185255 }, { "entry": "qft_superposed_n10", @@ -2665,7 +2665,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.290631012079495e-15, "global_phase": -1.8423667354437054e-17, - "seconds": 0.008628415991552174 + "seconds": 0.008150374982506037 }, { "entry": "qft_superposed_n10", @@ -2677,7 +2677,7 @@ "note": "single precision, fusion width 2", "strict": 2.840131214670391e-07, "global_phase": -1.3011922087152788e-07, - "seconds": 0.0030975419795140624 + "seconds": 0.0026380419731140137 }, { "entry": "qft_superposed_n10", @@ -2909,7 +2909,7 @@ "note": "double precision, fusion width 3", "strict": 1.0198506246188093e-15, "global_phase": 0.0, - "seconds": 5.3416e-05 + "seconds": 4.275e-05 }, { "entry": "grover_n3", @@ -2921,7 +2921,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.82855567997045e-16, "global_phase": 7.11825952004399e-16, - "seconds": 8.4958e-05 + "seconds": 7.975e-05 }, { "entry": "grover_n3", @@ -2933,7 +2933,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.82855567997045e-16, "global_phase": 7.11825952004399e-16, - "seconds": 9.4625e-05, + "seconds": 8.675e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -2948,7 +2948,7 @@ "note": "double precision, gate by gate", "strict": 1.1870146619100088e-15, "global_phase": 0.0, - "seconds": 0.5469834579853341 + "seconds": 0.7021260830806568 }, { "entry": "grover_n3", @@ -2960,7 +2960,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 4.858767716474483e-16, "global_phase": 0.0, - "seconds": 0.003071167040616274 + "seconds": 0.0027789160376414657 }, { "entry": "grover_n3", @@ -2972,7 +2972,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.322204543158198e-16, "global_phase": 0.0, - "seconds": 0.005749042029492557 + "seconds": 0.00676575000397861 }, { "entry": "grover_n3", @@ -2984,7 +2984,7 @@ "note": "single precision, fusion width 2", "strict": 1.712509627811334e-07, "global_phase": 0.0, - "seconds": 0.002888916991651058 + "seconds": 0.003002458019182086 }, { "entry": "grover_n3", @@ -3048,7 +3048,7 @@ "note": "double precision, fusion width 3", "strict": 3.926196862092386e-15, "global_phase": 0.0, - "seconds": 0.000102791 + "seconds": 9.7542e-05 }, { "entry": "grover_n5", @@ -3060,7 +3060,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.554278208317962e-15, "global_phase": 3.3051253236443238e-15, - "seconds": 0.0001035 + "seconds": 0.00011075 }, { "entry": "grover_n5", @@ -3072,7 +3072,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.554278208317962e-15, "global_phase": 3.3051253236443238e-15, - "seconds": 0.000118291, + "seconds": 0.000126916, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3087,19 +3087,19 @@ "note": "double precision, gate by gate", "strict": 3.979364197199202e-15, "global_phase": 0.0, - "seconds": 0.5724205840379 + "seconds": 0.5981747910846025 }, { "entry": "grover_n5", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 5.805919923523377e-15, + "measured": 5.8085659328642904e-15, "tolerance": 1.9326685410829237e-11, "status": "pass", "note": "double precision, a contraction of width 7.0", - "strict": 5.805919923523377e-15, + "strict": 5.8085659328642904e-15, "global_phase": 0.0, - "seconds": 0.32043320895172656 + "seconds": 0.49242537491954863 }, { "entry": "grover_n5", @@ -3111,7 +3111,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.063150391861205e-17, "global_phase": 0.0, - "seconds": 0.009067291975952685 + "seconds": 0.006217499962076545 }, { "entry": "grover_n5", @@ -3123,7 +3123,7 @@ "note": "single precision, fusion width 2", "strict": 1.1936071641818266e-07, "global_phase": 0.0, - "seconds": 0.0032502090325579047 + "seconds": 0.00277495791669935 }, { "entry": "grover_n5", @@ -3187,7 +3187,7 @@ "note": "double precision, fusion width 3", "strict": 1.6055183209665808e-14, "global_phase": 0.0, - "seconds": 0.000374833 + "seconds": 0.000367333 }, { "entry": "grover_n8", @@ -3199,7 +3199,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3818998850279718e-14, "global_phase": 1.3333198341892727e-14, - "seconds": 0.000328459 + "seconds": 0.000391792 }, { "entry": "grover_n8", @@ -3211,7 +3211,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3818998850279718e-14, "global_phase": 1.3333198341892727e-14, - "seconds": 0.0003385, + "seconds": 0.000327417, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3226,19 +3226,19 @@ "note": "double precision, gate by gate", "strict": 1.8051945192911557e-14, "global_phase": 0.0, - "seconds": 0.565311708021909 + "seconds": 0.6195897919824347 }, { "entry": "grover_n8", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 7.056334953387505e-14, + "measured": 7.313248445299498e-14, "tolerance": 1.4460064500364516e-08, "status": "pass", "note": "double precision, a contraction of width 12.0", - "strict": 7.056334953387505e-14, + "strict": 7.313248445299498e-14, "global_phase": 0.0, - "seconds": 0.6392848340328783 + "seconds": 1.0705279170069844 }, { "entry": "grover_n8", @@ -3250,7 +3250,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.0522346859459808e-15, "global_phase": 0.0, - "seconds": 0.006883416906930506 + "seconds": 0.007999791065230966 }, { "entry": "grover_n8", @@ -3262,7 +3262,7 @@ "note": "single precision, fusion width 2", "strict": 3.865674201535373e-07, "global_phase": 0.0, - "seconds": 0.005863834056071937 + "seconds": 0.08314812509343028 }, { "entry": "grover_n8", @@ -3326,7 +3326,7 @@ "note": "double precision, fusion width 3", "strict": 3.7861950351453296e-14, "global_phase": 0.0, - "seconds": 0.001538916 + "seconds": 0.002843167 }, { "entry": "grover_n10", @@ -3338,7 +3338,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.3673609522423125e-14, "global_phase": 3.2463955134398285e-14, - "seconds": 0.001879042 + "seconds": 0.001854166 }, { "entry": "grover_n10", @@ -3350,7 +3350,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.3673609522423125e-14, "global_phase": 3.2463955134398285e-14, - "seconds": 0.001859792, + "seconds": 0.001870833, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3365,19 +3365,19 @@ "note": "double precision, gate by gate", "strict": 4.53350780910714e-14, "global_phase": 0.0, - "seconds": 0.7103973750490695 + "seconds": 1.0090170409530401 }, { "entry": "grover_n10", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.5166794665845023e-13, + "measured": 1.3026389894527845e-13, "tolerance": 1.892533604466189e-05, "status": "pass", "note": "double precision, a contraction of width 18.0", - "strict": 1.5166794665845023e-13, + "strict": 1.3026389894527845e-13, "global_phase": 0.0, - "seconds": 2.696010999963619 + "seconds": 5.413727040984668 }, { "entry": "grover_n10", @@ -3389,7 +3389,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.2520782731179646e-15, "global_phase": 0.0, - "seconds": 0.009646791964769363 + "seconds": 0.026033334084786475 }, { "entry": "grover_n10", @@ -3401,7 +3401,7 @@ "note": "single precision, fusion width 2", "strict": 2.156421069340362e-07, "global_phase": 0.0, - "seconds": 0.014685875037685037 + "seconds": 0.06348679098300636 }, { "entry": "grover_n10", @@ -3465,7 +3465,7 @@ "note": "double precision, fusion width 3", "strict": 8.969588494495959e-16, "global_phase": 1.2447490626286985e-17, - "seconds": 4.6e-05 + "seconds": 3.7875e-05 }, { "entry": "qpe_t4_m5", @@ -3477,7 +3477,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.950557577583702e-16, "global_phase": 3.063604932067729e-16, - "seconds": 7.4417e-05 + "seconds": 8.625e-05 }, { "entry": "qpe_t4_m5", @@ -3489,7 +3489,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.950557577583702e-16, "global_phase": 3.063604932067729e-16, - "seconds": 8.6375e-05, + "seconds": 8.4375e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3504,7 +3504,7 @@ "note": "double precision, gate by gate", "strict": 6.852031677756625e-16, "global_phase": 1.2445605710183747e-16, - "seconds": 0.6482857909286395 + "seconds": 0.587304332992062 }, { "entry": "qpe_t4_m5", @@ -3516,7 +3516,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 1.8188266366102144e-15, "global_phase": 2.6517275470752373e-16, - "seconds": 0.11949854192789644 + "seconds": 0.09705262491479516 }, { "entry": "qpe_t4_m5", @@ -3528,7 +3528,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.132622887710837e-76, "global_phase": 8.636168555094445e-78, - "seconds": 0.006969000096432865 + "seconds": 0.011602874961681664 }, { "entry": "qpe_t4_m5", @@ -3540,7 +3540,7 @@ "note": "single precision, fusion width 2", "strict": 1.4589360127265824e-07, "global_phase": -1.0572389186336255e-07, - "seconds": 0.001979999942705035 + "seconds": 0.0020473749609664083 }, { "entry": "qpe_t4_m5", @@ -3604,7 +3604,7 @@ "note": "double precision, fusion width 3", "strict": 1.4100014542159497e-15, "global_phase": -1.6968573694255317e-16, - "seconds": 0.000109458 + "seconds": 0.000214916 }, { "entry": "qpe_t8_m173", @@ -3616,7 +3616,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.356875146241596e-16, "global_phase": 4.823252008114053e-16, - "seconds": 0.000204833 + "seconds": 0.000108416 }, { "entry": "qpe_t8_m173", @@ -3628,7 +3628,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.356875146241596e-16, "global_phase": 4.823252008114053e-16, - "seconds": 0.0002065, + "seconds": 0.000260666, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3643,19 +3643,19 @@ "note": "double precision, gate by gate", "strict": 1.3854297339966442e-15, "global_phase": -7.787135774401854e-17, - "seconds": 0.6427957919659093 + "seconds": 0.5656271659536287 }, { "entry": "qpe_t8_m173", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 7.080278555538819e-15, + "measured": 7.275801262821439e-15, "tolerance": 1.5373360013432097e-08, "status": "pass", "note": "double precision, a contraction of width 14.0", - "strict": 7.081943279347782e-15, - "global_phase": 1.5354539353671653e-16, - "seconds": 0.5324358330108225 + "strict": 7.291085071348791e-15, + "global_phase": 4.718447854656949e-16, + "seconds": 0.41777141706552356 }, { "entry": "qpe_t8_m173", @@ -3667,7 +3667,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.607656667869935e-76, "global_phase": -1.727233711018889e-77, - "seconds": 0.007291291956789792 + "seconds": 0.005859208991751075 }, { "entry": "qpe_t8_m173", @@ -3679,7 +3679,7 @@ "note": "single precision, fusion width 2", "strict": 2.729623098522114e-07, "global_phase": -2.0760425911703052e-07, - "seconds": 0.0033354159677401185 + "seconds": 0.004950125003233552 }, { "entry": "qpe_t8_m173", @@ -3743,7 +3743,7 @@ "note": "double precision, fusion width 3", "strict": 1.882816968641882e-15, "global_phase": 3.7724122817685328e-16, - "seconds": 0.001133125 + "seconds": 0.002549791 }, { "entry": "qpe_t12_m2741", @@ -3755,7 +3755,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.839500472473385e-16, "global_phase": 5.640957091605201e-16, - "seconds": 0.0006505 + "seconds": 0.000664917 }, { "entry": "qpe_t12_m2741", @@ -3767,7 +3767,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4625597378806557e-15, "global_phase": 1.2545156525992895e-15, - "seconds": 0.000660125, + "seconds": 0.000661083, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3782,7 +3782,7 @@ "note": "double precision, gate by gate", "strict": 2.1563814583286734e-15, "global_phase": -1.663867892004838e-16, - "seconds": 0.515387500054203 + "seconds": 0.5979814999736845 }, { "entry": "qpe_t12_m2741", @@ -3794,7 +3794,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.21584525039295e-75, "global_phase": 1.727233711018889e-76, - "seconds": 0.0061108749359846115 + "seconds": 0.007401999901048839 }, { "entry": "qpe_t12_m2741", @@ -3806,7 +3806,7 @@ "note": "single precision, fusion width 2", "strict": 4.3259611122588005e-07, "global_phase": -3.31067838033038e-07, - "seconds": 0.0035408339463174343 + "seconds": 0.003454208024777472 }, { "entry": "qpe_t12_m2741", @@ -3843,7 +3843,7 @@ "note": "double precision, fusion width 3", "strict": 1.4189449206665662e-15, "global_phase": 9.228121731687924e-16, - "seconds": 6.3e-05 + "seconds": 5.9625e-05 }, { "entry": "qpe_t6_third", @@ -3855,7 +3855,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.824931761242946e-16, "global_phase": -7.526127929350746e-16, - "seconds": 8.8084e-05 + "seconds": 9.3375e-05 }, { "entry": "qpe_t6_third", @@ -3867,7 +3867,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3608328976433878e-15, "global_phase": 1.178445704938736e-15, - "seconds": 9.15e-05, + "seconds": 0.000104291, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3882,19 +3882,19 @@ "note": "double precision, gate by gate", "strict": 1.5279328846936548e-15, "global_phase": -1.0746498541794729e-15, - "seconds": 0.5065369580406696 + "seconds": 0.6135030830046162 }, { "entry": "qpe_t6_third", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 7.935648197956683e-15, + "measured": 8.249384383476863e-15, "tolerance": 4.542902048736096e-10, "status": "pass", "note": "double precision, a contraction of width 11.0", - "strict": 7.996970982413447e-15, - "global_phase": -9.884495798115108e-16, - "seconds": 0.19211062497925013 + "strict": 8.296698201151784e-15, + "global_phase": -8.847928201806912e-16, + "seconds": 0.36848233302589506 }, { "entry": "qpe_t6_third", @@ -3906,7 +3906,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.829526496671626e-16, "global_phase": -1.0252284887645072e-16, - "seconds": 0.006212583044543862 + "seconds": 0.007307042018510401 }, { "entry": "qpe_t6_third", @@ -3918,7 +3918,7 @@ "note": "single precision, fusion width 2", "strict": 2.273125193510748e-07, "global_phase": -1.6413748348371467e-07, - "seconds": 0.0020346669480204582 + "seconds": 0.0026775419246405363 }, { "entry": "qpe_t6_third", @@ -3955,7 +3955,7 @@ "note": "double precision, fusion width 3", "strict": 2.278811280653084e-15, "global_phase": 1.4018513039698793e-15, - "seconds": 0.000303083 + "seconds": 0.000708833 }, { "entry": "qpe_t10_third", @@ -3967,7 +3967,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.5115343349619408e-15, "global_phase": -1.3405058207363578e-15, - "seconds": 0.000219917 + "seconds": 0.000233959 }, { "entry": "qpe_t10_third", @@ -3979,7 +3979,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.1163134250061386e-15, "global_phase": 1.946743766053711e-15, - "seconds": 0.000252792, + "seconds": 0.000204958, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -3994,19 +3994,19 @@ "note": "double precision, gate by gate", "strict": 2.574356364266145e-15, "global_phase": -1.8512625176080566e-15, - "seconds": 0.5185223330045119 + "seconds": 0.6370073329890147 }, { "entry": "qpe_t10_third", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 2.573123768696533e-15, + "measured": 2.5975954414774863e-15, "tolerance": 8.774588089962489e-05, "status": "pass", "note": "double precision, a contraction of width 22.0", - "strict": 2.941590859670544e-15, - "global_phase": -1.4254791673911768e-15, - "seconds": 0.3261465000687167 + "strict": 2.9071795232826038e-15, + "global_phase": -1.3054465531032094e-15, + "seconds": 0.42716441699303687 }, { "entry": "qpe_t10_third", @@ -4018,7 +4018,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.993372128915001e-16, "global_phase": -5.100801014823151e-17, - "seconds": 0.008167332969605923 + "seconds": 0.011731542064808309 }, { "entry": "qpe_t10_third", @@ -4030,7 +4030,7 @@ "note": "single precision, fusion width 2", "strict": 2.898835952510858e-07, "global_phase": -2.0481730274295468e-07, - "seconds": 0.0024386669974774122 + "seconds": 0.002491791034117341 }, { "entry": "qpe_t10_third", @@ -4086,7 +4086,7 @@ "note": "double precision, fusion width 3", "strict": 2.1287684798629586e-15, "global_phase": 4.054496842783867e-17, - "seconds": 0.000123708 + "seconds": 8.6709e-05 }, { "entry": "clifford_t_n4_d20", @@ -4098,7 +4098,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3114612183423928e-15, "global_phase": 8.36946064770723e-16, - "seconds": 0.000111125 + "seconds": 0.000117208 }, { "entry": "clifford_t_n4_d20", @@ -4110,7 +4110,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.3114612183423928e-15, "global_phase": 8.36946064770723e-16, - "seconds": 0.000100625, + "seconds": 9.6125e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4125,19 +4125,19 @@ "note": "double precision, gate by gate", "strict": 1.390711969694405e-15, "global_phase": -2.1877291266863018e-16, - "seconds": 0.5136416250606999 + "seconds": 0.6272456670412794 }, { "entry": "clifford_t_n4_d20", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.3031661551264778e-15, + "measured": 1.315112899831995e-15, "tolerance": 6.366438041334249e-12, "status": "pass", "note": "double precision, a contraction of width 6.0", - "strict": 1.3517325670657458e-15, - "global_phase": -3.5908063857443496e-16, - "seconds": 0.21206308307591826 + "strict": 1.3443465886380548e-15, + "global_phase": -2.788293583506887e-16, + "seconds": 0.3852867920650169 }, { "entry": "clifford_t_n4_d20", @@ -4149,7 +4149,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.726554759573411e-16, "global_phase": -1.6183299128189006e-16, - "seconds": 0.0053421660559251904 + "seconds": 0.011198082938790321 }, { "entry": "clifford_t_n4_d20", @@ -4161,7 +4161,7 @@ "note": "single precision, fusion width 2", "strict": 2.386055560508683e-07, "global_phase": 1.8691628929767302e-07, - "seconds": 0.0025102909421548247 + "seconds": 0.0027395000215619802 }, { "entry": "clifford_t_n4_d20", @@ -4217,7 +4217,7 @@ "note": "double precision, fusion width 3", "strict": 5.622384485102909e-15, "global_phase": 3.829288436678506e-17, - "seconds": 0.0003355 + "seconds": 0.000332708 }, { "entry": "clifford_t_n8_d40", @@ -4229,7 +4229,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.882352168215574e-15, "global_phase": 2.215740359183579e-15, - "seconds": 0.000208333 + "seconds": 0.000217125 }, { "entry": "clifford_t_n8_d40", @@ -4241,7 +4241,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.882352168215574e-15, "global_phase": 2.215740359183579e-15, - "seconds": 0.000437917, + "seconds": 0.000219333, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4256,19 +4256,19 @@ "note": "double precision, gate by gate", "strict": 4.036090676030125e-15, "global_phase": 3.1340158216307306e-16, - "seconds": 0.5802954999962822 + "seconds": 0.668299000011757 }, { "entry": "clifford_t_n8_d40", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.696204017944434e-13, + "measured": 3.7044137018767723e-13, "tolerance": 3.14722561000377e-08, "status": "pass", "note": "double precision, a contraction of width 13.0", - "strict": 3.696205781545818e-13, - "global_phase": 3.610715185491314e-16, - "seconds": 0.7041691250633448 + "strict": 3.7044150211265033e-13, + "global_phase": 3.1263549542583344e-16, + "seconds": 1.9335894579999149 }, { "entry": "clifford_t_n8_d40", @@ -4280,7 +4280,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.1078899783670994e-15, "global_phase": -4.910697073378121e-16, - "seconds": 0.009752375073730946 + "seconds": 0.010111875017173588 }, { "entry": "clifford_t_n8_d40", @@ -4292,7 +4292,7 @@ "note": "single precision, fusion width 2", "strict": 8.033646023253315e-07, "global_phase": 7.19311878181064e-07, - "seconds": 0.004483374999836087 + "seconds": 0.004670541035011411 }, { "entry": "clifford_t_n8_d40", @@ -4348,7 +4348,7 @@ "note": "double precision, fusion width 3", "strict": 7.23755922358584e-15, "global_phase": 1.7960187025050173e-17, - "seconds": 0.00216175 + "seconds": 0.002738625 }, { "entry": "clifford_t_n12_d40", @@ -4360,7 +4360,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.465338738445407e-15, "global_phase": 2.891942735534964e-15, - "seconds": 0.001462208 + "seconds": 0.001358917 }, { "entry": "clifford_t_n12_d40", @@ -4372,7 +4372,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.465338738445407e-15, "global_phase": 2.891942735534964e-15, - "seconds": 0.001337959, + "seconds": 0.001324042, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4387,19 +4387,19 @@ "note": "double precision, gate by gate", "strict": 5.220686102560184e-15, "global_phase": -3.371275496591598e-16, - "seconds": 0.6066575000295416 + "seconds": 0.7439858749276027 }, { "entry": "clifford_t_n12_d40", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.0935818055439814e-12, + "measured": 3.093233573327161e-12, "tolerance": 0.00018851685818136647, "status": "pass", "note": "double precision, a contraction of width 21.0", - "strict": 3.0935818188575394e-12, - "global_phase": -2.870072523067668e-16, - "seconds": 1.5533142080530524 + "strict": 3.093233596636626e-12, + "global_phase": -3.7974101259767676e-16, + "seconds": 4.754915624973364 }, { "entry": "clifford_t_n12_d40", @@ -4411,7 +4411,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.011129495297865e-14, "global_phase": 7.53693706235948e-15, - "seconds": 0.1194655419094488 + "seconds": 0.15469849994406104 }, { "entry": "clifford_t_n12_d40", @@ -4423,7 +4423,7 @@ "note": "single precision, fusion width 2", "strict": 1.5859800767816736e-06, "global_phase": 1.5273926930313058e-06, - "seconds": 0.017240250017493963 + "seconds": 0.0071299170376732945 }, { "entry": "clifford_t_n12_d40", @@ -4479,7 +4479,7 @@ "note": "double precision, fusion width 3", "strict": 1.5858100500850096e-15, "global_phase": -7.098047794018468e-16, - "seconds": 0.000118834 + "seconds": 0.000184 }, { "entry": "dyadic_n6_k20", @@ -4491,7 +4491,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4084340793192475e-15, "global_phase": 5.737431325486733e-16, - "seconds": 0.000166333 + "seconds": 0.000137375 }, { "entry": "dyadic_n6_k20", @@ -4503,7 +4503,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.7608481323261614e-15, "global_phase": -7.998262564678552e-16, - "seconds": 0.0001235, + "seconds": 0.000140334, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4518,19 +4518,19 @@ "note": "double precision, gate by gate", "strict": 1.1996783412008028e-15, "global_phase": 3.9083184448044817e-16, - "seconds": 0.5455879590008408 + "seconds": 0.6472109169699252 }, { "entry": "dyadic_n6_k20", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.3071509605271463e-14, + "measured": 1.3158728689178571e-14, "tolerance": 8.221463240828132e-11, "status": "pass", "note": "double precision, a contraction of width 8.0", - "strict": 1.311227129115627e-14, - "global_phase": 1.0330997300245407e-15, - "seconds": 0.2704114589141682 + "strict": 1.3198813415811089e-14, + "global_phase": 1.0278788206707726e-15, + "seconds": 0.6448764170054346 }, { "entry": "dyadic_n6_k20", @@ -4542,7 +4542,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.230505161772939e-15, "global_phase": 5.570366223823753e-16, - "seconds": 0.006878415937535465 + "seconds": 0.01588766695931554 }, { "entry": "dyadic_n6_k20", @@ -4554,7 +4554,7 @@ "note": "single precision, fusion width 2", "strict": 9.57930475196668e-07, "global_phase": 3.545260787119959e-07, - "seconds": 0.002955665928311646 + "seconds": 0.003020958974957466 }, { "entry": "dyadic_n6_k20", @@ -4610,7 +4610,7 @@ "note": "double precision, fusion width 3", "strict": 2.144929701446449e-15, "global_phase": -5.597427605381909e-16, - "seconds": 0.000517916 + "seconds": 0.000524625 }, { "entry": "dyadic_n10_k30", @@ -4622,7 +4622,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.163222238363559e-15, "global_phase": 6.746387470477434e-16, - "seconds": 0.000648834 + "seconds": 0.000640834 }, { "entry": "dyadic_n10_k30", @@ -4634,7 +4634,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.122060579030768e-15, "global_phase": -2.5189977060304857e-16, - "seconds": 0.00109925, + "seconds": 0.000976417, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4649,19 +4649,19 @@ "note": "double precision, gate by gate", "strict": 2.0893664437453894e-15, "global_phase": 5.116754972869361e-16, - "seconds": 0.5332417919998989 + "seconds": 0.7333922920515761 }, { "entry": "dyadic_n10_k30", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.723619716241108e-14, + "measured": 3.7656198484287305e-14, "tolerance": 2.931147265744985e-07, "status": "pass", "note": "double precision, a contraction of width 15.0", - "strict": 3.724174298417906e-14, - "global_phase": 6.426829558186028e-16, - "seconds": 0.5938497500028461 + "strict": 3.7657161072509634e-14, + "global_phase": 2.692503535623599e-16, + "seconds": 1.0180965829640627 }, { "entry": "dyadic_n10_k30", @@ -4673,7 +4673,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.48600669128831e-15, "global_phase": 6.871414700641309e-16, - "seconds": 0.05069237493444234 + "seconds": 0.07765779201872647 }, { "entry": "dyadic_n10_k30", @@ -4685,7 +4685,7 @@ "note": "single precision, fusion width 2", "strict": 1.31241549090106e-06, "global_phase": 2.0790676466732445e-07, - "seconds": 0.005365749937482178 + "seconds": 0.00598741602152586 }, { "entry": "dyadic_n10_k30", @@ -4714,7 +4714,7 @@ "note": "double precision, fusion width 3", "strict": 1.72086804212411e-15, "global_phase": -8.152710389464119e-16, - "seconds": 0.000114125 + "seconds": 0.0001075 }, { "entry": "rotations_n6", @@ -4726,7 +4726,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.905715024096332e-15, "global_phase": -9.8635387547214e-16, - "seconds": 0.000142792 + "seconds": 0.00013625 }, { "entry": "rotations_n6", @@ -4738,7 +4738,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.905715024096332e-15, "global_phase": -9.8635387547214e-16, - "seconds": 0.000133791, + "seconds": 0.00012525, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4753,19 +4753,19 @@ "note": "double precision, gate by gate", "strict": 1.7352268023762315e-15, "global_phase": -8.73954150636811e-16, - "seconds": 0.5062924999510869 + "seconds": 0.6870980840176344 }, { "entry": "rotations_n6", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 1.1489764934764644e-14, + "measured": 1.123991622924384e-14, "tolerance": 8.221463240828132e-11, "status": "pass", "note": "double precision, a contraction of width 8.0", - "strict": 1.1577243343164619e-14, - "global_phase": -1.420515811493234e-15, - "seconds": 0.25637258403003216 + "strict": 1.1327702083196756e-14, + "global_phase": -1.4075218098633676e-15, + "seconds": 0.5128341250820085 }, { "entry": "rotations_n6", @@ -4777,7 +4777,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.700975318360868e-15, "global_phase": -1.1330486121689853e-15, - "seconds": 0.011198083055205643 + "seconds": 0.009556917008012533 }, { "entry": "rotations_n6", @@ -4789,7 +4789,7 @@ "note": "single precision, fusion width 2", "strict": 4.913755143058781e-07, "global_phase": -1.0908246135531504e-09, - "seconds": 0.00333891692571342, + "seconds": 0.004204249940812588, "adapter": [ "U as a matrix" ] @@ -4821,7 +4821,7 @@ "note": "double precision, fusion width 3", "strict": 2.9061712219412836e-15, "global_phase": -1.5401496063733773e-15, - "seconds": 0.000519 + "seconds": 0.000525125 }, { "entry": "rotations_n10", @@ -4833,7 +4833,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.6382365134157053e-15, "global_phase": -1.0636506379805698e-15, - "seconds": 0.0007575 + "seconds": 0.001906708 }, { "entry": "rotations_n10", @@ -4845,7 +4845,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.6382365134157053e-15, "global_phase": -1.0636506379805698e-15, - "seconds": 0.000745083, + "seconds": 0.001822041, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4860,19 +4860,19 @@ "note": "double precision, gate by gate", "strict": 2.5904531582104556e-15, "global_phase": -1.0674759143452676e-15, - "seconds": 0.541006249957718 + "seconds": 0.6394752080086619 }, { "entry": "rotations_n10", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.614927339505327e-14, + "measured": 3.6398994878490694e-14, "tolerance": 2.931147265744985e-07, "status": "pass", "note": "double precision, a contraction of width 15.0", - "strict": 3.6180410198833924e-14, - "global_phase": -1.5007048895701067e-15, - "seconds": 0.6266333329258487 + "strict": 3.6424423842436794e-14, + "global_phase": -1.360817434149861e-15, + "seconds": 0.5811442079721019 }, { "entry": "rotations_n10", @@ -4884,7 +4884,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.286480728746005e-15, "global_phase": 1.2768800304762984e-15, - "seconds": 0.07842179201543331 + "seconds": 0.13190037501044571 }, { "entry": "rotations_n10", @@ -4896,7 +4896,7 @@ "note": "single precision, fusion width 2", "strict": 7.295684771927766e-07, "global_phase": -4.3192578052393335e-08, - "seconds": 0.0053058749763295054, + "seconds": 0.02416887495201081, "adapter": [ "U as a matrix" ] @@ -4928,7 +4928,7 @@ "note": "double precision, fusion width 3", "strict": 3.898968578999015e-15, "global_phase": -2.3527803658438282e-15, - "seconds": 0.002304 + "seconds": 0.002206417 }, { "entry": "rotations_n12", @@ -4940,7 +4940,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.331119798114088e-15, "global_phase": -3.031293947851528e-15, - "seconds": 0.003747625 + "seconds": 0.00379975 }, { "entry": "rotations_n12", @@ -4952,7 +4952,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.331119798114088e-15, "global_phase": -3.031293947851528e-15, - "seconds": 0.003781625, + "seconds": 0.003755458, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -4967,19 +4967,19 @@ "note": "double precision, gate by gate", "strict": 4.11654606819691e-15, "global_phase": -2.7871987707890047e-15, - "seconds": 0.6144214579835534 + "seconds": 0.7859607089776546 }, { "entry": "rotations_n12", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 2.6715355150968333e-12, + "measured": 2.6714347388008865e-12, "tolerance": 1.3263461525542181e-06, "status": "pass", "note": "double precision, a contraction of width 16.0", - "strict": 2.6715366654646042e-12, - "global_phase": -2.4792131886191788e-15, - "seconds": 0.9899737499654293 + "strict": 2.67143615180368e-12, + "global_phase": -2.7476337989625242e-15, + "seconds": 2.309309833915904 }, { "entry": "rotations_n12", @@ -4991,7 +4991,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.210254510477273e-14, "global_phase": -1.8295929187895565e-15, - "seconds": 0.7157033329131082 + "seconds": 0.7533062910661101 }, { "entry": "rotations_n12", @@ -5003,7 +5003,7 @@ "note": "single precision, fusion width 2", "strict": 9.826555759371395e-07, "global_phase": 2.2935179604588235e-07, - "seconds": 0.01786929101217538, + "seconds": 0.05670341697987169, "adapter": [ "U as a matrix" ] @@ -5106,7 +5106,7 @@ "status": "pass", "note": "the extension's published bound (quantum-sim.md section 5), summed over the op-log the engine ran", "strict": 1.5188537817569304e-06, - "seconds": 0.009780375 + "seconds": 0.009932583 }, { "entry": "mirror_n10", @@ -5133,7 +5133,7 @@ "status": "pass", "note": "double precision, fusion width 3", "strict": 1.984140267936255e-15, - "seconds": 0.001313208 + "seconds": 0.002223625 }, { "entry": "mirror_n10", @@ -5144,7 +5144,7 @@ "status": "pass", "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.117234406512196e-15, - "seconds": 0.0016265 + "seconds": 0.00262775 }, { "entry": "mirror_n10", @@ -5155,7 +5155,7 @@ "status": "pass", "note": "double precision, gate by gate", "strict": 2.7208750497259247e-15, - "seconds": 0.7724118329351768 + "seconds": 1.230893375002779 }, { "entry": "mirror_n10", @@ -5166,7 +5166,7 @@ "status": "pass", "note": "decision-diagram edge weights merged within 2^-42", "strict": 0.0, - "seconds": 0.13924079202115536 + "seconds": 0.13136491691693664 }, { "entry": "mirror_n10", @@ -5177,7 +5177,7 @@ "status": "pass", "note": "single precision, fusion width 2", "strict": 8.972856072673777e-07, - "seconds": 0.010589292040094733 + "seconds": 0.013315875083208084 }, { "entry": "mirror_n16", @@ -5188,7 +5188,7 @@ "status": "pass", "note": "the extension's published bound (quantum-sim.md section 5), summed over the op-log the engine ran", "strict": 1.5097785874851365e-05, - "seconds": 0.910945833 + "seconds": 0.75515325 }, { "entry": "mirror_n16", @@ -5207,7 +5207,7 @@ "status": "pass", "note": "double precision, fusion width 3", "strict": 2.238789057608218e-15, - "seconds": 0.240029167 + "seconds": 0.065996542 }, { "entry": "mirror_n16", @@ -5218,7 +5218,7 @@ "status": "pass", "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 3.2761650953232175e-15, - "seconds": 0.120349833 + "seconds": 0.109473333 }, { "entry": "mirror_n16", @@ -5229,7 +5229,7 @@ "status": "pass", "note": "double precision, gate by gate", "strict": 1.994124091015089e-15, - "seconds": 1.0359977500047535 + "seconds": 1.0006315830396488 }, { "entry": "mirror_n16", @@ -5240,7 +5240,7 @@ "status": "pass", "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.514930450382587e-13, - "seconds": 20.158708457951434 + "seconds": 23.486437750048935 }, { "entry": "mirror_n16", @@ -5251,7 +5251,7 @@ "status": "pass", "note": "single precision, fusion width 2", "strict": 1.0399434223545688e-06, - "seconds": 0.05674095801077783 + "seconds": 0.05714858300052583 }, { "entry": "mirror_n20", @@ -5262,7 +5262,7 @@ "status": "pass", "note": "the extension's published bound (quantum-sim.md section 5), summed over the op-log the engine ran", "strict": 4.738962099310268e-05, - "seconds": 11.940751417 + "seconds": 11.033335 }, { "entry": "mirror_n20", @@ -5281,7 +5281,7 @@ "status": "pass", "note": "double precision, fusion width 3", "strict": 1.783666617688025e-15, - "seconds": 0.490648625 + "seconds": 0.117145084 }, { "entry": "mirror_n20", @@ -5292,7 +5292,7 @@ "status": "pass", "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.3233717576401003e-15, - "seconds": 1.593181625 + "seconds": 1.524742833 }, { "entry": "mirror_n20", @@ -5303,7 +5303,7 @@ "status": "pass", "note": "double precision, gate by gate", "strict": 2.391665972196861e-15, - "seconds": 5.9168768340023234 + "seconds": 5.510132750030607 }, { "entry": "mirror_n20", @@ -5314,7 +5314,7 @@ "status": "pass", "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.51898665365181e-12, - "seconds": 880.1322402919177 + "seconds": 789.5434542079456 }, { "entry": "mirror_n20", @@ -5325,7 +5325,7 @@ "status": "pass", "note": "single precision, fusion width 2", "strict": 9.146325270517816e-07, - "seconds": 0.7256209999322891 + "seconds": 0.6787234999937937 }, { "entry": "small_angle_k8", @@ -5372,7 +5372,7 @@ "note": "double precision, fusion width 3", "strict": 1.85959557341835e-16, "global_phase": -5.1513497497288096e-20, - "seconds": 0.000677042 + "seconds": 0.000383792 }, { "entry": "small_angle_k8", @@ -5397,7 +5397,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.718539386259611e-17, "global_phase": 6.207071732258519e-17, - "seconds": 0.001149 + "seconds": 0.001049292 }, { "entry": "small_angle_k8", @@ -5422,7 +5422,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.718539386259611e-17, "global_phase": 6.207071732258519e-17, - "seconds": 9.2166e-05, + "seconds": 6.4083e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -5450,7 +5450,7 @@ "note": "double precision, gate by gate", "strict": 2.630646413577557e-16, "global_phase": -1.3512029458769615e-18, - "seconds": 1.3623762079514563 + "seconds": 1.2699615421006456 }, { "entry": "small_angle_k8", @@ -5475,7 +5475,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.5236203454172553e-16, "global_phase": 1.1441497725281051e-20, - "seconds": 0.0014503750717267394 + "seconds": 0.0010078750783577561 }, { "entry": "small_angle_k8", @@ -5500,7 +5500,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.8147667325496875e-16, "global_phase": 4.460496188388002e-19, - "seconds": 0.008664665976539254 + "seconds": 0.0075079998932778835 }, { "entry": "small_angle_k8", @@ -5525,7 +5525,7 @@ "note": "single precision, fusion width 2", "strict": 2.9370438261224258e-08, "global_phase": -8.206690548754471e-10, - "seconds": 0.0043485419591888785 + "seconds": 0.004513791995123029 }, { "entry": "small_angle_k8", @@ -5594,7 +5594,7 @@ "note": "double precision, fusion width 3", "strict": 1.82547570059512e-16, "global_phase": 6.91366666472064e-21, - "seconds": 3.875e-05 + "seconds": 1.3292e-05 }, { "entry": "small_angle_k16", @@ -5619,7 +5619,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0927932505288209e-16, "global_phase": 6.124134630745771e-17, - "seconds": 0.00013925 + "seconds": 6.9208e-05 }, { "entry": "small_angle_k16", @@ -5644,7 +5644,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0927932505288209e-16, "global_phase": 6.124134630745771e-17, - "seconds": 8.4958e-05, + "seconds": 9.0583e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -5672,7 +5672,7 @@ "note": "double precision, gate by gate", "strict": 1.565389992262524e-16, "global_phase": 3.847678097819925e-22, - "seconds": 0.6267753749853 + "seconds": 0.5479299579747021 }, { "entry": "small_angle_k16", @@ -5697,7 +5697,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.5653900018555572e-16, "global_phase": 7.161031376499654e-21, - "seconds": 0.0007934999885037541 + "seconds": 0.0006463329773396254 }, { "entry": "small_angle_k16", @@ -5722,7 +5722,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.584721728060106e-17, "global_phase": 3.757155249022045e-21, - "seconds": 0.006982999970205128 + "seconds": 0.005076666944660246 }, { "entry": "small_angle_k16", @@ -5747,7 +5747,7 @@ "note": "single precision, fusion width 2", "strict": 3.2498100863323152e-09, "global_phase": -8.463048083580325e-12, - "seconds": 0.0018560000462457538 + "seconds": 0.002402040991000831 }, { "entry": "small_angle_k16", @@ -5816,7 +5816,7 @@ "note": "double precision, fusion width 3", "strict": 2.1618425343289958e-16, "global_phase": -4.874625787480407e-24, - "seconds": 2.0459e-05 + "seconds": 1.3875e-05 }, { "entry": "small_angle_k24", @@ -5841,7 +5841,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.073974588850753e-17, "global_phase": 6.123234627532328e-17, - "seconds": 8.0083e-05 + "seconds": 7.1666e-05 }, { "entry": "small_angle_k24", @@ -5866,7 +5866,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.073974588850753e-17, "global_phase": 6.123234627532328e-17, - "seconds": 7.8959e-05, + "seconds": 7.6666e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -5894,7 +5894,7 @@ "note": "double precision, gate by gate", "strict": 2.4197409606121436e-16, "global_phase": -2.4697673580566565e-23, - "seconds": 0.6366067910566926 + "seconds": 0.5719750829739496 }, { "entry": "small_angle_k24", @@ -5919,7 +5919,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.315949512384786e-16, "global_phase": -3.9083572958578904e-24, - "seconds": 0.0006839169654995203 + "seconds": 0.0006134170107543468 }, { "entry": "small_angle_k24", @@ -5944,7 +5944,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.5063878560100614e-14, "global_phase": 1.3154399712170649e-20, - "seconds": 0.007417083019390702 + "seconds": 0.006621459033340216 }, { "entry": "small_angle_k24", @@ -5969,7 +5969,7 @@ "note": "single precision, fusion width 2", "strict": 6.871130644612338e-14, "global_phase": -3.3632504423353635e-14, - "seconds": 0.002111791050992906 + "seconds": 0.003068000078201294 }, { "entry": "small_angle_k24", @@ -6038,7 +6038,7 @@ "note": "double precision, fusion width 3", "strict": 1.9524967158251372e-16, "global_phase": 6.71583667849561e-25, - "seconds": 1.9709e-05 + "seconds": 1.4334e-05 }, { "entry": "small_angle_k26", @@ -6063,7 +6063,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.578845626274399e-17, "global_phase": 6.123235275851835e-17, - "seconds": 7.9458e-05 + "seconds": 0.000109041 }, { "entry": "small_angle_k26", @@ -6088,7 +6088,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.578845626274399e-17, "global_phase": 6.123235275851835e-17, - "seconds": 8.6958e-05, + "seconds": 0.000106042, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6116,7 +6116,7 @@ "note": "double precision, gate by gate", "strict": 2.5239932650251915e-16, "global_phase": 2.3332666200026874e-24, - "seconds": 0.6603905410738662 + "seconds": 0.861797875026241 }, { "entry": "small_angle_k26", @@ -6141,7 +6141,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.4293906912430874e-16, "global_phase": -1.6855137448329943e-24, - "seconds": 0.001490958034992218 + "seconds": 0.0005657499423250556 }, { "entry": "small_angle_k26", @@ -6166,7 +6166,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.1914924100062395e-15, "global_phase": 2.014580430297663e-22, - "seconds": 0.0069966670125722885 + "seconds": 0.005944291013292968 }, { "entry": "small_angle_k26", @@ -6191,7 +6191,7 @@ "note": "single precision, fusion width 2", "strict": 1.2288145633023052e-14, "global_phase": -8.408128157662514e-15, - "seconds": 0.0016306249890476465 + "seconds": 0.0032264580950140953 }, { "entry": "small_angle_k26", @@ -6260,7 +6260,7 @@ "note": "double precision, fusion width 3", "strict": 1.3940409624957706e-16, "global_phase": -3.6016109745977435e-25, - "seconds": 2.0416e-05 + "seconds": 1.4375e-05 }, { "entry": "small_angle_k28", @@ -6285,7 +6285,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.6411063727342416e-16, "global_phase": 6.123234392345849e-17, - "seconds": 6.65e-05 + "seconds": 0.000114875 }, { "entry": "small_angle_k28", @@ -6310,7 +6310,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.6411063727342416e-16, "global_phase": 6.123234392345849e-17, - "seconds": 0.00012525, + "seconds": 7.2667e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6338,7 +6338,7 @@ "note": "double precision, gate by gate", "strict": 1.1778473976565107e-16, "global_phase": 2.6539241761670182e-24, - "seconds": 0.578172791050747 + "seconds": 0.6975292500574142 }, { "entry": "small_angle_k28", @@ -6363,7 +6363,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 8.894478810177485e-17, "global_phase": 3.498968171638388e-25, - "seconds": 0.0005888330051675439 + "seconds": 0.0005626250058412552 }, { "entry": "small_angle_k28", @@ -6388,7 +6388,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.3696827562538982e-16, "global_phase": 2.6449066869591424e-24, - "seconds": 0.007188583025708795 + "seconds": 0.013894250034354627 }, { "entry": "small_angle_k28", @@ -6413,7 +6413,7 @@ "note": "single precision, fusion width 2", "strict": 2.9790264018692395e-15, "global_phase": -2.10203207147538e-15, - "seconds": 0.0025165840052068233 + "seconds": 0.0015727500431239605 }, { "entry": "small_angle_k28", @@ -6482,7 +6482,7 @@ "note": "double precision, fusion width 3", "strict": 2.30763959096193e-16, "global_phase": 3.8352550973466707e-25, - "seconds": 1.7667e-05 + "seconds": 1.4583e-05 }, { "entry": "small_angle_k30", @@ -6507,7 +6507,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.743777155297435e-17, "global_phase": 6.123234070875654e-17, - "seconds": 6.9375e-05 + "seconds": 9.2583e-05 }, { "entry": "small_angle_k30", @@ -6532,7 +6532,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.743777155297435e-17, "global_phase": 6.123234070875654e-17, - "seconds": 7.1416e-05, + "seconds": 7.8667e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6560,7 +6560,7 @@ "note": "double precision, gate by gate", "strict": 2.1365565322645643e-16, "global_phase": -8.86261455065536e-26, - "seconds": 0.5569509590277448 + "seconds": 0.8781664998969063 }, { "entry": "small_angle_k30", @@ -6585,7 +6585,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.0281877206483399e-16, "global_phase": -1.7738338483450532e-25, - "seconds": 0.0005896249786019325 + "seconds": 0.0005915829678997397 }, { "entry": "small_angle_k30", @@ -6610,7 +6610,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.560517226586893e-18, "global_phase": 5.359933175532669e-25, - "seconds": 0.00559750001411885 + "seconds": 0.01901520905084908 }, { "entry": "small_angle_k30", @@ -6635,7 +6635,7 @@ "note": "single precision, fusion width 2", "strict": 7.432791667721722e-16, "global_phase": -5.255080183697786e-16, - "seconds": 0.001738165970891714 + "seconds": 0.0015559589955955744 }, { "entry": "small_angle_k30", @@ -6704,7 +6704,7 @@ "note": "double precision, fusion width 3", "strict": 2.2258028030058234e-16, "global_phase": 8.805429279700935e-26, - "seconds": 1.7625e-05 + "seconds": 1.525e-05 }, { "entry": "small_angle_k32", @@ -6729,7 +6729,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659891128289178e-17, "global_phase": 6.123234007335431e-17, - "seconds": 7.8125e-05 + "seconds": 0.000130958 }, { "entry": "small_angle_k32", @@ -6754,7 +6754,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659891128289178e-17, "global_phase": 6.123234007335431e-17, - "seconds": 8.4667e-05, + "seconds": 0.003314042, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6782,7 +6782,7 @@ "note": "double precision, gate by gate", "strict": 2.2151021875367953e-16, "global_phase": -2.998362101329583e-26, - "seconds": 0.6412396669620648 + "seconds": 0.8593393330229446 }, { "entry": "small_angle_k32", @@ -6807,7 +6807,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1048856556976266e-16, "global_phase": -5.217293084528376e-26, - "seconds": 0.0007277920376509428 + "seconds": 0.008891250006854534 }, { "entry": "small_angle_k32", @@ -6832,7 +6832,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 5.350323266617113e-19, "global_phase": 1.3204155822915235e-25, - "seconds": 0.006270374986343086 + "seconds": 0.017017040983773768 }, { "entry": "small_angle_k32", @@ -6857,7 +6857,7 @@ "note": "single precision, fusion width 2", "strict": 1.8579668241137169e-16, "global_phase": -1.3137700460027175e-16, - "seconds": 0.0019725000020116568 + "seconds": 0.002526290947571397 }, { "entry": "small_angle_k32", @@ -6899,7 +6899,7 @@ "note": "double precision, fusion width 3", "strict": 2.221784032698946e-16, "global_phase": 4.3831469282588235e-26, - "seconds": 1.95e-05 + "seconds": 1.475e-05 }, { "entry": "below_grid_k33", @@ -6924,7 +6924,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.65958122267691e-17, "global_phase": 6.123234000694218e-17, - "seconds": 7.7167e-05 + "seconds": 0.000204584 }, { "entry": "below_grid_k33", @@ -6949,7 +6949,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.65958122267691e-17, "global_phase": 6.123234000694218e-17, - "seconds": 8.0542e-05, + "seconds": 6.6e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -6977,7 +6977,7 @@ "note": "double precision, gate by gate", "strict": 2.2191088715510154e-16, "global_phase": -1.518748762256435e-26, - "seconds": 0.65340341697447 + "seconds": 0.6403250839794055 }, { "entry": "below_grid_k33", @@ -7002,7 +7002,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1088862505292507e-16, "global_phase": -2.628214253855832e-26, - "seconds": 0.0007522499654442072 + "seconds": 0.0005986660253256559 }, { "entry": "below_grid_k33", @@ -7027,7 +7027,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.3375808166545222e-19, "global_phase": 6.597185983559708e-26, - "seconds": 0.0057669999077916145 + "seconds": 0.016191291972063482 }, { "entry": "below_grid_k33", @@ -7052,7 +7052,7 @@ "note": "single precision, fusion width 2", "strict": 9.28977634359184e-17, "global_phase": -6.568850230033155e-17, - "seconds": 0.0019293329678475857 + "seconds": 0.0015315830241888762 }, { "entry": "below_grid_k33", @@ -7094,7 +7094,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446130889769e-16, "global_phase": 3.419238090495615e-28, - "seconds": 1.8166e-05 + "seconds": 2.1917e-05 }, { "entry": "below_grid_k40", @@ -7119,7 +7119,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562386814e-17, "global_phase": 6.123233995799644e-17, - "seconds": 7.9458e-05 + "seconds": 0.000148959 }, { "entry": "below_grid_k40", @@ -7144,7 +7144,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562386814e-17, "global_phase": 6.123233995799644e-17, - "seconds": 7.6583e-05, + "seconds": 7.4417e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -7172,7 +7172,7 @@ "note": "double precision, gate by gate", "strict": 2.2204459676108604e-16, "global_phase": -1.1916179177194308e-28, - "seconds": 0.6326399170793593 + "seconds": 0.6737322080880404 }, { "entry": "below_grid_k40", @@ -7197,7 +7197,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102229429857054e-16, "global_phase": -2.0583878330314597e-28, - "seconds": 0.000771665945649147 + "seconds": 0.0006325000431388617 }, { "entry": "below_grid_k40", @@ -7222,7 +7222,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.16394544667156e-24, "global_phase": 5.152777687854373e-28, - "seconds": 0.005858458927832544 + "seconds": 0.009803041932173073 }, { "entry": "below_grid_k40", @@ -7247,7 +7247,7 @@ "note": "single precision, fusion width 2", "strict": 7.25762272319939e-19, "global_phase": -5.1319142422184975e-19, - "seconds": 0.0019507909892126918 + "seconds": 0.0015448329504579306 }, { "entry": "below_grid_k40", @@ -7317,7 +7317,7 @@ "note": "double precision, fusion width 3", "strict": 2.2204460492552957e-16, "global_phase": 2.6712795152298427e-30, - "seconds": 1.9958e-05 + "seconds": 1.4416e-05 }, { "entry": "below_grid_k47", @@ -7342,7 +7342,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562355044e-17, "global_phase": 6.12323399573716e-17, - "seconds": 7.8666e-05 + "seconds": 6.6333e-05 }, { "entry": "below_grid_k47", @@ -7367,7 +7367,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562355044e-17, "global_phase": 6.12323399573716e-17, - "seconds": 8.4542e-05, + "seconds": 8.025e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -7395,7 +7395,7 @@ "note": "double precision, gate by gate", "strict": 2.2204460492453302e-16, "global_phase": -9.309517411881617e-31, - "seconds": 0.6567415000172332 + "seconds": 0.6397697919746861 }, { "entry": "below_grid_k47", @@ -7420,7 +7420,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230246201737e-16, "global_phase": -1.6081157375256844e-30, - "seconds": 0.0007692920044064522 + "seconds": 0.0005665419157594442 }, { "entry": "below_grid_k47", @@ -7445,7 +7445,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.1568581975409175e-14, "global_phase": 2.2322358387255243e-14, - "seconds": 0.006502582924440503 + "seconds": 0.014190749963745475 }, { "entry": "below_grid_k47", @@ -7470,7 +7470,7 @@ "note": "single precision, fusion width 2", "strict": 5.67001775178211e-21, "global_phase": -4.009308001733202e-21, - "seconds": 0.0022434579441323876 + "seconds": 0.0015237500192597508 }, { "entry": "below_grid_k47", @@ -7540,7 +7540,7 @@ "note": "double precision, fusion width 3", "strict": 2.2204460492515585e-16, "global_phase": 1.3356397576093598e-30, - "seconds": 2.1e-05 + "seconds": 1.4209e-05 }, { "entry": "below_grid_k48", @@ -7565,7 +7565,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354982e-17, "global_phase": 6.123233995736958e-17, - "seconds": 8.6917e-05 + "seconds": 7.0667e-05 }, { "entry": "below_grid_k48", @@ -7590,7 +7590,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354982e-17, "global_phase": 6.123233995736958e-17, - "seconds": 9.2792e-05, + "seconds": 7.7958e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -7618,7 +7618,7 @@ "note": "double precision, gate by gate", "strict": 2.2204460492490674e-16, "global_phase": -4.654758705996424e-31, - "seconds": 0.6727488751057535 + "seconds": 0.6511507079703733 }, { "entry": "below_grid_k48", @@ -7643,7 +7643,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230246239108e-16, "global_phase": -8.040578687684036e-31, - "seconds": 0.0007828340167179704 + "seconds": 0.0005723750218749046 }, { "entry": "below_grid_k48", @@ -7668,7 +7668,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.5784290987704587e-14, "global_phase": 1.1161179193627622e-14, - "seconds": 0.00636587489861995 + "seconds": 0.010886457981541753 }, { "entry": "below_grid_k48", @@ -7693,7 +7693,7 @@ "note": "single precision, fusion width 2", "strict": 2.8350088758910386e-21, "global_phase": -2.004654000866601e-21, - "seconds": 0.0025755000533536077 + "seconds": 0.001484000007621944 }, { "entry": "below_grid_k48", @@ -7763,7 +7763,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446049250318e-16, "global_phase": 8.347748485046958e-32, - "seconds": 2.0625e-05 + "seconds": 1.4042e-05 }, { "entry": "below_grid_k52", @@ -7788,7 +7788,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354938e-17, "global_phase": 6.12323399573678e-17, - "seconds": 8.1791e-05 + "seconds": 0.00010725 }, { "entry": "below_grid_k52", @@ -7813,7 +7813,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354938e-17, "global_phase": 6.12323399573678e-17, - "seconds": 8.6375e-05, + "seconds": 6.3459e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -7841,7 +7841,7 @@ "note": "double precision, gate by gate", "strict": 2.2204460492503082e-16, "global_phase": -2.9092241912593063e-32, - "seconds": 0.6418082499876618 + "seconds": 0.604885375010781 }, { "entry": "below_grid_k52", @@ -7866,7 +7866,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230246251516e-16, "global_phase": -5.025361679814063e-32, - "seconds": 0.0007204590365290642 + "seconds": 0.000613166019320488 }, { "entry": "below_grid_k52", @@ -7891,7 +7891,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 9.865181867315367e-16, "global_phase": 6.975736996017264e-16, - "seconds": 0.008656500023789704 + "seconds": 0.006115790922194719 }, { "entry": "below_grid_k52", @@ -7916,7 +7916,7 @@ "note": "single precision, fusion width 2", "strict": 1.7718805474318958e-22, "global_phase": -1.2529087505416256e-22, - "seconds": 0.0020235830452293158 + "seconds": 0.002411250025033951 }, { "entry": "below_grid_k52", @@ -7986,7 +7986,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446049250313e-16, "global_phase": 3.2608392519714503e-34, - "seconds": 1.9958e-05 + "seconds": 1.45e-05 }, { "entry": "below_grid_k60", @@ -8011,7 +8011,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354932e-17, "global_phase": 6.123233995736765e-17, - "seconds": 8.1167e-05 + "seconds": 0.000117458 }, { "entry": "below_grid_k60", @@ -8036,7 +8036,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562354932e-17, "global_phase": 6.123233995736765e-17, - "seconds": 8.375e-05, + "seconds": 7.4709e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -8064,7 +8064,7 @@ "note": "double precision, gate by gate", "strict": 2.220446049250313e-16, "global_phase": -1.136415699710684e-34, - "seconds": 0.6803393330192193 + "seconds": 0.6919095000484958 }, { "entry": "below_grid_k60", @@ -8089,7 +8089,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230246251565e-16, "global_phase": -1.9630319061773865e-34, - "seconds": 0.0007486250251531601 + "seconds": 0.0006792499916628003 }, { "entry": "below_grid_k60", @@ -8114,7 +8114,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.853586666920065e-18, "global_phase": 2.7248972640692436e-18, - "seconds": 0.006305832997895777 + "seconds": 0.03584679204504937 }, { "entry": "below_grid_k60", @@ -8139,7 +8139,7 @@ "note": "single precision, fusion width 2", "strict": 6.921408388405842e-25, "global_phase": -4.894174806803225e-25, - "seconds": 0.001997250015847385 + "seconds": 0.0016620829701423645 }, { "entry": "below_grid_k60", @@ -8181,7 +8181,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446050500313e-16, "global_phase": -8.636168555094445e-78, - "seconds": 2.0834e-05 + "seconds": 1.4334e-05 }, { "entry": "tiny_radians", @@ -8206,7 +8206,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562364557e-17, "global_phase": 6.123233995748117e-17, - "seconds": 8.0584e-05 + "seconds": 6.5833e-05 }, { "entry": "tiny_radians", @@ -8231,7 +8231,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.659560562364557e-17, "global_phase": 6.123233995748117e-17, - "seconds": 8.4208e-05, + "seconds": 0.000116167, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -8259,7 +8259,7 @@ "note": "double precision, gate by gate", "strict": 2.220446048000313e-16, "global_phase": -8.636168555094445e-78, - "seconds": 0.6358422910561785 + "seconds": 0.768698540981859 }, { "entry": "tiny_radians", @@ -8284,7 +8284,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1102230233751565e-16, "global_phase": 6.15135748657355e-30, - "seconds": 0.0007358749862760305 + "seconds": 0.0005826249253004789 }, { "entry": "tiny_radians", @@ -8309,7 +8309,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.0710678118654759e-13, "global_phase": -8.636168555094445e-78, - "seconds": 0.007802124950103462 + "seconds": 0.01916762499604374 }, { "entry": "tiny_radians", @@ -8334,7 +8334,7 @@ "note": "single precision, fusion width 2", "strict": 5.2212207224549863e-20, "global_phase": -8.636168555094445e-78, - "seconds": 0.0033409999450668693 + "seconds": 0.0015508750220760703 }, { "entry": "tiny_radians", @@ -8403,7 +8403,7 @@ "note": "double precision, fusion width 3", "strict": 2.264462534400411e-16, "global_phase": 1.9176275486733354e-25, - "seconds": 1.9041e-05 + "seconds": 1.4167e-05 }, { "entry": "controlled_small_angle_k30", @@ -8428,7 +8428,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.5107736123526882e-16, "global_phase": 1.6248208038498013e-25, - "seconds": 8.625e-05 + "seconds": 7.3458e-05 }, { "entry": "controlled_small_angle_k30", @@ -8453,7 +8453,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.5107736123526882e-16, "global_phase": 1.6248208038498013e-25, - "seconds": 0.000134959, + "seconds": 0.000171708, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -8481,7 +8481,7 @@ "note": "double precision, gate by gate", "strict": 2.1789050545163395e-16, "global_phase": -4.43130727532768e-26, - "seconds": 0.6592351659201086 + "seconds": 0.7458120830124244 }, { "entry": "controlled_small_angle_k30", @@ -8506,7 +8506,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.2442154962177805e-16, "global_phase": -2.9672735360837903e-26, - "seconds": 0.0009957499569281936 + "seconds": 0.0011537079699337482 }, { "entry": "controlled_small_angle_k30", @@ -8531,7 +8531,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.264462534400411e-16, "global_phase": 1.9176275486733354e-25, - "seconds": 0.00674537499435246 + "seconds": 0.024198165978305042 }, { "entry": "controlled_small_angle_k30", @@ -8556,7 +8556,7 @@ "note": "single precision, fusion width 2", "strict": 3.035841329600863e-16, "global_phase": -1.5173170672237367e-16, - "seconds": 0.002111957990564406 + "seconds": 0.0026436670450493693 }, { "entry": "controlled_small_angle_k30", @@ -8644,7 +8644,7 @@ "note": "double precision, fusion width 3", "strict": 1.1478380657970898e-11, "global_phase": 1.2540980081523036e-14, - "seconds": 0.07758875 + "seconds": 0.074467333 }, { "entry": "repeated_phase_k19", @@ -8656,7 +8656,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1478380657970898e-11, "global_phase": 1.2540980081523036e-14, - "seconds": 0.117655792 + "seconds": 0.098682584 }, { "entry": "repeated_phase_k19", @@ -8668,7 +8668,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.1472378602661593e-11, "global_phase": 1.8012456755360483e-73, - "seconds": 0.8312161660287529 + "seconds": 0.7952923750272021 }, { "entry": "repeated_phase_k19", @@ -8680,7 +8680,7 @@ "note": "single precision, fusion width 2", "strict": 3.567080057109706e-06, "global_phase": -3.567080057094577e-06, - "seconds": 2.928019499988295 + "seconds": 2.700869375024922 }, { "entry": "repeated_phase_k19", @@ -8736,7 +8736,7 @@ "note": "double precision, fusion width 3", "strict": 5.74251759013435e-12, "global_phase": -4.491256677518576e-16, - "seconds": 0.035743292 + "seconds": 0.040903791 }, { "entry": "repeated_phase_k19_quarter", @@ -8748,7 +8748,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 5.74251759013435e-12, "global_phase": -4.491256677518576e-16, - "seconds": 0.053904667 + "seconds": 0.058367125 }, { "entry": "repeated_phase_k19_quarter", @@ -8760,7 +8760,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 5.740297126521909e-12, "global_phase": -2.703379842801214e-73, - "seconds": 0.4167492090491578 + "seconds": 0.38878375000786036 }, { "entry": "repeated_phase_k19_quarter", @@ -8772,7 +8772,7 @@ "note": "single precision, fusion width 2", "strict": 1.6820540622575209e-06, "global_phase": -1.6820540622559346e-06, - "seconds": 1.5386294170748442 + "seconds": 1.429333291016519 }, { "entry": "repeated_phase_k19_quarter", @@ -8828,7 +8828,7 @@ "note": "double precision, fusion width 3", "strict": 2.220446049250313e-16, "global_phase": 0.0, - "seconds": 0.001460959 + "seconds": 0.002154542 }, { "entry": "h_squared_chain", @@ -8840,7 +8840,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.7734780031702986e-13, "global_phase": 1.2540383223268955e-13, - "seconds": 0.001473917 + "seconds": 0.001911125 }, { "entry": "h_squared_chain", @@ -8852,7 +8852,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.268858116783184e-74, "global_phase": 0.0, - "seconds": 0.016374084050767124 + "seconds": 0.05185154196806252 }, { "entry": "h_squared_chain", @@ -8864,7 +8864,7 @@ "note": "single precision, fusion width 2", "strict": 4.268858116783184e-74, "global_phase": 0.0, - "seconds": 0.04478637489955872 + "seconds": 0.036795167019590735 }, { "entry": "h_squared_chain", @@ -8876,7 +8876,7 @@ "note": "double precision, gate by gate", "strict": 3.2152058793144533e-13, "global_phase": 0.0, - "seconds": 2.0371106249513105 + "seconds": 2.6928648749599233 }, { "entry": "h_squared_chain", @@ -8893,7 +8893,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0004470840794965625 + "seconds": 0.0026462500682100654 }, { "entry": "h_squared_chain", @@ -8902,7 +8902,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.000233083 + "seconds": 2.7083e-05 }, { "entry": "h_squared_chain", @@ -8919,7 +8919,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0013815 + "seconds": 0.001441542 }, { "entry": "h_squared_chain", @@ -8975,7 +8975,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 1.875e-05 + "seconds": 1.35e-05 }, { "entry": "gate_id", @@ -8987,7 +8987,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 7.825e-05 + "seconds": 7.1625e-05 }, { "entry": "gate_id", @@ -8999,7 +8999,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 8.8959e-05, + "seconds": 7.9417e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9014,7 +9014,7 @@ "note": "double precision, gate by gate", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.6600649169413373 + "seconds": 0.6993002920644358 }, { "entry": "gate_id", @@ -9026,7 +9026,7 @@ "note": "double precision, a contraction of width 1.0", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.0006435000104829669 + "seconds": 0.0013960839714854956 }, { "entry": "gate_id", @@ -9038,7 +9038,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006946791079826653 + "seconds": 0.010596374981105328 }, { "entry": "gate_id", @@ -9050,7 +9050,7 @@ "note": "single precision, fusion width 2", "strict": 3.96561472339793e-08, "global_phase": -5.3183955982678255e-09, - "seconds": 0.0018669170094653964 + "seconds": 0.0017524169525131583 }, { "entry": "gate_id", @@ -9106,7 +9106,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 2.0292e-05 + "seconds": 1.3791e-05 }, { "entry": "gate_x", @@ -9118,7 +9118,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 7.8834e-05 + "seconds": 0.000110416 }, { "entry": "gate_x", @@ -9130,7 +9130,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 8.5542e-05, + "seconds": 0.000161458, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9145,7 +9145,7 @@ "note": "double precision, gate by gate", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.6785006250720471 + "seconds": 0.7178686249535531 }, { "entry": "gate_x", @@ -9157,7 +9157,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.612115705267018e-16, "global_phase": 2.3791499247742048e-17, - "seconds": 0.0008207909995689988 + "seconds": 0.000586083042435348 }, { "entry": "gate_x", @@ -9169,7 +9169,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006621917011216283 + "seconds": 0.02003120898734778 }, { "entry": "gate_x", @@ -9181,7 +9181,7 @@ "note": "single precision, fusion width 2", "strict": 3.96561472339793e-08, "global_phase": -5.3183955982678255e-09, - "seconds": 0.0020375410094857216 + "seconds": 0.0018387909512966871 }, { "entry": "gate_x", @@ -9237,7 +9237,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 2.2042e-05 + "seconds": 1.4166e-05 }, { "entry": "gate_y", @@ -9249,7 +9249,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 8.2833e-05 + "seconds": 7.1542e-05 }, { "entry": "gate_y", @@ -9261,7 +9261,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.00010125, + "seconds": 7.5708e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9276,7 +9276,7 @@ "note": "double precision, gate by gate", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.6903110829880461 + "seconds": 0.7043202079366893 }, { "entry": "gate_y", @@ -9288,7 +9288,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.612115705267018e-16, "global_phase": 2.3791499247742048e-17, - "seconds": 0.000765959033742547 + "seconds": 0.0006266250275075436 }, { "entry": "gate_y", @@ -9300,7 +9300,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006353874923661351 + "seconds": 0.006635542027652264 }, { "entry": "gate_y", @@ -9312,7 +9312,7 @@ "note": "single precision, fusion width 2", "strict": 3.96561472339793e-08, "global_phase": -5.3183955982678255e-09, - "seconds": 0.0019235420040786266 + "seconds": 0.0028175830375403166 }, { "entry": "gate_y", @@ -9368,7 +9368,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 1.7625e-05 + "seconds": 2.825e-05 }, { "entry": "gate_z", @@ -9380,7 +9380,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 8.2958e-05 + "seconds": 7.4625e-05 }, { "entry": "gate_z", @@ -9392,7 +9392,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 8.5667e-05, + "seconds": 6.7292e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9407,7 +9407,7 @@ "note": "double precision, gate by gate", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.6563534589949995 + "seconds": 0.7838113330071792 }, { "entry": "gate_z", @@ -9419,7 +9419,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.612115705267018e-16, "global_phase": 2.3791499247742048e-17, - "seconds": 0.0008107080357149243 + "seconds": 0.0005688749952241778 }, { "entry": "gate_z", @@ -9431,7 +9431,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.00788291695062071 + "seconds": 0.011409500031732023 }, { "entry": "gate_z", @@ -9443,7 +9443,7 @@ "note": "single precision, fusion width 2", "strict": 3.96561472339793e-08, "global_phase": -5.3183955982678255e-09, - "seconds": 0.0018880829447880387 + "seconds": 0.00179704197216779 }, { "entry": "gate_z", @@ -9499,7 +9499,7 @@ "note": "double precision, fusion width 3", "strict": 1.2276852703978877e-16, "global_phase": -1.6687439983489124e-17, - "seconds": 2.1375e-05 + "seconds": 2.5708e-05 }, { "entry": "gate_h", @@ -9511,7 +9511,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.3023652669763116e-17, "global_phase": -6.214105046513707e-20, - "seconds": 8.3208e-05 + "seconds": 7.0666e-05 }, { "entry": "gate_h", @@ -9523,7 +9523,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 4.3023652669763116e-17, "global_phase": -6.214105046513707e-20, - "seconds": 8.5959e-05, + "seconds": 0.000275917, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9538,7 +9538,7 @@ "note": "double precision, gate by gate", "strict": 1.0613476464155822e-16, "global_phase": -1.3839838747142408e-17, - "seconds": 0.6653042500838637 + "seconds": 0.992700457922183 }, { "entry": "gate_h", @@ -9550,7 +9550,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.4067532397194434e-16, "global_phase": -4.0823347678073176e-18, - "seconds": 0.0007674170192331076 + "seconds": 0.0005706249503418803 }, { "entry": "gate_h", @@ -9562,7 +9562,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.2980934883817818e-16, "global_phase": 5.485399732509767e-18, - "seconds": 0.00651154201477766 + "seconds": 0.012739459052681923 }, { "entry": "gate_h", @@ -9574,7 +9574,7 @@ "note": "single precision, fusion width 2", "strict": 5.870101997830907e-08, "global_phase": -3.165382910808944e-09, - "seconds": 0.002065958920866251 + "seconds": 0.0034594159806147218 }, { "entry": "gate_h", @@ -9630,7 +9630,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 2.1333e-05 + "seconds": 1.4417e-05 }, { "entry": "gate_s", @@ -9642,7 +9642,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 8.2083e-05 + "seconds": 7.7041e-05 }, { "entry": "gate_s", @@ -9654,7 +9654,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 8.4417e-05, + "seconds": 0.000481625, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9669,7 +9669,7 @@ "note": "double precision, gate by gate", "strict": 7.941848649409825e-17, "global_phase": -2.2006940457149062e-17, - "seconds": 0.6649972919840366 + "seconds": 0.8086855839937925 }, { "entry": "gate_s", @@ -9681,7 +9681,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.615108259473306e-16, "global_phase": 2.51305584158725e-17, - "seconds": 0.0007732079830020666 + "seconds": 0.0005640420131385326 }, { "entry": "gate_s", @@ -9693,7 +9693,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006882666959427297 + "seconds": 0.015368500025942922 }, { "entry": "gate_s", @@ -9705,7 +9705,7 @@ "note": "single precision, fusion width 2", "strict": 3.96561472339793e-08, "global_phase": -5.3183955982678255e-09, - "seconds": 0.001822874997742474 + "seconds": 0.004583708010613918 }, { "entry": "gate_s", @@ -9761,7 +9761,7 @@ "note": "double precision, fusion width 3", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 2.1291e-05 + "seconds": 1.4125e-05 }, { "entry": "gate_sdg", @@ -9773,7 +9773,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 7.9833e-05 + "seconds": 6.975e-05 }, { "entry": "gate_sdg", @@ -9785,7 +9785,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.815859464913049e-17, "global_phase": -2.401552920934474e-17, - "seconds": 0.000101083, + "seconds": 7.9583e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9800,7 +9800,7 @@ "note": "double precision, gate by gate", "strict": 7.827453581328017e-17, "global_phase": -2.6024117961540415e-17, - "seconds": 0.6879187499871477 + "seconds": 0.8161654169671237 }, { "entry": "gate_sdg", @@ -9812,7 +9812,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.6116569270757267e-16, "global_phase": 2.1113380911481146e-17, - "seconds": 0.0007539589423686266 + "seconds": 0.0005950418999418616 }, { "entry": "gate_sdg", @@ -9824,7 +9824,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006352666998282075 + "seconds": 0.028955791029147804 }, { "entry": "gate_sdg", @@ -9836,7 +9836,7 @@ "note": "single precision, fusion width 2", "strict": 4.041685167365834e-08, "global_phase": -3.5211407407071473e-09, - "seconds": 0.0020010420121252537 + "seconds": 0.003033249988220632 }, { "entry": "gate_sdg", @@ -9892,7 +9892,7 @@ "note": "double precision, fusion width 3", "strict": 7.853716323280881e-17, "global_phase": -2.312587473280089e-17, - "seconds": 2.2667e-05 + "seconds": 1.4667e-05 }, { "entry": "gate_t", @@ -9904,7 +9904,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.992952424721852e-17, "global_phase": -2.2074877633532985e-17, - "seconds": 9.4083e-05 + "seconds": 7.325e-05 }, { "entry": "gate_t", @@ -9916,7 +9916,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.992952424721852e-17, "global_phase": -2.2074877633532985e-17, - "seconds": 9.4625e-05, + "seconds": 0.000127042, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -9931,7 +9931,7 @@ "note": "double precision, gate by gate", "strict": 8.897950494461851e-17, "global_phase": -1.7725634002671274e-17, - "seconds": 0.7020925000542775 + "seconds": 0.7963309170445427 }, { "entry": "gate_t", @@ -9943,7 +9943,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.583379157683397e-16, "global_phase": 2.4806146796528305e-17, - "seconds": 0.0009455840336158872 + "seconds": 0.0006130000110715628 }, { "entry": "gate_t", @@ -9955,7 +9955,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.726175410066437e-17, "global_phase": -2.7402490746767553e-17, - "seconds": 0.006809458020143211 + "seconds": 0.018232957925647497 }, { "entry": "gate_t", @@ -9967,7 +9967,7 @@ "note": "single precision, fusion width 2", "strict": 3.9294051504657585e-08, "global_phase": -5.440896726885419e-09, - "seconds": 0.0018907909980043769 + "seconds": 0.0017661669990047812 }, { "entry": "gate_t", @@ -10023,7 +10023,7 @@ "note": "double precision, fusion width 3", "strict": 7.853716323280881e-17, "global_phase": -2.312587473280089e-17, - "seconds": 2.2083e-05 + "seconds": 1.4333e-05 }, { "entry": "gate_tdg", @@ -10035,7 +10035,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.992952424721852e-17, "global_phase": -2.2074877633532985e-17, - "seconds": 8.2917e-05 + "seconds": 6.5416e-05 }, { "entry": "gate_tdg", @@ -10047,7 +10047,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.992952424721852e-17, "global_phase": -2.2074877633532985e-17, - "seconds": 8.6459e-05, + "seconds": 0.00015575, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10062,7 +10062,7 @@ "note": "double precision, gate by gate", "strict": 8.431147619128386e-17, "global_phase": -2.74751183636626e-17, - "seconds": 0.6570957499789074 + "seconds": 0.7063159999670461 }, { "entry": "gate_tdg", @@ -10074,7 +10074,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.621579032190157e-16, "global_phase": 1.8282281350235733e-17, - "seconds": 0.000716750044375658 + "seconds": 0.0005677080480381846 }, { "entry": "gate_tdg", @@ -10086,7 +10086,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.726175410066437e-17, "global_phase": -2.7402490746767553e-17, - "seconds": 0.006481458083726466 + "seconds": 0.015360749908722937 }, { "entry": "gate_tdg", @@ -10098,7 +10098,7 @@ "note": "single precision, fusion width 2", "strict": 3.9294051504657585e-08, "global_phase": -5.440896726885419e-09, - "seconds": 0.0022270840127021074 + "seconds": 0.0015462500741705298 }, { "entry": "gate_tdg", @@ -10154,7 +10154,7 @@ "note": "double precision, fusion width 3", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 1.8958e-05 + "seconds": 1.6792e-05 }, { "entry": "gate_sx", @@ -10166,7 +10166,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 8.6e-05 + "seconds": 0.000113167 }, { "entry": "gate_sx", @@ -10178,7 +10178,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 9.1542e-05, + "seconds": 7.1791e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10193,7 +10193,7 @@ "note": "double precision, gate by gate", "strict": 2.1256783263827326e-16, "global_phase": 8.210562796199066e-17, - "seconds": 0.6551397920120507 + "seconds": 1.019597707898356 }, { "entry": "gate_sx", @@ -10205,7 +10205,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.1090496388272583e-16, "global_phase": 8.243520055263914e-17, - "seconds": 0.0009732079925015569 + "seconds": 0.0005787080153822899 }, { "entry": "gate_sx", @@ -10217,7 +10217,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.110604477631002e-17, "global_phase": 2.0920862582516193e-17, - "seconds": 0.007463417015969753 + "seconds": 0.030845083063468337 }, { "entry": "gate_sx", @@ -10229,7 +10229,7 @@ "note": "single precision, fusion width 2", "strict": 6.78300679413258e-08, "global_phase": 1.3427146129244078e-08, - "seconds": 0.0025349579518660903 + "seconds": 0.0015356669900938869 }, { "entry": "gate_sx", @@ -10285,7 +10285,7 @@ "note": "double precision, fusion width 3", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 1.8916e-05 + "seconds": 1.3708e-05 }, { "entry": "gate_sxdg", @@ -10297,7 +10297,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 7.8125e-05 + "seconds": 0.000271917 }, { "entry": "gate_sxdg", @@ -10309,7 +10309,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.1089515082943579e-16, "global_phase": -7.799576258747036e-17, - "seconds": 0.000101458, + "seconds": 0.000122292, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10324,7 +10324,7 @@ "note": "double precision, gate by gate", "strict": 1.7383536862858317e-16, "global_phase": -9.046543988136775e-17, - "seconds": 0.6299727089935914 + "seconds": 1.290608249953948 }, { "entry": "gate_sxdg", @@ -10336,7 +10336,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.6741400176489413e-16, "global_phase": -1.3098476345895072e-17, - "seconds": 0.0007317919516935945 + "seconds": 0.000650708912871778 }, { "entry": "gate_sxdg", @@ -10348,7 +10348,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.110604477631002e-17, "global_phase": 2.0920862582516193e-17, - "seconds": 0.006665875087492168 + "seconds": 0.0174330830341205 }, { "entry": "gate_sxdg", @@ -10360,7 +10360,7 @@ "note": "single precision, fusion width 2", "strict": 6.78300679413258e-08, "global_phase": 1.3427146129244078e-08, - "seconds": 0.0016049999976530671 + "seconds": 0.0018510830122977495 }, { "entry": "gate_sxdg", @@ -10416,7 +10416,7 @@ "note": "double precision, fusion width 3", "strict": 7.704220013563471e-17, "global_phase": -2.4223802756456756e-17, - "seconds": 1.6875e-05 + "seconds": 2.375e-05 }, { "entry": "gate_p", @@ -10428,7 +10428,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.704220013563471e-17, "global_phase": -2.4223802756456756e-17, - "seconds": 0.000124292 + "seconds": 0.000114333 }, { "entry": "gate_p", @@ -10440,7 +10440,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 7.704220013563471e-17, "global_phase": -2.4223802756456756e-17, - "seconds": 0.000203584, + "seconds": 7.1958e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10455,7 +10455,7 @@ "note": "double precision, gate by gate", "strict": 7.704220013563471e-17, "global_phase": -2.4223802756456756e-17, - "seconds": 0.5901338330004364 + "seconds": 0.9806178340222687 }, { "entry": "gate_p", @@ -10467,7 +10467,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.603191180512201e-16, "global_phase": 2.4727213882336242e-17, - "seconds": 0.0006500000599771738 + "seconds": 0.001393625047057867 }, { "entry": "gate_p", @@ -10479,7 +10479,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.7124430933596e-17, "global_phase": -2.551922345944299e-17, - "seconds": 0.007014084025286138 + "seconds": 0.011579458019696176 }, { "entry": "gate_p", @@ -10491,7 +10491,7 @@ "note": "single precision, fusion width 2", "strict": 4.069058074240716e-08, "global_phase": -4.899699442767947e-09, - "seconds": 0.0017437089700251818 + "seconds": 0.004895874997600913 }, { "entry": "gate_p", @@ -10547,7 +10547,7 @@ "note": "double precision, fusion width 3", "strict": 8.906935906670267e-17, "global_phase": -2.0163293299049675e-17, - "seconds": 1.6291e-05 + "seconds": 1.5792e-05 }, { "entry": "gate_rz", @@ -10559,7 +10559,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.906935906670267e-17, "global_phase": -2.0163293299049675e-17, - "seconds": 8.1459e-05 + "seconds": 8.0958e-05 }, { "entry": "gate_rz", @@ -10571,7 +10571,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.906935906670267e-17, "global_phase": -2.0163293299049675e-17, - "seconds": 7.875e-05, + "seconds": 0.000116833, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10586,7 +10586,7 @@ "note": "double precision, gate by gate", "strict": 8.906935906670267e-17, "global_phase": -2.0163293299049675e-17, - "seconds": 0.625785082927905 + "seconds": 1.0173114999197423 }, { "entry": "gate_rz", @@ -10598,7 +10598,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.423352576881746e-17, "global_phase": 3.694430415771201e-18, - "seconds": 0.0007293749367818236 + "seconds": 0.0017916669603437185 }, { "entry": "gate_rz", @@ -10610,7 +10610,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.4301320525273574e-17, "global_phase": 2.3736116645869262e-18, - "seconds": 0.0067540829768404365 + "seconds": 0.007624458987265825 }, { "entry": "gate_rz", @@ -10622,7 +10622,7 @@ "note": "single precision, fusion width 2", "strict": 4.9245204249981744e-08, "global_phase": -5.909026658431931e-09, - "seconds": 0.0019239999819546938 + "seconds": 0.003764165914617479 }, { "entry": "gate_rz", @@ -10678,7 +10678,7 @@ "note": "double precision, fusion width 3", "strict": 8.351343419056392e-17, "global_phase": -3.476965240722211e-17, - "seconds": 2.0375e-05 + "seconds": 1.8333e-05 }, { "entry": "gate_rx", @@ -10690,7 +10690,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.351343419056392e-17, "global_phase": -3.476965240722211e-17, - "seconds": 9.2291e-05 + "seconds": 0.000110875 }, { "entry": "gate_rx", @@ -10702,7 +10702,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.351343419056392e-17, "global_phase": -3.476965240722211e-17, - "seconds": 9.7292e-05, + "seconds": 7e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10717,7 +10717,7 @@ "note": "double precision, gate by gate", "strict": 8.351343419056392e-17, "global_phase": -3.476965240722211e-17, - "seconds": 0.7063675000099465 + "seconds": 1.0660541669931263 }, { "entry": "gate_rx", @@ -10729,7 +10729,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 4.747293914809713e-17, "global_phase": -1.7259486340313865e-17, - "seconds": 0.0007421249756589532 + "seconds": 0.0005597079871222377 }, { "entry": "gate_rx", @@ -10741,7 +10741,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.9052959352986414e-16, "global_phase": -9.775449483214286e-19, - "seconds": 0.0069761250633746386 + "seconds": 0.022473041084595025 }, { "entry": "gate_rx", @@ -10753,7 +10753,7 @@ "note": "single precision, fusion width 2", "strict": 7.129914998234027e-08, "global_phase": -3.2649839578724243e-09, - "seconds": 0.002346124965697527 + "seconds": 0.0015348340384662151 }, { "entry": "gate_rx", @@ -10809,7 +10809,7 @@ "note": "double precision, fusion width 3", "strict": 6.842613937384835e-17, "global_phase": -3.969624109223988e-17, - "seconds": 1.875e-05 + "seconds": 1.5083e-05 }, { "entry": "gate_ry", @@ -10821,7 +10821,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 6.842613937384835e-17, "global_phase": -3.969624109223988e-17, - "seconds": 9.1e-05 + "seconds": 0.000121042 }, { "entry": "gate_ry", @@ -10833,7 +10833,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 6.842613937384835e-17, "global_phase": -3.969624109223988e-17, - "seconds": 8.2208e-05, + "seconds": 7.9917e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10848,7 +10848,7 @@ "note": "double precision, gate by gate", "strict": 6.842613937384835e-17, "global_phase": -3.969624109223988e-17, - "seconds": 0.6641252089757472 + "seconds": 0.7625105420593172 }, { "entry": "gate_ry", @@ -10860,7 +10860,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 1.6948196926025085e-16, "global_phase": -3.031878606224255e-17, - "seconds": 0.0007669170154258609 + "seconds": 0.0005788750713691115 }, { "entry": "gate_ry", @@ -10872,7 +10872,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.076873167985705e-16, "global_phase": -9.487130142598933e-19, - "seconds": 0.007180667016655207 + "seconds": 0.007256000069901347 }, { "entry": "gate_ry", @@ -10884,7 +10884,7 @@ "note": "single precision, fusion width 2", "strict": 6.62136778343432e-08, "global_phase": -6.580287270675968e-09, - "seconds": 0.0020042499527335167 + "seconds": 0.0018285000696778297 }, { "entry": "gate_ry", @@ -10940,7 +10940,7 @@ "note": "double precision, fusion width 3", "strict": 8.691864484222037e-17, "global_phase": -2.533016296550929e-17, - "seconds": 2.0625e-05 + "seconds": 1.2875e-05 }, { "entry": "gate_u", @@ -10952,7 +10952,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.691864484222037e-17, "global_phase": -2.533016296550929e-17, - "seconds": 8.175e-05 + "seconds": 8.1292e-05 }, { "entry": "gate_u", @@ -10964,7 +10964,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 8.691864484222037e-17, "global_phase": -2.533016296550929e-17, - "seconds": 0.000163875, + "seconds": 6.6375e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -10979,7 +10979,7 @@ "note": "double precision, gate by gate", "strict": 9.062939036628874e-17, "global_phase": -2.5197304693384104e-17, - "seconds": 0.7177870830055326 + "seconds": 0.7099299590336159 }, { "entry": "gate_u", @@ -10991,7 +10991,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 4.01615510436094e-17, "global_phase": -1.2559845816239341e-17, - "seconds": 0.0009107080986723304 + "seconds": 0.0005679579917341471 }, { "entry": "gate_u", @@ -11003,7 +11003,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 9.242975907293169e-17, "global_phase": -3.9457728612879396e-17, - "seconds": 0.006574749946594238 + "seconds": 0.011642374913208187 }, { "entry": "gate_u", @@ -11015,7 +11015,7 @@ "note": "single precision, fusion width 2", "strict": 5.612864953246846e-08, "global_phase": 5.11756754852118e-09, - "seconds": 0.0021525000920519233, + "seconds": 0.0015421248972415924, "adapter": [ "U as a matrix" ] @@ -11074,7 +11074,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 2.2e-05 + "seconds": 1.6583e-05 }, { "entry": "gate_cx", @@ -11086,7 +11086,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 8.2375e-05 + "seconds": 0.000110667 }, { "entry": "gate_cx", @@ -11098,7 +11098,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000102041, + "seconds": 7.25e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11113,7 +11113,7 @@ "note": "double precision, gate by gate", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.6885488330153748 + "seconds": 0.558161791996099 }, { "entry": "gate_cx", @@ -11125,7 +11125,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 3.778483450154536e-16, "global_phase": 6.050544364771103e-18, - "seconds": 0.0011385419638827443 + "seconds": 0.0010853749699890614 }, { "entry": "gate_cx", @@ -11137,7 +11137,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.424447715313029e-17, "global_phase": -1.260889585891152e-17, - "seconds": 0.007710082922130823 + "seconds": 0.00798595801461488 }, { "entry": "gate_cx", @@ -11149,7 +11149,7 @@ "note": "single precision, fusion width 2", "strict": 4.296790162479773e-08, "global_phase": -7.042653724334558e-10, - "seconds": 0.004395208088681102 + "seconds": 0.0014834579778835177 }, { "entry": "gate_cx", @@ -11205,7 +11205,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 2.5417e-05 + "seconds": 1.6042e-05 }, { "entry": "gate_cy", @@ -11217,7 +11217,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 9.1625e-05 + "seconds": 6.9125e-05 }, { "entry": "gate_cy", @@ -11229,7 +11229,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.000135375, + "seconds": 6.8667e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11244,7 +11244,7 @@ "note": "double precision, gate by gate", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.78905216709245 + "seconds": 0.8031259160488844 }, { "entry": "gate_cy", @@ -11256,7 +11256,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 3.778483450154536e-16, "global_phase": 6.050544364771103e-18, - "seconds": 0.0012263329699635506 + "seconds": 0.0008610000368207693 }, { "entry": "gate_cy", @@ -11268,7 +11268,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.801829443895296e-17, "global_phase": -1.2344437959503701e-17, - "seconds": 0.007531457929871976 + "seconds": 0.04415529198013246 }, { "entry": "gate_cy", @@ -11280,7 +11280,7 @@ "note": "single precision, fusion width 2", "strict": 5.6825705358055105e-08, "global_phase": -2.1986460052579153e-09, - "seconds": 0.002031874959357083 + "seconds": 0.002013999968767166 }, { "entry": "gate_cy", @@ -11336,7 +11336,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 2.4709e-05 + "seconds": 2.75e-05 }, { "entry": "gate_cz", @@ -11348,7 +11348,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 8.5208e-05 + "seconds": 7.2292e-05 }, { "entry": "gate_cz", @@ -11360,7 +11360,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 0.00014625, + "seconds": 0.000119292, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11375,7 +11375,7 @@ "note": "double precision, gate by gate", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.7159432499902323 + "seconds": 1.2432489159982651 }, { "entry": "gate_cz", @@ -11387,7 +11387,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 8.156704561960557e-17, "global_phase": -6.427926048830758e-17, - "seconds": 0.0013074999442324042 + "seconds": 0.0008590839570388198 }, { "entry": "gate_cz", @@ -11399,7 +11399,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.2301684670985136e-17, "global_phase": 1.4944812019014365e-17, - "seconds": 0.009142042021267116 + "seconds": 0.04187512502539903 }, { "entry": "gate_cz", @@ -11411,7 +11411,7 @@ "note": "single precision, fusion width 2", "strict": 4.296790162479773e-08, "global_phase": -7.042653724334558e-10, - "seconds": 0.002105124993249774 + "seconds": 0.0015359580283984542 }, { "entry": "gate_cz", @@ -11467,7 +11467,7 @@ "note": "double precision, fusion width 3", "strict": 9.011893242098248e-17, "global_phase": -3.534699716199192e-17, - "seconds": 2.8375e-05 + "seconds": 2.8875e-05 }, { "entry": "gate_ch", @@ -11479,7 +11479,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0533633233600722e-16, "global_phase": -6.049332165550436e-17, - "seconds": 9.3125e-05 + "seconds": 0.000121458 }, { "entry": "gate_ch", @@ -11491,7 +11491,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.0533633233600722e-16, "global_phase": -6.049332165550436e-17, - "seconds": 0.000105084, + "seconds": 0.000281875, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11506,7 +11506,7 @@ "note": "double precision, gate by gate", "strict": 8.985218225594548e-17, "global_phase": -3.5719863374613633e-17, - "seconds": 0.7333125000586733 + "seconds": 1.246499832952395 }, { "entry": "gate_ch", @@ -11518,7 +11518,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 8.772139154731484e-17, "global_phase": -9.37410417629485e-18, - "seconds": 0.0009569579269737005 + "seconds": 0.0007760409498587251 }, { "entry": "gate_ch", @@ -11530,7 +11530,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.1310339669549782e-16, "global_phase": -9.561523159884953e-18, - "seconds": 0.006895167054608464 + "seconds": 0.018536749994382262 }, { "entry": "gate_ch", @@ -11542,7 +11542,7 @@ "note": "single precision, fusion width 2", "strict": 3.830341195150859e-08, "global_phase": -4.95768373465406e-10, - "seconds": 0.0019716660026460886 + "seconds": 0.0021364999702200294 }, { "entry": "gate_ch", @@ -11598,7 +11598,7 @@ "note": "double precision, fusion width 3", "strict": 1.0208510354511309e-16, "global_phase": -3.1023325683456925e-17, - "seconds": 3.1333e-05 + "seconds": 0.001398541 }, { "entry": "gate_csx", @@ -11610,7 +11610,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9841132369045797e-16, "global_phase": -6.062903440956213e-17, - "seconds": 9.675e-05 + "seconds": 6.7292e-05 }, { "entry": "gate_csx", @@ -11622,7 +11622,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9841132369045797e-16, "global_phase": -6.062903440956213e-17, - "seconds": 9.3292e-05, + "seconds": 0.0001615, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11637,7 +11637,7 @@ "note": "double precision, gate by gate", "strict": 1.0607870396802327e-16, "global_phase": -2.968106878572714e-17, - "seconds": 0.7143757090670988 + "seconds": 0.8055441250326112 }, { "entry": "gate_csx", @@ -11649,7 +11649,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 9.680265184438853e-17, "global_phase": -4.4577935608648455e-18, - "seconds": 0.0010830420069396496 + "seconds": 0.002128459047526121 }, { "entry": "gate_csx", @@ -11661,7 +11661,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 5.398241258913e-17, "global_phase": 9.271704718585812e-18, - "seconds": 0.008394917007535696 + "seconds": 0.04627887497190386 }, { "entry": "gate_csx", @@ -11673,7 +11673,7 @@ "note": "single precision, fusion width 2", "strict": 9.135192126279703e-08, "global_phase": -4.1025140345377066e-09, - "seconds": 0.0025467919185757637 + "seconds": 0.0015586670488119125 }, { "entry": "gate_csx", @@ -11729,7 +11729,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 2.3083e-05 + "seconds": 3.1625e-05 }, { "entry": "gate_swap", @@ -11741,7 +11741,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 8.5541e-05 + "seconds": 7.5083e-05 }, { "entry": "gate_swap", @@ -11753,7 +11753,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 9.3083e-05, + "seconds": 7.5125e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11768,7 +11768,7 @@ "note": "double precision, gate by gate", "strict": 8.857402632175859e-17, "global_phase": -9.647844174701355e-18, - "seconds": 0.739341166918166 + "seconds": 0.7619529999792576 }, { "entry": "gate_swap", @@ -11780,7 +11780,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 9.01323343579344e-17, "global_phase": -3.574487808951742e-17, - "seconds": 0.0009713330073282123 + "seconds": 0.0006532080005854368 }, { "entry": "gate_swap", @@ -11792,7 +11792,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.929333588180882e-17, "global_phase": 1.4669463408880753e-17, - "seconds": 0.007196167018264532 + "seconds": 0.0166486669331789 }, { "entry": "gate_swap", @@ -11804,7 +11804,7 @@ "note": "single precision, fusion width 2", "strict": 4.296790162479773e-08, "global_phase": -7.042653724334558e-10, - "seconds": 0.003392416052520275 + "seconds": 0.0034385829931125045 }, { "entry": "gate_swap", @@ -11860,7 +11860,7 @@ "note": "double precision, fusion width 3", "strict": 8.915186535406673e-17, "global_phase": -3.5692466279524444e-17, - "seconds": 2.3458e-05 + "seconds": 1.7167e-05 }, { "entry": "gate_cp", @@ -11872,7 +11872,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9817542452890808e-16, "global_phase": -5.941143185791318e-17, - "seconds": 9.1166e-05 + "seconds": 0.000123583 }, { "entry": "gate_cp", @@ -11884,7 +11884,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9817542452890808e-16, "global_phase": -5.941143185791318e-17, - "seconds": 9.975e-05, + "seconds": 0.000117209, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -11899,7 +11899,7 @@ "note": "double precision, gate by gate", "strict": 8.915186535406673e-17, "global_phase": -3.5692466279524444e-17, - "seconds": 0.7373385420069098 + "seconds": 0.7207425410160795 }, { "entry": "gate_cp", @@ -11911,7 +11911,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 4.974582733262186e-16, "global_phase": -2.029888880742396e-17, - "seconds": 0.0012492919340729713 + "seconds": 0.0008771659340709448 }, { "entry": "gate_cp", @@ -11923,7 +11923,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.235558624947136e-17, "global_phase": 1.496056354469242e-17, - "seconds": 0.007103707990609109 + "seconds": 0.01241858396679163 }, { "entry": "gate_cp", @@ -11935,7 +11935,7 @@ "note": "single precision, fusion width 2", "strict": 4.301606447545541e-08, "global_phase": -6.996408136330974e-10, - "seconds": 0.0020885829580947757 + "seconds": 0.002208916936069727 }, { "entry": "gate_cp", @@ -11991,7 +11991,7 @@ "note": "double precision, fusion width 3", "strict": 9.698821067454252e-17, "global_phase": -3.59045673273073e-17, - "seconds": 2.7e-05 + "seconds": 1.6292e-05 }, { "entry": "gate_crx", @@ -12003,7 +12003,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9851544823524085e-16, "global_phase": -5.956982339748994e-17, - "seconds": 8.1833e-05 + "seconds": 7.4167e-05 }, { "entry": "gate_crx", @@ -12015,7 +12015,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9851544823524085e-16, "global_phase": -5.956982339748994e-17, - "seconds": 0.000141167, + "seconds": 7.2e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12030,7 +12030,7 @@ "note": "double precision, gate by gate", "strict": 8.937313609797023e-17, "global_phase": -3.551321375263718e-17, - "seconds": 0.7483639999991283 + "seconds": 0.8944710000650957 }, { "entry": "gate_crx", @@ -12042,7 +12042,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 5.905751555211743e-17, "global_phase": -4.0461299578041385e-17, - "seconds": 0.0012154580326750875 + "seconds": 0.0024242079816758633 }, { "entry": "gate_crx", @@ -12054,7 +12054,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.765720863933407e-17, "global_phase": -9.482197611873177e-18, - "seconds": 0.00849475001450628 + "seconds": 0.03131554205901921 }, { "entry": "gate_crx", @@ -12066,7 +12066,7 @@ "note": "single precision, fusion width 2", "strict": 4.162956293979161e-08, "global_phase": -3.4714031841852236e-10, - "seconds": 0.0020091250771656632 + "seconds": 0.0016199999954551458 }, { "entry": "gate_crx", @@ -12122,7 +12122,7 @@ "note": "double precision, fusion width 3", "strict": 1.0024255523485516e-16, "global_phase": -3.6054244168158195e-17, - "seconds": 2.3833e-05 + "seconds": 2.0375e-05 }, { "entry": "gate_cry", @@ -12134,7 +12134,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.980659682132769e-16, "global_phase": -5.968868788740983e-17, - "seconds": 9e-05 + "seconds": 7.3084e-05 }, { "entry": "gate_cry", @@ -12146,7 +12146,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.980659682132769e-16, "global_phase": -5.968868788740983e-17, - "seconds": 0.000169959, + "seconds": 7.6958e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12161,7 +12161,7 @@ "note": "double precision, gate by gate", "strict": 9.069659730700616e-17, "global_phase": -3.563116664468008e-17, - "seconds": 0.7056761670392007 + "seconds": 1.3870113339507952 }, { "entry": "gate_cry", @@ -12173,7 +12173,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 9.178037186815411e-17, "global_phase": -3.6321921215572887e-17, - "seconds": 0.0012542919721454382 + "seconds": 0.0008876660140231252 }, { "entry": "gate_cry", @@ -12185,7 +12185,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 9.707217474362964e-17, "global_phase": -8.644535780344246e-18, - "seconds": 0.010712124989368021 + "seconds": 0.015472875093109906 }, { "entry": "gate_cry", @@ -12197,7 +12197,7 @@ "note": "single precision, fusion width 2", "strict": 4.267426359551002e-08, "global_phase": -3.6525359836624644e-10, - "seconds": 0.0026933749904856086 + "seconds": 0.002669833949767053 }, { "entry": "gate_cry", @@ -12253,7 +12253,7 @@ "note": "double precision, fusion width 3", "strict": 9.947118394848183e-17, "global_phase": -3.5386121754067354e-17, - "seconds": 2.575e-05 + "seconds": 2.9917e-05 }, { "entry": "gate_crz", @@ -12265,7 +12265,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9815193236339522e-16, "global_phase": -5.946576214758588e-17, - "seconds": 9.1375e-05 + "seconds": 0.000115583 }, { "entry": "gate_crz", @@ -12277,7 +12277,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9815193236339522e-16, "global_phase": -5.946576214758588e-17, - "seconds": 9.5792e-05, + "seconds": 6.9833e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12292,7 +12292,7 @@ "note": "double precision, gate by gate", "strict": 9.947118394848183e-17, "global_phase": -3.5386121754067354e-17, - "seconds": 0.8031141249230132 + "seconds": 0.9984477909747511 }, { "entry": "gate_crz", @@ -12304,7 +12304,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 4.992581333239521e-16, "global_phase": -2.2004954527095423e-17, - "seconds": 0.0016674589132890105 + "seconds": 0.0008617499843239784 }, { "entry": "gate_crz", @@ -12316,7 +12316,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.2365718473423015e-17, "global_phase": 1.4328304100354705e-17, - "seconds": 0.008539333008229733 + "seconds": 0.007276791031472385 }, { "entry": "gate_crz", @@ -12328,7 +12328,7 @@ "note": "single precision, fusion width 2", "strict": 4.083610273043291e-08, "global_phase": -2.29070122492177e-10, - "seconds": 0.0022659170208498836 + "seconds": 0.0016031250124797225 }, { "entry": "gate_crz", @@ -12384,7 +12384,7 @@ "note": "double precision, fusion width 3", "strict": 8.902240780164087e-17, "global_phase": -3.5454719336911746e-17, - "seconds": 3.3666e-05 + "seconds": 2.8875e-05 }, { "entry": "gate_cu", @@ -12396,7 +12396,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9900977238579004e-16, "global_phase": -5.778302861011668e-17, - "seconds": 9.8083e-05 + "seconds": 7.6916e-05 }, { "entry": "gate_cu", @@ -12408,7 +12408,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9900977238579004e-16, "global_phase": -5.778302861011668e-17, - "seconds": 0.0001105, + "seconds": 7.0833e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12423,7 +12423,7 @@ "note": "double precision, gate by gate", "strict": 9.116147684377254e-17, "global_phase": -3.288207428251009e-17, - "seconds": 0.7930143749108538 + "seconds": 0.9770995000144467 }, { "entry": "gate_cu", @@ -12435,7 +12435,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 2.572025557052927e-16, "global_phase": 1.3800428260067192e-17, - "seconds": 0.0012696670601144433 + "seconds": 0.0008562079165130854 }, { "entry": "gate_cu", @@ -12447,7 +12447,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.0045300706224988e-16, "global_phase": -3.793081001973975e-17, - "seconds": 0.007740834029391408 + "seconds": 0.01790783298201859 }, { "entry": "gate_cu", @@ -12459,7 +12459,7 @@ "note": "single precision, fusion width 2", "strict": 3.781885610752036e-08, "global_phase": -8.849624579695987e-10, - "seconds": 0.002226875047199428, + "seconds": 0.008807957987301052, "adapter": [ "U as a matrix" ] @@ -12518,7 +12518,7 @@ "note": "double precision, fusion width 3", "strict": 8.114732548118926e-17, "global_phase": -3.46438477984978e-17, - "seconds": 2.3625e-05 + "seconds": 1.4625e-05 }, { "entry": "gate_rzz", @@ -12530,7 +12530,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.875523507253141e-16, "global_phase": -6.500887442050855e-17, - "seconds": 8.7333e-05 + "seconds": 7.8334e-05 }, { "entry": "gate_rzz", @@ -12542,7 +12542,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.875523507253141e-16, "global_phase": -6.500887442050855e-17, - "seconds": 9.3042e-05, + "seconds": 0.000154041, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12557,7 +12557,7 @@ "note": "double precision, gate by gate", "strict": 8.114732548118926e-17, "global_phase": -3.46438477984978e-17, - "seconds": 0.7214878750964999 + "seconds": 0.8263376669492573 }, { "entry": "gate_rzz", @@ -12569,7 +12569,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 3.132901957985602e-16, "global_phase": 5.792832858446134e-17, - "seconds": 0.0012397919781506062 + "seconds": 0.0008921250700950623 }, { "entry": "gate_rzz", @@ -12581,7 +12581,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 8.865470546336336e-17, "global_phase": 1.650644909206721e-17, - "seconds": 0.007890457985922694 + "seconds": 0.005681542097590864 }, { "entry": "gate_rzz", @@ -12593,7 +12593,7 @@ "note": "single precision, fusion width 2", "strict": 3.6217862026912536e-08, "global_phase": -2.001740753797614e-08, - "seconds": 0.0022805420449003577 + "seconds": 0.0016523749800398946 }, { "entry": "gate_rzz", @@ -12649,7 +12649,7 @@ "note": "double precision, fusion width 3", "strict": 1.203844925257312e-16, "global_phase": -3.9846685910587735e-17, - "seconds": 2.3041e-05 + "seconds": 1.9625e-05 }, { "entry": "gate_rxx", @@ -12661,7 +12661,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2266091037362635e-16, "global_phase": -6.390672161584823e-17, - "seconds": 9.6958e-05 + "seconds": 8.1e-05 }, { "entry": "gate_rxx", @@ -12673,7 +12673,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2266091037362635e-16, "global_phase": -6.390672161584823e-17, - "seconds": 0.000103, + "seconds": 0.000117542, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12688,7 +12688,7 @@ "note": "double precision, gate by gate", "strict": 2.993293632559793e-17, "global_phase": -1.5868953958951843e-17, - "seconds": 0.7132997079752386 + "seconds": 0.9942690000170842 }, { "entry": "gate_rxx", @@ -12700,7 +12700,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 2.7024896234354156e-16, "global_phase": -7.113148978257477e-17, - "seconds": 0.0013462500646710396 + "seconds": 0.0038889580173417926 }, { "entry": "gate_rxx", @@ -12712,7 +12712,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.5088529315976045e-16, "global_phase": 1.755149544000275e-17, - "seconds": 0.007711999933235347 + "seconds": 0.010925250011496246 }, { "entry": "gate_rxx", @@ -12724,7 +12724,7 @@ "note": "single precision, fusion width 2", "strict": 1.2554825913126517e-07, "global_phase": 6.8084188181270535e-09, - "seconds": 0.0020524999126791954 + "seconds": 0.0025155419716611505 }, { "entry": "gate_rxx", @@ -12780,7 +12780,7 @@ "note": "double precision, fusion width 3", "strict": 1.288187406182432e-16, "global_phase": -5.957428546725693e-17, - "seconds": 2.45e-05 + "seconds": 2.8917e-05 }, { "entry": "gate_ryy", @@ -12792,7 +12792,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2962602289809404e-16, "global_phase": -8.332955701122513e-17, - "seconds": 8.0417e-05 + "seconds": 8.4042e-05 }, { "entry": "gate_ryy", @@ -12804,7 +12804,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2962602289809404e-16, "global_phase": -8.332955701122513e-17, - "seconds": 8.7834e-05, + "seconds": 0.000132417, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12819,7 +12819,7 @@ "note": "double precision, gate by gate", "strict": 1.1667039620467854e-16, "global_phase": -3.318898649554226e-17, - "seconds": 0.6715597920119762 + "seconds": 1.003961291979067 }, { "entry": "gate_ryy", @@ -12831,7 +12831,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 3.365212531259756e-16, "global_phase": 3.591202806032668e-17, - "seconds": 0.0010125000262632966 + "seconds": 0.0008524999720975757 }, { "entry": "gate_ryy", @@ -12843,7 +12843,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.2181771912564385e-16, "global_phase": -3.182350774689283e-17, - "seconds": 0.007109249942004681 + "seconds": 0.03313570795580745 }, { "entry": "gate_ryy", @@ -12855,7 +12855,7 @@ "note": "single precision, fusion width 2", "strict": 1.2389415268537378e-07, "global_phase": 8.666792549211895e-09, - "seconds": 0.0020860000513494015 + "seconds": 0.0019044169457629323 }, { "entry": "gate_ryy", @@ -12911,7 +12911,7 @@ "note": "double precision, fusion width 3", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 2.2333e-05 + "seconds": 1.8167e-05 }, { "entry": "gate_negcx", @@ -12923,7 +12923,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 7.1625e-05 + "seconds": 0.000113792 }, { "entry": "gate_negcx", @@ -12935,7 +12935,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9816663129359017e-16, "global_phase": -5.942718338359123e-17, - "seconds": 8.125e-05, + "seconds": 0.000127833, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -12950,7 +12950,7 @@ "note": "double precision, gate by gate", "strict": 8.91361828527817e-17, "global_phase": -3.568434112943644e-17, - "seconds": 0.6061415410367772, + "seconds": 1.2405191669240594, "adapter": [ "negcx as x, cx, x" ] @@ -12965,7 +12965,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 6.041622321583409e-16, "global_phase": 2.8010171756885993e-17, - "seconds": 0.0011324590304866433, + "seconds": 0.00135087501257658, "adapter": [ "negcx as x, cx, x" ] @@ -12980,7 +12980,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.424447715313029e-17, "global_phase": -1.260889585891152e-17, - "seconds": 0.007902625016868114 + "seconds": 0.06010599993169308 }, { "entry": "gate_negcx", @@ -12992,7 +12992,7 @@ "note": "single precision, fusion width 2", "strict": 4.286542552850247e-08, "global_phase": -4.328999574845852e-10, - "seconds": 0.0020679589360952377 + "seconds": 0.0016232091002166271 }, { "entry": "gate_negcx", @@ -13048,7 +13048,7 @@ "note": "double precision, fusion width 3", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 3.225e-05 + "seconds": 2.0042e-05 }, { "entry": "gate_ccx", @@ -13060,7 +13060,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 8.6125e-05 + "seconds": 7.4584e-05 }, { "entry": "gate_ccx", @@ -13072,7 +13072,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.000102958, + "seconds": 7.0708e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13087,7 +13087,7 @@ "note": "double precision, gate by gate", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 0.6733255409635603 + "seconds": 1.1989442500052974 }, { "entry": "gate_ccx", @@ -13099,7 +13099,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 1.3744133063303021e-16, "global_phase": -2.814523452227737e-17, - "seconds": 0.002241124981082976 + "seconds": 0.0008930000476539135 }, { "entry": "gate_ccx", @@ -13111,7 +13111,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.6170785510676706e-16, "global_phase": -2.4539622958386736e-18, - "seconds": 0.007149667013436556 + "seconds": 0.007365084020420909 }, { "entry": "gate_ccx", @@ -13123,7 +13123,7 @@ "note": "single precision, fusion width 2", "strict": 2.505080409941186e-08, "global_phase": 2.4572498391005102e-09, - "seconds": 0.0020743749337270856 + "seconds": 0.001663499977439642 }, { "entry": "gate_ccx", @@ -13179,7 +13179,7 @@ "note": "double precision, fusion width 3", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 4.4041e-05 + "seconds": 2.2667e-05 }, { "entry": "gate_ccz", @@ -13191,7 +13191,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.002171125 + "seconds": 7.0667e-05 }, { "entry": "gate_ccz", @@ -13203,7 +13203,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 9.5959e-05, + "seconds": 0.000620917, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13218,7 +13218,7 @@ "note": "double precision, gate by gate", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 0.7086746669374406 + "seconds": 0.8200022919336334 }, { "entry": "gate_ccz", @@ -13230,7 +13230,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 1.3744133063303021e-16, "global_phase": -2.814523452227737e-17, - "seconds": 0.001305249985307455 + "seconds": 0.0009385420707985759 }, { "entry": "gate_ccz", @@ -13242,7 +13242,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.4495985349309682e-17, "global_phase": 1.7289083146586244e-19, - "seconds": 0.007399083930067718 + "seconds": 0.023963917046785355 }, { "entry": "gate_ccz", @@ -13254,7 +13254,7 @@ "note": "single precision, fusion width 2", "strict": 2.505080409941186e-08, "global_phase": 2.4572498391005102e-09, - "seconds": 0.0020327920792624354 + "seconds": 0.0016103750094771385 }, { "entry": "gate_ccz", @@ -13310,7 +13310,7 @@ "note": "double precision, fusion width 3", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 2.5875e-05 + "seconds": 2e-05 }, { "entry": "gate_cswap", @@ -13322,7 +13322,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 9.6917e-05 + "seconds": 7.5083e-05 }, { "entry": "gate_cswap", @@ -13334,7 +13334,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470248802848714e-16, "global_phase": -5.533171119339035e-17, - "seconds": 0.000116666, + "seconds": 0.000117083, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13349,7 +13349,7 @@ "note": "double precision, gate by gate", "strict": 1.3855057211099486e-16, "global_phase": -2.8088910435967144e-17, - "seconds": 0.7115917910123244 + "seconds": 1.0741413749055937 }, { "entry": "gate_cswap", @@ -13361,7 +13361,7 @@ "note": "double precision, a contraction of width 6.0", "strict": 1.3744133063303021e-16, "global_phase": -2.814523452227737e-17, - "seconds": 0.001284250058233738 + "seconds": 0.0042279999470338225 }, { "entry": "gate_cswap", @@ -13373,7 +13373,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.0254124592450465e-17, "global_phase": 8.866276048486312e-20, - "seconds": 0.006985957967117429 + "seconds": 0.013357375049963593 }, { "entry": "gate_cswap", @@ -13385,7 +13385,7 @@ "note": "single precision, fusion width 2", "strict": 2.505080409941186e-08, "global_phase": 2.4572498391005102e-09, - "seconds": 0.0024481250438839197 + "seconds": 0.0027890000492334366 }, { "entry": "gate_cswap", @@ -13441,7 +13441,7 @@ "note": "double precision, fusion width 3", "strict": 1.3855069357692387e-16, "global_phase": -2.8088848837941315e-17, - "seconds": 2.9042e-05 + "seconds": 2.1834e-05 }, { "entry": "gate_c2p", @@ -13453,7 +13453,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470249484123369e-16, "global_phase": -5.5331649595364525e-17, - "seconds": 9.2542e-05 + "seconds": 7.3875e-05 }, { "entry": "gate_c2p", @@ -13465,7 +13465,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.470249484123369e-16, "global_phase": -5.5331649595364525e-17, - "seconds": 0.000112125, + "seconds": 8.1708e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13480,7 +13480,7 @@ "note": "double precision, gate by gate", "strict": 1.381935547493514e-16, "global_phase": -2.3764661567994983e-18, - "seconds": 0.7085941249970347 + "seconds": 0.9787547079613432 }, { "entry": "gate_c2p", @@ -13492,7 +13492,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 1.352333458073505e-16, "global_phase": -2.9436715280550853e-17, - "seconds": 0.002868416951969266 + "seconds": 0.0023358339676633477 }, { "entry": "gate_c2p", @@ -13504,7 +13504,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.4494944356881143e-17, "global_phase": 1.7280707492796442e-19, - "seconds": 0.007674457971006632 + "seconds": 0.011240249965339899 }, { "entry": "gate_c2p", @@ -13516,7 +13516,7 @@ "note": "single precision, fusion width 2", "strict": 2.5050870937410084e-08, "global_phase": 2.4572404383192984e-09, - "seconds": 0.002219707937911153 + "seconds": 0.0038095839554443955 }, { "entry": "gate_c2p", @@ -13572,7 +13572,7 @@ "note": "double precision, fusion width 3", "strict": 1.385638179882964e-16, "global_phase": -2.8091482637843886e-17, - "seconds": 3.0791e-05 + "seconds": 4e-05 }, { "entry": "gate_c2rz", @@ -13584,7 +13584,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.4470597500024585e-16, "global_phase": -5.569630515112943e-17, - "seconds": 9.1417e-05 + "seconds": 0.000127209 }, { "entry": "gate_c2rz", @@ -13596,7 +13596,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.4470597500024585e-16, "global_phase": -5.569630515112943e-17, - "seconds": 9.7958e-05, + "seconds": 7.3042e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13611,7 +13611,7 @@ "note": "double precision, gate by gate", "strict": 1.382070635945764e-16, "global_phase": -2.3707862926640698e-18, - "seconds": 0.7585006250301376 + "seconds": 0.861918666982092 }, { "entry": "gate_c2rz", @@ -13623,7 +13623,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 1.4044232659053483e-16, "global_phase": -2.38846211370799e-18, - "seconds": 0.0021687919506803155 + "seconds": 0.0014320409391075373 }, { "entry": "gate_c2rz", @@ -13635,7 +13635,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.4794165255085104e-17, "global_phase": 1.6610444227779503e-19, - "seconds": 0.012352249934338033 + "seconds": 0.009361000033095479 }, { "entry": "gate_c2rz", @@ -13647,7 +13647,7 @@ "note": "single precision, fusion width 2", "strict": 3.4097718185246246e-08, "global_phase": -1.165989000760594e-08, - "seconds": 0.002133250003680587 + "seconds": 0.002034542034380138 }, { "entry": "gate_c2rz", @@ -13703,7 +13703,7 @@ "note": "double precision, fusion width 3", "strict": 1.385606040263293e-16, "global_phase": -2.8089793690612016e-17, - "seconds": 3.0125e-05 + "seconds": 2.0333e-05 }, { "entry": "gate_c2ry", @@ -13715,7 +13715,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.4813348680394973e-16, "global_phase": -5.532178000472185e-17, - "seconds": 9.5625e-05 + "seconds": 8.2209e-05 }, { "entry": "gate_c2ry", @@ -13727,7 +13727,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.4813348680394973e-16, "global_phase": -5.532178000472185e-17, - "seconds": 0.0001285, + "seconds": 8.2583e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13742,7 +13742,7 @@ "note": "double precision, gate by gate", "strict": 1.381563334637396e-16, "global_phase": -2.3894788829053065e-18, - "seconds": 0.7230751249007881 + "seconds": 0.7866553330095485 }, { "entry": "gate_c2ry", @@ -13754,7 +13754,7 @@ "note": "double precision, a contraction of width 3.0", "strict": 1.404446644746442e-16, "global_phase": -2.404722727917057e-18, - "seconds": 0.001935333013534546 + "seconds": 0.006903458968736231 }, { "entry": "gate_c2ry", @@ -13766,7 +13766,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 6.141577281672248e-17, "global_phase": -5.4139581805191244e-17, - "seconds": 0.009426667005755007 + "seconds": 0.01593583298381418 }, { "entry": "gate_c2ry", @@ -13778,7 +13778,7 @@ "note": "single precision, fusion width 2", "strict": 3.411380878821099e-08, "global_phase": -1.1663097509706392e-08, - "seconds": 0.00235316704493016 + "seconds": 0.0018315829802304506 }, { "entry": "gate_c2ry", @@ -13834,7 +13834,7 @@ "note": "double precision, fusion width 3", "strict": 1.1418412035005258e-16, "global_phase": -9.306014224130332e-18, - "seconds": 3.575e-05 + "seconds": 2.1e-05 }, { "entry": "gate_c3x", @@ -13846,7 +13846,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2057454549202864e-16, "global_phase": -3.850320092070849e-17, - "seconds": 9.175e-05 + "seconds": 7.9459e-05 }, { "entry": "gate_c3x", @@ -13858,7 +13858,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.2057454549202864e-16, "global_phase": -3.850320092070849e-17, - "seconds": 8.7667e-05, + "seconds": 7.1708e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -13873,7 +13873,7 @@ "note": "double precision, gate by gate", "strict": 2.2850088420415793e-16, "global_phase": 1.2992703127221225e-17, - "seconds": 0.7309216250432655 + "seconds": 1.1969808749854565 }, { "entry": "gate_c3x", @@ -13885,7 +13885,7 @@ "note": "double precision, a contraction of width 4.0", "strict": 1.0734769178841271e-16, "global_phase": -9.403586273589279e-18, - "seconds": 0.0024314159527420998 + "seconds": 0.0030977909918874502 }, { "entry": "gate_c3x", @@ -13897,7 +13897,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 1.112211140817646e-16, "global_phase": -6.344245552251684e-17, - "seconds": 0.007021332974545658 + "seconds": 0.029777207993902266 }, { "entry": "gate_c3x", @@ -13909,7 +13909,7 @@ "note": "single precision, fusion width 2", "strict": 1.6502501688319433e-08, "global_phase": 4.00531217091603e-10, - "seconds": 0.002360624959692359 + "seconds": 0.002489916980266571 }, { "entry": "gate_c3x", @@ -13965,7 +13965,7 @@ "note": "double precision, fusion width 3", "strict": 1.1418412035005258e-16, "global_phase": -9.306014224130332e-18, - "seconds": 3.6041e-05 + "seconds": 2.2417e-05 }, { "entry": "gate_c3z", @@ -13977,7 +13977,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.599966217654964e-16, "global_phase": 1.4446076422946466e-17, - "seconds": 0.000130458 + "seconds": 7.5625e-05 }, { "entry": "gate_c3z", @@ -13989,7 +13989,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.599966217654964e-16, "global_phase": 1.4446076422946466e-17, - "seconds": 9.8041e-05, + "seconds": 7.0125e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14004,7 +14004,7 @@ "note": "double precision, gate by gate", "strict": 2.2850089960147827e-16, "global_phase": 1.299270222922428e-17, - "seconds": 0.7469101659953594 + "seconds": 1.1528718749759719 }, { "entry": "gate_c3z", @@ -14016,7 +14016,7 @@ "note": "double precision, a contraction of width 4.0", "strict": 3.3768940600253865e-16, "global_phase": -1.609024639425753e-17, - "seconds": 0.0023125000298023224 + "seconds": 0.0015487089985981584 }, { "entry": "gate_c3z", @@ -14028,7 +14028,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 4.070586436385354e-17, "global_phase": -3.264981576007027e-17, - "seconds": 0.007286041975021362 + "seconds": 0.021413750015199184 }, { "entry": "gate_c3z", @@ -14040,7 +14040,7 @@ "note": "single precision, fusion width 2", "strict": 1.6502501688319433e-08, "global_phase": 4.00531217091603e-10, - "seconds": 0.0022216669749468565 + "seconds": 0.0016822500620037317 }, { "entry": "gate_c3z", @@ -14096,7 +14096,7 @@ "note": "double precision, fusion width 3", "strict": 1.4948344912607779e-16, "global_phase": -1.2703930273265457e-16, - "seconds": 2.1042e-05 + "seconds": 1.325e-05 }, { "entry": "full_turn_rz_t1_0", @@ -14108,7 +14108,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4948344912607779e-16, "global_phase": -1.2703930273265457e-16, - "seconds": 8.2e-05 + "seconds": 6.8666e-05 }, { "entry": "full_turn_rz_t1_0", @@ -14120,7 +14120,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4948344912607779e-16, "global_phase": -1.2703930273265457e-16, - "seconds": 9.1083e-05, + "seconds": 7.2125e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14135,7 +14135,7 @@ "note": "double precision, gate by gate", "strict": 1.4948344912607779e-16, "global_phase": -1.2703930273265457e-16, - "seconds": 0.7267001669388264 + "seconds": 1.1541737919906154 }, { "entry": "full_turn_rz_t1_0", @@ -14147,7 +14147,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.9056138362361657e-16, "global_phase": -7.990180385963304e-17, - "seconds": 0.0007772910175845027 + "seconds": 0.0006017080741003156 }, { "entry": "full_turn_rz_t1_0", @@ -14159,7 +14159,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006728749955072999 + "seconds": 0.051466416916809976 }, { "entry": "full_turn_rz_t1_0", @@ -14171,7 +14171,7 @@ "note": "single precision, fusion width 2", "strict": 8.90724488612628e-08, "global_phase": 7.818648375738633e-08, - "seconds": 0.0021120000164955854 + "seconds": 0.0029993749922141433 }, { "entry": "full_turn_rz_t1_0", @@ -14227,7 +14227,7 @@ "note": "double precision, fusion width 3", "strict": 1.4345679644901053e-16, "global_phase": -7.291263256419637e-17, - "seconds": 2.5125e-05 + "seconds": 2.6375e-05 }, { "entry": "full_turn_rx_t1_0", @@ -14239,7 +14239,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4345679644901053e-16, "global_phase": -7.291263256419637e-17, - "seconds": 7.9e-05 + "seconds": 7.5959e-05 }, { "entry": "full_turn_rx_t1_0", @@ -14251,7 +14251,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.4345679644901053e-16, "global_phase": -7.291263256419637e-17, - "seconds": 8.7625e-05, + "seconds": 7.6875e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14266,7 +14266,7 @@ "note": "double precision, gate by gate", "strict": 1.4345679644901053e-16, "global_phase": -7.291263256419637e-17, - "seconds": 0.7404857910005376 + "seconds": 1.793335041962564 }, { "entry": "full_turn_rx_t1_0", @@ -14278,7 +14278,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.847827009626881e-16, "global_phase": -2.523059717935201e-17, - "seconds": 0.000813000020571053 + "seconds": 0.0006077500293031335 }, { "entry": "full_turn_rx_t1_0", @@ -14290,7 +14290,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.006693999981507659 + "seconds": 0.01697458396665752 }, { "entry": "full_turn_rx_t1_0", @@ -14302,7 +14302,7 @@ "note": "single precision, fusion width 2", "strict": 9.286830585039391e-08, "global_phase": 2.5246449585516763e-08, - "seconds": 0.0021868750918656588 + "seconds": 0.0015781669644638896 }, { "entry": "full_turn_rx_t1_0", @@ -14358,7 +14358,7 @@ "note": "double precision, fusion width 3", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 2.4375e-05 + "seconds": 1.3708e-05 }, { "entry": "full_turn_ry_t1_0", @@ -14370,7 +14370,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 8.8916e-05 + "seconds": 8.7416e-05 }, { "entry": "full_turn_ry_t1_0", @@ -14382,7 +14382,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 7.9292e-05, + "seconds": 0.000121167, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14397,7 +14397,7 @@ "note": "double precision, gate by gate", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.7576122080208734 + "seconds": 0.9568086660001427 }, { "entry": "full_turn_ry_t1_0", @@ -14409,7 +14409,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.145218421465822e-16, "global_phase": 1.6471238045877752e-17, - "seconds": 0.0008263749768957496 + "seconds": 0.0013836669968441129 }, { "entry": "full_turn_ry_t1_0", @@ -14421,7 +14421,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.008214833913370967 + "seconds": 0.009133500047028065 }, { "entry": "full_turn_ry_t1_0", @@ -14433,7 +14433,7 @@ "note": "single precision, fusion width 2", "strict": 1.03517635576141e-07, "global_phase": -2.429020790497895e-10, - "seconds": 0.003141332999803126 + "seconds": 0.0015652499860152602 }, { "entry": "full_turn_ry_t1_0", @@ -14489,7 +14489,7 @@ "note": "double precision, fusion width 3", "strict": 9.42812133633664e-17, "global_phase": -1.4642115032431582e-17, - "seconds": 2.1959e-05 + "seconds": 1.4709e-05 }, { "entry": "full_turn_p_t1_0", @@ -14501,7 +14501,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.42812133633664e-17, "global_phase": -1.4642115032431582e-17, - "seconds": 8.325e-05 + "seconds": 0.000112334 }, { "entry": "full_turn_p_t1_0", @@ -14513,7 +14513,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 9.42812133633664e-17, "global_phase": -1.4642115032431582e-17, - "seconds": 9.2125e-05, + "seconds": 0.000177167, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14528,7 +14528,7 @@ "note": "double precision, gate by gate", "strict": 9.42812133633664e-17, "global_phase": -1.4642115032431582e-17, - "seconds": 0.766350332996808 + "seconds": 0.9143914580345154 }, { "entry": "full_turn_p_t1_0", @@ -14540,7 +14540,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 2.6640113228721536e-16, "global_phase": 3.249538384058998e-17, - "seconds": 0.0009114590939134359 + "seconds": 0.00114733399823308 }, { "entry": "full_turn_p_t1_0", @@ -14552,7 +14552,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.00728962488938123 + "seconds": 0.02458954101894051 }, { "entry": "full_turn_p_t1_0", @@ -14564,7 +14564,7 @@ "note": "single precision, fusion width 2", "strict": 5.281740492289452e-08, "global_phase": -1.1788513077551646e-08, - "seconds": 0.0022234999341890216 + "seconds": 0.0041678749257698655 }, { "entry": "full_turn_p_t1_0", @@ -14620,7 +14620,7 @@ "note": "double precision, fusion width 3", "strict": 2.7979863037694193e-16, "global_phase": -2.5699069640890605e-16, - "seconds": 3.2042e-05 + "seconds": 1.5125e-05 }, { "entry": "full_turn_rz_t2_0", @@ -14632,7 +14632,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.7979863037694193e-16, "global_phase": -2.5699069640890605e-16, - "seconds": 0.000132875 + "seconds": 0.000109875 }, { "entry": "full_turn_rz_t2_0", @@ -14644,7 +14644,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.7979863037694193e-16, "global_phase": -2.5699069640890605e-16, - "seconds": 9.0208e-05, + "seconds": 7.0791e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14659,7 +14659,7 @@ "note": "double precision, gate by gate", "strict": 2.7979863037694193e-16, "global_phase": -2.5699069640890605e-16, - "seconds": 0.71128829207737 + "seconds": 0.8841374579351395 }, { "entry": "full_turn_rz_t2_0", @@ -14671,7 +14671,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.0608999734962266e-16, "global_phase": -2.249110223171109e-16, - "seconds": 0.0008625410264357924 + "seconds": 0.0005542909493669868 }, { "entry": "full_turn_rz_t2_0", @@ -14683,7 +14683,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.007432083017192781 + "seconds": 0.017945125000551343 }, { "entry": "full_turn_rz_t2_0", @@ -14695,7 +14695,7 @@ "note": "single precision, fusion width 2", "strict": 1.6144369169283853e-07, "global_phase": 1.4723470506158917e-07, - "seconds": 0.0019264579750597477 + "seconds": 0.0015363330021500587 }, { "entry": "full_turn_rz_t2_0", @@ -14751,7 +14751,7 @@ "note": "double precision, fusion width 3", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 2.7125e-05 + "seconds": 1.4084e-05 }, { "entry": "full_turn_u_t1_0", @@ -14763,7 +14763,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 9.5792e-05 + "seconds": 7e-05 }, { "entry": "full_turn_u_t1_0", @@ -14775,7 +14775,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 9.6333e-05, + "seconds": 6.675e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14790,7 +14790,7 @@ "note": "double precision, gate by gate", "strict": 1.46781205111376e-16, "global_phase": -3.05412677549014e-17, - "seconds": 0.7300282920477912 + "seconds": 1.1654333749320358 }, { "entry": "full_turn_u_t1_0", @@ -14802,7 +14802,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.145218421465822e-16, "global_phase": 1.6471238045877752e-17, - "seconds": 0.001068082987330854 + "seconds": 0.0013584160478785634 }, { "entry": "full_turn_u_t1_0", @@ -14814,7 +14814,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 7.823846913581342e-17, "global_phase": -2.389053613710233e-17, - "seconds": 0.014115583035163581 + "seconds": 0.014724832959473133 }, { "entry": "full_turn_u_t1_0", @@ -14826,7 +14826,7 @@ "note": "single precision, fusion width 2", "strict": 3.96561472339793e-08, "global_phase": -5.3183955982678255e-09, - "seconds": 0.0022812909446656704, + "seconds": 0.0015173329738900065, "adapter": [ "U as a matrix" ] @@ -14885,7 +14885,7 @@ "note": "double precision, fusion width 3", "strict": 9.02558849753476e-17, "global_phase": -3.5446437687523536e-17, - "seconds": 4.4542e-05 + "seconds": 2.8625e-05 }, { "entry": "gate_gphase_controlled", @@ -14897,7 +14897,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9856040498679177e-16, "global_phase": -6.181819723743999e-17, - "seconds": 9.5917e-05 + "seconds": 0.00012525 }, { "entry": "gate_gphase_controlled", @@ -14909,7 +14909,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.9856040498679177e-16, "global_phase": -6.181819723743999e-17, - "seconds": 9.7292e-05, + "seconds": 7.8833e-05, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -14942,7 +14942,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 3.019615798246159e-17, "global_phase": 1.3818898041286565e-17, - "seconds": 0.007037041010335088 + "seconds": 0.07803987490478903 }, { "entry": "gate_gphase_controlled", @@ -15007,7 +15007,7 @@ "note": "double precision, fusion width 3", "strict": 2.383329718893769e-16, "global_phase": 0.0, - "seconds": 3.5667e-05 + "seconds": 2.5083e-05 }, { "entry": "controlled_rz_full_turn", @@ -15019,7 +15019,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.79306168888485e-16, "global_phase": -6.162975822039155e-33, - "seconds": 8.3417e-05 + "seconds": 7.1083e-05 }, { "entry": "controlled_rz_full_turn", @@ -15031,7 +15031,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 1.79306168888485e-16, "global_phase": -6.162975822039155e-33, - "seconds": 9.4625e-05, + "seconds": 0.00011475, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -15046,7 +15046,7 @@ "note": "double precision, gate by gate", "strict": 2.383329718893769e-16, "global_phase": 0.0, - "seconds": 0.7365032079396769 + "seconds": 1.0266576660797 }, { "entry": "controlled_rz_full_turn", @@ -15058,7 +15058,7 @@ "note": "double precision, a contraction of width 2.0", "strict": 3.051434889952961e-16, "global_phase": -6.162975822039156e-33, - "seconds": 0.001084459014236927 + "seconds": 0.0007291659712791443 }, { "entry": "controlled_rz_full_turn", @@ -15070,7 +15070,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.220446049250313e-16, "global_phase": 0.0, - "seconds": 0.007645791978575289 + "seconds": 0.020958124892786145 }, { "entry": "controlled_rz_full_turn", @@ -15082,7 +15082,7 @@ "note": "single precision, fusion width 2", "strict": 6.181723814526122e-08, "global_phase": 0.0, - "seconds": 0.0022295829840004444 + "seconds": 0.001647041062824428 }, { "entry": "controlled_rz_full_turn", @@ -15172,7 +15172,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0031144159147515893 + "seconds": 0.000343416933901608 }, { "entry": "clifford_ghz_n100", @@ -15181,7 +15181,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 5.291e-06 + "seconds": 5.167e-06 }, { "entry": "clifford_ghz_n100", @@ -15198,7 +15198,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000609875 + "seconds": 0.000417666 }, { "entry": "clifford_ghz_n1000", @@ -15215,7 +15215,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00014937506057322025 + "seconds": 0.00010233395732939243 }, { "entry": "clifford_ghz_n1000", @@ -15224,7 +15224,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 4.4584e-05 + "seconds": 2.95e-05 }, { "entry": "clifford_ghz_n1000", @@ -15241,7 +15241,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.014881375 + "seconds": 0.010169208 }, { "entry": "clifford_ghz_n5000", @@ -15258,7 +15258,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.003994166967459023 + "seconds": 0.005294292001053691 }, { "entry": "clifford_ghz_n5000", @@ -15267,7 +15267,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.001584584 + "seconds": 0.001288875 }, { "entry": "clifford_ghz_n5000", @@ -15292,7 +15292,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 3.358395770192146e-05 + "seconds": 0.0004349169321358204 }, { "entry": "clifford_cluster_n65", @@ -15301,7 +15301,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 6.5e-06 + "seconds": 4.25e-06 }, { "entry": "clifford_cluster_n65", @@ -15318,7 +15318,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00022525 + "seconds": 0.000900667 }, { "entry": "clifford_cluster_n1000", @@ -15335,7 +15335,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0001759580336511135 + "seconds": 0.00013208400923758745 }, { "entry": "clifford_cluster_n1000", @@ -15344,7 +15344,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 9.6625e-05 + "seconds": 7.075e-05 }, { "entry": "clifford_cluster_n1000", @@ -15361,7 +15361,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.014522875 + "seconds": 0.011389125 }, { "entry": "clifford_cluster_n5000", @@ -15378,7 +15378,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.003936209017410874 + "seconds": 0.004756750073283911 }, { "entry": "clifford_cluster_n5000", @@ -15387,7 +15387,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.002841667 + "seconds": 0.002375292 }, { "entry": "clifford_cluster_n5000", @@ -15412,7 +15412,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 7.095793262124062e-05 + "seconds": 5.1332986913621426e-05 }, { "entry": "clifford_random_n63", @@ -15421,7 +15421,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 2.0167e-05 + "seconds": 1.4167e-05 }, { "entry": "clifford_random_n63", @@ -15438,7 +15438,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000548792 + "seconds": 0.000372834 }, { "entry": "clifford_random_n64", @@ -15455,7 +15455,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00016962504014372826 + "seconds": 3.595894668251276e-05 }, { "entry": "clifford_random_n64", @@ -15464,7 +15464,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 1.9459e-05 + "seconds": 1.4125e-05 }, { "entry": "clifford_random_n64", @@ -15481,7 +15481,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000499875 + "seconds": 0.000319167 }, { "entry": "clifford_random_n65", @@ -15498,7 +15498,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 5.3582945838570595e-05 + "seconds": 3.729097079485655e-05 }, { "entry": "clifford_random_n65", @@ -15507,7 +15507,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 3.2084e-05 + "seconds": 2.6375e-05 }, { "entry": "clifford_random_n65", @@ -15524,7 +15524,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.000516209 + "seconds": 0.000336292 }, { "entry": "clifford_random_n127", @@ -15541,7 +15541,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 8.216698188334703e-05 + "seconds": 5.4582953453063965e-05 }, { "entry": "clifford_random_n127", @@ -15550,7 +15550,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 3.9083e-05 + "seconds": 2.7958e-05 }, { "entry": "clifford_random_n127", @@ -15567,7 +15567,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0012055 + "seconds": 0.000813125 }, { "entry": "clifford_random_n128", @@ -15584,7 +15584,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 7.83340074121952e-05 + "seconds": 5.429191514849663e-05 }, { "entry": "clifford_random_n128", @@ -15593,7 +15593,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 4.3958e-05 + "seconds": 2.7125e-05 }, { "entry": "clifford_random_n128", @@ -15610,7 +15610,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.001126542 + "seconds": 0.000746167 }, { "entry": "clifford_random_n129", @@ -15627,7 +15627,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 8.274998981505632e-05 + "seconds": 5.512498319149017e-05 }, { "entry": "clifford_random_n129", @@ -15636,7 +15636,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 4.275e-05 + "seconds": 2.8667e-05 }, { "entry": "clifford_random_n129", @@ -15653,7 +15653,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.001216125 + "seconds": 0.0007365 }, { "entry": "clifford_random_n1000", @@ -15670,7 +15670,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.002268084092065692 + "seconds": 0.0016585829434916377 }, { "entry": "clifford_random_n1000", @@ -15679,7 +15679,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.001518083 + "seconds": 0.001009958 }, { "entry": "clifford_random_n1000", @@ -15696,7 +15696,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.044789375 + "seconds": 0.030227125 }, { "entry": "clifford_random_n2000", @@ -15713,7 +15713,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.0043587080435827374 + "seconds": 0.004239624948240817 }, { "entry": "clifford_random_n2000", @@ -15722,7 +15722,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 0.002777375 + "seconds": 0.003427834 }, { "entry": "clifford_random_n2000", @@ -15777,7 +15777,7 @@ "note": "double precision, fusion width 3", "strict": 1.3244320535236393e-15, "global_phase": -2.5571778398004984e-77, - "seconds": 0.002147708 + "seconds": 0.000947 }, { "entry": "clifford_random_n10_as_state", @@ -15789,7 +15789,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.0439850796711554e-15, "global_phase": 1.900363860637374e-15, - "seconds": 0.000682125 + "seconds": 0.000807042 }, { "entry": "clifford_random_n10_as_state", @@ -15801,7 +15801,7 @@ "note": "double precision, fusion up to 5 qubits from 14 qubits", "strict": 2.0439850796711554e-15, "global_phase": 1.900363860637374e-15, - "seconds": 0.000595709, + "seconds": 0.000395333, "adapter": [ "read from the published OpenQASM 3 text" ] @@ -15816,19 +15816,19 @@ "note": "double precision, gate by gate", "strict": 4.3182725538710424e-15, "global_phase": 3.146394755705127e-15, - "seconds": 1.59596608299762 + "seconds": 1.481040291953832 }, { "entry": "clifford_random_n10_as_state", "engine": "quimb.tensor_network", "quantity": "distance from the exact state, modulo a global phase", - "measured": 3.4191249340431586e-14, + "measured": 3.5169901818997685e-14, "tolerance": 7.041552439966656e-07, "status": "pass", "note": "double precision, a contraction of width 16.0", - "strict": 3.4347844724605076e-14, - "global_phase": 3.2761113787564192e-15, - "seconds": 1.3227987909922376 + "strict": 3.531697004362356e-14, + "global_phase": 3.21968618102247e-15, + "seconds": 0.8477470419602469 }, { "entry": "clifford_random_n10_as_state", @@ -15840,7 +15840,7 @@ "note": "decision-diagram edge weights merged within 2^-42", "strict": 2.253673324449967e-16, "global_phase": -2.5571778398004988e-77, - "seconds": 0.0360091250622645 + "seconds": 0.03871849994175136 }, { "entry": "clifford_random_n10_as_state", @@ -15852,7 +15852,7 @@ "note": "single precision, fusion width 2", "strict": 1.3551576450466702e-06, "global_phase": 6.85627931991555e-07, - "seconds": 0.0175901249749586 + "seconds": 0.015559333027340472 }, { "entry": "clifford_random_n10_as_state", @@ -15869,7 +15869,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 3.8334052078425884e-05 + "seconds": 3.0540977604687214e-05 }, { "entry": "clifford_random_n10_as_state", @@ -15878,7 +15878,7 @@ "measured": 0, "tolerance": 0, "status": "pass", - "seconds": 1.0583e-05 + "seconds": 7.875e-06 }, { "entry": "clifford_random_n10_as_state", @@ -15895,7 +15895,7 @@ "measured": true, "tolerance": true, "status": "pass", - "seconds": 0.00017675 + "seconds": 0.000124917 }, { "entry": "clifford_random_n10_as_state", @@ -16082,7 +16082,7 @@ "tolerance": 2.76696570893817e-13, "status": "pass", "note": "29 two-site updates at bond 2; truncation from its reported discarded weight", - "seconds": 0.001589583, + "seconds": 0.00112575, "accuracy": { "class": "exact", "max_bond": 64, @@ -16098,7 +16098,7 @@ "tolerance": 8.450256244926496e-14, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.003456791, + "seconds": 0.007779584, "accuracy": { "class": "exact" } @@ -16111,7 +16111,7 @@ "tolerance": 2.76696570893817e-13, "status": "pass", "note": "29 two-site updates at bond 2, and 0 truncations, from its log", - "seconds": 0.003731167 + "seconds": 0.00026725 }, { "entry": "mps_ghz_n30", @@ -16121,7 +16121,7 @@ "tolerance": 8.566965708938169e-13, "status": "pass", "note": "29 two-site updates at bond 2; its cutoff drops at most 1e-28 of weight at each", - "seconds": 0.8411782910116017 + "seconds": 0.6262620000634342 }, { "entry": "mps_ghz_n30", @@ -16131,7 +16131,7 @@ "tolerance": 8.450256244926496e-14, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.9288393330061808 + "seconds": 0.6740093750413507 }, { "entry": "mps_ghz_n50", @@ -16141,7 +16141,7 @@ "tolerance": 4.67521792199987e-13, "status": "pass", "note": "49 two-site updates at bond 2; truncation from its reported discarded weight", - "seconds": 0.000986958, + "seconds": 0.000794333, "accuracy": { "class": "exact", "max_bond": 64, @@ -16157,7 +16157,7 @@ "tolerance": 1.4083760408211617e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.004632333, + "seconds": 0.002289292, "accuracy": { "class": "exact" } @@ -16170,7 +16170,7 @@ "tolerance": 4.67521792199987e-13, "status": "pass", "note": "49 two-site updates at bond 2, and 0 truncations, from its log", - "seconds": 0.000601542 + "seconds": 0.000307292 }, { "entry": "mps_ghz_n50", @@ -16180,7 +16180,7 @@ "tolerance": 1.447521792199987e-12, "status": "pass", "note": "49 two-site updates at bond 2; its cutoff drops at most 1e-28 of weight at each", - "seconds": 0.8758880420355126 + "seconds": 0.6501935409614816 }, { "entry": "mps_ghz_n50", @@ -16190,7 +16190,7 @@ "tolerance": 1.4083760408211617e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.9672316659707576 + "seconds": 0.6996900420635939 }, { "entry": "mps_ghz_n100", @@ -16200,7 +16200,7 @@ "tolerance": 9.445848454657303e-13, "status": "pass", "note": "99 two-site updates at bond 2; truncation from its reported discarded weight", - "seconds": 0.001417083, + "seconds": 0.000970708, "accuracy": { "class": "exact", "max_bond": 64, @@ -16216,7 +16216,7 @@ "tolerance": 2.8167520816427206e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.00561525, + "seconds": 0.003119125, "accuracy": { "class": "exact" } @@ -16238,7 +16238,7 @@ "tolerance": 2.9245848454657303e-12, "status": "pass", "note": "99 two-site updates at bond 2; its cutoff drops at most 1e-28 of weight at each", - "seconds": 0.8999580409144983 + "seconds": 0.6343237078981474 }, { "entry": "mps_ghz_n100", @@ -16248,7 +16248,7 @@ "tolerance": 2.8167520816427206e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.9571129579562694 + "seconds": 0.6844658330082893 }, { "entry": "mps_qft_n30", @@ -16258,7 +16258,7 @@ "tolerance": 5.3837041007541454e-11, "status": "pass", "note": "8990 two-site updates at bond 1; truncation from its reported discarded weight", - "seconds": 0.013786791, + "seconds": 0.008429625, "accuracy": { "class": "exact", "max_bond": 64, @@ -16274,7 +16274,7 @@ "tolerance": 7.408057974723756e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.109312958, + "seconds": 0.064939, "accuracy": { "class": "exact" } @@ -16287,7 +16287,7 @@ "tolerance": 7.557546801821243e-12, "status": "pass", "note": "1262 two-site updates at bond 1, and 0 truncations, from its log", - "seconds": 0.007108083 + "seconds": 0.004755625 }, { "entry": "mps_qft_n30", @@ -16297,7 +16297,7 @@ "tolerance": 2.3363704100754143e-10, "status": "pass", "note": "8990 two-site updates at bond 1; its cutoff drops at most 1e-28 of weight at each", - "seconds": 1.8894032500684261 + "seconds": 1.2922196669969708 }, { "entry": "mps_qft_n30", @@ -16307,7 +16307,7 @@ "tolerance": 7.408057974723756e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 1.2531822089804336 + "seconds": 0.862622749991715 }, { "entry": "mps_qft_n40", @@ -16317,7 +16317,7 @@ "tolerance": 1.2767583029650018e-10, "status": "pass", "note": "21320 two-site updates at bond 1; truncation from its reported discarded weight", - "seconds": 0.024466375, + "seconds": 0.015562916, "accuracy": { "class": "exact", "max_bond": 64, @@ -16333,7 +16333,7 @@ "tolerance": 1.2675384367404737e-12, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.322320834, + "seconds": 0.187425625, "accuracy": { "class": "exact" } @@ -16346,7 +16346,7 @@ "tolerance": 1.3665865136181795e-11, "status": "pass", "note": "2282 two-site updates at bond 1, and 0 truncations, from its log", - "seconds": 0.013835708 + "seconds": 0.008756208 }, { "entry": "mps_qft_n40", @@ -16356,7 +16356,7 @@ "tolerance": 5.540758302965001e-10, "status": "pass", "note": "21320 two-site updates at bond 1; its cutoff drops at most 1e-28 of weight at each", - "seconds": 3.2153038749238476 + "seconds": 1.945818042033352 }, { "entry": "mps_qft_n40", @@ -16366,7 +16366,7 @@ "tolerance": 1.2675384367404737e-12, "status": "pass", "note": "contraction of width 1.0", - "seconds": 1.567623334005475 + "seconds": 0.9455756669631228 }, { "entry": "mps_qft_n30_bond256", @@ -16376,7 +16376,7 @@ "tolerance": 5.3837041007541454e-11, "status": "pass", "note": "8990 two-site updates at bond 1; truncation from its reported discarded weight", - "seconds": 0.012208708, + "seconds": 0.008298958, "accuracy": { "class": "exact", "max_bond": 256, @@ -16560,7 +16560,7 @@ "tolerance": 1.964309233906341e-12, "status": "pass", "note": "118 two-site updates at bond 4; truncation from its reported discarded weight", - "seconds": 0.004369458, + "seconds": 0.003116959, "accuracy": { "class": "exact", "max_bond": 64, @@ -16576,7 +16576,7 @@ "tolerance": 3.563571497430284e-09, "status": "pass", "note": "contraction of width 10.9", - "seconds": 0.283974333, + "seconds": 0.1849785, "accuracy": { "class": "exact" } @@ -16589,7 +16589,7 @@ "tolerance": 1.964309233906341e-12, "status": "pass", "note": "118 two-site updates at bond 4, and 0 truncations, from its log", - "seconds": 0.00099275 + "seconds": 0.000684083 }, { "entry": "tn_mirror_n40", @@ -16599,7 +16599,7 @@ "tolerance": 3.066648591607605e-12, "status": "pass", "note": "118 two-site updates at bond 1; its cutoff drops at most 1e-28 of weight at each", - "seconds": 0.9480152500327677 + "seconds": 0.5295150000602007 }, { "entry": "tn_mirror_n40", @@ -16609,7 +16609,7 @@ "tolerance": 5.605336642470576e-13, "status": "pass", "note": "contraction of width 1.0", - "seconds": 0.9976278330432251 + "seconds": 0.5808975420659408 }, { "entry": "bit_order_named_bits", @@ -16780,7 +16780,7 @@ "entry": "ghz_counts_n8", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.09955994386617024, + "measured": 0.21479136037794136, "tolerance": 1.0, "status": "pass" }, @@ -16788,7 +16788,7 @@ "entry": "ghz_counts_n8", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.0021599999999999953, + "measured": 0.004660000000000053, "tolerance": 0.02217450161929334, "status": "pass" }, @@ -16895,7 +16895,7 @@ "entry": "qft_counts_n8", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.4560179507508429, + "measured": 0.38527832404157086, "tolerance": 1.0, "status": "pass" }, @@ -16903,7 +16903,7 @@ "entry": "qft_counts_n8", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.026974999999999996, + "measured": 0.030047499999999994, "tolerance": 0.04479339348223444, "status": "pass" }, @@ -16977,7 +16977,7 @@ "entry": "grover_counts_n5", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.1583716700083005, + "measured": 0.20547373810892686, "tolerance": 1.0, "status": "pass" }, @@ -16985,7 +16985,7 @@ "entry": "grover_counts_n5", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.0005359386253356598, + "measured": 0.0005376771175860968, "tolerance": 0.03012634777731961, "status": "pass" }, @@ -17059,7 +17059,7 @@ "entry": "rotations_counts_n6", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.2871721572793732, + "measured": 0.4403894792117234, "tolerance": 1.0, "status": "pass" }, @@ -17067,7 +17067,7 @@ "entry": "rotations_counts_n6", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.010470101748990412, + "measured": 0.012669028080634965, "tolerance": 0.025992412604050198, "status": "pass" }, @@ -17141,7 +17141,7 @@ "entry": "teleport", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.24752407359068593, + "measured": 0.15684533117227129, "tolerance": 1.0, "status": "pass" }, @@ -17149,7 +17149,7 @@ "entry": "teleport", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.004483679899192404, + "measured": 0.002503679899192396, "tolerance": 0.016954146745431286, "status": "pass" }, @@ -17207,7 +17207,7 @@ "entry": "reset_after_superposition", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.014749621313506702, + "measured": 0.020280729306071717, "tolerance": 1.0, "status": "pass" }, @@ -17215,7 +17215,7 @@ "entry": "reset_after_superposition", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.00032000000000004247, + "measured": 0.00043999999999999595, "tolerance": 0.02217450161929334, "status": "pass" }, @@ -17309,14 +17309,14 @@ "measured": 46.092566604708445, "tolerance": 1.0, "status": "known", - "note": "10: 50246 shots, probability 0; 11: 0 shots, expected 50000.0 \u00b1 1084.8 | known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2.", + "note": "10: 49689 shots, probability 0; 11: 0 shots, expected 50000.0 \u00b1 1084.8 | known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2.", "right": "the exact reference: a second measurement of a qubit in the same basis repeats the first, so only 00 and 11 occur. Every other engine that ran this program met it (the results files)." }, { "entry": "measure_twice", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 1.00492, + "measured": 1.0, "tolerance": 0.02217450161929334, "status": "known", "note": "known: MQT DDSIM 2.7.0's qasm_simulator, given h q[0]; c[0] = measure q[0]; c[1] = measure q[0]; with nothing between the two measurements, returns 00 and 10: c[0] is never set. With x in place of h it gives 10 on every shot; with a barrier between the measurements, 00 and 11; with c[1] measured first and c[0] second, ValueError [changePermutation]. Each is a case of the reproducer, with the circuit built in Qiskit 2.6.2.", @@ -17409,7 +17409,7 @@ "entry": "feedback_flip", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.06913884990706268, + "measured": 0.0414833099442376, "tolerance": 1.0, "status": "pass" }, @@ -17417,7 +17417,7 @@ "entry": "feedback_flip", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.0015000000000000013, + "measured": 0.0008999999999999564, "tolerance": 0.02217450161929334, "status": "pass" }, @@ -17508,7 +17508,7 @@ "entry": "ghz_by_fusion", "engine": "ddsim.statevector", "quantity": "largest deviation of an outcome's count, in units of its Bernstein bound", - "measured": 0.12015070282256382, + "measured": 0.2519974917605985, "tolerance": 1.0, "status": "pass" }, @@ -17516,7 +17516,7 @@ "entry": "ghz_by_fusion", "engine": "ddsim.statevector", "quantity": "L1 distance from the exact distribution, \u03a3|count/shots \u2212 p| over every outcome (twice the total variation), against its bound", - "measured": 0.002779999999999977, + "measured": 0.004739999999999994, "tolerance": 0.022791103731202682, "status": "pass" }, @@ -17637,8 +17637,8 @@ 219 ], "seconds": [ - 0.000713625, - 0.0011460409732535481 + 0.000466875, + 0.004668458015657961 ] }, { @@ -17683,8 +17683,8 @@ 1677 ], "seconds": [ - 0.003478833, - 0.0039891250198706985 + 0.002268209, + 0.002673208015039563 ] }, { @@ -17729,8 +17729,8 @@ 5471 ], "seconds": [ - 0.009456667, - 0.01284174993634224 + 0.006061083, + 0.0085850830655545 ] }, { @@ -17775,8 +17775,8 @@ 12705 ], "seconds": [ - 0.019662541, - 0.030041791032999754 + 0.013007667, + 0.020378957968205214 ] }, { @@ -17821,8 +17821,8 @@ 24483 ], "seconds": [ - 0.033810291, - 0.05932000000029802 + 0.02334175, + 0.04012487502768636 ] }, { @@ -17867,8 +17867,8 @@ 66087 ], "seconds": [ - 0.104346791, - 0.17587320797611028 + 0.071989625, + 0.1137794170062989 ] }, { @@ -17913,8 +17913,8 @@ 221 ], "seconds": [ - 0.000678291, - 0.0006189170526340604 + 0.000461542, + 0.00041970901656895876 ] }, { @@ -17951,8 +17951,8 @@ 1679 ], "seconds": [ - 0.003349208, - 0.0039539579302072525 + 0.002256791, + 0.002899249899201095 ] }, { @@ -17989,8 +17989,8 @@ 5473 ], "seconds": [ - 0.00923875, - 0.012668208102695644 + 0.005989791, + 0.008677458972670138 ] }, { @@ -18027,8 +18027,8 @@ 423 ], "seconds": [ - 0.001081541, - 0.001112625002861023 + 0.000696084, + 0.0008016250794753432 ] }, { @@ -18065,8 +18065,8 @@ 3139 ], "seconds": [ - 0.005938583, - 0.006987332948483527 + 0.003718166, + 0.004977540927939117 ] }, { @@ -18103,8 +18103,8 @@ 21 ], "seconds": [ - 0.000127083, - 9.929097723215818e-05 + 8.2125e-05, + 6.987503729760647e-05 ] }, { @@ -18141,8 +18141,8 @@ 225 ], "seconds": [ - 0.00075525, - 0.0007836250588297844 + 0.00052075, + 0.0005826669512316585 ] }, { @@ -18179,8 +18179,8 @@ 1825 ], "seconds": [ - 0.00559825, - 0.007090709055773914 + 0.003611083, + 0.0055151249980553985 ] }, { @@ -18217,8 +18217,8 @@ 0 ], "seconds": [ - 8.375e-05, - 0.00013129098806530237 + 6.8375e-05, + 8.65840120241046e-05 ] }, { @@ -18263,8 +18263,8 @@ 72 ], "seconds": [ - 0.000386584, - 0.0003179999766871333 + 0.00027425, + 0.0001989169977605343 ] }, { @@ -18293,8 +18293,8 @@ 1 ], "seconds": [ - 1.2417e-05, - 4.0375045500695705e-05 + 9.167e-06, + 2.3583066649734974e-05 ] }, { @@ -18323,8 +18323,8 @@ 2 ], "seconds": [ - 1.6375e-05, - 3.433390520513058e-05 + 1.2209e-05, + 2.420798409730196e-05 ] }, { @@ -18353,8 +18353,8 @@ 3 ], "seconds": [ - 2.9709e-05, - 4.5792083255946636e-05 + 1.8375e-05, + 3.020802978426218e-05 ] }, { @@ -18383,8 +18383,8 @@ 1 ], "seconds": [ - 1.25e-05, - 3.574998117983341e-05 + 9.875e-06, + 2.358399797230959e-05 ] }, { @@ -18413,8 +18413,8 @@ 2 ], "seconds": [ - 1.8959e-05, - 4.145794082432985e-05 + 2.0167e-05, + 2.6250025257468224e-05 ] }, { @@ -18443,8 +18443,8 @@ 2 ], "seconds": [ - 2.0041e-05, - 4.045804962515831e-05 + 1.4292e-05, + 2.7666916139423847e-05 ] }, { @@ -18488,7 +18488,7 @@ "measured": 0.2304771050227863, "tolerance": 1.0, "status": "pass", - "seconds": 0.00616 + "seconds": 0.003694375 }, { "entry": "surface_z_d3", @@ -18497,7 +18497,7 @@ "measured": 0.2661128636247814, "tolerance": 1.0, "status": "pass", - "seconds": 0.07386995805427432 + "seconds": 0.04119587503373623 }, { "entry": "surface_z_d5", @@ -18506,7 +18506,7 @@ "measured": 0.3987789919630123, "tolerance": 1.0, "status": "pass", - "seconds": 0.142562708 + "seconds": 0.087233625 }, { "entry": "surface_z_d5", @@ -18515,7 +18515,7 @@ "measured": 0.3144512933839094, "tolerance": 1.0, "status": "pass", - "seconds": 0.5058500830782577 + "seconds": 0.3433140409179032 }, { "entry": "surface_z_d7", @@ -18524,7 +18524,7 @@ "measured": 0.39835596383900373, "tolerance": 1.0, "status": "pass", - "seconds": 0.365892958 + "seconds": 0.2379985 }, { "entry": "surface_z_d7", @@ -18533,7 +18533,7 @@ "measured": 0.3695550268608843, "tolerance": 1.0, "status": "pass", - "seconds": 2.6451887079747394 + "seconds": 2.1052502089878544 }, { "entry": "surface_z_d9", @@ -18542,7 +18542,7 @@ "measured": 0.4456060942390596, "tolerance": 1.0, "status": "pass", - "seconds": 0.739955167 + "seconds": 0.51243175 }, { "entry": "surface_z_d9", @@ -18551,7 +18551,7 @@ "measured": 0.4416700552118457, "tolerance": 1.0, "status": "pass", - "seconds": 5.452272666967474 + "seconds": 4.264874542015605 }, { "entry": "surface_z_d11", @@ -18560,7 +18560,7 @@ "measured": 0.4733064448042587, "tolerance": 1.0, "status": "pass", - "seconds": 1.420455292 + "seconds": 1.035609416 }, { "entry": "surface_z_d11", @@ -18569,7 +18569,7 @@ "measured": 0.4942569297658577, "tolerance": 1.0, "status": "pass", - "seconds": 10.257314375019632 + "seconds": 8.321117167011835 }, { "entry": "surface_z_d15", @@ -18578,7 +18578,7 @@ "measured": 0.6057844326922145, "tolerance": 1.0, "status": "pass", - "seconds": 3.62115825 + "seconds": 2.494983083 }, { "entry": "surface_z_d15", @@ -18587,7 +18587,7 @@ "measured": 0.5193975117197764, "tolerance": 1.0, "status": "pass", - "seconds": 30.263309958041646 + "seconds": 22.33989433303941 }, { "entry": "surface_x_d3", @@ -18596,7 +18596,7 @@ "measured": 0.23096664789658297, "tolerance": 1.0, "status": "pass", - "seconds": 0.02895525 + "seconds": 0.018775375 }, { "entry": "surface_x_d3", @@ -18605,7 +18605,7 @@ "measured": 0.3346705906065203, "tolerance": 1.0, "status": "pass", - "seconds": 0.13329529203474522 + "seconds": 0.08016495895572007 }, { "entry": "surface_x_d5", @@ -18614,7 +18614,7 @@ "measured": 0.3987789919630123, "tolerance": 1.0, "status": "pass", - "seconds": 0.132574167 + "seconds": 0.090218458 }, { "entry": "surface_x_d5", @@ -18623,7 +18623,7 @@ "measured": 0.31454438499280807, "tolerance": 1.0, "status": "pass", - "seconds": 0.544620250002481 + "seconds": 0.34453762497287244 }, { "entry": "surface_x_d7", @@ -18632,7 +18632,7 @@ "measured": 0.39835596383900373, "tolerance": 1.0, "status": "pass", - "seconds": 0.35978625 + "seconds": 0.23715375 }, { "entry": "surface_x_d7", @@ -18641,7 +18641,7 @@ "measured": 0.3695550268608843, "tolerance": 1.0, "status": "pass", - "seconds": 2.668296250049025 + "seconds": 2.027249166974798 }, { "entry": "unrotated_z_d3", @@ -18650,7 +18650,7 @@ "measured": 0.44319045410204105, "tolerance": 1.0, "status": "pass", - "seconds": 0.05550675 + "seconds": 0.037378833 }, { "entry": "unrotated_z_d3", @@ -18659,7 +18659,7 @@ "measured": 0.29227715759520817, "tolerance": 1.0, "status": "pass", - "seconds": 0.1821864580269903 + "seconds": 0.12103662500157952 }, { "entry": "unrotated_z_d5", @@ -18668,7 +18668,7 @@ "measured": 0.3643716825843924, "tolerance": 1.0, "status": "pass", - "seconds": 0.2942975 + "seconds": 0.198720458 }, { "entry": "unrotated_z_d5", @@ -18677,7 +18677,7 @@ "measured": 0.3905954253802165, "tolerance": 1.0, "status": "pass", - "seconds": 1.9498585000401363 + "seconds": 1.517868374940008 }, { "entry": "repetition_d3", @@ -18686,7 +18686,7 @@ "measured": 0.21696476647114454, "tolerance": 1.0, "status": "pass", - "seconds": 0.010206875 + "seconds": 0.007140334 }, { "entry": "repetition_d3", @@ -18695,7 +18695,7 @@ "measured": 0.22689176096366143, "tolerance": 1.0, "status": "pass", - "seconds": 0.08801833400502801 + "seconds": 0.07909966690931469 }, { "entry": "repetition_d9", @@ -18704,7 +18704,7 @@ "measured": 0.3716880031955475, "tolerance": 1.0, "status": "pass", - "seconds": 0.096232 + "seconds": 0.068405958 }, { "entry": "repetition_d9", @@ -18713,7 +18713,7 @@ "measured": 0.32865368253332666, "tolerance": 1.0, "status": "pass", - "seconds": 0.4348553749732673 + "seconds": 0.3132927499245852 }, { "entry": "repetition_d25", @@ -18722,7 +18722,7 @@ "measured": 0.47629975805018154, "tolerance": 1.0, "status": "pass", - "seconds": 0.657339291 + "seconds": 0.5353145 }, { "entry": "repetition_d25", @@ -18731,7 +18731,7 @@ "measured": 0.4600737027185245, "tolerance": 1.0, "status": "pass", - "seconds": 5.5631000000284985 + "seconds": 4.257399541907944 }, { "entry": "surface_z_d5_noiseless", @@ -18740,7 +18740,7 @@ "measured": 0.0, "tolerance": 1.0, "status": "pass", - "seconds": 0.004339625 + "seconds": 0.002813709 }, { "entry": "surface_z_d5_noiseless", @@ -18749,7 +18749,7 @@ "measured": 0.0, "tolerance": 1.0, "status": "pass", - "seconds": 0.11899908306077123 + "seconds": 0.0772967078955844 }, { "entry": "color_d3", @@ -18758,7 +18758,7 @@ "measured": 0.33316165193450636, "tolerance": 1.0, "status": "pass", - "seconds": 0.025478875 + "seconds": 0.014507542 }, { "entry": "color_d3", @@ -18767,7 +18767,7 @@ "measured": 0.34309871881715936, "tolerance": 1.0, "status": "pass", - "seconds": 0.10999533301219344 + "seconds": 0.064140958013013 }, { "entry": "qec_inverted_and_tagged", @@ -18776,7 +18776,7 @@ "measured": 0.05174210467167158, "tolerance": 1.0, "status": "pass", - "seconds": 0.000713917 + "seconds": 0.000479334 }, { "entry": "qec_inverted_and_tagged", @@ -18785,7 +18785,7 @@ "measured": 0.07132019833119274, "tolerance": 1.0, "status": "pass", - "seconds": 0.06435250001959503 + "seconds": 0.04029116698075086 }, { "entry": "qec_measure_flip_noise", @@ -18794,7 +18794,7 @@ "measured": 0.16886264250373062, "tolerance": 1.0, "status": "pass", - "seconds": 0.001271 + "seconds": 0.000742625 }, { "entry": "qec_measure_flip_noise", @@ -18803,7 +18803,7 @@ "measured": 0.03989205940511376, "tolerance": 1.0, "status": "pass", - "seconds": 0.06716670899186283 + "seconds": 0.039392083999700844 }, { "entry": "qec_depolarize_merge", @@ -18812,7 +18812,7 @@ "measured": 0.0989377295879301, "tolerance": 1.0, "status": "pass", - "seconds": 0.002213625 + "seconds": 0.001542333 }, { "entry": "qec_depolarize_merge", @@ -18821,7 +18821,7 @@ "measured": 0.20788039812338693, "tolerance": 1.0, "status": "pass", - "seconds": 0.06893695902545005 + "seconds": 0.04233116703107953 }, { "entry": "qec_pauli_observable", @@ -18830,7 +18830,7 @@ "measured": 0.21396059499360365, "tolerance": 1.0, "status": "pass", - "seconds": 0.000662375 + "seconds": 0.000425958 }, { "entry": "qec_pauli_observable", @@ -18839,7 +18839,7 @@ "measured": 0.0461483636260614, "tolerance": 1.0, "status": "pass", - "seconds": 0.06313629203941673 + "seconds": 0.04201687499880791 }, { "entry": "qec_correlated", @@ -18848,7 +18848,7 @@ "measured": 0.11269506781951577, "tolerance": 1.0, "status": "pass", - "seconds": 0.0011695 + "seconds": 0.000789 }, { "entry": "qec_correlated", @@ -18857,7 +18857,7 @@ "measured": 0.08676522920618003, "tolerance": 1.0, "status": "pass", - "seconds": 0.07208904204890132 + "seconds": 0.04364404093939811 }, { "entry": "qec_pauli_channel", @@ -18866,7 +18866,7 @@ "measured": 0.08546188592769022, "tolerance": 1.0, "status": "pass", - "seconds": 0.00248625 + "seconds": 0.001630416 }, { "entry": "qec_pauli_channel", @@ -18875,7 +18875,7 @@ "measured": 0.23903625236925427, "tolerance": 1.0, "status": "pass", - "seconds": 0.07269837497733533 + "seconds": 0.04272733302786946 }, { "entry": "measure_twice", -- 2.54.0 (Apple Git-157)